Skip to content

Commit b78395d

Browse files
authored
Merge branch 'master' into gabor
2 parents 5cb4295 + 3bd5cf6 commit b78395d

File tree

10 files changed

+82
-15
lines changed

10 files changed

+82
-15
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ os:
55
- osx
66
julia:
77
- 1.0
8-
- 1.2
98
- 1.3
9+
- 1.4
1010
- nightly
1111
# because of Zygote needs to allow failing on nightly
1212
matrix:

src/KernelFunctions.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ export transform
88
export params, duplicate, set! # Helpers
99

1010
export Kernel
11-
export ConstantKernel, WhiteKernel, ZeroKernel
11+
export ConstantKernel, WhiteKernel, EyeKernel, ZeroKernel
1212
export SqExponentialKernel, ExponentialKernel, GammaExponentialKernel
1313
export ExponentiatedKernel
1414
export MaternKernel, Matern32Kernel, Matern52Kernel
1515
export LinearKernel, PolynomialKernel
1616
export RationalQuadraticKernel, GammaRationalQuadraticKernel
17+
export MahalanobisKernel
1718
export KernelSum, KernelProduct
1819
export TransformedKernel, ScaledKernel
1920

@@ -44,7 +45,7 @@ include("distances/dotproduct.jl")
4445
include("distances/delta.jl")
4546
include("transform/transform.jl")
4647

47-
for k in ["exponential","matern","polynomial","constant","rationalquad","exponentiated","gabor"]
48+
for k in ["exponential","matern","polynomial","constant","rationalquad","exponentiated","cosine","maha","gabor"]
4849
include(joinpath("kernels",k*".jl"))
4950
end
5051
include("kernels/transformedkernel.jl")
@@ -53,7 +54,6 @@ include("matrix/kernelmatrix.jl")
5354
include("kernels/kernelsum.jl")
5455
include("kernels/kernelproduct.jl")
5556
include("approximations/nystrom.jl")
56-
5757
include("generic.jl")
5858

5959
include("zygote_adjoints.jl")

src/kernels/constant.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ Kernel function working as an equivalent to add white noise.
2323
"""
2424
struct WhiteKernel <: BaseKernel end
2525

26+
const EyeKernel = WhiteKernel
27+
2628
kappa::WhiteKernel,δₓₓ::Real) = δₓₓ
2729

2830
metric(::WhiteKernel) = Delta()

src/kernels/cosine.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"""
2+
CosineKernel
3+
4+
The cosine kernel is a stationary kernel for a sinusoidal given by
5+
```
6+
κ(x,y) = cos( π * (x-y) )
7+
```
8+
9+
"""
10+
struct CosineKernel <: BaseKernel end
11+
12+
kappa::CosineKernel, d::Real) = cospi(d)
13+
14+
metric(::CosineKernel) = Euclidean()

src/kernels/exponential.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Base.show(io::IO,::SqExponentialKernel) = print(io,"Squared Exponential Kernel")
2020
## Aliases ##
2121
const RBFKernel = SqExponentialKernel
2222
const GaussianKernel = SqExponentialKernel
23+
const SEKernel = SqExponentialKernel
2324

2425
"""
2526
`ExponentialKernel([ρ=1.0])`
@@ -48,7 +49,7 @@ The γ-exponential kernel is an isotropic Mercer kernel given by the formula:
4849
"""
4950
struct GammaExponentialKernel{Tγ<:Real} <: BaseKernel
5051
γ::Vector{Tγ}
51-
function GammaExponentialKernel(;γ::T=2.0) where {T<:Real}
52+
function GammaExponentialKernel(;gamma::T=2.0, γ::T=gamma) where {T<:Real}
5253
@check_args(GammaExponentialKernel, γ, γ >= zero(T), "γ > 0")
5354
return new{T}([γ])
5455
end

src/kernels/maha.jl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"""
2+
MahalanobisKernel(P::AbstractMatrix)
3+
4+
Mahalanobis distance-based kernel given by
5+
```math
6+
κ(x,y) = exp(-r^2), r^2 = maha(x,P,y) = (x-y)'*inv(P)*(x-y)
7+
```
8+
where the matrix P is the metric.
9+
10+
"""
11+
struct MahalanobisKernel{T<:Real, A<:AbstractMatrix{T}} <: BaseKernel
12+
P::A
13+
function MahalanobisKernel(P::AbstractMatrix{T}) where {T<:Real}
14+
LinearAlgebra.checksquare(P)
15+
new{T,typeof(P)}(P)
16+
end
17+
end
18+
19+
kappa::MahalanobisKernel, d::T) where {T<:Real} = exp(-d)
20+
21+
metric::MahalanobisKernel) = SqMahalanobis.P)

src/kernels/matern.jl

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,20 @@ For `ν=n+1/2, n=0,1,2,...` it can be simplified and you should instead use [`Ex
88
"""
99
struct MaternKernel{Tν<:Real} <: BaseKernel
1010
ν::Vector{Tν}
11-
function MaternKernel(;ν::T=1.5) where {T<:Real}
11+
function MaternKernel(;nu::T=1.5, ν::T=nu) where {T<:Real}
1212
@check_args(MaternKernel, ν, ν > zero(T), "ν > 0")
1313
return new{T}([ν])
1414
end
1515
end
1616

1717
@inline function kappa::MaternKernel, d::Real)
1818
ν = first.ν)
19-
iszero(d) ? one(d) : exp((one(d)-ν)*logtwo-logabsgamma(ν)[1] + ν*log(sqrt(2ν)*d)+log(besselk(ν,sqrt(2ν)*d)))
19+
iszero(d) ? one(d) :
20+
exp(
21+
(one(d) - ν) * logtwo - logabsgamma(ν)[1] +
22+
ν * log(sqrt(2ν) * d) +
23+
log(besselk(ν, sqrt(2ν) * d))
24+
)
2025
end
2126

2227
metric(::MaternKernel) = Euclidean()
@@ -30,7 +35,7 @@ The matern 3/2 kernel is an isotropic Mercer kernel given by the formula:
3035
"""
3136
struct Matern32Kernel <: BaseKernel end
3237

33-
kappa::Matern32Kernel, d::Real) = (1+sqrt(3)*d)*exp(-sqrt(3)*d)
38+
kappa::Matern32Kernel, d::Real) = (1 + sqrt(3) * d) * exp(-sqrt(3) * d)
3439

3540
metric(::Matern32Kernel) = Euclidean()
3641

@@ -43,6 +48,6 @@ The matern 5/2 kernel is an isotropic Mercer kernel given by the formula:
4348
"""
4449
struct Matern52Kernel <: BaseKernel end
4550

46-
kappa::Matern52Kernel, d::Real) = (1+sqrt(5)*d+5*d^2/3)*exp(-sqrt(5)*d)
51+
kappa::Matern52Kernel, d::Real) = (1 + sqrt(5) * d + 5 * d^2 / 3) * exp(-sqrt(5) * d)
4752

4853
metric(::Matern52Kernel) = Euclidean()

src/kernels/rationalquad.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ where `α` is a shape parameter of the Euclidean distance. Check [`GammaRational
88
"""
99
struct RationalQuadraticKernel{Tα<:Real} <: BaseKernel
1010
α::Vector{Tα}
11-
function RationalQuadraticKernel(;α::T=2.0) where {T}
11+
function RationalQuadraticKernel(;alpha::T=2.0, α::T=alpha) where {T}
1212
@check_args(RationalQuadraticKernel, α, α > zero(T), "α > 1")
1313
return new{T}([α])
1414
end
@@ -29,7 +29,7 @@ where `α` is a shape parameter of the Euclidean distance and `γ` is another sh
2929
struct GammaRationalQuadraticKernel{Tα<:Real, Tγ<:Real} <: BaseKernel
3030
α::Vector{Tα}
3131
γ::Vector{Tγ}
32-
function GammaRationalQuadraticKernel(;α::Tα=2.0, γ::Tγ=2.0) where {Tα<:Real, Tγ<:Real}
32+
function GammaRationalQuadraticKernel(;alpha::Tα=2.0, gamma::Tγ=2.0, α::Tα=alpha, γ::Tγ=gamma) where {Tα<:Real, Tγ<:Real}
3333
@check_args(GammaRationalQuadraticKernel, α, α > one(Tα), "α > 1")
3434
@check_args(GammaRationalQuadraticKernel, γ, γ >= one(Tγ), "γ >= 1")
3535
return new{Tα, Tγ}([α], [γ])

src/trainable.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ trainable(k::PolynomialKernel) = (k.d, k.c)
1616

1717
trainable(k::RationalQuadraticKernel) = (k.α,)
1818

19+
trainable(k::MahalanobisKernel) = (k.P,)
20+
1921
#### Composite kernels
2022

2123
trainable::KernelProduct) = κ.kernels

test/test_kernels.jl

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ x = rand()*2; v1 = rand(3); v2 = rand(3); id = IdentityTransform()
1616
@test eltype(k) == Any
1717
@test kappa(k,1.0) == 1.0
1818
@test kappa(k,0.0) == 0.0
19+
@test EyeKernel == WhiteKernel
1920
end
2021
@testset "ConstantKernel" begin
2122
c = 2.0
@@ -25,6 +26,15 @@ x = rand()*2; v1 = rand(3); v2 = rand(3); id = IdentityTransform()
2526
@test kappa(k,0.5) == c
2627
end
2728
end
29+
@testset "Cosine" begin
30+
k = CosineKernel()
31+
@test eltype(k) == Any
32+
@test kappa(k, 1.0) -1.0 atol=1e-5
33+
@test kappa(k, 2.0) 1.0 atol=1e-5
34+
@test kappa(k, 1.5) 0.0 atol=1e-5
35+
@test kappa(k,x) cospi(x) atol=1e-5
36+
@test k(v1, v2) cospi(sqrt(sum(abs2.(v1-v2)))) atol=1e-5
37+
end
2838
@testset "Exponential" begin
2939
@testset "SqExponentialKernel" begin
3040
k = SqExponentialKernel()
@@ -44,6 +54,7 @@ x = rand()*2; v1 = rand(3); v2 = rand(3); id = IdentityTransform()
4454
@test kappa(k,x) exp(-(x)^(γ))
4555
@test k(v1,v2) exp(-norm(v1-v2)^(2γ))
4656
@test kappa(GammaExponentialKernel(),x) == kappa(k,x)
57+
@test GammaExponentialKernel(gamma=γ).γ == [γ]
4758
#Coherence :
4859
@test KernelFunctions._kernel(GammaExponentialKernel=1.0),v1,v2) KernelFunctions._kernel(SqExponentialKernel(),v1,v2)
4960
@test KernelFunctions._kernel(GammaExponentialKernel=0.5),v1,v2) KernelFunctions._kernel(ExponentialKernel(),v1,v2)
@@ -62,6 +73,7 @@ x = rand()*2; v1 = rand(3); v2 = rand(3); id = IdentityTransform()
6273
ν = 2.0
6374
k = MaternKernel=ν)
6475
matern(x,ν) = 2^(1-ν)/gamma(ν)*(sqrt(2ν)*x)^ν*besselk(ν,sqrt(2ν)*x)
76+
@test MaternKernel(nu=ν).ν == [ν]
6577
@test kappa(k,x) matern(x,ν)
6678
@test kappa(k,0.0) == 1.0
6779
@test kappa(MaternKernel=ν),x) == kappa(k,x)
@@ -101,19 +113,29 @@ x = rand()*2; v1 = rand(3); v2 = rand(3); id = IdentityTransform()
101113
@test kappa(PolynomialKernel(d=1.0,c=c),x) kappa(LinearKernel(c=c),x)
102114
end
103115
end
116+
@testset "Mahalanobis" begin
117+
P = rand(3,3)
118+
k = MahalanobisKernel(P)
119+
@test kappa(k,x) == exp(-x)
120+
@test k(v1,v2) exp(-sqmahalanobis(v1,v2, k.P))
121+
@test kappa(ExponentialKernel(),x) == kappa(k,x)
122+
end
104123
@testset "RationalQuadratic" begin
105124
@testset "RationalQuadraticKernel" begin
106-
k = RationalQuadraticKernel()
125+
α = 2.0
126+
k = RationalQuadraticKernel=α)
127+
@test RationalQuadraticKernel(alpha=α).α == [α]
107128
@test kappa(k,x) (1.0+x/2.0)^-2
108129
@test k(v1,v2) (1.0+norm(v1-v2)^2/2.0)^-2
109-
@test kappa(RationalQuadraticKernel(),x) == kappa(k,x)
130+
@test kappa(RationalQuadraticKernel(α=α),x) == kappa(k,x)
110131
end
111132
@testset "GammaRationalQuadraticKernel" begin
112133
k = GammaRationalQuadraticKernel()
113134
@test kappa(k,x) (1.0+x^2.0/2.0)^-2
114135
@test k(v1,v2) (1.0+norm(v1-v2)^4.0/2.0)^-2
115136
@test kappa(GammaRationalQuadraticKernel(),x) == kappa(k,x)
116137
a = 1.0 + rand()
138+
@test GammaRationalQuadraticKernel(alpha=a).α == [a]
117139
#Coherence test
118140
@test kappa(GammaRationalQuadraticKernel=a,γ=1.0),x) kappa(RationalQuadraticKernel=a),x)
119141
end
@@ -127,8 +149,8 @@ x = rand()*2; v1 = rand(3); v2 = rand(3); id = IdentityTransform()
127149
ks = ScaledKernel(k,s)
128150
@test kappa(kt,v1,v2) == kappa(transform(k,ScaleTransform(s)),v1,v2)
129151
@test kappa(kt,v1,v2) == kappa(transform(k,s),v1,v2)
130-
@test kappa(kt,v1,v2) == kappa(k,s*v1,s*v2)
131-
@test kappa(ktard,v1,v2) == kappa(transform(k,ARDTransform(v)),v1,v2)
152+
@test kappa(kt,v1,v2) kappa(k,s*v1,s*v2) atol=1e-5
153+
@test kappa(ktard,v1,v2) kappa(transform(k,ARDTransform(v)),v1,v2) atol=1e-5
132154
@test kappa(ktard,v1,v2) == kappa(transform(k,v),v1,v2)
133155
@test kappa(ktard,v1,v2) == kappa(k,v.*v1,v.*v2)
134156
@test KernelFunctions.metric(kt) == KernelFunctions.metric(k)

0 commit comments

Comments
 (0)