imh_laplace: Independence Metropolis-Hastings with Laplace proposal

View source: R/imh_laplace.R

imh_laplaceR Documentation

Independence Metropolis-Hastings with Laplace proposal

Description

Sample from a posterior using independence Metropolis-Hastings with a multivariate-normal proposal centred at the Laplace mode and scaled by the inverse Hessian. For posteriors that are well- approximated by a Gaussian near the mode this is dramatically cheaper than HMC: each iteration is one log-posterior evaluation plus one accept/reject step. Embarrassingly parallel across chains.

Use cases:

  • Quick draws when Laplace is "almost right" but you want asymptotically-correct samples.

  • Cross-validation, simulation studies, or other repeated-fit workflows where HMC startup cost dominates.

  • Sanity check on the Laplace approximation: low IMH acceptance means the posterior is far from Gaussian and Laplace is biased.

Usage

imh_laplace(
  log_posterior,
  mode,
  hessian,
  n_iter = 2000L,
  warmup = n_iter%/%2L,
  scale = 1,
  init = NULL,
  thin = 1L,
  seed = NULL,
  verbose = FALSE
)

Arguments

log_posterior

Function ⁠function(theta) -> numeric⁠ returning the unnormalized log posterior at a single parameter vector.

mode

Numeric vector of length d: the Laplace mode (i.e., tulpa_laplace(...)$mode[seq_len(d)] for the fixed-effects block, or any other mode you trust).

hessian

Symmetric positive-definite ⁠d x d⁠ matrix: the negative Hessian of log_posterior at mode (or H_beta from tulpa_laplace).

n_iter

Total iterations including warmup (default 2000).

warmup

Warmup iterations to discard (default n_iter / 2).

scale

Optional inflation factor on the proposal covariance (default 1.0). Values slightly > 1 (e.g., 1.5) give heavier-tailed proposals that improve mixing when Laplace underestimates posterior spread.

init

Optional starting parameter vector (default = mode).

thin

Keep every thin-th post-warmup sample (default 1).

seed

Optional integer RNG seed. Scoped to this call: the caller's .Random.seed is restored on exit, so two calls with the same seed give identical draws regardless of the surrounding RNG stream.

verbose

Print acceptance rate at end (default FALSE).

Value

A list with class tulpa_fit carrying:

  • draws: (n_iter - warmup) / thin x d matrix of draws.

  • means: posterior means.

  • accept_prob: per-iteration acceptance indicators.

  • mean_accept: overall post-warmup acceptance rate.

  • log_prob: per-draw log posterior values.

  • inference_mode: "exact".

  • inference_tier: 1L.

  • backend: "imh_laplace".

Tier

Tier 1 (Exact). The MH accept/reject step makes the chain asymptotically correct under the standard MH conditions. Tier status does not depend on Laplace's quality – only its quality affects efficiency.

See Also

tulpa_laplace() for the mode + Hessian, bridge_sampling() for marginal-likelihood estimation on the resulting draws.

Examples

# Toy: Bernoulli logistic with one covariate.
set.seed(1)
n <- 100
x <- rnorm(n)
eta <- 0.3 + 1.2 * x
y <- rbinom(n, 1, plogis(eta))
X <- cbind(1, x)

lap <- tulpa_laplace(y, n_trials = rep(1L, n), X = X,
                     family = "binomial")

log_post <- function(beta) {
  eta <- as.numeric(X %*% beta)
  sum(y * eta - log1p(exp(eta))) +
    sum(dnorm(beta, 0, 10, log = TRUE))
}

fit <- imh_laplace(log_post, mode = lap$mode[1:2],
                   hessian = lap$H_beta, n_iter = 1000)
fit$mean_accept
colMeans(fit$draws)


tulpa documentation built on Oct. 19, 2026, 5:09 p.m.