Public API
GPPP
Core functionality for working with GPPPs.
Stheno.@gppp — Macro@gppp(model_expression)Construct a GaussianProcessProbabilisticProgramme (GPPP) from a code snippet.
f = @gppp let
    f1 = GP(SEKernel())
    f2 = GP(Matern52Kernel())
    f3 = f1 + f2
end
x_local = randn(5)
x = BlockData(GPPPInput(:f1, x_local), GPPPInput(:f2, x_local), GPPPInput(:f3, x_local))
y = rand(f(x, 1e-12))
f1, f2, f3 = split(x, y)
isapprox(f1 + f2, f3; rtol=1e-4)
# output
trueStheno.GPPPInput — TypeGPPPInput(p, x::AbstractVector)An collection of inputs for a GPPP. p indicates which process the vector x should be extracted from. The required type of p is determined by the type of the keys in the GPPP indexed.
julia> x = [1.0, 1.5, 0.3];
julia> v = GPPPInput(:a, x)
3-element GPPPInput{Symbol, Float64, Vector{Float64}}:
 (:a, 1.0)
 (:a, 1.5)
 (:a, 0.3)
julia> v isa AbstractVector{Tuple{Symbol, Float64}}
true
julia> v == map(x_ -> (:a, x_), x)
trueStheno.BlockData — TypeBlockData{T, TV<:AbstractVector{T}, TX<:AbstractVector{TV}} <: AbstractVector{T}A strictly ordered collection of AbstractVectors, representing a ragged array of data.
Very useful when working with GPPPs. For example
f = @gppp let
    f1 = GP(SEKernel())
    f2 = GP(Matern52Kernel())
    f3 = f1 + f2
end
# Specify a `BlockData` set that can be used to index into
# the `f2` and `f3` processes in `f`.
x = BlockData(
    GPPPInput(:f2, randn(4)),
    GPPPInput(:f3, randn(3)),
)
# Index into `f` at the input.
f(x)Base.split — FunctionBase.split(x::BlockData, Y::AbstractVecOrMat)Convenience functionality to make working with the output of operations on GPPPs easier. Splits up the rows of Y according to the sizes of the data in x.
julia> Y = vcat(randn(5, 3), randn(4, 3));
julia> x = BlockData(randn(5), randn(4));
julia> Y1, Y2 = split(x, Y);
julia> Y1 == Y[1:5, :]
true
julia> Y2 == Y[6:end, :]
trueWorks with any BlockData, so blocks can e.g. be GPPPInputs. This is particularly helpful for working with the output from rand and marginals from a GPPP indexed at BlockData. For example
f = @gppp let
    f1 = GP(SEKernel())
    f2 = GP(Matern52Kernel())
    f3 = f1 + f2
end
x = BlockData(GPPPInput(:f2, randn(3)), GPPPInput(:f3, randn(4)))
y = rand(f(x))
y2, y3 = split(x, y)Functionality also works with any AbstractVector.
Building GPPPs
If in doubt about what any of these transformations can do, play around with them!
Base.:+ — Function+(fa::AbstractGP, fb::AbstractGP)Produces an AbstractGP f satisfying f(x) = fa(x) + fb(x).
Base.:* — Function*(f, g::AbstractGP)Produce an AbstractGP h satisfying to h(x) = f(x) * g(x), for some deterministic function f.
If f isa Real, then h(x) = f * g(x).
Stheno.stretch — Functionstretch(f::AbstractGP, l::Union{AbstractVecOrMat{<:Real}, Real})This is the primary mechanism by which to introduce length scales to your programme.
If l isa Real or l isa AbstractMatrix{<:Real}, stretch(f, l)(x) == f(l * x) for any input x. In the l isa Real case, this is equivalent to scaling the length scale by 1 / l.
l isa AbstractVector{<:Real} is equivalent to stretch(f, Diagonal(l)).
Equivalent to f ∘ Stretch(l).
Stheno.periodic — Functionperiodic(g::AbstractGP, f::Real)Produce an AbstractGP with period f.
Stheno.shift — Functionshift(f::AbstractGP, a::Real)
shift(f::AbstractGP, a::AbstractVector{<:Real})Returns the DerivedGP g given by g(x) = f(x - a)
Stheno.select — Functionselect(f::AbstractGP, idx)Select the dimensions of the input to f given by idx.
Stheno.additive_gp — Functionadditive_gp(fs)Produces the GP given by
sum(fs[1](x[1]) + fs[2](x[2]) + ... + fs[D](x[D]))Requires that length(fs) is the same as the dimension of the inputs to be used.
additive_gp(fs, indices)fs should be a collection of GPs, and indices a collection of collections of integer indices. For example, indices might be something like [1:2, 3, 4:6], in which case fs would need to comprise exactly three elements. In general, this functions requires that length(fs) == length(indices).
Produces the GP given by
sum(fs[1](x[indices[1]]) + fs[2](x[indices[2]]) + ... + fs[D](x[indices[D]]))