|
1 | | -""" |
2 | | - PiecewisePolynomialKernel{V}(maha::AbstractMatrix) |
| 1 | +@doc raw""" |
| 2 | + PiecewisePolynomialKernel(; degree::Int=0, dim::Int) |
| 3 | + PiecewisePolynomialKernel{degree}(dim::Int) |
| 4 | +
|
| 5 | +Piecewise polynomial kernel of degree `degree` for inputs of dimension `dim` with support in |
| 6 | +the unit ball. |
| 7 | +
|
| 8 | +# Definition |
3 | 9 |
|
4 | | -Piecewise Polynomial covariance function with compact support, V = 0,1,2,3. |
5 | | -The kernel functions are 2V times continuously differentiable and the corresponding |
6 | | -processes are hence V times mean-square differentiable. The kernel function is: |
| 10 | +For inputs ``x, x' \in \mathbb{R}^d`` of dimension ``d``, the piecewise polynomial kernel |
| 11 | +of degree ``v \in \{0,1,2,3\}`` is defined as |
7 | 12 | ```math |
8 | | - κ(x, y) = max(1 - r, 0)^(j + V) * f(r, j) with j = floor(D / 2) + V + 1 |
| 13 | +k(x, x'; v) = \max(1 - \|x - x'\|, 0)^{\alpha(v,d)} f_{v,d}(\|x - x'\|), |
9 | 14 | ``` |
10 | | -where `r` is the Mahalanobis distance mahalanobis(x,y) with `maha` as the metric. |
| 15 | +where ``\alpha(v, d) = \lfloor \frac{d}{2}\rfloor + 2v + 1`` and ``f_{v,d}`` are |
| 16 | +polynomials of degree ``v`` given by |
| 17 | +```math |
| 18 | +\begin{aligned} |
| 19 | +f_{0,d}(r) &= 1, \\ |
| 20 | +f_{1,d}(r) &= 1 + (j + 1) r, \\ |
| 21 | +f_{2,d}(r) &= 1 + (j + 2) r + \big((j^2 + 4j + 3) / 3\big) r^2, \\ |
| 22 | +f_{3,d}(r) &= 1 + (j + 3) r + \big((6 j^2 + 36j + 45) / 15\big) r^2 + \big((j^3 + 9 j^2 + 23j + 15) / 15\big) r^3, |
| 23 | +\end{aligned} |
| 24 | +``` |
| 25 | +where ``j = \lfloor \frac{d}{2}\rfloor + v + 1``. |
| 26 | +
|
| 27 | +The kernel is ``2v`` times continuously differentiable and the corresponding Gaussian |
| 28 | +process is hence ``v`` times mean-square differentiable. |
11 | 29 | """ |
12 | | -struct PiecewisePolynomialKernel{V,A<:AbstractMatrix{<:Real}} <: SimpleKernel |
13 | | - maha::A |
14 | | - j::Int |
15 | | - function PiecewisePolynomialKernel{V}(maha::AbstractMatrix{<:Real}) where {V} |
16 | | - V in (0, 1, 2, 3) || error("Invalid parameter V=$(V). Should be 0, 1, 2 or 3.") |
17 | | - LinearAlgebra.checksquare(maha) |
18 | | - j = div(size(maha, 1), 2) + V + 1 |
19 | | - return new{V,typeof(maha)}(maha, j) |
| 30 | +struct PiecewisePolynomialKernel{D,C<:Tuple} <: SimpleKernel |
| 31 | + alpha::Int |
| 32 | + coeffs::C |
| 33 | + |
| 34 | + function PiecewisePolynomialKernel{D}(dim::Int) where {D} |
| 35 | + dim > 0 || error("number of dimensions has to be positive") |
| 36 | + j = div(dim, 2) + D + 1 |
| 37 | + alpha = j + D |
| 38 | + coeffs = piecewise_polynomial_coefficients(Val(D), j) |
| 39 | + return new{D,typeof(coeffs)}(alpha, coeffs) |
20 | 40 | end |
21 | 41 | end |
22 | 42 |
|
23 | | -function PiecewisePolynomialKernel(; v::Integer=0, maha::AbstractMatrix{<:Real}) |
24 | | - return PiecewisePolynomialKernel{v}(maha) |
25 | | -end |
| 43 | +# TODO: remove `maha` keyword argument in next breaking release |
| 44 | +function PiecewisePolynomialKernel(; v::Int=-1, degree::Int=v, maha=nothing, dim::Int=-1) |
| 45 | + if v != -1 |
| 46 | + Base.depwarn( |
| 47 | + "keyword argument `v` is deprecated, use `degree` instead", |
| 48 | + :PiecewisePolynomialKernel, |
| 49 | + ) |
| 50 | + end |
26 | 51 |
|
27 | | -# Have to reconstruct the type parameter |
28 | | -# See also https://github.com/FluxML/Functors.jl/issues/3#issuecomment-626747663 |
29 | | -function Functors.functor(::Type{<:PiecewisePolynomialKernel{V}}, x) where {V} |
30 | | - function reconstruct_kernel(xs) |
31 | | - return PiecewisePolynomialKernel{V}(xs.maha) |
| 52 | + if maha !== nothing |
| 53 | + Base.depwarn( |
| 54 | + "keyword argument `maha` is deprecated, use a `LinearTransform` instead", |
| 55 | + :PiecewisePolynomialKernel, |
| 56 | + ) |
| 57 | + dim = size(maha, 1) |
| 58 | + return transform( |
| 59 | + PiecewisePolynomialKernel{degree}(dim), LinearTransform(cholesky(maha).U) |
| 60 | + ) |
| 61 | + else |
| 62 | + return PiecewisePolynomialKernel{degree}(dim) |
32 | 63 | end |
33 | | - return (maha=x.maha,), reconstruct_kernel |
34 | 64 | end |
35 | 65 |
|
36 | | -_f(κ::PiecewisePolynomialKernel{0}, r, j) = 1 |
37 | | -_f(κ::PiecewisePolynomialKernel{1}, r, j) = 1 + (j + 1) * r |
38 | | -_f(κ::PiecewisePolynomialKernel{2}, r, j) = 1 + (j + 2) * r + (j^2 + 4 * j + 3) / 3 * r .^ 2 |
39 | | -function _f(κ::PiecewisePolynomialKernel{3}, r, j) |
40 | | - return 1 + |
41 | | - (j + 3) * r + |
42 | | - (6 * j^2 + 36j + 45) / 15 * r .^ 2 + |
43 | | - (j^3 + 9 * j^2 + 23j + 15) / 15 * r .^ 3 |
| 66 | +piecewise_polynomial_coefficients(::Val{0}, ::Int) = (1,) |
| 67 | +piecewise_polynomial_coefficients(::Val{1}, j::Int) = (1, j + 1) |
| 68 | +piecewise_polynomial_coefficients(::Val{2}, j::Int) = (1, j + 2, (j^2 + 4 * j)//3 + 1) |
| 69 | +function piecewise_polynomial_coefficients(::Val{3}, j::Int) |
| 70 | + return (1, j + 3, (2 * j^2 + 12 * j)//5 + 3, (j^3 + 9 * j^2 + 23 * j)//15 + 1) |
44 | 71 | end |
45 | | - |
46 | | -function kappa(κ::PiecewisePolynomialKernel{V}, r) where {V} |
47 | | - return max(1 - r, 0)^(κ.j + V) * _f(κ, r, κ.j) |
| 72 | +function piecewise_polynomial_coefficients(::Val{D}, ::Int) where {D} |
| 73 | + return error("invalid degree $D, only 0, 1, 2, or 3 are supported") |
48 | 74 | end |
49 | 75 |
|
50 | | -metric(κ::PiecewisePolynomialKernel) = Mahalanobis(κ.maha) |
| 76 | +kappa(κ::PiecewisePolynomialKernel, r) = max(1 - r, 0)^κ.alpha * evalpoly(r, κ.coeffs) |
| 77 | + |
| 78 | +metric(::PiecewisePolynomialKernel) = Euclidean() |
51 | 79 |
|
52 | | -function Base.show(io::IO, κ::PiecewisePolynomialKernel{V}) where {V} |
| 80 | +function Base.show(io::IO, κ::PiecewisePolynomialKernel{D}) where {D} |
53 | 81 | return print( |
54 | | - io, "Piecewise Polynomial Kernel (v = ", V, ", size(maha) = ", size(κ.maha), ")" |
| 82 | + io, |
| 83 | + "Piecewise Polynomial Kernel (degree = ", |
| 84 | + D, |
| 85 | + ", ⌊dim/2⌋ = ", |
| 86 | + κ.alpha - 1 - 2 * D, |
| 87 | + ")", |
55 | 88 | ) |
56 | 89 | end |
0 commit comments