Skip to content

GP Conditioning

This module provides tools for conditioning Gaussian processes on observations made through linear functionals. This enables GP regression with not just point observations, but also derivatives, integrals, and other linear transformations.

Overview

The core workflow is:

  1. Create a GP prior with a kernel

  2. Define observations using LinearObservation

  3. Condition the GP using condition_on_observation

  4. Query the posterior with mean, var, cov, or rand

julia
using FunctionalGPs, AbstractGPs

# Prior GP
k = Matern52Kernel()
f = GP(k)

# Observe function values
X = [0.0, 0.5, 1.0]
y = sin.(X)
f_post = condition_on_observation(f, X, y; noise=0.01)

# Posterior predictions
X_new = 0:0.1:1
posterior_mean = mean(f_post(X_new))
posterior_var = var(f_post(X_new))

Types

FunctionalGPs.LinearObservation Type
julia
LinearObservation{Tℒ, Tε, Ty}

Represents a noisy observation of a GP through a linear functional.

Given a GP f, a linear functional , and observed values y, this encodes the observation model y = ℒ(f) + ε where ε is additive Gaussian noise.

Fields

  • linfunc: The linear functional applied to the GP

  • noise: The noise distribution (MvNormal or nothing for noise-free)

  • y: The observed values

See also: condition_on_observation, LinearConditionalGP

source
FunctionalGPs.LinearConditionalGP Type
julia
LinearConditionalGP <: AbstractGP

A Gaussian process conditioned on linear observations.

This type represents a GP posterior after conditioning on one or more LinearObservations. It stores the prior GP and all observation data needed for efficient posterior inference.

Use condition_on_observation to construct instances rather than calling the constructor directly.

Posterior Computations

For a LinearConditionalGP f, you can:

  • Evaluate at points: f(X) returns a FiniteGP

  • Get posterior mean: mean(f(X))

  • Get posterior variance: var(f(X))

  • Get posterior covariance: cov(f(X))

  • Sample: rand(rng, f(X), n)

  • Apply further functionals: ℒ(f) returns an MvNormal

See also: LinearObservation, condition_on_observation

source

Conditioning

FunctionalGPs.condition_on_observation Function
julia
condition_on_observation(f::AbstractGP, observation::LinearObservation) -> LinearConditionalGP
condition_on_observation(f::AbstractGP, ℒ, y; noise=nothing) -> LinearConditionalGP
condition_on_observation(f::AbstractGP, X::AbstractVector, y; noise=nothing) -> LinearConditionalGP

Condition a GP on observations through a linear functional.

Returns a LinearConditionalGP representing the posterior distribution.

Methods

  • condition_on_observation(f, obs): Condition on a LinearObservation

  • condition_on_observation(f, ℒ, y; noise): Condition on ℒ(f) = y with optional noise

  • condition_on_observation(f, X, y; noise): Shorthand for point evaluation at X

Multiple observations can be added sequentially by calling condition_on_observation on an existing LinearConditionalGP.

Example

julia
using FunctionalGPs, AbstractGPs

k = Matern52Kernel()
f = GP(k)

# Condition on function values
X = [0.0, 0.5, 1.0]
y = sin.(X)
f_post = condition_on_observation(f, X, y; noise=0.01)

# Add derivative observation
∂x = PartialDerivative((1,))
= EvaluationFunctional([0.25])  ∂x
f_post2 = condition_on_observation(f_post, ℒ, [0.5]; noise=1e-6)

# Compute posterior at new points
X_new = 0:0.1:1
μ = mean(f_post2(X_new))
σ² = var(f_post2(X_new))
source

Posterior Access

After conditioning, you can access properties of the posterior:

FunctionalGPs.G_chol Function
julia
G_chol(f::LinearConditionalGP)

Return the Cholesky factorization of the Gram matrix G = ℒ(ℒ(k)) + Σ_ε.

This is the core matrix needed for posterior computations and is cached (memoized).

source
FunctionalGPs.representer_weights Function
julia
representer_weights(f::LinearConditionalGP)

Compute the representer weights G⁻¹(y - ℒ(m) - μ_ε) used for posterior mean computation.

The posterior mean at new points is m(x) + k(x, ℒ) * representer_weights(f). This is cached (memoized) for efficiency.

source
FunctionalGPs.predictive_residual Function
julia
predictive_residual(f::LinearConditionalGP)

Compute the predictive residual y - ℒ(m) - μ_ε where y is observed data, ℒ(m) is the prior mean evaluated through the functional, and μ_ε is the noise mean.

This is cached (memoized) for efficiency.

source
FunctionalGPs.y_vec Function
julia
y_vec(f::LinearConditionalGP)

Return all observed values concatenated into a single vector.

source

Noise Access

FunctionalGPs.εs Function
julia
εs(f::LinearConditionalGP)

Return the tuple of noise distributions from all observations.

source
FunctionalGPs.μs Function
julia
μs(f::LinearConditionalGP)

Return the tuple of noise means from all observations.

source

Applying Functionals to GPs

Linear functionals can be applied directly to GPs (both prior and posterior) to obtain the distribution of the transformed quantity:

julia
# Prior GP
f = GP(Matern52Kernel())

# Distribution of integral over [0, 1]
= VectorizedLebesgueIntegral(Interval(0.0, 1.0))
integral_dist =(f)  # Returns MvNormal

# For a posterior GP
f_post = condition_on_observation(f, [0.5], [0.0]; noise=0.01)
posterior_integral =(f_post; noise=1e-6)

This works because linear functionals preserve Gaussianity: if f ~ GP(m, k), then ℒ(f) ~ Normal(ℒ(m), ℒ(ℒ(k))).

See also

For models that need to bundle several linear functionals of the same GP into a single joint Gaussian — preserving the cross-covariances between blocks that are otherwise dropped by independent per-functional treatment, e.g. inside a Turing or DynamicPPL model — see the Joint Functional Gaussians page in this API Reference.