Fits the community (spAbundance msNMix) N-mixture model: a per-species
Royle (2004) N-mixture with Gaussian community hyperpriors on the per-species
abundance and detection coefficients,
$$N_{s,i} \sim \mathrm{Poisson}(\lambda_{s,i}), \quad
y_{s,i,j} | N \sim \mathrm{Binomial}(N_{s,i}, p_{s,i,j}),$$
$$\log \lambda_{s,i} = X_\lambda^{(i)} (\mu_\lambda + b^\lambda_s), \quad
\mathrm{logit}\, p_{s,i,j} = X_p^{(ij)} (\mu_p + b^p_s),$$
$$b^\lambda_s \sim N(0, \Sigma_\lambda), \quad b^p_s \sim N(0, \Sigma_p).$$
The latent abundances integrate out per species-site in closed form (the
shared N-mixture kernel exposed by nmix_site_marginal()); the
per-species coefficient deviations \(b_s = (b^\lambda_s, b^p_s)\) are the
random effects. Both solvers assemble the per-species marginal in compiled
code via a native oracle (no per-group round trip into R). At n_quad = 1
(the default, the joint Laplace / glmer nAGQ = 1) the fit is a Laplace-EM
(block-coordinate Newton mode + closed-form covariance M-step + Schur-
complement SEs) – the fast production path. A higher n_quad routes the same
native oracle through the shared compiled AGHQ engine (tulpa_re_aghq()),
replacing each species' Laplace integral with adaptive Gauss-Hermite
quadrature to reduce the small-cluster (few species) downward bias of the
community covariances Sigma_lambda / Sigma_p – at a
n_quad^(p_lambda + p_p) per-species grid cost. Each species'
marginal – value, abundance/detection score, and the per-site observed-
information block carrying the \(\mathrm{Var}(N_i\mid y_i)\) abundance/
detection coupling – is supplied as the per-group oracle, so there is one
marginal/quadrature/covariance implementation across the package. The
Gaussian community priors pin \((\mu_\lambda, \mu_p)\) as fixed effects, so
no sum-to-zero constraint is needed; their standard errors come from the
marginal observed-information Hessian.
The abundance mixing distribution is Poisson (mixture = "P") or negative
binomial (mixture = "NB"). Under NB the dispersion is itself a per-species
random effect, log_r_s ~ N(mu_log_r, sigma_log_r) (i.e.
r_s ~ LogNormal): the per-species RE vector widens to
b_s = (b_lambda_s, b_p_s, b_logr_s), the community log-dispersion mu_log_r
joins (mu_lambda, mu_p) as a fixed effect, and sigma_log_r joins the
community covariances as a third (scalar) block, all integrated jointly by the
same AGHQ engine. The per-species size is
\(r_s = \exp(\mu_{\log r} + b^{\log r}_s)\). Poisson is the
\(r \to \infty\) limit (no dispersion coordinate).
Usage
nmix_laplace_re(
y,
site_idx,
species_idx,
X_lambda,
X_p,
n_sites,
n_species,
mu_lambda_init = NULL,
mu_p_init = NULL,
Sigma_lambda_init = NULL,
Sigma_p_init = NULL,
K_max = NULL,
headroom = NULL,
max_iter = 200L,
optimizer = c("em", "joint_fd", "joint_grad"),
mixture = c("P", "NB", "ZIP", "ZINB"),
r_init = 10,
sigma_logr_init = 0.5,
omega_init = 0.2,
sigma_omega_init = 0.5,
n_quad = 1L,
n_quad_scalar = .TOBS_MIN_SCALAR_NQUAD,
lkj_eta = 1,
sigma_beta = 100,
omega_sigma_prior = c(1, 0.05),
logr_sigma_prior = NULL,
verbose = FALSE
)Arguments
- y
Integer vector of counts, one entry per observed visit (long form, all species stacked).
- site_idx
Integer vector (same length as
y), 1-based site index.- species_idx
Integer vector (same length as
y), 1-based species index.- X_lambda
Numeric matrix
[n_sites x p_lambda]of abundance covariates (shared across species; one row per site).- X_p
Numeric matrix
[n_obs x p_p]of detection covariates (long form, row order matchingy).- n_sites, n_species
Integer counts.
- mu_lambda_init, mu_p_init
Optional warm starts for the community means. Default: the column means of independent per-species
nmix_laplace()fits.- Sigma_lambda_init, Sigma_p_init
Optional warm starts for the community covariances. Default: the (ridge-regularized) sample covariance of the per-species coefficient estimates.
- K_max
Marginal-sum truncation (default
max(y) + 100), applied per site (seeheadroom).- headroom
Latent-N states summed above each site's own
max(y_i).NULL(default) derives it fromK_max: an unsetK_maxcaps each site atmax(y_i) + 100, an explicit one truncates globally and uncapped. A caller that resolved the ceiling itself passes both.- max_iter
Optimizer iteration cap (default 200).
- optimizer
Outer optimize driver over the shared native oracle:
"em"(default) is the fast Laplace-EM (block-coordinate Newton mode + closed-form covariance M-step + Schur SE), the exactn_quad = 1solver."joint_grad"and"joint_fd"are the joint(theta, log-Cholesky Sigma)optimizers (tulpa_re_aghq()) and both do then_quad > 1AGHQ debias of the community covariances."joint_grad"(the fast debias path) supplies the analytic Fisher-identity gradient – one group sweep per step, no per-coordinate objective re-solve – and requiresn_quad > 1(atn_quad = 1use the EM)."joint_fd"finite-differences the objective (slower; the FD sweep re-solves every per-species mode per coordinate) and is kept for correctness / architecture validation and as then_quad = 1joint reference.- mixture
Abundance mixing distribution:
"P"(Poisson, default),"NB"(negative binomial with a per-species dispersion random effectlog_r_s ~ N(mu_log_r, sigma_log_r)), or their zero-inflated counterparts"ZIP"/"ZINB"(a per-species structural-zero random effectlogit_omega_s ~ N(mu_omega, sigma_omega); a shareomega_sof a species' sites is structurally empty). None of"NB"/"ZIP"/"ZINB"has a closed-form EM, so each defaultsoptimizerto"joint_grad"and errors onoptimizer = "em". The defaultn_quadwhen unsupplied is3for"NB"and the zero-inflated"ZIP"/"ZINB"(the tensor grid isn_quad^(p_lambda + p_p + [NB] + [ZI]), so a coarser grid keeps it tractable; #355).- r_init
Initial community-mean negative-binomial size for the joint optimizer (
mixture = "NB"only; default10, a moderate overdispersion start). The optimizer carriesmu_log_r = log(r_init)as the(p_lambda + p_p + 1)-th fixed effect.- sigma_logr_init
Initial standard deviation of the per-species log-dispersion random effect
log_r_s(mixture = "NB"/"ZINB"only; default0.5). Seeds the scalar log_r covariance block.- omega_init
Initial community-mean structural-zero probability for the joint optimizer (
mixture = "ZIP"/"ZINB"only; default0.2). The optimizer carriesmu_omega = qlogis(omega_init)as a trailing fixed effect.- sigma_omega_init
Initial standard deviation of the per-species structural-zero-logit random effect
logit_omega_s(mixture = "ZIP"/"ZINB"only; default0.5). Seeds the scalar omega covariance block.- n_quad
Quadrature points per random-effect dimension passed to
tulpa_re_aghq()(default 1, the joint Laplace). A highern_quaddebiases the community covariances at an_quad^(p_lambda + p_p)per-species grid cost, so keep it modest when the coefficient dimension is large. This sets the order of the correlated coefficient blocks (lambda,p); the scalar nuisance blocks usen_quad_scalar.- n_quad_scalar
Quadrature points for the scalar nuisance random-effect blocks – the negative-binomial dispersion
log_rand the zero-inflationlogit_omega(default 3). These integrate a 1-D posterior, sotulpa_re_aghq()'s per-block quadrature runs them at this coarser order rather than the fulln_quad, trimming then_quad^(NB + ZI)factor the nuisance axes would otherwise multiply into the tensor grid. Floored at 3 (and the floor wins over a smallern_quad): the rule is converged there, and below it the reported community-mean SE on that block can collapse by an order of magnitude with no other symptom.- lkj_eta
LKJ shape regularizing each correlated community covariance block's correlation off the boundary (default 1, no penalty); passed through to
tulpa_re_aghq(). Does not touch the marginal SDs.- sigma_beta
Weak Gaussian ridge SD on the community means (default 100, i.e.
tau = 1e-4, matching the other Laplace paths); stabilizes a weakly-identified community mean without materially shifting it.- omega_sigma_prior
Penalized-Complexity prior
c(U, alpha)(P(sigma_omega > U) = alpha) on the per-species structural-zero random effect SD (mixture = "ZIP"/"ZINB"only; defaultc(1, 0.05), interior mode ~ 0.33).sigma_omegais the softest AGHQ direction and at few species can collapse to the boundary, flattening the marginal Hessian and attenuating the recovered SD; the weak prior adds curvature there (passed totulpa_re_aghq()'ssigma_prior) without biasing an identified fit.NULLrestores pure ML on the structural-zero variance. Ignored for Poisson / NB.- logr_sigma_prior
Penalized-Complexity prior
c(U, alpha)(P(sigma_log_r > U) = alpha) on the per-species log-dispersion random effect SD (mixture = "NB"/"ZINB"only; defaultNULL, pure ML).sigma_log_ris the same shape of parameter assigma_omega– one scalar variance over species – and settles near its lower boundary the same way at few species. At 8 and 36 species with a simulatedsigma_logr = 0.5,n_quad = 3andn_quad_scalar = 3, fits recoveringsigma_log_r >= 0.30coveredmu_log_r33/34 while those below covered 2/5.That split is a property of those two group counts and does not carry to a third. Re-measured at 18 species on the same fixture and seeds (19 fits), one fit sits below 0.30, the point-estimate error is uncorrelated with the recovered SD (Spearman -0.08), and the reported SE is very nearly a deterministic multiple of it (Spearman +0.98, R^2 = 0.99). So what a threshold split picks up at 18 species is the SE side alone: a low recovered SD buys a proportionally narrower interval around an error that did not shrink with it. Both halves moving together is what the 8-and-36 pool showed and what is absent there.
The SE itself is \(\mathrm{se}^2 = (\hat\sigma_{\log r}^2 + c) / S\), with
cthe per-species inverse information forlog_r_s. Measured over 97 fits at 8 / 18 / 36 species,cis 0.130 / 0.133 / 0.141 – one constant across a factor of 4.5 inS– so the shape is right andsigma_hatis the input that is off. Its attenuation (0.418 / 0.448 / 0.487 against a simulated 0.5) is monotone inSand passes straight into the interval.A 1.28x-too-narrow
mu_log_rinterval at 18 species on this fixture is mostly the seed block, not the estimator.mu_log_ris a population mean and each seed drawsSlog-dispersions around it, so the across-seed error carries asigma_logr^2 / Sterm that the SE includes and that is itself measured on ~19 seeds: it supplies about two thirds of the spread, and the 18-species blocks drew it 18-21% wide (chi-square p = 0.12 and 0.03). Putting that draw at its expectation and rebuilding the SE at the simulated sigma gives a scale of 0.990 / 1.035 / 0.963 at 8 / 18 / 36 species. Usesimulate_ms_abun()'struth$mu_log_r_realto score against the seed's own realized species mean and keep the two apart.A fit now says whether its dispersion variance is distinguishable from zero at all:
fit$ms_dispersion$sigma_log_r_boundarycarries the boundary test and a fit that fails it warns.What the penalty reaches on this block appears to be the boundary rather than the calibration. Measured on 20 seeds of that fixture at 8 species with
c(U, alpha) = c(1, 0.05): asigma_log_rof 0.01-0.06 lifts by an order of magnitude and a seed that stopped at a singular marginal Hessian under pure ML converges and covers, while paired coverage holds at 17 of 19 with the same two seeds missing, both of them atsigma_log_raround 0.2 where the penalty is weak. The fits that were already calibrated take a small systematic shift (mu_log_rby -0.006, p = 0.001; SEs a median 4.2% narrower). Hence theNULLdefault: it is a lever for a fit whose dispersion variance came back near zero or that failed outright, rather than a correction expected to hold across fits.When both this and
omega_sigma_priorare set they must be equal: the engine applies one Penalized-Complexity prior across every block it regularizes. Ignored for Poisson / ZIP.- verbose
Unused (kept for backward compatibility); the engine is silent.
Value
A list of class nmix_re_fit: mu_lambda, mu_p (community
means), vcov (their joint covariance from the AGHQ marginal Hessian,
(p_lambda + p_p) square; marginalizes the community-covariance
uncertainty rather than plugging in Sigma), Sigma_lambda, Sigma_p
(community covariances), b_lambda, b_p (per-species BLUP deviations,
n_species rows), log_lik (AGHQ marginal), converged, K_max,
n_quad, lkj_eta, and (when mixture = "NB") the dispersion summaries:
mu_log_r (community-mean log-dispersion; its SE is the trailing vcov
diagonal), sigma_log_r (the per-species log-dispersion SD), b_logr
(per-species deviations), r_s (per-species sizes
\(\exp(\mu_{\log r} + b^{\log r}_s)\)), and r equal to
\(\exp(\mu_{\log r})\) (the community-mean size, the LogNormal median).
References
Royle, J. A. (2004). N-mixture models for estimating population size from
spatially replicated counts. Biometrics 60, 108-115.
Doser, J. et al. (2023). spAbundance. msNMix().
See also
nmix_laplace() (single species), nmix_site_marginal()
(the per-species marginal primitive), tulpa_re_aghq() (the shared
random-effect integrator).