Skip to main content

gam_models/
transformation_normal.rs

1//! Conditional transformation model: estimate h(y|x) such that h(Y|x) ~ N(0,1).
2//!
3//! Given a response variable y and covariates x with a pre-built covariate design
4//! operator, this family estimates a smooth monotone transformation h(y | x) mapping
5//! the conditional distribution of Y|x onto a standard normal.
6//!
7//! The response-direction basis is `[1, I_1(y), ..., I_K(y)]`, tensored with an
8//! arbitrary covariate design operator. Column 0 is an unconstrained location
9//! component `b(x)`. The I-spline columns are direct non-negative shape
10//! functions `α_k(x)`, giving the SCOP representation
11//! `h(y, x) = b(x) + ε·(y−median_y) + Σ_k I_k(y) α_k(x)` and
12//! `h'(y, x) = ε + Σ_k M_k(y) α_k(x)`. Monotonicity is exact:
13//! the fixed derivative floor `ε` keeps the change-of-variables log-density
14//! away from the `log(0)` singularity, while the non-negative M-spline basis
15//! and the factored Khatri-Rao cone `α_k(x_i) >= 0` supply the learned shape.
16//!
17//! The log-likelihood per observation is the finite-support normalized
18//! change-of-variables density for a standard normal target:
19//!
20//!   ℓ_i = -½ h_i² + log(h'_i) - log(Φ(h_U(x_i)) - Φ(h_L(x_i)))
21//!
22//! where `h_i = b(x_i) + ε·(y_i−median_y) + Σ_k I_k(y_i) α_k(x_i)`
23//! and `h'_i = ε + Σ_k M_k(y_i) α_k(x_i)`. The endpoint normalizer is
24//! required because the I-spline response basis saturates at finite support
25//! values rather than mapping onto the full real line.
26
27mod alo_replay;
28mod endpoint_normalizer;
29
30// Shared imports re-exported so every concern submodule pulls them through
31// `use super::*;` without re-listing. `pub(crate)` lets the child globs see them.
32pub use alo_replay::{
33    TransformationNormalAloRowGeometry, TransformationNormalAloRowInput,
34    transformation_normal_alo_row_geometry,
35};
36pub(crate) use endpoint_normalizer::{
37    LogNormalCdfDiffDerivatives, endpoint_chain_first, endpoint_chain_fourth,
38    endpoint_chain_second, endpoint_chain_third, log_normal_cdf_diff,
39    log_normal_cdf_diff_derivatives,
40};
41
42pub(crate) use crate::custom_family::{
43    BlockWorkingSet, BlockwiseFitOptions, CustomFamily, CustomFamilyBlockPsiDerivative,
44    CustomFamilyHyperLayout, CustomFamilyJointHyperModeSelection,
45    CustomFamilyPsiDerivativeOperator, CustomFamilyWarmStart, ExactNewtonJointGradientEvaluation,
46    ExactNewtonJointHessianWorkspace, FamilyEvaluation, JointHessianSourcePreference,
47    MaterializablePsiDerivativeOperator, MaterializationIntent, ParameterBlockSpec,
48    ParameterBlockState, PenaltyMatrix, SharedCustomFamilyHyperLayout,
49    evaluate_custom_family_joint_hyper_best_mode_shared, fit_custom_family,
50    fit_custom_family_fixed_log_lambdas_from_mode_selection,
51    fit_custom_family_user_fixed_log_lambdas_from_mode_selection,
52};
53pub(crate) use crate::fit_orchestration::drivers::{
54    ExactJointEfsEvaluation, ExactJointEvaluation, ExactJointHyperSetup, SpatialFitProvenance,
55    freeze_term_collection_from_design, optimize_spatial_length_scale_exact_joint,
56    spatial_length_scale_term_indices,
57};
58pub(crate) use crate::inference::model::{
59    TRANSFORMATION_SCORE_PIT_CLIP_EPS, TransformationScoreCalibration,
60};
61pub(crate) use crate::model_types::UnifiedFitResult;
62pub(crate) use crate::penalized_projection::solve_penalizedweighted_projection;
63pub(crate) use crate::probability::standard_normal_quantile;
64pub(crate) use crate::spatial_psi_bridge::build_block_spatial_psi_derivatives;
65pub(crate) use gam_linalg::faer_ndarray::{fast_ab, fast_abt, fast_atb};
66pub(crate) use gam_linalg::matrix::{
67    DenseDesignMatrix, DenseDesignOperator, DesignMatrix, FiniteSignedWeightsView, LinearOperator,
68    PsdWeightsView, SymmetricMatrix, dense_rowwise_kronecker,
69};
70pub(crate) use gam_problem::{
71    ExactNewtonJointPsiSecondOrderTerms, ExactNewtonJointPsiTerms, ExactNewtonJointPsiWorkspace,
72};
73pub(crate) use gam_terms::basis::initializewiggle_knots_from_seed;
74pub(crate) use gam_terms::basis::{
75    BasisOptions, Dense, KnotSource, create_basis, create_ispline_derivative_dense,
76    ispline_function_penalties,
77};
78pub(crate) use gam_terms::smooth::{
79    SpatialLengthScaleOptimizationOptions, SpatialLogKappaCoords, TermCollectionDesign,
80    TermCollectionSpec,
81};
82// #1521: relocated DOWN into gam_terms::smooth (was drivers::build_term_collection_design).
83pub(crate) use gam_problem::{
84    DriftDerivResult, HyperOperator, ProjectedFactorCache, ProjectedFactorKey,
85};
86pub(crate) use gam_runtime::resource::{MatrixMaterializationError, ResourcePolicy};
87pub(crate) use gam_terms::smooth::build_term_collection_design;
88pub(crate) use ndarray::{Array1, Array2, ArrayView1, ArrayView2, ArrayViewMut2, s};
89pub(crate) use std::cell::RefCell;
90pub(crate) use std::sync::{Arc, Mutex, OnceLock};
91
92mod config;
93mod custom_family;
94mod error;
95mod family;
96mod fit;
97mod kronecker_design;
98mod operators;
99mod penalty_scaling;
100mod psi_operator;
101mod response_basis;
102mod scop_curvature;
103mod scop_density;
104mod scop_psi;
105mod warm_start;
106
107pub use config::*;
108pub use error::*;
109pub use family::*;
110pub use fit::*;
111pub(crate) use kronecker_design::*;
112pub(crate) use operators::*;
113pub(crate) use penalty_scaling::*;
114pub use psi_operator::*;
115pub use response_basis::effective_response_num_internal_knots;
116pub(crate) use response_basis::{
117    assert_rowwise_kronecker_dimensions, build_response_basis, response_endpoint_value_bases,
118    response_floor_offsets,
119};
120pub use scop_density::*;
121pub(crate) use warm_start::*;
122
123#[cfg(test)]
124mod tests;