pub struct GlmLikelihoodSpec {
pub spec: LikelihoodSpec,
pub scale: LikelihoodScaleMetadata,
}Expand description
Explicit GLM likelihood specification: response/link spec plus scale semantics.
spec is the canonical (ResponseFamily, InverseLink) selector. scale
records how the scale parameter is handled (profiled Gaussian sigma, fixed
dispersion, fixed/estimated Gamma shape). The Gamma shape is mutated in
place during PIRLS via with_gamma_shape; preserving that field on this
struct is what lets the inner solver thread the estimated shape into
deviance / log-likelihood / weight evaluation without a separate side
channel.
Fields§
§spec: LikelihoodSpec§scale: LikelihoodScaleMetadataImplementations§
Source§impl GlmLikelihoodSpec
impl GlmLikelihoodSpec
Sourcepub fn canonical(spec: LikelihoodSpec) -> Self
pub fn canonical(spec: LikelihoodSpec) -> Self
Build a GlmLikelihoodSpec from a LikelihoodSpec, deriving the
canonical default scale metadata for the response family.
pub fn link_function(&self) -> LinkFunction
pub fn fixed_phi(&self) -> Option<f64>
Sourcepub fn coefficient_covariance_scale(&self, profiled_gaussian_phi: f64) -> f64
pub fn coefficient_covariance_scale(&self, profiled_gaussian_phi: f64) -> f64
Multiplier converting the stored unscaled inverse penalized Hessian
H⁻¹ into the reported coefficient covariance Vb = H⁻¹ · scale.
§Invariant
Vb is the inverse of the Hessian of the actual penalized objective the
inner solver minimizes. The stored Hessian is always assembled as
H = XᵀWX + S_λ, with the penalty S_λ added unscaled (see
pirls::penalty::add_to_hessian). Whether H is already that true
objective Hessian — and hence whether any post-hoc dispersion multiply is
warranted — is decided entirely by what the IRLS working weight W
carries:
-
Working weight already carries the reciprocal dispersion / full Fisher information. Then
H = Xᵀ(W_sf/φ)X + S_λalready equals the true penalized Hessian (e.g. mgcv’sXᵀW_sfX/φ + S_λfor Gamma), soVb = H⁻¹and the scale is exactly1.0. This is the case for Gamma (W = prior·shape = prior/φ), Tweedie (W = prior·μ^{2−p}/φ), Beta and Negative-Binomial (the working weight is the complete fixed-scale Fisher information), and the fixed-scale exponential families Poisson/Binomial (φ ≡ 1). MultiplyingH⁻¹by the dispersion again for any of these double-counts it and shrinks every SE by√dispersion. -
Working weight is scale-free (
W = priorweights, the profiled Gaussian convention). Then the data term carries an implicit unit scale andH = XᵀPX + S_λis the Hessian of½·(scaled deviance)·σ²⁻¹without theσ². The correct covariance restores it:Vb = H⁻¹ · σ̂². Only this branch returns a non-unit scale.
profiled_gaussian_phi is the profiled residual variance σ̂² and is
consulted only for the scale-free profiled-Gaussian branch; every
other family ignores it. This deliberately does NOT touch
dispersion() / dispersion_from_likelihood, which still report the
response-level observation noise (1/shape for Gamma, 1/(1+φ) for
Beta, …) used by predictive-interval construction — a distinct quantity
from the coefficient-covariance scale defined here.
pub fn gamma_shape(&self) -> Option<f64>
Sourcepub fn with_gamma_shape(self, shape: f64) -> Self
pub fn with_gamma_shape(self, shape: f64) -> Self
Mutate the Gamma shape parameter in place while preserving the rest of the spec. The shape only takes effect for Gamma families; for other families the scale metadata is left untouched.
Sourcepub fn beta_phi_is_estimated(&self) -> bool
pub fn beta_phi_is_estimated(&self) -> bool
Whether the Beta-regression precision phi is estimated from data.
Sourcepub fn with_beta_phi(self, phi: f64) -> Self
pub fn with_beta_phi(self, phi: f64) -> Self
Mutate the Beta precision phi in place, on BOTH the family variant
(where every PIRLS weight / deviance / log-likelihood expression reads it
via ResponseFamily::Beta { phi }) and the scale metadata (the
estimated-vs-fixed contract). No-op for non-Beta families. The inner
solver calls this once per inner solve after a moment estimate of phi
from the working residuals, so the IRLS weights Var(y)=mu(1-mu)/(1+phi)
reflect the true precision rather than the phi=1 seed (issue #567).
Sourcepub fn tweedie_phi_is_estimated(&self) -> bool
pub fn tweedie_phi_is_estimated(&self) -> bool
Whether the Tweedie exponential-dispersion phi is estimated from data.
Sourcepub fn with_tweedie_phi(self, phi: f64) -> Self
pub fn with_tweedie_phi(self, phi: f64) -> Self
Mutate the Tweedie dispersion phi in place. Unlike Beta, the Tweedie
power p (not phi) is what is carried on the ResponseFamily::Tweedie
variant; the dispersion lives purely in the scale metadata and is read by
the IRLS weight (prior·μ^{2−p}/phi) through fixed_phi(). So updating
the metadata here is sufficient to thread the estimated phi into every
weight / covariance expression. No-op for non-Tweedie families (issue
#771).
Sourcepub fn negbin_theta_is_estimated(&self) -> bool
pub fn negbin_theta_is_estimated(&self) -> bool
Whether the Negative-Binomial overdispersion theta is estimated from
data (issue #802).
Sourcepub fn with_negbin_theta(self, theta: f64) -> Self
pub fn with_negbin_theta(self, theta: f64) -> Self
Mutate the Negative-Binomial overdispersion theta in place, on BOTH the
family variant (where every PIRLS weight / deviance / log-likelihood
expression reads it via ResponseFamily::NegativeBinomial { theta }) and
the scale metadata (the estimated-vs-fixed contract). No-op for non-NB
families. The inner solver calls this once per inner solve after a
maximum-likelihood estimate of theta from the working residuals, so the
IRLS weight W = μθ/(θ+μ) and the variance Var(y)=mu+mu^2/theta reflect
the data’s overdispersion rather than the seed theta (issue #802). This
mirrors with_beta_phi exactly — both keep the family variant and the
scale metadata as two synchronized views of one estimated parameter.
No-op for a user-fixed theta (theta_fixed = true /
FixedNegBinTheta, issue #983): the held value is the contract, and
this mutator must never let an estimation path overwrite it — the
PIRLS refresh gate (negbin_theta_is_estimated()) already skips the
call, this enforces the same invariant at the data itself.
Sourcepub fn negbin_theta(&self) -> Option<f64>
pub fn negbin_theta(&self) -> Option<f64>
The estimated Negative-Binomial theta, read from the family variant
(the canonical store), or None for non-NB families.
Sourcepub fn with_negbin_theta_frozen_for_search(self, theta: f64) -> Self
pub fn with_negbin_theta_frozen_for_search(self, theta: f64) -> Self
Produce a copy of this spec with the Negative-Binomial overdispersion
theta PINNED at theta for the duration of the smoothing-parameter
(λ) search (#1082). Converts an EstimatedNegBinTheta spec into the
statistically-identical FixedNegBinTheta form (theta_fixed = true),
which gates off the per-inner-solve ML refresh in
GamWorkingModel::update_with_curvature (its guard is
negbin_theta_is_estimated()).
Rationale: with θ estimated, the inner solver re-derives θ from each
outer iterate’s warm-start η, so θ — and hence the NB working response,
deviance and penalty-logdet that feed the REML criterion — drifts every
outer evaluation. The outer optimizer then chases a moving target and the
projected-gradient convergence test never trips, grinding the loop to
max_iter (the #1082 negative-binomial tensor timeout). Holding θ fixed
across the λ-search makes the REML objective F(ρ) = REML(ρ, θ_frozen) a
genuine stationary function of ρ, so the loop converges in a handful of
iterations — and θ is still ML-refreshed at the single final, reported fit
(the refine_dispersion_at_converged_eta = true accept-fit), exactly as
the function-level docs require (“estimate the scale at the converged fit,
not inside the λ search; mgcv likewise”). No-op for non-NB families and
for an already user-fixed θ.
Trait Implementations§
Source§impl Clone for GlmLikelihoodSpec
impl Clone for GlmLikelihoodSpec
Source§fn clone(&self) -> GlmLikelihoodSpec
fn clone(&self) -> GlmLikelihoodSpec
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for GlmLikelihoodSpec
impl Debug for GlmLikelihoodSpec
Source§impl<'de> Deserialize<'de> for GlmLikelihoodSpec
impl<'de> Deserialize<'de> for GlmLikelihoodSpec
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl PartialEq for GlmLikelihoodSpec
impl PartialEq for GlmLikelihoodSpec
Source§fn eq(&self, other: &GlmLikelihoodSpec) -> bool
fn eq(&self, other: &GlmLikelihoodSpec) -> bool
self and other values to be equal, and is used by ==.