Skip to contents

ridge_path() refits the same model across a grid of loading-ridge penalty scales (tau, i.e. gllvmTMBcontrol(loading_ridge = tau)) and reports, for every trait, how the largest loading and its communality move as the penalty weakens (tau growing toward Inf, i.e. plain maximum likelihood with no ridge).

Usage

ridge_path(
  formula,
  data,
  family,
  tau = c(0.5, 1, 2, 4, 8, Inf),
  unit = NULL,
  trait = "trait",
  weights = NULL,
  missing = miss_control(),
  control = gllvmTMBcontrol(),
  ...
)

Arguments

formula, data, family, unit, trait, weights, missing

Passed to gllvmTMB() at every grid point, exactly as you would call it directly. unit has no default – it must name the sampling-unit column, matching gllvmTMB()'s own required argument.

tau

Numeric vector of ridge scales to sweep. Order does not matter: the function sorts internally, both for refitting and for the printed classification. Every entry must be a positive number; Inf is allowed and requests plain ML. Default c(0.5, 1, 2, 4, 8, Inf).

control

A gllvmTMBcontrol() object providing every OTHER setting (n_init, se, warn_runaway, ...). Its own loading_ridge / aghq_ridge value is overridden at every grid point and does not need to be set. The estimator is always "ml": loading_ridge cannot be combined with estimator = "mspl" (see gllvmTMB()).

...

Passed to gllvmTMB() at every grid point.

Value

A data frame of class c("gllvmTMB_ridge_path", "data.frame") with one row per tau x trait combination:

tau

The ridge scale for this row's refit.

trait

Trait name.

max_loading

The largest |loading| for this trait across the model's reduced-rank blocks at this tau.

communality

This trait's between-unit communality at this tau (from extract_communality(), level = "unit"); NA if unavailable.

logLik_at_map

The UNPENALISED log-likelihood evaluated at the penalised (MAP) point – not a maximum for any finite tau, so it is not comparable across tau as a model-selection criterion. At tau = Inf this is the ordinary maximum log-likelihood.

convergence

The optimiser's convergence code (0 = converged); NA if the refit errored.

fit_error

The error message if this grid point's refit failed outright; NA otherwise.

Details

This is a SENSITIVITY diagnostic, never an identification certificate. A ridge that stabilises a fit does not prove the underlying model is identified; it only prevents the optimiser from drifting to an unbounded point. The path lets you tell two situations apart that a single fit cannot: a trait whose loading and communality settle down as the penalty weakens is behaving like an ordinary, data-determined estimate; a trait that keeps moving toward the boundary as the penalty weakens is one whose finite estimate under any single tau is being determined by the penalty, not by the data.

Every grid point is a COLD refit: each tau starts from the model's own default initial values, not from the previous grid point's solution. This trades some speed for comparability across tau – a warm-started path could stay near one local optimum across the whole grid and never reveal that a later tau has a different, better optimum, which would understate exactly the instability this function exists to detect.

print() classifies each trait using a SIGNED statistic – a shrinking or flat loading is always "interior", regardless of magnitude; only a substantial POSITIVE move counts as "penalty-determined". Two comparisons are possible, chosen automatically per trait:

A converged tau = Inf point is available

The largest finite-tau loading is compared directly to the Inf loading (the plain signed relative change). A blow-up there – exactly what the paragraph above calls "moving toward boundary" – is compared against boundary_rel_thresh (default 0.10, i.e. a >10% increase from the last finite tau to Inf). This comparison is never skipped when a converged Inf point exists: it is the diagnostic the previous paragraph promises.

No converged tau = Inf point is available

The last two finite-tau grid points are compared using the log-log slope (elasticity) d(log loading) / d(log tau), not the raw relative change. The raw relative change decays like 1/tau for a fixed absolute grid spacing even when a trait is genuinely still moving – a tau = c(2000, 2100) pair (a 1.05x ratio) gives a still-growing trait only a 5% raw change, an artifact of the grid geometry rather than the trait's behaviour. The elasticity is invariant to that spacing (for loading ~ tau^k it recovers k exactly at any two grid points) and is compared against elasticity_thresh (default 0.10).

Both are heuristics, not formal tests; see print.gllvmTMB_ridge_path's arguments to adjust either threshold.

tau = Inf requests a plain maximum-likelihood refit with no ridge at all. That refit can legitimately fail to converge, or converge to an extreme loading, for exactly the traits this function exists to flag – that failure or extremity is itself part of the diagnostic evidence, not a bug to work around. fit_error records the message when a grid point's refit errors outright, and the row's other columns are NA for that point; the classifier then falls back to the finite-tau elasticity comparison, since a failed Inf refit contributes no loading to compare.

See also

screen_gllvmTMB() for the pre-fit response screen this complements; the loading ridge itself is documented at gllvmTMBcontrol()'s loading_ridge argument.

Examples

if (FALSE) { # \dontrun{
n <- 40
df <- data.frame(
  unit = factor(seq_len(n)),
  a = rbinom(n, 1, 0.5),
  b = rbinom(n, 1, 0.5)
)
path <- ridge_path(
  traits(a, b) ~ 1 + latent(1 | unit, d = 1),
  data = df,
  family = binomial(),
  unit = "unit",
  tau = c(1, 2, 4, Inf)
)
path
} # }