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 AbstractMvNormaltrue

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 Categoricaltrue
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, functions 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.