Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"

[compat]
AbstractGPs = "0.3, 0.4, 0.5"
AbstractGPs = "0.6"
ChainRulesCore = "1.7"
Distributions = "0.25"
FastGaussQuadrature = "0.4"
Expand Down
1 change: 1 addition & 0 deletions src/ApproximateGPs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export SparseVariationalApproximation
export DefaultQuadrature, Analytic, GaussHermite, MonteCarlo

include("utils.jl")
include("latent_gp.jl")
include("sparse_variational.jl")
include("expected_loglik.jl")
include("elbo.jl")
Expand Down
50 changes: 50 additions & 0 deletions src/latent_gp.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""
LatentGP(f<:AbstractGP, lik, Σy)

- `f` is a `AbstractGP`.
- `lik` is the likelihood function which maps samples from `f` to the
corresponding conditional likelihood distributions (i.e., `lik` must return a
`Distribution` compatible with the observations).
- `Σy` is the noise under which the latent GP is "observed"; this represents
the jitter used to avoid numeric instability and should generally be small.
"""
struct LatentGP{Tf<:AbstractGP,Tlik,TΣy}
f::Tf
lik::Tlik
Σy::TΣy
end

"""
LatentFiniteGP(fx<:FiniteGP, lik)

- `fx` is a `FiniteGP`.
- `lik` is the likelihood function which maps samples from `f` to the
corresponding conditional likelihood distributions (i.e., `lik` must return a
`Distribution` compatible with the observations).
"""
struct LatentFiniteGP{Tfx<:FiniteGP,Tlik}
fx::Tfx
lik::Tlik
end

(lgp::LatentGP)(x) = LatentFiniteGP(lgp.f(x, lgp.Σy), lgp.lik)

Base.length(lgpx::LatentFiniteGP) = length(lgpx.fx)

function Distributions.rand(rng::AbstractRNG, lfgp::LatentFiniteGP)
f = rand(rng, lfgp.fx)
y = rand(rng, lfgp.lik(f))
return (f=f, y=y)
end

"""
logpdf(lfgp::LatentFiniteGP, y::NamedTuple{(:f, :y)})

```math
log p(y, f; x)
```
The joint log density of the Gaussian process output `f` and observation `y`.
"""
function Distributions.logpdf(lfgp::LatentFiniteGP, y::NamedTuple{(:f, :y)})
return logpdf(lfgp.fx, y.f) + logpdf(lfgp.lik(y.f), y.y)
end
19 changes: 19 additions & 0 deletions test/latent_gp.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@testset "latent_gp" begin
gp = GP(SqExponentialKernel())
x = rand(10)
y = rand(10)

lgp = LatentGP(gp, x -> MvNormal(x, 0.1), 1e-5)
@test lgp isa LatentGP
@test lgp.f isa AbstractGPs.AbstractGP
@test lgp.Σy isa Real

lfgp = lgp(x)
@test lfgp isa AbstractGPs.LatentFiniteGP
@test lfgp.fx isa AbstractGPs.FiniteGP
@test length(lfgp) == length(x)

f = rand(10)
@test logpdf(lfgp, (f=f, y=y)) isa Real
@test rand(lfgp) isa NamedTuple{(:f, :y)}
end
4 changes: 4 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ const PKGDIR = dirname(dirname(pathof(ApproximateGPs)))
include("test_utils.jl")

@testset "ApproximateGPs" begin
include("latent_gp.jl")
println(" ")
@info "Ran latent_gp tests"

include("expected_loglik.jl")
println(" ")
@info "Ran expected_loglik tests"
Expand Down