Skip to content

INLA

INLA is Latte's default inference engine. Given a latent Gaussian model, inla computes posterior marginals for the latent field and the hyperparameters without any MCMC. It does this by nesting two approximations.

How it works

INLA never builds the full joint posterior. It goes after each marginal directly, in two steps.

The first step is the latent field at a fixed value of the hyperparameters θ. The conditional p(xy,θ) is approximated by a Gaussian centred at its mode. When the observations are Gaussian this is exact; otherwise it is a Laplace approximation, and how accurately you take it is the main accuracy setting (see Tuning below).

The second step is the hyperparameters. The marginal posterior p(θy)p(θ)p(yθ) is reconstructed by evaluating it at a handful of θ points, where the marginal likelihood p(yθ) comes from the first step, and fitting a smooth surface through them. Each latent marginal then falls out as a weighted mixture of the Gaussians from the first step, one per θ point.

So there are two things you actually control: how accurately the inner marginals are taken, and where the θ points are placed. Drag the grid in the picture below to see the second one at work.

the hyperparameter posterior p(θ|y)
θ = log τ  ·  3 grid points
a latent marginal p(xᵢ|y) = weighted mix of per-θ Gaussians
xᵢ
per-θ GaussianINLA marginalexact (fine grid)

Tuning

The defaults work well for most models. Here is what to reach for when one doesn't.

Latent marginal accuracy (latent_marginalization_method)

The inner Gaussian is symmetric, but real latent marginals are often skewed. This sets how much of that skew you recover.

  • GaussianMarginal(): just the inner Gaussian. Fastest, but symmetric.

  • SimplifiedLaplace(), the default: a cheap correction that adds the skewness back. Accurate enough for most models.

  • LaplaceMarginal(): a full Laplace approximation for each component. The most accurate and the most expensive. Worth it when the simplified correction isn't enough, for instance with strongly non-Gaussian likelihoods or very few observations behind each latent value.

julia
inla(model, y; latent_marginalization_method = LaplaceMarginal())

Hyperparameter exploration (exploration_strategy)

This decides where the θ points go.

  • AutoExplorationStrategy(), the default: a dense grid when there are only a few hyperparameters, switching to a central composite design (CCD) as the count grows.

  • GridExplorationStrategy(integration_step_z = …, max_log_drop = …): an explicit grid. Lowering integration_step_z packs in more points. The default grid is fairly coarse, and a denser one noticeably sharpens skewed hyperparameter tails (the Validation page measures exactly this). Each extra point costs about one more inner solve.

  • CCDExplorationStrategy(): forces the CCD design. The practical choice once you have several hyperparameters and a full grid gets too expensive.

julia
inla(model, y; exploration_strategy = GridExplorationStrategy(integration_step_z = 0.5))

Mode finding (mode_init, mode_diagnostic)

The θ points are placed around the mode of p(θy). On difficult posteriors (multimodal, very skewed, nearly degenerate) the optimiser can settle on a poor mode. Latte checks for this afterwards and, by default, warns you if it finds a better point on the grid (mode_diagnostic = :warn). When that happens, give the search a better starting point, or a few of them, through mode_init.

Other knobs

  • latent_indices computes marginals only for the components you ask for, which saves a lot of time on large latent fields.

  • DIC, WAIC, CPO and the marginal likelihood are computed along the way by default, through accumulators.

Reference

Latte.inla Function
julia
inla(model::LatentGaussianModel, y::AbstractVector; kwargs...)

Unified INLA inference with automatic parameter selection and progress tracking.

This function provides a simplified interface for INLA inference, automatically selecting sensible defaults while supporting advanced customization.

Arguments

  • model::LatentGaussianModel: The INLA model specification

  • y::AbstractVector: Observed data

Keyword Arguments

  • latent_marginalization_method = nothing: Method for latent marginalization. nothing resolves per model via default_marginalization: compact LTM models get the VBC mean correction (VBCMarginal), everything else simplified Laplace (SimplifiedLaplace).

  • hyperparameter_marginalization_method::HyperparameterMarginalizationMethod = AutoHyperparameterMarginal(): Method for hyperparameter marginalization (GridSum for D=1, CCD interpolant for D≥2)

  • latent_indices::Union{Nothing, AbstractVector{<:Integer}} = nothing: Indices to marginalize (default: all)

  • exploration_strategy::ExplorationStrategy = AutoExplorationStrategy(): Hyperparameter exploration strategy. AutoExplorationStrategy() uses grid for D ≤ 2, CCD for D ≥ 3. Can also pass GridExplorationStrategy(...) or CCDExplorationStrategy(...) directly.

  • mode_method = BFGS(): Optimization method for mode finding

  • mode_iterations::Int = 1000: Maximum iterations for mode finding

  • progress::Bool = true: Enable progress tracking

  • accumulators::Tuple = (DICStrategy(), MarginalLogLikelihoodStrategy(), WAICStrategy(), CPOStrategy()): Tuple of PosteriorStrategy configs for model comparison metrics. Each strategy is materialised into a fresh accumulator per call, so the tuple can be safely reused across multiple inla() runs. Pass e.g. WAICStrategy(n_nodes=25) to tune knobs.

Returns

  • INLAResult: Complete INLA inference results with marginals and diagnostics

Examples

julia
# Basic usage with default settings
result = inla(model, y)

# Custom exploration parameters
result = inla(model, y, exploration_strategy=GridExplorationStrategy(max_log_drop=3.0, interpolation_subdivisions=3))

# Disable progress tracking
result = inla(model, y, progress=false)

# Opt into the heavier adaptive latent marginalization
result = inla(model, y,
    latent_marginalization_method=AdaptiveMarginal(),
    latent_indices=1:100)

# Force CCD exploration on a 2D model
result = inla(model, y,
    exploration_strategy=CCDExplorationStrategy())

Progress Tracking

When progress=true, displays a 3-phase progress bar:

  • Phase 1 (33%): Mode finding with iteration tracking

  • Phase 2 (66%): Exploration with grid point evaluation

  • Phase 3 (100%): Hyperparameter marginalization (may include adaptive expansion)

Each phase shows detailed real-time information about the computation.

source

Limits

The Validation page measures all of these.

  • Skewed hyperparameter tails. The coarse default grid does not resolve them well; densify it with GridExplorationStrategy(integration_step_z = …). For non-Gaussian likelihoods a small gap survives even then, and that part comes from the inner Laplace approximation rather than the grid.

  • Non-identified hyperparameters. When the data only pin down a combination of hyperparameters (say σ2+1/τ in a Gaussian-Gaussian IID model), the outer surface cannot follow the degenerate ridge, so those marginals drift even though the inner Laplace matches the exact posterior. A sampler like HMC-Laplace handles this case.

  • Many hyperparameters. The full grid grows exponentially in their number. The Auto/CCD path softens that, and HMC-Laplace scales better when θ is large.

References

See also