From 6559873f11e76be0eb0fcaac3c2078cc8bf861dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Galy-Fajou?= Date: Tue, 11 Feb 2020 15:21:13 +0100 Subject: [PATCH] Adapting test to the new backend --- src/generic.jl | 6 ++- src/kernels/scaledkernel.jl | 2 - src/kernels/transformedkernel.jl | 12 ++++-- src/matrix/kernelmatrix.jl | 8 ++-- src/transform/ardtransform.jl | 2 +- test/test_kernelmatrix.jl | 18 +++++++++ test/test_kernels.jl | 64 +++++--------------------------- test/test_transform.jl | 7 ++++ 8 files changed, 53 insertions(+), 66 deletions(-) diff --git a/src/generic.jl b/src/generic.jl index 8e0414203..8c6f04339 100644 --- a/src/generic.jl +++ b/src/generic.jl @@ -5,7 +5,11 @@ Base.iterate(k::Kernel, ::Any) = nothing # default fallback for evaluating a kernel with two arguments (such as vectors etc) kappa(κ::Kernel, x, y) = kappa(κ, evaluate(metric(κ), x, y)) -kappa(κ::TransformedKernel, x, y) = kappa(κ.kernel, κ.transform(x), κ.transform(y)) +kappa(κ::TransformedKernel, x, y) = kappa(kernel(κ), apply(κ.transform,x), apply(κ.transform,y)) +kappa(κ::TransformedKernel{<:Kernel,<:ScaleTransform}, x, y) = kappa(κ.kernel, _scale(κ.transform, metric(κ.kernel), x, y)) +_scale(t::ScaleTransform, metric::Euclidean, x, y) = first(t.s) * evaluate(metric, x, y) +_scale(t::ScaleTransform, metric::Union{SqEuclidean,DotProduct}, x, y) = first(t.s)^2 * evaluate(metric, x, y) +_scale(t::ScaleTransform, metric, x, y) = evaluate(metric, apply(t, x), apply(t, y)) ### Syntactic sugar for creating matrices and using kernel functions for k in [:ExponentialKernel,:SqExponentialKernel,:GammaExponentialKernel,:MaternKernel,:Matern32Kernel,:Matern52Kernel,:LinearKernel,:PolynomialKernel,:ExponentiatedKernel,:ZeroKernel,:WhiteKernel,:ConstantKernel,:RationalQuadraticKernel,:GammaRationalQuadraticKernel] diff --git a/src/kernels/scaledkernel.jl b/src/kernels/scaledkernel.jl index 78bb7fcb3..c208a30c7 100644 --- a/src/kernels/scaledkernel.jl +++ b/src/kernels/scaledkernel.jl @@ -8,8 +8,6 @@ function ScaledKernel(kernel::Tk,σ::Tσ=1.0) where {Tk<:Kernel,Tσ<:Real} ScaledKernel{Tk,Tσ}(kernel,[σ]) end -@inline transform(k::ScaledKernel) = transform(k.kernel) - @inline kappa(k::ScaledKernel, x) = first(k.σ)*kappa(k.kernel, x) @inline metric(k::ScaledKernel) = metric(k.kernel) diff --git a/src/kernels/transformedkernel.jl b/src/kernels/transformedkernel.jl index df790fb1c..8b914acb0 100644 --- a/src/kernels/transformedkernel.jl +++ b/src/kernels/transformedkernel.jl @@ -3,11 +3,15 @@ struct TransformedKernel{Tk<:Kernel,Tr<:Transform} <: Kernel transform::Tr end +@inline kernel(κ) = κ.kernel + @inline transform(κ::Kernel,t::Transform) = TransformedKernel(κ,t) -@inline kappa(k::TransformedKernel, x) = kappa(k.kernel, x) +@inline kappa(κ::TransformedKernel, x) = kappa(κ.kernel, x) + +@inline metric(κ::TransformedKernel) = metric(κ.kernel) -@inline metric(k::TransformedKernel) = metric(k.kernel) +params(κ::TransformedKernel) = (params(κ.transform),params(κ.kernel)) +opt_params(κ::TransformedKernel) = (opt_params(κ.transform),opt_params(κ.kernel)) -params(k::TransformedKernel) = (params(k.transform),params(k.kernel)) -opt_params(k::TransformedKernel) = (opt_params(k.transform),opt_params(k.kernel)) +Base.show(io::IO,κ::TransformedKernel) = print(io,"$(κ.kernel) with $(κ.transform)") diff --git a/src/matrix/kernelmatrix.jl b/src/matrix/kernelmatrix.jl index 503fd4160..e01572164 100644 --- a/src/matrix/kernelmatrix.jl +++ b/src/matrix/kernelmatrix.jl @@ -21,7 +21,7 @@ function kernelmatrix!( map!(x->kappa(κ,x),K,pairwise(metric(κ),X,dims=obsdim)) end -kernelmatrix!(K::Matrix, κ::TransformedKernel, X; obsdim::Int = defaultobs) = +kernelmatrix!(K::Matrix, κ::TransformedKernel, X::AbstractMatrix; obsdim::Int = defaultobs) = kernelmatrix!(K, kernel(κ), apply(κ.transform, X, obsdim = obsdim), obsdim = obsdim) function kernelmatrix!( @@ -38,7 +38,7 @@ function kernelmatrix!( map!(x->kappa(κ,x),K,pairwise(metric(κ),X,Y,dims=obsdim)) end -kernelmatrix!(K::AbstractMatrix, κ::TransformedKernel, X, Y; obsdim::Int = defaultobs) = +kernelmatrix!(K::AbstractMatrix, κ::TransformedKernel, X::AbstractMatrix, Y::AbstractMatrix; obsdim::Int = defaultobs) = kernelmatrix!(K, kernel(κ), apply(κ.transform, X, obsdim = obsdim), apply(κ.transform, Y, obsdim = obsdim), obsdim = obsdim) ## Apply kernel on two reals ## @@ -87,7 +87,7 @@ function kernelmatrix( K = map(x->kappa(κ,x),pairwise(metric(κ),X,dims=obsdim)) end -kernelmatrix(κ::TransformedKernel, X; obsdim::Int = defaultobs) = +kernelmatrix(κ::TransformedKernel, X::AbstractMatrix; obsdim::Int = defaultobs) = kernelmatrix(kernel(κ), apply(κ.transform, X, obsdim = obsdim), obsdim = obsdim) function kernelmatrix( @@ -105,7 +105,7 @@ end @inline _kernelmatrix(κ::Kernel,X,Y,obsdim) = map(x->kappa(κ,x),pairwise(metric(κ),X,Y,dims=obsdim)) -kernelmatrix(κ::TransformedKernel, X, Y; obsdim::Int = defaultobs) = +kernelmatrix(κ::TransformedKernel, X::AbstractMatrix, Y::AbstractMatrix; obsdim::Int = defaultobs) = kernelmatrix(kernel(κ), apply(κ.transform, X, obsdim = obsdim), apply(κ.transform, Y, obsdim = obsdim), obsdim = obsdim) """ diff --git a/src/transform/ardtransform.jl b/src/transform/ardtransform.jl index debc78967..0f4b23e9b 100644 --- a/src/transform/ardtransform.jl +++ b/src/transform/ardtransform.jl @@ -28,7 +28,7 @@ end params(t::ARDTransform) = t.v dim(t::ARDTransform) = length(t.v) -function apply(t::ARDTransform,X::AbstractMatrix{<:Real};obsdim::Int) +function apply(t::ARDTransform,X::AbstractMatrix{<:Real};obsdim::Int = defaultobs) @boundscheck if dim(t) != size(X,feature_dim(obsdim)) throw(DimensionMismatch("Array has size $(size(X,!Bool(obsdim-1)+1)) on dimension $(!Bool(obsdim-1)+1)) which does not match the length of the scale transform length , $(dim(t)).")) #TODO Add test end diff --git a/test/test_kernelmatrix.jl b/test/test_kernelmatrix.jl index 82c955799..942f1d122 100644 --- a/test/test_kernelmatrix.jl +++ b/test/test_kernelmatrix.jl @@ -10,7 +10,9 @@ B = rand(dims...) C = rand(8,9) K = [zeros(dims[1],dims[1]),zeros(dims[2],dims[2])] Kdiag = [zeros(dims[1]),zeros(dims[2])] +s = rand() k = SqExponentialKernel() +kt = sqexponentialkernel(s) @testset "Kernel Matrix Operations" begin @testset "Inplace Kernel Matrix" begin for obsdim in [1,2] @@ -33,6 +35,22 @@ k = SqExponentialKernel() @test_throws DimensionMismatch kernelmatrix(k,A,C,obsdim=obsdim) end end + @testset "Transformed Kernel Matrix Operations" begin + @testset "Inplace Kernel Matrix" begin + for obsdim in [1,2] + @test kernelmatrix!(K[obsdim],kt,A,B,obsdim=obsdim) == kernelmatrix(k,s*A,s*B,obsdim=obsdim) + @test kernelmatrix!(K[obsdim],kt,A,obsdim=obsdim) == kernelmatrix(k,s*A,obsdim=obsdim) + @test kerneldiagmatrix!(Kdiag[obsdim],kt,A,obsdim=obsdim) == kerneldiagmatrix(k,s*A,obsdim=obsdim) + end + end + @testset "Kernel matrix" begin + for obsdim in [1,2] + @test kernelmatrix(kt,A,B,obsdim=obsdim) == kernelmatrix(k,s*A,s*B,obsdim=obsdim) + @test kernelmatrix(kt,A,obsdim=obsdim) == kernelmatrix(k,s*A,obsdim=obsdim) + @test kerneldiagmatrix(kt,A,obsdim=obsdim) == kerneldiagmatrix(k,s*A,obsdim=obsdim) + end + end + end @testset "KernelSum" begin k1 = SqExponentialKernel() k2 = LinearKernel() diff --git a/test/test_kernels.jl b/test/test_kernels.jl index 9b5d6f5c2..7b1959c54 100644 --- a/test/test_kernels.jl +++ b/test/test_kernels.jl @@ -72,12 +72,6 @@ x = rand()*2; v1 = rand(3); v2 = rand(3); id = IdentityTransform() @test kappa(k,x) ≈ exp(x) @test kappa(k,-x) ≈ exp(-x) @test k(v1,v2) ≈ exp(dot(v1,v2)) - # l = 0.5 - # k = ExponentiatedKernel(l) - # @test k(v1,v2) ≈ exp(l^2*dot(v1,v2)) - # v = rand(3) - # k = ExponentiatedKernel(v) - # @test k(v1,v2) ≈ exp(dot(v.*v1,v.*v2)) end end @testset "Matern" begin @@ -88,36 +82,18 @@ x = rand()*2; v1 = rand(3); v2 = rand(3); id = IdentityTransform() @test kappa(k,x) ≈ matern(x,ν) @test kappa(k,0.0) == 1.0 @test kappa(MaternKernel(ν),x) == kappa(k,x) - # l = 0.5; ν = 3.0 - # k = MaternKernel(l,ν) - # @test k(v1,v2) ≈ matern(l*norm(v1-v2),ν) - # v = rand(3); ν = 2.1 - # k = MaternKernel(v,ν) - # @test k(v1,v2) ≈ matern(norm(v.*(v1-v2)),ν) end @testset "Matern32Kernel" begin k = Matern32Kernel() @test kappa(k,x) ≈ (1+sqrt(3)*x)exp(-sqrt(3)*x) @test k(v1,v2) ≈ (1+sqrt(3)*norm(v1-v2))exp(-sqrt(3)*norm(v1-v2)) @test kappa(Matern32Kernel(),x) == kappa(k,x) - # l = 0.5 - # k = Matern32Kernel(l) - # @test k(v1,v2) ≈ (1+l*sqrt(3)*norm(v1-v2))exp(-l*sqrt(3)*norm(v1-v2)) - # v = rand(3) - # k = Matern32Kernel(v) - # @test k(v1,v2) ≈ (1+sqrt(3)*norm(v.*(v1-v2)))exp(-sqrt(3)*norm(v.*(v1-v2))) end @testset "Matern52Kernel" begin k = Matern52Kernel() @test kappa(k,x) ≈ (1+sqrt(5)*x+5/3*x^2)exp(-sqrt(5)*x) @test k(v1,v2) ≈ (1+sqrt(5)*norm(v1-v2)+5/3*norm(v1-v2)^2)exp(-sqrt(5)*norm(v1-v2)) @test kappa(Matern52Kernel(),x) == kappa(k,x) - # l = 0.5 - # k = Matern52Kernel(l) - # @test k(v1,v2) ≈ (1+l*sqrt(5)*norm(v1-v2)+l^2*5/3*norm(v1-v2)^2)exp(-l*sqrt(5)*norm(v1-v2)) - # v = rand(3) - # k = Matern52Kernel(v) - # @test k(v1,v2) ≈ (1+sqrt(5)*norm(v.*(v1-v2))+5/3*norm(v.*(v1-v2))^2)exp(-sqrt(5)*norm(v.*(v1-v2))) end @testset "Coherence Materns" begin @test kappa(MaternKernel(0.5),x) ≈ kappa(ExponentialKernel(),x) @@ -132,25 +108,12 @@ x = rand()*2; v1 = rand(3); v2 = rand(3); id = IdentityTransform() @test kappa(k,x) ≈ x @test k(v1,v2) ≈ dot(v1,v2) @test kappa(LinearKernel(),x) == kappa(k,x) - # l = 0.5 - # k = LinearKernel(l,c) - # @test k(v1,v2) ≈ l^2*dot(v1,v2) + c - # v = rand(3) - # k = LinearKernel(v,c) - # @test k(v1,v2) ≈ dot(v.*v1,v.*v2) + c end @testset "PolynomialKernel" begin k = PolynomialKernel() @test kappa(k,x) ≈ x^2 @test k(v1,v2) ≈ dot(v1,v2)^2 @test kappa(PolynomialKernel(),x) == kappa(k,x) - # d = 3.0 - # l = 0.5 - # k = PolynomialKernel(l,d,c) - # @test k(v1,v2) ≈ (l^2*dot(v1,v2) + c)^d - # v = rand(3) - # k = PolynomialKernel(v,d,c) - # @test k(v1,v2) ≈ (dot(v.*v1,v.*v2) + c)^d #Coherence test @test kappa(PolynomialKernel(1.0,c),x) ≈ kappa(LinearKernel(c),x) end @@ -161,31 +124,27 @@ x = rand()*2; v1 = rand(3); v2 = rand(3); id = IdentityTransform() @test kappa(k,x) ≈ (1.0+x/2.0)^-2 @test k(v1,v2) ≈ (1.0+norm(v1-v2)^2/2.0)^-2 @test kappa(RationalQuadraticKernel(),x) == kappa(k,x) - # l = 0.5 - # a = 1.0 + rand() - # k = RationalQuadraticKernel(l,a) - # @test k(v1,v2) ≈ (1.0+l^2*norm(v1-v2)^2/a)^-a - # v = rand(3) - # k = RationalQuadraticKernel(v,a) - # @test k(v1,v2) ≈ (1.0+norm(v.*(v1-v2))^2/a)^-a end @testset "GammaRationalQuadraticKernel" begin k = GammaRationalQuadraticKernel() @test kappa(k,x) ≈ (1.0+x^2.0/2.0)^-2 @test k(v1,v2) ≈ (1.0+norm(v1-v2)^4.0/2.0)^-2 @test kappa(GammaRationalQuadraticKernel(),x) == kappa(k,x) - # l = 0.5 a = 1.0 + rand() - # g = 4.0 - # k = GammaRationalQuadraticKernel(l,a,g) - # @test k(v1,v2) ≈ (1.0+(l^2g)*norm(v1-v2)^(2g)/a)^-a - # v = rand(3) - # k = GammaRationalQuadraticKernel(v,a,g) - # @test k(v1,v2) ≈ (1.0+(norm(v.*(v1-v2))^(2g))/a)^-a #Coherence test @test kappa(GammaRationalQuadraticKernel(a,1.0),x) ≈ kappa(RationalQuadraticKernel(a),x) end end + @testset "Transformed/Scaled Kernel" begin + s = rand() + k = SqExponentialKernel() + kt = KernelFunctions.TransformedKernel(k,ScaleTransform(s)) + ks = KernelFunctions.ScaledKernel(k,s) + @test KernelFunctions.kappa(kt,v1,v2) == KernelFunctions.kappa(KernelFunctions.transform(k,ScaleTransform(s)),v1,v2) + @test KernelFunctions.metric(kt) == KernelFunctions.metric(k) + @test kappa(ks,x) == s*kappa(k,x) + @test kappa(ks,x) == kappa(s*k,x) + end @testset "KernelCombinations" begin k1 = LinearKernel() k2 = SqExponentialKernel() @@ -194,9 +153,6 @@ x = rand()*2; v1 = rand(3); v2 = rand(3); id = IdentityTransform() k = k1 + k2 @test KernelFunctions.metric(k) == [KernelFunctions.DotProduct(),KernelFunctions.SqEuclidean()] @test length(k) == 2 - # @test transform(k) == [transform(k1),transform(k2)] - # @test transform(k,X) == [transform(k1,X),transform(k2,X)] - # @test transform(k,X,1) == [transform(k1,X,1),transform(k2,X,1)] end @testset "KernelProduct" begin diff --git a/test/test_transform.jl b/test/test_transform.jl index 17bc81886..2d6dc4c5e 100644 --- a/test/test_transform.jl +++ b/test/test_transform.jl @@ -16,6 +16,9 @@ f(x) = sin.(x) @testset "Transform Test" begin ## Test Scale Transform + @testset "IdentityTransform" begin + @test KernelFunctions.apply(IdentityTransform(),X)==X + end @testset "ScaleTransform" begin t = ScaleTransform(s) @test all(KernelFunctions.apply(t,X).==s*X) @@ -29,6 +32,10 @@ f(x) = sin.(x) vt2 = ARDTransform(v2) @test all(KernelFunctions.apply(vt1,X,obsdim=1).==v1'.*X) @test all(KernelFunctions.apply(vt2,X,obsdim=2).==v2.*X) + newv1 = rand(5) + KernelFunctions.set!(vt1,newv1) + @test all(vt1.v .== newv1) + @test_throws DimensionMismatch KernelFunctions.apply(vt1,rand(3,4)) end ## Test LowRankTransform @testset "LowRankTransform" begin