Skip to content

Commit b7a1f62

Browse files
committed
Fix merge conflicts
2 parents 2fe2000 + 18e3730 commit b7a1f62

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+704
-396
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "KernelFunctions"
22
uuid = "ec8451be-7e33-11e9-00cf-bbf324bd1392"
3-
version = "0.3.1"
3+
version = "0.3.2"
44

55
[deps]
66
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"

src/generic.jl

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@ printshifted(io::IO,κ::Kernel,shift::Int) = print(io,"$κ")
1515
Base.show(io::IO::Kernel) = print(io,nameof(typeof(κ)))
1616

1717
### Syntactic sugar for creating matrices and using kernel functions
18-
for k in subtypes(BaseKernel)
19-
if k [FBMKernel] continue end #for kernels without `metric` or `kappa`
18+
function concretetypes(k, ktypes::Vector)
19+
isempty(subtypes(k)) ? push!(ktypes, k) : concretetypes.(subtypes(k), Ref(ktypes))
20+
return ktypes
21+
end
22+
23+
for k in concretetypes(Kernel, [])
2024
@eval begin
21-
@inline::$k)(d::Real) = kappa(κ,d) #TODO Add test
2225
@inline::$k)(x::AbstractVector{<:Real}, y::AbstractVector{<:Real}) = kappa(κ, x, y)
2326
@inline::$k)(X::AbstractMatrix{T}, Y::AbstractMatrix{T}; obsdim::Integer=defaultobs) where {T} = kernelmatrix(κ, X, Y, obsdim=obsdim)
2427
@inline::$k)(X::AbstractMatrix{T}; obsdim::Integer=defaultobs) where {T} = kernelmatrix(κ, X, obsdim=obsdim)

src/kernels/fbm.jl

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,30 @@ For `h=1/2`, this is the Wiener Kernel, for `h>1/2`, the increments are
1010
positively correlated and for `h<1/2` the increments are negatively correlated.
1111
"""
1212
struct FBMKernel{T<:Real} <: BaseKernel
13-
h::T
13+
h::Vector{T}
1414
function FBMKernel(; h::T=0.5) where {T<:Real}
15-
@assert h<=1.0 && h>=0.0 "FBMKernel: Given Hurst index h is invalid."
16-
return new{T}(h)
15+
@assert 0.0 <= h <= 1.0 "FBMKernel: Given Hurst index h is invalid."
16+
return new{T}([h])
1717
end
1818
end
1919

20-
Base.show(io::IO, κ::FBMKernel) = print(io, "Fractional Brownian Motion Kernel (h = $(κ.h))")
20+
Base.show(io::IO, κ::FBMKernel) = print(io, "Fractional Brownian Motion Kernel (h = $(first(k.h)))")
21+
22+
const sqroundoff = 1e-15
2123

2224
_fbm(modX, modY, modXY, h) = (modX^h + modY^h - modXY^h)/2
2325

2426
function kernelmatrix::FBMKernel, X::AbstractMatrix; obsdim::Int = defaultobs)
2527
@assert obsdim [1,2] "obsdim should be 1 or 2 (see docs of kernelmatrix))"
26-
modX = sum(abs2, X; dims = 3 - obsdim)
27-
modXX = pairwise(SqEuclidean(), X, dims = obsdim)
28+
modX = sum(abs2, X; dims = feature_dim(obsdim))
29+
modXX = pairwise(SqEuclidean(sqroundoff), X, dims = obsdim)
2830
return _fbm.(vec(modX), reshape(modX, 1, :), modXX, κ.h)
2931
end
3032

3133
function kernelmatrix!(K::AbstractMatrix, κ::FBMKernel, X::AbstractMatrix; obsdim::Int = defaultobs)
3234
@assert obsdim [1,2] "obsdim should be 1 or 2 (see docs of kernelmatrix))"
33-
modX = sum(abs2, X; dims = 3 - obsdim)
34-
modXX = pairwise(SqEuclidean(), X, dims = obsdim)
35+
modX = sum(abs2, X; dims = feature_dim(obsdim))
36+
modXX = pairwise(SqEuclidean(sqroundoff), X, dims = obsdim)
3537
K .= _fbm.(vec(modX), reshape(modX, 1, :), modXX, κ.h)
3638
return K
3739
end
@@ -43,9 +45,9 @@ function kernelmatrix(
4345
obsdim::Int = defaultobs,
4446
)
4547
@assert obsdim [1,2] "obsdim should be 1 or 2 (see docs of kernelmatrix))"
46-
modX = sum(abs2, X, dims=3-obsdim)
47-
modY = sum(abs2, Y, dims=3-obsdim)
48-
modXY = pairwise(SqEuclidean(), X, Y,dims=obsdim)
48+
modX = sum(abs2, X, dims = feature_dim(obsdim))
49+
modY = sum(abs2, Y, dims = feature_dim(obsdim))
50+
modXY = pairwise(SqEuclidean(sqroundoff), X, Y,dims = obsdim)
4951
return _fbm.(vec(modX), reshape(modY, 1, :), modXY, κ.h)
5052
end
5153

@@ -57,9 +59,9 @@ function kernelmatrix!(
5759
obsdim::Int = defaultobs,
5860
)
5961
@assert obsdim [1,2] "obsdim should be 1 or 2 (see docs of kernelmatrix))"
60-
modX = sum(abs2, X, dims=3-obsdim)
61-
modY = sum(abs2, Y, dims=3-obsdim)
62-
modXY = pairwise(SqEuclidean(), X, Y,dims=obsdim)
62+
modX = sum(abs2, X, dims = feature_dim(obsdim))
63+
modY = sum(abs2, Y, dims = feature_dim(obsdim))
64+
modXY = pairwise(SqEuclidean(sqroundoff), X, Y,dims = obsdim)
6365
K .= _fbm.(vec(modX), reshape(modY, 1, :), modXY, κ.h)
6466
return K
6567
end
@@ -72,23 +74,15 @@ function _kernel(
7274
obsdim::Int = defaultobs
7375
)
7476
@assert length(x) == length(y) "x and y don't have the same dimension!"
75-
return κ(x,y)
77+
return kappa(κ, x, y)
7678
end
7779

78-
#Syntactic Sugar
79-
function::FBMKernel)(x::AbstractVector{<:Real}, y::AbstractVector{<:Real})
80+
function kappa::FBMKernel, x::AbstractVector{<:Real}, y::AbstractVector{<:Real})
8081
modX = sum(abs2, x)
8182
modY = sum(abs2, y)
82-
modXY = sqeuclidean(x, y)
83-
return (modX^κ.h + modY^κ.h - modXY^κ.h)/2
83+
modXY = evaluate(SqEuclidean(sqroundoff), x, y)
84+
h = first.h)
85+
return (modX^h + modY^h - modXY^h)/2
8486
end
8587

86-
::FBMKernel)(x::Real, y::Real) = (abs2(x)^κ.h + abs2(y)^κ.h - abs2(x-y)^κ.h)/2
87-
88-
function::FBMKernel)(X::AbstractMatrix{<:Real}, Y::AbstractMatrix{<:Real}; obsdim::Integer=defaultobs)
89-
return kernelmatrix(κ, X, Y, obsdim=obsdim)
90-
end
91-
92-
function::FBMKernel)(X::AbstractMatrix{<:Real}; obsdim::Integer=defaultobs)
93-
return kernelmatrix(κ, X, obsdim=obsdim)
94-
end
88+
::FBMKernel)(x::Real, y::Real) = (abs2(x)^first.h) + abs2(y)^first.h) - abs2(x-y)^first.h))/2

src/matrix/kernelmatrix.jl

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
"""
2-
```
3-
kernelmatrix!(K::Matrix, κ::Kernel, X::Matrix; obsdim::Integer=2)
4-
kernelmatrix!(K::Matrix, κ::Kernel, X::Matrix, Y::Matrix; obsdim::Integer=2)
5-
```
6-
In-place version of `kernelmatrix` where pre-allocated matrix `K` will be overwritten with the kernel matrix.
2+
kernelmatrix!(K::Matrix, κ::Kernel, X::Matrix; obsdim::Integer = 2)
3+
kernelmatrix!(K::Matrix, κ::Kernel, X::Matrix, Y::Matrix; obsdim::Integer = 2)
4+
5+
In-place version of [`kernelmatrix`](@ref) where pre-allocated matrix `K` will be overwritten with the kernel matrix.
76
"""
87
kernelmatrix!
98

@@ -21,7 +20,7 @@ function kernelmatrix!(
2120
map!(x->kappa(κ,x),K,pairwise(metric(κ),X,dims=obsdim))
2221
end
2322

24-
kernelmatrix!(K::Matrix, κ::TransformedKernel, X::AbstractMatrix; obsdim::Int = defaultobs) =
23+
kernelmatrix!(K::AbstractMatrix, κ::TransformedKernel, X::AbstractMatrix; obsdim::Int = defaultobs) =
2524
kernelmatrix!(K, kernel(κ), apply.transform, X, obsdim = obsdim), obsdim = obsdim)
2625

2726
function kernelmatrix!(
@@ -61,13 +60,12 @@ _kernel(κ::TransformedKernel, x::AbstractVector, y::AbstractVector; obsdim::Int
6160
_kernel(kernel(κ), apply.transform, x), apply.transform, y), obsdim = obsdim)
6261

6362
"""
64-
```
65-
kernelmatrix(κ::Kernel, X::Matrix ; obsdim::Int=2)
66-
kernelmatrix(κ::Kernel, X::Matrix, Y::Matrix; obsdim::Int=2)
67-
```
63+
kernelmatrix(κ::Kernel, X::Matrix; obsdim::Int = 2)
64+
kernelmatrix(κ::Kernel, X::Matrix, Y::Matrix; obsdim::Int = 2)
65+
6866
Calculate the kernel matrix of `X` (and `Y`) with respect to kernel `κ`.
69-
`obsdim=1` means the matrix `X` (and `Y`) has size #samples x #dimension
70-
`obsdim=2` means the matrix `X` (and `Y`) has size #dimension x #samples
67+
`obsdim = 1` means the matrix `X` (and `Y`) has size #samples x #dimension
68+
`obsdim = 2` means the matrix `X` (and `Y`) has size #dimension x #samples
7169
"""
7270
kernelmatrix
7371

@@ -109,12 +107,11 @@ kernelmatrix(κ::TransformedKernel, X::AbstractMatrix, Y::AbstractMatrix; obsdim
109107
kernelmatrix(kernel(κ), apply.transform, X, obsdim = obsdim), apply.transform, Y, obsdim = obsdim), obsdim = obsdim)
110108

111109
"""
112-
```
113-
kerneldiagmatrix(κ::Kernel, X::Matrix; obsdim::Int=2)
114-
```
110+
kerneldiagmatrix(κ::Kernel, X::Matrix; obsdim::Int = 2)
111+
115112
Calculate the diagonal matrix of `X` with respect to kernel `κ`
116-
`obsdim=1` means the matrix `X` has size #samples x #dimension
117-
`obsdim=2` means the matrix `X` has size #dimension x #samples
113+
`obsdim = 1` means the matrix `X` has size #samples x #dimension
114+
`obsdim = 2` means the matrix `X` has size #dimension x #samples
118115
"""
119116
function kerneldiagmatrix(
120117
κ::Kernel,
@@ -130,10 +127,9 @@ function kerneldiagmatrix(
130127
end
131128

132129
"""
133-
```
134-
kerneldiagmatrix!(K::AbstractVector,κ::Kernel, X::Matrix; obsdim::Int=2)
135-
```
136-
In place version of `kerneldiagmatrix`
130+
kerneldiagmatrix!(K::AbstractVector,κ::Kernel, X::Matrix; obsdim::Int = 2)
131+
132+
In place version of [`kerneldiagmatrix`](@ref)
137133
"""
138134
function kerneldiagmatrix!(
139135
K::AbstractVector,

src/trainable.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import .Flux.trainable
44

55
trainable(k::ConstantKernel) = (k.c,)
66

7+
trainable(k::FBMKernel) = (k.h,)
8+
79
trainable(k::GammaExponentialKernel) = (k.γ,)
810

911
trainable(k::GammaRationalQuadraticKernel) = (k.α, k.γ)

test/approximations/nystrom.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
@testset "nystrom" begin
2+
dims = [10,5]
3+
X = rand(dims...)
4+
k = SqExponentialKernel()
5+
for obsdim in [1, 2]
6+
@test kernelmatrix(k, X; obsdim=obsdim) kernelmatrix(nystrom(k, X, 1.0; obsdim=obsdim))
7+
@test kernelmatrix(k, X; obsdim=obsdim) kernelmatrix(nystrom(k, X, collect(1:dims[obsdim]); obsdim=obsdim))
8+
end
9+
end

test/distances/delta.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
@testset "delta" begin
2+
A = rand(10,5)
3+
B = rand(20,5)
4+
d = KernelFunctions.Delta()
5+
@test pairwise(d,A,dims=1) == Matrix(I,size(A,1),size(A,1))
6+
@test pairwise(d,A,B,dims=1) == zeros(size(A,1),size(B,1))
7+
@test d(1,2) == 0
8+
@test d(1,1) == 1
9+
@test_throws DimensionMismatch d(rand(3),rand(4))
10+
end

test/distances/dotproduct.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
@testset "dotproduct" begin
2+
A = rand(10,5)
3+
B = rand(20,5)
4+
d = KernelFunctions.DotProduct()
5+
@test diag(pairwise(d,A,dims=2)) == [dot(A[:,i],A[:,i]) for i in 1:size(A,2)]
6+
@test_throws DimensionMismatch d(rand(3),rand(4))
7+
@test d(3.0,2.0) == 6.0
8+
end

test/test_generic.jl renamed to test/generic.jl

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
using KernelFunctions
2-
3-
k = SqExponentialKernel()
4-
5-
@testset "Generic functions to test" begin
1+
@testset "generic" begin
2+
k = SqExponentialKernel()
63
@test length(k) == 1
74
@test iterate(k) == (k,nothing)
85
@test iterate(k,1) == nothing

test/kernels/constant.jl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
@testset "constant" begin
2+
@testset "ZeroKernel" begin
3+
k = ZeroKernel()
4+
@test eltype(k) == Any
5+
@test kappa(k,2.0) == 0.0
6+
@test KernelFunctions.metric(ZeroKernel()) == KernelFunctions.Delta()
7+
end
8+
@testset "WhiteKernel" begin
9+
k = WhiteKernel()
10+
@test eltype(k) == Any
11+
@test kappa(k,1.0) == 1.0
12+
@test kappa(k,0.0) == 0.0
13+
@test EyeKernel == WhiteKernel
14+
@test metric(WhiteKernel()) == KernelFunctions.Delta()
15+
end
16+
@testset "ConstantKernel" begin
17+
c = 2.0
18+
k = ConstantKernel(c=c)
19+
@test eltype(k) == Any
20+
@test kappa(k,1.0) == c
21+
@test kappa(k,0.5) == c
22+
@test metric(ConstantKernel()) == KernelFunctions.Delta()
23+
@test metric(ConstantKernel(c=2.0)) == KernelFunctions.Delta()
24+
end
25+
end

test/kernels/cosine.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
@testset "cosine" begin
2+
rng = MersenneTwister(123456)
3+
x = rand(rng)*2
4+
v1 = rand(rng, 3)
5+
v2 = rand(rng, 3)
6+
7+
k = CosineKernel()
8+
@test eltype(k) == Any
9+
@test kappa(k, 1.0) -1.0 atol=1e-5
10+
@test kappa(k, 2.0) 1.0 atol=1e-5
11+
@test kappa(k, 1.5) 0.0 atol=1e-5
12+
@test kappa(k,x) cospi(x) atol=1e-5
13+
@test k(v1, v2) cospi(sqrt(sum(abs2.(v1-v2)))) atol=1e-5
14+
end

test/kernels/custom.jl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# minimal definition of a custom kernel
2+
struct MyKernel <: Kernel end
3+
4+
KernelFunctions.kappa(::MyKernel, d2::Real) = exp(-d2)
5+
KernelFunctions.metric(::MyKernel) = SqEuclidean()
6+
7+
# some syntactic sugar
8+
::MyKernel)(x::AbstractVector{<:Real}, y::AbstractVector{<:Real}) = kappa(κ, x, y)
9+
::MyKernel)(X::AbstractMatrix{<:Real}, Y::AbstractMatrix{<:Real}; obsdim = 2) = kernelmatrix(κ, X, Y; obsdim = obsdim)
10+
::MyKernel)(X::AbstractMatrix{<:Real}; obsdim = 2) = kernelmatrix(κ, X; obsdim = obsdim)
11+
12+
@testset "custom" begin
13+
@test kappa(MyKernel(), 3) == kappa(SqExponentialKernel(), 3)
14+
@test kappa(MyKernel(), 1, 3) == kappa(SqExponentialKernel(), 1, 3)
15+
@test kappa(MyKernel(), [1, 2], [3, 4]) == kappa(SqExponentialKernel(), [1, 2], [3, 4])
16+
@test kernelmatrix(MyKernel(), [1 2; 3 4], [5 6; 7 8]) == kernelmatrix(SqExponentialKernel(), [1 2; 3 4], [5 6; 7 8])
17+
@test kernelmatrix(MyKernel(), [1 2; 3 4]) == kernelmatrix(SqExponentialKernel(), [1 2; 3 4])
18+
19+
@test MyKernel()([1, 2], [3, 4]) == SqExponentialKernel()([1, 2], [3, 4])
20+
@test MyKernel()([1 2; 3 4], [5 6; 7 8]) == SqExponentialKernel()([1 2; 3 4], [5 6; 7 8])
21+
@test MyKernel()([1 2; 3 4]) == SqExponentialKernel()([1 2; 3 4])
22+
end

test/kernels/exponential.jl

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
@testset "exponential" begin
2+
rng = MersenneTwister(123456)
3+
x = rand(rng)*2
4+
v1 = rand(rng, 3)
5+
v2 = rand(rng, 3)
6+
@testset "SqExponentialKernel" begin
7+
k = SqExponentialKernel()
8+
@test kappa(k,x) exp(-x)
9+
@test k(v1,v2) exp(-norm(v1-v2)^2)
10+
@test kappa(SqExponentialKernel(),x) == kappa(k,x)
11+
@test metric(SqExponentialKernel()) == SqEuclidean()
12+
end
13+
@testset "ExponentialKernel" begin
14+
k = ExponentialKernel()
15+
@test kappa(k,x) exp(-x)
16+
@test k(v1,v2) exp(-norm(v1-v2))
17+
@test kappa(ExponentialKernel(),x) == kappa(k,x)
18+
@test metric(ExponentialKernel()) == Euclidean()
19+
end
20+
@testset "GammaExponentialKernel" begin
21+
γ = 2.0
22+
k = GammaExponentialKernel=γ)
23+
@test kappa(k,x) exp(-(x)^(γ))
24+
@test k(v1,v2) exp(-norm(v1-v2)^(2γ))
25+
@test kappa(GammaExponentialKernel(),x) == kappa(k,x)
26+
@test GammaExponentialKernel(gamma=γ).γ == [γ]
27+
@test metric(GammaExponentialKernel()) == SqEuclidean()
28+
@test metric(GammaExponentialKernel=2.0)) == SqEuclidean()
29+
30+
#Coherence :
31+
@test KernelFunctions._kernel(GammaExponentialKernel=1.0),v1,v2) KernelFunctions._kernel(SqExponentialKernel(),v1,v2)
32+
@test KernelFunctions._kernel(GammaExponentialKernel=0.5),v1,v2) KernelFunctions._kernel(ExponentialKernel(),v1,v2)
33+
end
34+
end

test/kernels/exponentiated.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
@testset "exponentiated" begin
2+
rng = MersenneTwister(123456)
3+
x = rand(rng)*2
4+
v1 = rand(rng, 3)
5+
v2 = rand(rng, 3)
6+
7+
k = ExponentiatedKernel()
8+
@test kappa(k,x) exp(x)
9+
@test kappa(k,-x) exp(-x)
10+
@test k(v1,v2) exp(dot(v1,v2))
11+
@test metric(ExponentiatedKernel()) == KernelFunctions.DotProduct()
12+
end

test/kernels/fbm.jl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
@testset "FBM" begin
2+
h = 0.3
3+
k = FBMKernel(h = h)
4+
v1 = rand(3); v2 = rand(3)
5+
@test k(v1,v2) (sqeuclidean(v1, zero(v1))^h + sqeuclidean(v2, zero(v2))^h - sqeuclidean(v1-v2, zero(v1-v2))^h)/2 atol=1e-5
6+
7+
# kernelmatrix tests
8+
m1 = rand(3,3)
9+
m2 = rand(3,3)
10+
@test kernelmatrix(k, m1, m1) kernelmatrix(k, m1) atol=1e-5
11+
@test kernelmatrix(k, m1, m2) k(m1, m2) atol=1e-5
12+
13+
14+
x1 = rand()
15+
x2 = rand()
16+
@test kernelmatrix(k, x1*ones(1,1), x2*ones(1,1))[1] k(x1, x2) atol=1e-5
17+
end

test/kernels/gabor.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
@testset "Gabor" begin
2+
ell = abs(rand())
3+
p = abs(rand())
4+
k = GaborKernel(ell=ell, p=p)
5+
@test k.ell ell atol=1e-5
6+
@test k.p p atol=1e-5
7+
@test kappa(k,v1,v2) exp(-sqeuclidean(v1,v2) ./(k.ell.^2))*cospi(euclidean(v1,v2)./ k.p) atol=1e-5
8+
@test kappa(k,v1,v2) kappa(transform(SqExponentialKernel(), 1/k.ell),v1,v2)*kappa(transform(CosineKernel(), 1/k.p), v1,v2) atol=1e-5
9+
10+
k = GaborKernel()
11+
@test k.ell 1.0 atol=1e-5
12+
@test k.p 1.0 atol=1e-5
13+
end

0 commit comments

Comments
 (0)