Fits a GLM with a Matern spatial field via the SPDE approach. Uses CHOLMOD sparse solver with optional nested Laplace for hyperparameter integration.
Arguments
- y
Integer response vector.
- X
Design matrix.
- spatial
A
tulpa_spatialobject fromspatial_spde()orspatial_spde_custom().- family
Distribution family:
"binomial","poisson","neg_binomial_2", or"gaussian"(continuous-field geostatistics, withphithe observation-noise standard deviation).- n_trials
Integer vector of trial sizes (binomial only).
- range
Spatial range parameter. If NULL, uses nested Laplace to integrate over range and sigma.
- sigma
Marginal standard deviation. If NULL, uses nested Laplace.
- nested_laplace
Logical. If TRUE (default when range/sigma are NULL), use nested Laplace approximation over hyperparameters.
- phi
Dispersion passed to the family, held fixed. One convention at every door: for
gaussian/lognormalthis is the residual VARIANCE (the SD issqrt(phi)), forneg_binomial_2the size,gammathe shape,betathe precision,tthe scale;binomialandpoissonignore it. The compiled kernels parameterize the two variance families by the residual SD and are handedsqrt(phi)at the boundary.- offset
Optional fixed additive term on the linear predictor (
eta = offset + X beta + A w), lengthlength(y);NULL-> no offset.- re_idx, n_re_groups, sigma_re
Optional single iid random-intercept
(1 | g)term alongside the Matern field:re_idxis a length-length(y)1-based group index,n_re_groupsthe number of groups, andsigma_rethe (conditioned) random-effect SD. The field and the RE block are Laplace- marginalised jointly.n_re_groups = 0(default) is no RE term. Not supported for a fractional-nu field.- mode
Inference method (the method is an argument, not a parallel verb):
"laplace"(default) is the nested-Laplace integration over(range, sigma)documented here;"nuts"delegates totulpa_nuts_spde()for exact HMC over the field (and, unless bothrangeandsigmaare fixed, the Matern hyperparameters).mode = "nuts"does not support anoffsetor a random-effect term, and its sampler knobs pass viacontrol(seetulpa_nuts_spde()); it returns that sampler's draws object.- control
A named list of numerical / tuning knobs (statistical arguments stay in the signature above). Recognized entries:
method: hyperparameter integration backend when nested Laplace is active."ccd"(default) uses a central composite design centered on the joint posterior mode of(range, sigma), oriented by the local Hessian (9 design points instead ofn_grid^2), folding the PC priors fromspatial$prior_range/spatial$prior_sigmainto the integrated marginal and falling back to"grid"if the surface is too flat for a Hessian-based design."grid"uses a rectangular grid inlog(range) x log(sigma)around the prior modes.n_grid: grid points per hyperparameter dimension formethod = "grid"(ignored under"ccd"). Default 5.diagnose_k: if TRUE (default), compute the outer Pareto-\(\hat{k}\) accuracy diagnostic ($pareto_k) by importance sampling the joint(range, sigma)posterior on the log scale against the Gaussian proposal that orients the integration. Seetulpa_psis().k_samples: importance draws fordiagnose_k. Default 500, each one extra batched SPDE marginal evaluation. It is a precision knob: the GPD tail size is held at the fraction the default budget implies, so a larger budget sharpens the same k-hat rather than moving it to a deeper quantile of the weight distribution (gcol33/tulpa#631).k_tail_points: expert override for that tail size, in upper-tail order statistics. Silently capped at 20% of the draws, beyond which body ratios enter the tail and bias the shape.mode_find: tuning for the outer(range, sigma)mode-find undermethod = "ccd", aslist(factr =, ndeps =, maxit =); supply any subset.ndepsis the central-difference step foroptim()'s numerical gradient on the log scale (default 1e-2): it must clear the inner solver's convergence tolerance, and a step wide enough that its truncation error exceeds the reduction the line search chases near a flat optimum leaves L-BFGS-B aborting at the mode it just reached, in which case the CCD design declines to the rectangular grid.factris the relative-reduction stop in units of.Machine$double.eps(default 1e5);maxitthe iteration cap (default 300).max_iter: maximum Newton iterations. Default 100.tol: Newton convergence tolerance. Default 1e-6.n_threads: OpenMP threads. Default 1.checkpoint: grid-cell checkpoint/resume speclist(path =, resume =). Each solved(range, sigma)cell is appended topath; aresume = TRUErun loads the finished cells and re-solves only the rest, so a killed or rebooted fit resumes instead of restarting.resume = FALSEstarts a fresh file. DefaultNULL(off).
Value
A list with:
mode: mode of the latent field (beta + mesh node effects)log_marginal: log marginal likelihoodconverged: convergence flagspatial: the spatial specification (for prediction)pareto_k,pareto_k_is_ess: outer Pareto-\(\hat{k}\) and its importance-sampling ESS (NAwhendiagnose_k = FALSE)pareto_k_proposal_source,pareto_k_first_pass: which proposal family the reported k-hat came from (several candidates are scored and the best kept), and the k-hat of the first pass – the proposal exactly as placed, before refinement. A large gap says the placement is poor even where the verdict is fine.nested: nested Laplace results (if used)
References
Lindgren, Rue & Lindstrom (2011). An explicit link between Gaussian fields and Gaussian Markov random fields: the stochastic partial differential equation approach. JRSS-B 73(4):423-498. Rue, Martino & Chopin (2009). Approximate Bayesian inference for latent Gaussian models by using integrated nested Laplace approximations. JRSS-B 71(2):319-392.
Examples
# \donttest{
if (requireNamespace("fmesher", quietly = TRUE)) {
set.seed(1)
n <- 200L
coords <- cbind(runif(n), runif(n))
mesh <- fmesher::fm_mesh_2d(loc = coords, max.edge = c(0.15, 0.4), cutoff = 0.05)
fem <- fmesher::fm_fem(mesh)
A <- as(fmesher::fm_basis(mesh, loc = coords), "CsparseMatrix")
spec <- spatial_spde_custom(C = fem$c0, G = fem$g1, A = A, nu = 1,
prior_range = c(0.3, 0.5), prior_sigma = c(0.6, 0.05))
w <- as.numeric(rnorm(spec$n_mesh, 0, 0.6)); w <- w - mean(w)
x <- rnorm(n)
y <- rpois(n, exp(2.0 + 0.5 * x + as.numeric(spec$A %*% w)))
fit <- fit_spde(y = y, X = cbind(1, x), spatial = spec, family = "poisson")
fit$nested$range_mean
}
# }