diff --git a/Project.toml b/Project.toml index e76daa0..585189b 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "GPLikelihoods" uuid = "6031954c-0455-49d7-b3b9-3e1c99afaf40" authors = ["willtebbutt "] -version = "0.1.1" +version = "0.1.0" [deps] AbstractGPs = "99985d1d-32ba-4be9-9821-2ec096f28918" diff --git a/test/likelihoods/bernoulli.jl b/test/likelihoods/bernoulli.jl index 0bb5d9b..6b58912 100644 --- a/test/likelihoods/bernoulli.jl +++ b/test/likelihoods/bernoulli.jl @@ -1,13 +1,4 @@ @testset "BernoulliLikelihood" begin - rng = MersenneTwister(123) - gp = GP(SqExponentialKernel()) - x = rand(rng, 10) - y = rand(rng, 10) lik = BernoulliLikelihood() - lgp = LatentGP(gp, lik, 1e-5) - lfgp = lgp(x) - - @test typeof(lik(rand(rng, lfgp.fx))) <: Distribution - @test length(rand(rng, lik(rand(rng, lfgp.fx)))) == 10 - @test Functors.functor(lik)[1] == () + test_interface(lik, SqExponentialKernel(), rand(10)) end diff --git a/test/likelihoods/categorical.jl b/test/likelihoods/categorical.jl index 88574d5..eea8dd0 100644 --- a/test/likelihoods/categorical.jl +++ b/test/likelihoods/categorical.jl @@ -1,22 +1,8 @@ @testset "CategoricalLikelihood" begin - rng = MersenneTwister(123) - gp = GP(IndependentMOKernel(SqExponentialKernel())) + lik = CategoricalLikelihood() IN_DIM = 3 OUT_DIM = 4 N = 10 - x = [rand(rng, IN_DIM) for _=1:N] - X = MOInput(x, OUT_DIM) - lik = CategoricalLikelihood() - lgp = LatentGP(gp, lik, 1e-5) - lfgp = lgp(X) - - Y = rand(rng, lfgp.fx) - - y = [Y[[i + j*N for j in 0:(OUT_DIM - 1)]] for i in 1:N] - # Replace with mo_inverse_transform once it is merged - - @test length(lik(rand(3)).p) == 4 - @test lik(y) isa Distribution - @test length(rand(rng, lik(y))) == 10 - @test Functors.functor(lik)[1] == () + X = MOInput([rand(IN_DIM) for _ in 1:N], OUT_DIM) + test_interface(lik, IndependentMOKernel(SqExponentialKernel()), X) end diff --git a/test/likelihoods/gaussian.jl b/test/likelihoods/gaussian.jl index 4d5c39f..75216de 100644 --- a/test/likelihoods/gaussian.jl +++ b/test/likelihoods/gaussian.jl @@ -1,35 +1,13 @@ @testset "GaussianLikelihood" begin - rng = MersenneTwister(123) - gp = GP(SqExponentialKernel()) - x = rand(rng, 10) - y = rand(rng, 10) lik = GaussianLikelihood(1e-5) - lgp = LatentGP(gp, lik, 1e-5) - lfgp = lgp(x) - - @test lik(rand(rng, lfgp.fx)) isa Distribution - @test length(rand(rng, lik(rand(rng, lfgp.fx)))) == 10 - @test keys(Functors.functor(lik)[1]) == (:σ²,) + test_interface(lik, SqExponentialKernel(), rand(10); functor_args=(:σ²,)) end @testset "HeteroscedasticGaussianLikelihood" begin - rng = MersenneTwister(123) - gp = GP(IndependentMOKernel(SqExponentialKernel())) + lik = HeteroscedasticGaussianLikelihood() IN_DIM = 3 OUT_DIM = 2 # one for the mean the other for the log-standard deviation N = 10 - x = [rand(rng, IN_DIM) for _ in 1:N] - X = MOInput(x, OUT_DIM) - lik = HeteroscedasticGaussianLikelihood() - lgp = LatentGP(gp, lik, 1e-5) - lfgp = lgp(X) - - Y = rand(rng, lfgp.fx) - - y = [Y[[i + j*N for j in 0:(OUT_DIM - 1)]] for i in 1:N] - # Replace with mo_inverse_transform once it is merged - - @test lik(y) isa Distribution - @test length(rand(rng, lik(y))) == 10 - @test Functors.functor(lik)[1] == () + X = MOInput([rand(IN_DIM) for _ in 1:N], OUT_DIM) + test_interface(lik, IndependentMOKernel(SqExponentialKernel()), X) end diff --git a/test/likelihoods/poisson.jl b/test/likelihoods/poisson.jl index a690387..dda81e3 100644 --- a/test/likelihoods/poisson.jl +++ b/test/likelihoods/poisson.jl @@ -1,13 +1,4 @@ @testset "PoissonLikelihood" begin - rng = MersenneTwister(123) - gp = GP(SqExponentialKernel()) - x = rand(rng, 10) - y = rand(rng, 10) lik = PoissonLikelihood() - lgp = LatentGP(gp, lik, 1e-5) - lfgp = lgp(x) - - @test lik(rand(rng, lfgp.fx)) isa Distribution - @test length(rand(rng, lik(rand(rng, lfgp.fx)))) == 10 - @test Functors.functor(lik)[1] == () + test_interface(lik, SqExponentialKernel(), rand(10)) end diff --git a/test/runtests.jl b/test/runtests.jl index 00b5165..db7ba16 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -7,6 +7,8 @@ using Distributions @testset "GPLikelihoods.jl" begin + include("test_utils.jl") + @testset "likelihoods" begin include("likelihoods/bernoulli.jl") include("likelihoods/categorical.jl") diff --git a/test/test_utils.jl b/test/test_utils.jl new file mode 100644 index 0000000..e82d408 --- /dev/null +++ b/test/test_utils.jl @@ -0,0 +1,52 @@ +function test_interface( + rng::AbstractRNG, lik, k::Kernel, x::AbstractVector; functor_args=(), +) + gp = GP(k) + lgp = LatentGP(gp, lik, 1e-5) + lfgp = lgp(x) + + # Check if likelihood produces a distribution + @test lik(rand(rng, lfgp.fx)) isa Distribution + + N = length(x) + y = rand(rng, lfgp.fx) + + if x isa MOInput + # TODO: replace with mo_inverse_transform + N = length(x.x) + y = [y[[i + j*N for j in 0:(x.out_dim - 1)]] for i in 1:N] + end + + # Check if the likelihood samples are of correct length + @test length(rand(rng, lik(y))) == N + + # Check if functor works properly + if functor_args == () + @test Functors.functor(lik)[1] == functor_args + else + @test keys(Functors.functor(lik)[1]) == functor_args + end +end + +""" + test_interface(lik, k::Kernel, x::AbstractVector; functor_args=()) + +This function provides unified method to check the interface of the various likelihoods +defined. It checks if the likelihood produces a distribution, length of likelihood +samples is correct and if the functor works as intended. +... +# Arguments +- `lik`: the likelihood to test the interface of +- `k::Kernel`: the kernel to use for the GP +- `x::AbstractVector`: intputs to compute the likelihood on +- `functor_args=()`: a collection of symbols of arguments to match functor parameters with. +... +""" +function test_interface( + lik, + k::KernelFunctions.Kernel, + x::AbstractVector; + kwargs... +) + test_interface(Random.GLOBAL_RNG, lik, k, x; kwargs...) +end