Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test utils revamp #159

Merged
merged 41 commits into from
Sep 25, 2020
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
e322d2c
Fix style
Aug 30, 2020
81b2bb8
Fix convention
Aug 30, 2020
c795cdb
First pass over test set implementation
Aug 30, 2020
24b0422
Add standardised tests to BaseKernels
Aug 30, 2020
32877de
Test composite kernels
Aug 30, 2020
a32eae6
Fix some tests
Aug 30, 2020
5815b41
Fix maha
Aug 30, 2020
14178ce
Fix sm
Aug 30, 2020
7ab9c52
Fix up maha
Aug 30, 2020
180c934
Remove redundant file
Aug 30, 2020
4954575
Move existing test utils over to module
Aug 30, 2020
a79de46
Add Gamma Exponential kernel reference
Aug 31, 2020
4ba9c35
Update src/matrix/kernelpdmat.jl
willtebbutt Aug 31, 2020
ce11e1d
Remove repeated code
Sep 2, 2020
1086241
Warn about breaking change
Sep 7, 2020
1c8216d
Merge in master
Sep 7, 2020
e73b23d
Resolve merge conflict
Sep 7, 2020
22295f6
Update src/test_utils.jl
willtebbutt Sep 7, 2020
a945ab6
Merge in master
Sep 8, 2020
463d1ea
Merge in master
Sep 8, 2020
523313d
Resolve merge conflict
Sep 21, 2020
b58c649
Bump patch
Sep 21, 2020
2e508e9
Fix up tests
Sep 21, 2020
e821f1a
Remove dead space
Sep 22, 2020
09efe1a
Fix rational quadratic parameter test
Sep 22, 2020
7eaae64
Fix some style issues
Sep 22, 2020
13772f9
Add extra parameter check
Sep 22, 2020
7a7fdf1
Update src/basekernels/rationalquad.jl
willtebbutt Sep 22, 2020
c8965ac
Tweak check
Sep 22, 2020
cc559eb
Fix RQ convention to match EQ
Sep 22, 2020
8c079a5
Refactor tests
Sep 22, 2020
dbd0c16
Fix nn issues
Sep 22, 2020
d250375
Merge branch 'master' into wct/test-utils
Sep 23, 2020
efb18be
Fix weird printing issue
Sep 23, 2020
93ec40d
Update src/test_utils.jl
willtebbutt Sep 24, 2020
c7f2490
Update test/kernels/kernelsum.jl
willtebbutt Sep 24, 2020
bc345f6
Update src/test_utils.jl
willtebbutt Sep 24, 2020
ab492c0
Test FBM kernel
Sep 24, 2020
e2bb5b5
Fix up Gabor
Sep 24, 2020
ef044ea
Loosen dof bound
Sep 25, 2020
e63002e
Perturb test
Sep 25, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
name = "KernelFunctions"
uuid = "ec8451be-7e33-11e9-00cf-bbf324bd1392"
version = "0.7.2"
version = "0.8.0"

[deps]
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"
Distances = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7"
Functors = "d9f16b24-f501-4c13-a1f2-28368ffc5196"
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
StatsFuns = "4c63d2b9-4356-54db-8cca-17b64c39e42c"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
ZygoteRules = "700de1a5-db45-46bc-99cf-38207098b444"

[compat]
Expand Down
70 changes: 47 additions & 23 deletions src/KernelFunctions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ KernelFunctions. [Github](https://github.com/JuliaGaussianProcesses/KernelFuncti
"""
module KernelFunctions

@warn "SqExponentialKernel changed convention in version 0.8.0. This kernel now divides the
squared distance by 2 to better align itself with standard practice. This warning will
be removed in 0.9.0."

export kernelmatrix, kernelmatrix!, kerneldiagmatrix, kerneldiagmatrix!
export transform
export duplicate, set! # Helpers
Expand Down Expand Up @@ -31,6 +35,8 @@ export NystromFact, nystrom

export spectral_mixture_kernel, spectral_mixture_product_kernel

export ColVecs, RowVecs

export MOInput
export IndependentMOKernel, LatentFactorMOKernel

Expand All @@ -53,35 +59,53 @@ abstract type Kernel end
abstract type SimpleKernel <: Kernel end

include("utils.jl")
include("distances/pairwise.jl")
include("distances/dotproduct.jl")
include("distances/delta.jl")
include("distances/sinus.jl")
include("transform/transform.jl")

for f in readdir(joinpath(@__DIR__, "basekernels"))
endswith(f, ".jl") && include(joinpath("basekernels", f))
end

include("kernels/transformedkernel.jl")
include("kernels/scaledkernel.jl")
include("matrix/kernelmatrix.jl")
include("kernels/kernelsum.jl")
include("kernels/kernelproduct.jl")
include("kernels/tensorproduct.jl")
include("approximations/nystrom.jl")
include(joinpath("distances", "pairwise.jl"))
include(joinpath("distances", "dotproduct.jl"))
include(joinpath("distances", "delta.jl"))
include(joinpath("distances", "sinus.jl"))
include(joinpath("transform", "transform.jl"))

include(joinpath("basekernels", "constant.jl"))
include(joinpath("basekernels", "cosine.jl"))
include(joinpath("basekernels", "exponential.jl"))
include(joinpath("basekernels", "exponentiated.jl"))
include(joinpath("basekernels", "fbm.jl"))
include(joinpath("basekernels", "gabor.jl"))
include(joinpath("basekernels", "maha.jl"))
include(joinpath("basekernels", "matern.jl"))
include(joinpath("basekernels", "nn.jl"))
include(joinpath("basekernels", "periodic.jl"))
include(joinpath("basekernels", "piecewisepolynomial.jl"))
include(joinpath("basekernels", "polynomial.jl"))
include(joinpath("basekernels", "rationalquad.jl"))
include(joinpath("basekernels", "sm.jl"))
include(joinpath("basekernels", "wiener.jl"))

include(joinpath("kernels", "transformedkernel.jl"))
include(joinpath("kernels", "scaledkernel.jl"))
include(joinpath("matrix", "kernelmatrix.jl"))
include(joinpath("kernels", "kernelsum.jl"))
include(joinpath("kernels", "kernelproduct.jl"))
include(joinpath("kernels", "tensorproduct.jl"))
include(joinpath("approximations", "nystrom.jl"))
include("generic.jl")

include("mokernels/mokernel.jl")
include("mokernels/moinput.jl")
include("mokernels/independent.jl")
include("mokernels/slfm.jl")
include(joinpath("mokernels", "mokernel.jl"))
include(joinpath("mokernels", "moinput.jl"))
include(joinpath("mokernels", "independent.jl"))
include(joinpath("mokernels", "slfm.jl"))

include("zygote_adjoints.jl")

include("test_utils.jl")

function __init__()
@require Kronecker="2c470bb0-bcc8-11e8-3dad-c9649493f05e" include("matrix/kernelkroneckermat.jl")
@require PDMats="90014a1f-27ba-587c-ab20-58faa44d9150" include("matrix/kernelpdmat.jl")
@require Kronecker="2c470bb0-bcc8-11e8-3dad-c9649493f05e" begin
include(joinpath("matrix", "kernelkroneckermat.jl"))
end
@require PDMats="90014a1f-27ba-587c-ab20-58faa44d9150" begin
include(joinpath("matrix", "kernelpdmat.jl"))
end
end

end
19 changes: 12 additions & 7 deletions src/basekernels/exponential.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ related form of the kernel or [`GammaExponentialKernel`](@ref) for a generalizat
"""
struct SqExponentialKernel <: SimpleKernel end

kappa(κ::SqExponentialKernel, d²::Real) = exp(-d²)
kappa(κ::SqExponentialKernel, d²::Real) = exp(-d² / 2)

metric(::SqExponentialKernel) = SqEuclidean()

Expand Down Expand Up @@ -48,12 +48,15 @@ const LaplacianKernel = ExponentialKernel
"""
GammaExponentialKernel(; γ = 2.0)

The γ-exponential kernel is an isotropic Mercer kernel given by the formula:
The γ-exponential kernel [1] is an isotropic Mercer kernel given by the formula:
```
κ(x,y) = exp(-‖x-y‖^(2γ))
κ(x,y) = exp(-‖x-y‖^γ)
```
Where `γ > 0`, (the keyword `γ` can be replaced by `gamma`)
For `γ = 1`, see `SqExponentialKernel` and `γ = 0.5`, see `ExponentialKernel`
For `γ = 2`, see `SqExponentialKernel` and `γ = 1`, see `ExponentialKernel`.

[1] - Gaussian Processes for Machine Learning, Carl Edward Rasmussen and Christopher K. I.
Williams, MIT Press, 2006.
"""
struct GammaExponentialKernel{Tγ<:Real} <: SimpleKernel
γ::Vector{Tγ}
Expand All @@ -65,10 +68,12 @@ end

@functor GammaExponentialKernel

kappa(κ::GammaExponentialKernel, d²::Real) = exp(-d²^first(κ.γ))
kappa(κ::GammaExponentialKernel, d::Real) = exp(-d^first(κ.γ))

metric(::GammaExponentialKernel) = SqEuclidean()
metric(::GammaExponentialKernel) = Euclidean()

iskroncompatible(::GammaExponentialKernel) = true

Base.show(io::IO, κ::GammaExponentialKernel) = print(io, "Gamma Exponential Kernel (γ = ", first(κ.γ), ")")
function Base.show(io::IO, κ::GammaExponentialKernel)
print(io, "Gamma Exponential Kernel (γ = ", first(κ.γ), ")")
end
25 changes: 9 additions & 16 deletions src/basekernels/gabor.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ struct GaborKernel{K<:Kernel} <: Kernel
kernel::K
function GaborKernel(;ell=nothing, p=nothing)
k = _gabor(ell=ell, p=p)
new{typeof(k)}(k)
return new{typeof(k)}(k)
end
end

Expand Down Expand Up @@ -57,24 +57,17 @@ end

Base.show(io::IO, κ::GaborKernel) = print(io, "Gabor Kernel (ell = ", κ.ell, ", p = ", κ.p, ")")

function kernelmatrix(
κ::GaborKernel,
X::AbstractMatrix;
obsdim::Int=defaultobs)
kernelmatrix(κ.kernel, X; obsdim=obsdim)
function kernelmatrix(κ::GaborKernel, X::AbstractMatrix; obsdim::Int=defaultobs)
return kernelmatrix(κ.kernel, X; obsdim=obsdim)
end

function kernelmatrix(
κ::GaborKernel,
X::AbstractMatrix,
Y::AbstractMatrix;
obsdim::Int=defaultobs)
kernelmatrix(κ.kernel, X, Y; obsdim=obsdim)
κ::GaborKernel, X::AbstractMatrix, Y::AbstractMatrix;
obsdim::Int=defaultobs,
)
return kernelmatrix(κ.kernel, X, Y; obsdim=obsdim)
end

function kerneldiagmatrix(
κ::GaborKernel,
X::AbstractMatrix;
obsdim::Int=defaultobs) #TODO Add test
kerneldiagmatrix(κ.kernel, X; obsdim=obsdim)
function kerneldiagmatrix(κ::GaborKernel, X::AbstractMatrix; obsdim::Int=defaultobs) #TODO Add test
return kerneldiagmatrix(κ.kernel, X; obsdim=obsdim)
end
6 changes: 3 additions & 3 deletions src/basekernels/sm.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ function spectral_mixture_kernel(
γs::AbstractMatrix{<:Real},
ωs::AbstractMatrix{<:Real}
)
spectral_mixture_kernel(SqExponentialKernel(), αs, γs, ωs)
return spectral_mixture_kernel(SqExponentialKernel(), αs, γs, ωs)
end

"""
Expand Down Expand Up @@ -95,14 +95,14 @@ function spectral_mixture_product_kernel(
throw(DimensionMismatch("The dimensions of αs, γs, ans ωs do not match"))
end
return TensorProduct(spectral_mixture_kernel(h, α, reshape(γ, 1, :), reshape(ω, 1, :))
for (α, γ, ω) in zip(eachrow(αs), eachrow(γs), eachrow(ωs)))
for (α, γ, ω) in zip(eachrow(αs), eachrow(γs), eachrow(ωs)))
end

function spectral_mixture_product_kernel(
αs::AbstractMatrix{<:Real},
γs::AbstractMatrix{<:Real},
ωs::AbstractMatrix{<:Real}
)
spectral_mixture_product_kernel(SqExponentialKernel(), αs, γs, ωs)
return spectral_mixture_product_kernel(SqExponentialKernel(), αs, γs, ωs)
end

14 changes: 4 additions & 10 deletions src/matrix/kernelkroneckermat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,16 @@ using .Kronecker

export kernelkronmat

function kernelkronmat(
κ::Kernel,
X::AbstractVector,
dims::Int
)
function kernelkronmat(κ::Kernel, X::AbstractVector, dims::Int)
@assert iskroncompatible(κ) "The chosen kernel is not compatible for kroenecker matrices (see [`iskroncompatible`](@ref))"
k = kernelmatrix(κ, X)
kronecker(k, dims)
end

function kernelkronmat(
κ::Kernel,
X::AbstractVector{<:AbstractVector};
obsdim::Int=defaultobs
)
@assert iskroncompatible(κ) "The chosen kernel is not compatible for kroenecker matrices"
κ::Kernel, X::AbstractVector{<:AbstractVector}; obsdim::Int=defaultobs,
)
@assert iskroncompatible(κ) "The chosen kernel is not compatible for Kronecker matrices"
Ks = kernelmatrix.(κ, X)
K = reduce(⊗, Ks)
end
Expand Down
20 changes: 4 additions & 16 deletions src/matrix/kernelmatrix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,7 @@ function kernelmatrix!(K::AbstractMatrix, κ::SimpleKernel, x::AbstractVector)
end

function kernelmatrix!(
K::AbstractMatrix,
κ::SimpleKernel,
x::AbstractVector,
y::AbstractVector,
K::AbstractMatrix, κ::SimpleKernel, x::AbstractVector, y::AbstractVector,
)
validate_inplace_dims(K, x, y)
pairwise!(K, metric(κ), x, y)
Expand All @@ -102,19 +99,13 @@ end
const defaultobs = 2

function kernelmatrix!(
K::AbstractMatrix,
κ::Kernel,
X::AbstractMatrix;
obsdim::Int = defaultobs
K::AbstractMatrix, κ::Kernel, X::AbstractMatrix; obsdim::Int = defaultobs
)
return kernelmatrix!(K, κ, vec_of_vecs(X; obsdim=obsdim))
end

function kernelmatrix!(
K::AbstractMatrix,
κ::Kernel,
X::AbstractMatrix,
Y::AbstractMatrix;
K::AbstractMatrix, κ::Kernel, X::AbstractMatrix, Y::AbstractMatrix;
obsdim::Int = defaultobs
)
x = vec_of_vecs(X; obsdim=obsdim)
Expand All @@ -133,10 +124,7 @@ function kernelmatrix(κ::Kernel, X::AbstractMatrix, Y::AbstractMatrix; obsdim=d
end

function kerneldiagmatrix!(
K::AbstractVector,
κ::Kernel,
X::AbstractMatrix;
obsdim::Int = defaultobs
K::AbstractVector, κ::Kernel, X::AbstractMatrix; obsdim::Int = defaultobs
)
return kerneldiagmatrix!(K, κ, vec_of_vecs(X; obsdim=obsdim))
end
Expand Down
32 changes: 18 additions & 14 deletions src/matrix/kernelpdmat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,28 @@ using .PDMats: PDMat
export kernelpdmat

"""
Compute a positive-definite matrix in the form of a `PDMat` matrix see [PDMats.jl]() with the cholesky decomposition precomputed
The algorithm recursively tries to add recursively a diagonal nugget until positive definiteness is achieved or that the noise is too big
Compute a positive-definite matrix in the form of a `PDMat` matrix see [PDMats.jl](https://github.com/JuliaStats/PDMats.jl)
with the cholesky decomposition precomputed.
The algorithm recursively tries to add recursively a diagonal nugget until positive
definiteness is achieved or that the noise is too big.
"""
function kernelpdmat(
κ::Kernel,
X::AbstractMatrix;
obsdim::Int = defaultobs
)
K = kernelmatrix(κ,X,obsdim=obsdim)
Kmax =maximum(K)
function kernelpdmat(κ::Kernel, X::AbstractMatrix; obsdim::Int=defaultobs)
K = kernelmatrix(κ, X; obsdim=obsdim)
Kmax = maximum(K)
α = eps(eltype(K))
while !isposdef(K+α*I) && α < 0.01*Kmax
while !isposdef(K + α * I) && α < 0.01 * Kmax
α *= 2.0
end
if α >= 0.01*Kmax
throw(ErrorException("Adding noise on the diagonal was not sufficient to build a positive-definite matrix:\n\t- Check that your kernel parameters are not extreme\n\t- Check that your data is sufficiently sparse\n\t- Maybe use a different kernel"))
if α >= 0.01 * Kmax
error(
"Adding noise on the diagonal was not sufficient to build a positive-definite" *
" matrix:\n\t- Check that your kernel parameters are not extreme\n\t- Check" *
" that your data is sufficiently sparse\n\t- Maybe use a different kernel",
)
end
return PDMat(K+α*I)
return PDMat(K + α * I)
end

kernelpdmat(κ::Kernel,X::AbstractVector{<:Real};obsdim=defaultobs) = kernelpdmat(κ,reshape(X,1,:),obsdim=2)
function kernelpdmat(κ::Kernel, X::AbstractVector{<:Real}; obsdim=defaultobs)
return kernelpdmat(κ, reshape(X, 1, :); obsdim=2)
end
Loading