pub struct PenaltyNullSplit { /* private fields */ }Expand description
The λ-invariant declared-null subspace of a penalty reparameterization, materialized in both coefficient frames (#2454).
§The invariant this type exists to hold
gam.reparam keeps only balanced-penalty eigendirections above a relative
rank tolerance and rebuilds the penalty the model applies as
S̃(λ) = E(λ)ᵀE(λ) on that subspace alone. Everything the criterion is
made of is a function of S̃: the inner solve minimizes −ℓ + ½βᵀS̃β,
H = −∇²ℓ + S̃, and the reported penalty energy is ‖E β̂‖².
A per-block S_k whose own root rank exceeds the split’s penalized rank
therefore describes a DIFFERENT penalty. Two things go wrong if one is used
anywhere the criterion is differentiated or normalized:
½ λ_k β̂ᵀS_kβ̂charges β̂’s energy in directionsS̃never penalized — andβ̂is free there, so that energy isO(1)and∂/∂ρ_kmultiplies it byλ_k. That is an additivec·λin the outer gradient, invisible at‖ρ‖ ≤ 1and sign-flipping it a dozen e-folds up.−½log|Σ_k λ_k S_k|₊charges MORE directions than½log|H|can ever inflate, becauseH’s penalty part isS̃. The two halves of the LAML ratio then saturate at different rates and the criterion acquires an asymptotic slope of½(rank(S̃) − rank(S))per unit ρ — unbounded below, with no interior optimum and no certifiable λ=∞ rail.
Projecting restores the identity every outer derivative is built on:
Σ_k λ_k (Π S_k Π) = Π (Σ_k λ_k S_k) Π = S̃(λ), and because Π is
λ-invariant by construction, ∂S̃/∂ρ_k = λ_k · Π S_k Π exactly. One penalty
object then serves the value, the quadratic, the per-block scores, the
tr(H⁻¹Ḣ_k) drift, the log|S|₊ and its rank, and the outer Hessian.
A None basis means “nothing declared null” and every project is the
identity, which is the case for any penalty whose numerical rank agrees
with the split’s.
Implementations§
Source§impl PenaltyNullSplit
impl PenaltyNullSplit
Sourcepub fn identity() -> Self
pub fn identity() -> Self
The identity split: nothing is declared null, every projection is a no-op. This is what a penalty system with no dense reparameterization (Kronecker marginal grids, sparse-native identity frames) carries.
Sourcepub fn declared_null_dim(&self) -> usize
pub fn declared_null_dim(&self) -> usize
The number of declared-null directions, or 0 for the identity split.
Sourcepub fn basis(&self, frame: PenaltyFrame) -> Option<&Array2<f64>>
pub fn basis(&self, frame: PenaltyFrame) -> Option<&Array2<f64>>
The declared-null basis in frame, if this split declares anything.
Sourcepub fn project_canonical(
&self,
penalty: &CanonicalPenalty,
frame: PenaltyFrame,
) -> Result<CanonicalPenalty, EstimationError>
pub fn project_canonical( &self, penalty: &CanonicalPenalty, frame: PenaltyFrame, ) -> Result<CanonicalPenalty, EstimationError>
Π S_k Π for a canonical penalty expressed in frame.
The penalty is returned unchanged when this split declares nothing null, or when the basis does not match the penalty’s dimension — a shape disagreement the projection must not paper over by guessing.
Sourcepub fn project_coordinate(
&self,
coord: &PenaltyCoordinate,
frame: PenaltyFrame,
) -> PenaltyCoordinate
pub fn project_coordinate( &self, coord: &PenaltyCoordinate, frame: PenaltyFrame, ) -> PenaltyCoordinate
Π S_k Π for a solver-side penalty coordinate expressed in frame.
Trait Implementations§
Source§impl Clone for PenaltyNullSplit
impl Clone for PenaltyNullSplit
Source§fn clone(&self) -> PenaltyNullSplit
fn clone(&self) -> PenaltyNullSplit
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for PenaltyNullSplit
impl RefUnwindSafe for PenaltyNullSplit
impl Send for PenaltyNullSplit
impl Sync for PenaltyNullSplit
impl Unpin for PenaltyNullSplit
impl UnsafeUnpin for PenaltyNullSplit
impl UnwindSafe for PenaltyNullSplit
Blanket Implementations§
impl<T> Allocation for T
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> DistributionExt for Twhere
T: ?Sized,
impl<T> DistributionExt for Twhere
T: ?Sized,
impl<T, U> Imply<T> for U
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Pointable for T
impl<T> Pointable for T
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.