GPLikelihoods
GPLikelihoods.jl
provides a practical interface to connect Gaussian and non-conjugate likelihoods to Gaussian Processes. The API is very basic: Every AbstractLikelihood
object is a functor taking a Real
or an AbstractVector
as an input and returning a Distribution
from Distributions.jl
.
Single-latent vs multi-latent likelihoods
Most likelihoods, like the GaussianLikelihood
, only require one latent Gaussian process. Passing a Real
will therefore return a UnivariateDistribution
, and passing an AbstractVector{<:Real}
will return a multivariate product of distributions.
julia> f = 2.0;
julia> GaussianLikelihood()(f) == Normal(2.0, 1e-3)
true
julia> fs = [2.0, 3.0, 1.5];
julia> GaussianLikelihood()(fs) isa AbstractMvNormal
true
Some likelihoods, like the CategoricalLikelihood
, require multiple latent Gaussian processes, and an AbstractVector{<:Real}
needs to be passed. To obtain a product of distributions an AbstractVector{<:AbstractVector{<:Real}}
has to be passed (we recommend using ColVecs
and RowVecs
from KernelFunctions.jl if you need to transform an AbstractMatrix
).
julia> fs = [2.0, 3.0, 4.5];
julia> CategoricalLikelihood()(fs) isa Categorical
true
julia> Fs = [rand(3) for _ in 1:4];
julia> CategoricalLikelihood()(Fs) isa Product{<:Any,<:Categorical}
true
Constrained parameters
The function values f
of the latent Gaussian process live in the real domain $\mathbb{R}$. For some likelihoods, the domain of the distribution parameter p
that is modulated by the latent Gaussian process is constrained to some subset of $\mathbb{R}$, e.g. only positive values or values in an interval.
To connect these two domains, a transformation from f
to p
is required. For this, we provide the Link
type, which can be passed to the likelihood constructors. (Alternatively, function
s can also directly be passed and will be wrapped in a Link
.)
We typically call this passed transformation the invlink
. This comes from the statistics literature, where the "link" is defined as f = link(p)
, whereas here we need p = invlink(f)
.
For more details about which likelihoods require a Link
check out their docs.
A classical example is the BernoulliLikelihood
for classification, with the probability parameter $p \in [0, 1]$. The default is to use a logistic
transformation, but one could also use the inverse of the probit
link:
julia> f = 2.0;
julia> BernoulliLikelihood()(f) == Bernoulli(logistic(f))
true
julia> BernoulliLikelihood(NormalCDFLink())(f) == Bernoulli(normcdf(f))
true
Note that we passed the inverse of the probit
function which is the normcdf
function.