Gaussian Approximation
Provided by GaussianMarkovRandomFields.jl
The gaussian_approximation function is implemented in GaussianMarkovRandomFields.jl v0.4+ and re-exported by Latte.jl for user convenience. This documentation describes the re-exported functionality.
The Gaussian approximation functionality provides efficient Newton-Raphson optimization for finding posterior modes in INLA. This is the core computational engine for constructing Gaussian approximations to non-Gaussian posteriors.
Overview
The Gaussian approximation process finds the mode of the posterior distribution p(x|y) and constructs a Gaussian approximation around it using Fisher scoring (Newton-Raphson with Fisher information matrix). This approximation forms the foundation of the INLA methodology.
Main Function
GaussianMarkovRandomFields.gaussian_approximation Function
gaussian_approximation(prior_gmrf, obs_lik; kwargs...) -> AbstractGMRFFind Gaussian approximation to the posterior using Fisher scoring.
This function finds the mode of the posterior distribution and constructs a Gaussian approximation around it using Fisher scoring (Newton-Raphson with Fisher information matrix).
Works for GMRF, ConstrainedGMRF, and ChordalGMRF priors, automatically handling constraint projection when needed.
Arguments
prior_gmrf: Prior GMRF distribution for the latent field (GMRF, ConstrainedGMRF, or ChordalGMRF)obs_lik: Materialized observation likelihood (contains data and hyperparameters)
Keyword Arguments
max_iter::Int=50: Maximum number of Fisher scoring iterationsmean_change_tol::Real=1e-4: Convergence tolerance for mean changenewton_dec_tol::Real=1e-5: Newton decrement convergence toleranceadaptive_stepsize::Bool=true: Enable adaptive stepsize with backtracking line searchmax_linesearch_iter::Int=10: Maximum line search iterations per Newton stepverbose::Bool=false: Print iteration information
Returns
- Gaussian approximation to the posterior p(x | θ, y) (same type as input prior)
Example
# Set up components
prior_gmrf = GMRF(μ_prior, Q_prior)
obs_model = ExponentialFamily(Poisson)
obs_lik = obs_model(y)
# Find Gaussian approximation - uses adaptive stepsize by default
posterior_gmrf = gaussian_approximation(prior_gmrf, obs_lik)
# For well-conditioned problems, disable adaptive stepsize for speed
posterior_gmrf = gaussian_approximation(prior_gmrf, obs_lik; adaptive_stepsize=false)gaussian_approximation(prior::WorkspaceGMRF, obs_lik::ObservationLikelihood; kwargs...)Workspace-aware Gaussian approximation via Fisher scoring. Uses the workspace's factorisation engine for numeric-only refactorisation on each Newton step.
sourcegaussian_approximation(prior::LatentModel, obs_lik; θ, ws=nothing, kwargs...)Materialise the Gaussian latent prior at θ and delegate to the (::AbstractGMRF, obs_lik) / (::WorkspaceGMRF, obs_lik) dispatch for fixed-Q Newton.
gaussian_approximation(prior::NonGaussianLatentPrior, obs_lik; θ, ws=nothing, x0, kwargs...)Iterated-linearisation Gaussian approximation. The Newton loop calls local_quadratic(prior, x_k; θ...) per iterate to re-linearise the prior at the current iterate; the line-search merit uses the exact log p(x | θ) carried in LocalLatentQuadratic.logp_ref.
Hyperparameter values may be passed splatted (τ = 1.0) or as a θ::NamedTuple keyword; both forms merge before dispatch. Non-Gaussian priors don't have a canonical mean, so x0 defaults to zeros(length(prior)) — pass it explicitly for problems where zero is a poor starting point (e.g. priors with reflection symmetry through zero).
When a ws::GMRFWorkspace is supplied, it must be seeded with the full structural sparsity pattern that local_quadratic(prior, x; θ...) produces across all Newton iterates (the workspace reuses one symbolic factorisation, and the per-iterate precision values are copied onto it positionally). Seeding from a generic, non-degenerate x is the safe way to capture every structural coupling.
Implementation Details
The gaussian_approximation function uses NonlinearSolve.jl with Newton-Raphson optimization and CHOLMOD factorization for efficient sparse linear algebra.
Basic Usage
using Latte
using GaussianMarkovRandomFields
using Distributions
# Set up prior GMRF
μ_prior = zeros(10)
Q_prior = spdiagm(0 => ones(10))
prior_gmrf = GMRF(μ_prior, Q_prior)
# Set up observation model
obs_model = ExponentialFamily(Poisson)
θ_named = NamedTuple() # No hyperparameters for Poisson
# Generate synthetic data
x_true = rand(prior_gmrf)
data_dist = conditional_distribution(obs_model, x_true; θ_named...)
y_obs = rand(data_dist)
# Find Gaussian approximation
obs_lik = obs_model(y_obs; θ_named...)
posterior_gmrf = gaussian_approximation(prior_gmrf, obs_lik)
# Extract posterior statistics
posterior_mean = mean(posterior_gmrf)
posterior_precision = precision_matrix(posterior_gmrf)
println("Gaussian approximation computed successfully")Mathematical Properties
The Gaussian approximation finds the mode of the posterior distribution and constructs a Gaussian around it. For observation models with Gaussian likelihood, this approximation is exact:
# For Gaussian observations, the approximation is exact
obs_model = ExponentialFamily(Normal)
θ_named = (σ = 0.5,)
# The posterior precision combines prior and observation precision
# Q_posterior = Q_prior + Q_obs
# μ_posterior = Q_posterior^(-1) * (Q_prior * μ_prior + Q_obs * y)Performance Considerations
Fisher Information vs Hessian
The implementation uses Fisher scoring, which approximates the Hessian with the Fisher information matrix. This has several advantages:
Stability: Fisher information is always positive semi-definite
Efficiency: Often faster convergence than pure Newton-Raphson
Numerical robustness: Less sensitive to poor conditioning
Sparse Linear Algebra
The implementation leverages sparse linear algebra throughout:
Sparse precision matrices are preserved during optimization
Cholesky factorizations use sparse solvers when available
Memory usage scales with the sparsity pattern of the prior
Optimization Details
The implementation uses NonlinearSolve.jl with Newton-Raphson method:
Jacobian computation: Uses automatic differentiation for precise gradients and Hessians
Linear solver: CHOLMOD factorization for sparse precision matrices
Convergence: Built-in tolerances for
abstol=1e-6andreltol=1e-6Permutation handling: Preserves sparsity patterns from the prior GMRF
Mathematical Background
Fisher Scoring Update
At each iteration, the algorithm performs the update:
Q_new = Q_prior - Hessian_obs(μ_current)
gradient = Q_prior * (μ_current - μ_prior) - grad_obs(μ_current)
μ_new = μ_current - Q_new⁻¹ * gradientWhere:
Q_prioris the prior precision matrixμ_prioris the prior meanHessian_obsis the Hessian of the observation log-likelihoodgrad_obsis the gradient of the observation log-likelihood
Gaussian Approximation
The final Gaussian approximation takes the form:
p(x|y) ≈ N(μ_mode, Q_mode⁻¹)Where μ_mode is the posterior mode and Q_mode is the posterior precision matrix.
Error Handling
The function handles various edge cases:
Non-convergence: NonlinearSolve.jl provides convergence diagnostics
Numerical issues: CHOLMOD factorization handles ill-conditioned matrices robustly
Matrix conditioning: Sparse factorization with automatic pivoting
For problematic cases, consider:
Checking observation model implementations (
loglik,loggrad,loghessian)Verifying prior GMRF is well-conditioned
Using more informative priors to improve conditioning