Okay, I came back to this and after some hacking have got the following to run and produce basically sensible results.
struct SparseFiniteGP{T1<:Stheno.FiniteGP, T2<:Stheno.FiniteGP} <: Distributions.AbstractMvNormal
fobs::T1
finducing::T2
end
function Stheno.logpdf(f::T, y::AbstractArray{T1, 1}) where {T <: SparseFiniteGP, T1 <: Real}
return elbo(f.fobs, y, f.finducing)
end
Base.length(f::SparseFiniteGP) = length(f.fobs)
Distributions._rand!(rng::Random._GLOBAL_RNG, f::SparseFiniteGP1, x::Array{T}) where {T<:Real} = rand(f.fobs)
@model function example_model_sparse(x, z, xu)
f = GP(Matern32(), GPC())
fsparse = SparseFiniteGP(f(x, 1e-6), f(xu, 1e-6))
y ~ fsparse
λ = exp.(y)
z .~ Poisson.(λ)
end
chn_sparse = sample(example_model_sparse(x, z, xu), NUTS(), 200)
On the left is the dense model’s posterior for λ, on the right is the sparse model’s posterior (with the locations of the inducing points shown by the vertical lines).
The posteriors do have some differences, but…with 900 observations, drawing 200 NUTS samples from the dense model takes something like 4 hours. Using the sparse model with 19 inducing points, the same sampling run takes about 60 seconds, i.e. a roughly 240-fold speedup.
@willtebbutt, do you think a type like this is worth having in Stheno? If so, I can start work on a PR…