Skip to content

Loss-library test coverage map

This doc cross-references every public symbol exported from torchregress.losses with the dedicated test class that locks its behavior and the discriminator invariant the test guards.

When you change a loss internals formula, factory, or protocol, the table below tells you which tests/losses/test_*.py file (and which Test* class inside it) is the right entry point. The invariants listed are the mathematical or structural promises the test enforces — failing any of them is the canonical way a contract break shows up in CI.

Conventions

  • DEDICATED — the symbol has a Test<S> class (or top-level test_* function) that locks in its contract.
  • DIRECT-LIGHT — covered indirectly via the per-symbol regression suite (test_loss_fixes.py, test_sls_internals.py, test_eiv_internals.py, test_functional_wrappers.py, test_indirect_utilities.py), each one introduced to fill gaps in the per-class suites.
  • INDIRECT — exercised only by other tests' incidental usage. Marked so refactors catch them on the next review pass.

Master matrix

Note: Test* class names are best-effort. If a refactor renames or splits a class, run grep '^class Test' tests/losses/<file>.py for the current names rather than trusting this table verbatim. The test-file column is more stable -- use that as the canonical entry point.

Symbol Module Test file Test class / function Discriminator invariant
BaseLoss base.py tests/losses/test_base.py TestBaseLoss _reduce honours mean/sum/none/min/max; _reduce_with_mask filters & re-normalises only the masked entries
RegressionLoss base.py tests/losses/test_base.py TestRegressionLoss forward raises NotImplementedError until subclassed; reduction flows through to subclasses
DistributionLoss base.py tests/losses/test_base.py TestDistributionLoss Flags _extract_distribution_parameters and _calculate_nll as abstract; concrete subclass returns scalar
WeightedLossWrapper base.py tests/losses/test_base.py TestWeightedLossWrapper + tests/losses/test_loss_fixes.py::TestWeightedLossWrapperPreservesReduction Honours the wrapped loss' pre-set reduction (sum/none); auto-mean fallback only when no prior reduction
WeightedMSELoss base.py tests/losses/test_base.py TestWeightedLossWrapper MSE wrapping honours mask & weights
WeightedL1Loss base.py tests/losses/test_base.py TestWeightedLossWrapper L1 wrapping honours reduction inheritance
WeightedHuberLoss base.py tests/losses/test_base.py::TestWeightedClassificationLosses (slip) + test_functional_wrappers.py TestWeightedLossWrapper Huber's delta parameter passes through unchanged
WeightedCrossEntropyLoss base.py tests/losses/test_base.py TestWeightedClassificationLosses Per-sample weights propagate to native CrossEntropyLoss
WeightedNLLLoss base.py tests/losses/test_base.py TestWeightedClassificationLosses Mask-filtered per-sample NLL matches native NLLLoss mean
BalancedMSELoss balanced_mse.py tests/losses/test_balanced_mse.py (per-class suite) Effective MSE under target-density weights
BinReweightedMSELoss balanced_mse.py tests/losses/test_balanced_mse.py (per-class suite) Binned inverse-frequency weighted MSE with automatic edges
BalancedMSEBMC balanced_mse_bmc.py tests/losses/test_balanced_mse_bmc.py (per-class suite) Batch-coupled noise-adaptive Balanced MSE (BMC), label prior + sigma fitting, hand-formula parity
RankSimLoss rank_sim.py tests/losses/test_rank_sim.py (per-class suite) Ranking-similarity regularizer with blackbox rank gradient; hand-computable ranking checks
BetaNLLLoss beta_nll.py tests/losses/test_beta_nll.py + tests/losses/test_functional_wrappers.py TestBetaNLLLossWrapper Detached var⁻ᵝ rescaling; reduces to vanilla Gaussian NLL at β=0
beta_nll_loss beta_nll.py tests/losses/test_functional_wrappers.py TestBetaNLLLossWrapper::test_parity_with_class Functional wrapper parity with BetaNLLLoss on tuple & concat inputs
CensoredGaussianNLLLoss censored.py tests/losses/test_censored.py (per-class) Censoring mask propagates to NLL
CensoredQuantileLoss censored.py tests/losses/test_censored.py (per-class) Pinball loss with left-/right-censoring adjustments
AFTLoss censored.py tests/losses/test_censored.py (per-class suite) Accelerated-failure-time log-location residual
CQR conformal.py tests/losses/test_conformal.py TestCQR + tests/losses/test_loss_fixes.py::TestCQRCalibrationInvariants Finite-sample quantile thresholds; alpha restoration after calibrate; empty/all-masked calibration raises; calibrated interval is [q_lo - q_hat, q_hi + q_hat]
CTI conformal.py tests/losses/test_conformal.py TestCTI Smallest density-level-set interval via grid search
SLSConformal conformal.py tests/losses/test_sls_conformal.py (per-class) Score = G(X,Y) / q_τ(X); interval from frontier level set
ConformalLoss conformal.py tests/losses/test_conformal.py TestSplitConformal, TestCQR, etc. Method-routes to underlying predictor; pinball training loss for cqr/uacqr; rejects unknown kwargs
ConformalPredictor conformal.py tests/losses/test_conformal.py (base for Test*Conformal) Virtual _compute_scores/_build_intervals; Mondrian + normalised + weighted composable features
LevelSetConformalPredictor conformal.py tests/losses/test_conformal.py (via TestCTI, TestDistributionalConformal, TestSLSConformal) Shared _grid_search_level_set utility
LocalConformal conformal.py tests/losses/test_conformal.py TestLocalConformal + tests/losses/test_loss_fixes.py::TestLocalConformalSentinelFallback Sentinel True column guards against underflow when cum-weights miss 1-α
LocalConformalMAD conformal.py tests/losses/test_conformal.py TestLocalConformalMAD + tests/losses/test_loss_fixes.py::TestLocalConformalSentinelFallback Same sentinel behaviour under MAD scaling
SplitConformal conformal.py tests/losses/test_conformal.py TestSplitConformal |residual| score; symmetric ŷ ± q_hat interval
UACQR conformal.py tests/losses/test_conformal.py (per-class) CQR with width-normalised scores
DensityConformal conformal.py tests/losses/test_conformal.py TestDensityConformal KDE-adaptive score normalisation
DistributionalConformal conformal.py tests/losses/test_conformal.py TestDistributionalConformal PIT-based score; ICDF interval construction
MonteCarloConformal conformal.py tests/losses/test_conformal.py TestMonteCarloConformal MC sample mean/median + std normalisation
MultiTargetConformal conformal.py tests/losses/test_conformal.py (per-class) Per-dimension calibration independence
PrevalenceAdjustedCP conformal.py tests/losses/test_conformal.py TestPrevalenceAdjustedCP Group-prevalence scales miscoverage rate
R2CConformal conformal.py tests/losses/test_conformal.py TestR2CConformal APS-style sorted-bin inclusion
BaseEIVLoss eiv.py tests/losses/test_eiv_internals.py TestBaseEIVLossInternals _prepare_covariance_from_sigma interpretation of scalar / 1d / 2d / 3d sigma; explicit() factory returns adapter
EnsembleEIVLoss eiv.py tests/losses/test_eiv.py TestEIVLoss::test_ensemble_eiv_loss Gaussian-perturbation ensemble averaging
FunctionalEIVLoss eiv.py tests/losses/test_eiv.py TestEIVLoss::test_functional_eiv_loss + TestEIVLossNumericalStability Jacobian-variance + NLL; analytical/mc/hybrid branches finite & monotonic in n_samples
InputNoiseBinnedPDFLoss eiv.py (specialized class — INDIRECT, exercised via test_eiv.py) — Binned-PDF marginalisation with Ordinal base
LatentMarginalizationLoss eiv.py tests/losses/test_eiv_correctness.py TestEIVCorrectness::test_latent_marginalization_gaussian_prior + test_latent_marginalization_custom_sampler Analytical Gaussian-prior posterior and custom-sampler posterior paths; log-mean-exp marginalisation
InputNoiseMDNLoss eiv.py (per-class — INDIRECT via test_mdn.py) — MDN base loss + marginalisation
NoisyInputPredictor eiv.py tests/losses/test_eiv_internals.py TestNoisyInputPredictor forward(x) returns mean over MC perturbations; antithetic yields distinct rows; non-tensor model is rejected
OrthogonalDistanceRegressionLoss eiv.py tests/losses/test_eiv.py TestEIVLoss::test_odr_loss + TestEIVLossNumericalStability::test_odr_gradient_flow Latent-x optimisation step (approx) recovers Mahalanobis sum
StructuralEIVLoss eiv.py tests/losses/test_eiv.py TestEIVLoss::test_structural_eiv_loss Cross-covariance σ_xy propagates through NLL
EvidentialRegressionLoss evidential.py tests/losses/test_evidential.py TestEvidentialRegressionLoss NIG posterior + KL regularisation
ExpectileLoss expectile.py tests/losses/test_expectile.py + tests/losses/test_functional_wrappers.py TestExpectileLoss + TestExpectileLossWrapper τ=0.5 collapses to MSE; asymmetric weights τ/1-τ
expectile_loss expectile.py tests/losses/test_functional_wrappers.py TestExpectileLossWrapper Parity with ExpectileLoss class
MultiExpectileLoss expectile.py tests/losses/test_non_gaussian_consistency.py TestExpectileContract Average across expectile levels per sample
ExpectileCrossoverLoss expectile.py tests/losses/test_non_gaussian_consistency.py TestExpectileContract Crossover penalty on pairs of predictands
FaithfulGaussianLoss faithful_gaussian.py tests/losses/test_faithful_gaussian.py (per-class) Mean / variance decoupled layers
GaussianCRPSLoss gaussian.py tests/losses/test_gaussian.py TestGaussianLosses::test_gaussian_crps_loss_matches_metric Analytic CRPS matches shared crps_gaussian metric
GaussianNLLLoss gaussian.py tests/losses/test_gaussian.py TestGaussianLosses::test_gaussian_nll_loss + test_gaussian_consistency.py Accepts tuple / concat / mean-only formats; reduction modes
LowRankGaussianLoss gaussian.py tests/losses/test_gaussian.py TestGaussianLosses::test_low_rank_gaussian_loss cov_factor @ cov_factor.T + diag(cov_diag) NLL
MultivariateGaussianLoss gaussian.py tests/losses/test_gaussian.py + consistency suite TestGaussianLosses::test_multivariate_gaussian_loss Cholesky NLL with jitter; respects shape contracts
create_gaussian_nll gaussian.py tests/losses/test_indirect_utilities.py TestCreateGaussianNll Factory routes by covariance_type; full ≈ multivariate route identity; use_mse_for_unit_variance → WeightedMSELoss
GaussianWassersteinBoundLoss gaussian_wasserstein.py tests/losses/test_gaussian_wasserstein.py + consistency hybrid tests (per-class) |μ-μ̂|² + |Σ½-Σ̂½|_F² in 4 covariance parameterisations
gaussian_wasserstein_bound_loss gaussian_wasserstein.py tests/losses/test_functional_wrappers.py TestGaussianWassersteinBoundWrapper Functional parity across diag / covariance / sqrt / cholesky modes
symmetric_spd_matrix_sqrt gaussian_wasserstein.py tests/losses/test_indirect_utilities.py TestSymmetricSpsMatrixSqrt eigh-based sqrt: symmetric, S·S = Σ, eps floors singletons
DensityWeightedLoss imbalanced.py tests/losses/test_imbalanced.py (per-class) Target-density reweighting
FocalRLoss imbalanced.py tests/losses/test_imbalanced.py (per-class) Focal-style per-sample modulation
LDSLoss imbalanced.py tests/losses/test_imbalanced.py (per-class) Label-distribution-shift reweighting
PropensityWeightedLoss imbalanced.py tests/losses/test_imbalanced.py (per-class) Inverse-propensity weighting
get_regression_loss loss_registry.py tests/losses/test_loss_registry.py (per-class) Lookup by registry key
list_regression_losses loss_registry.py tests/losses/test_loss_registry.py (per-class) Sorted list of registered names
create_loss_from_config loss_registry.py tests/losses/test_loss_registry.py (per-class) YAML-style config construction with aliases
MixtureDensityLoss (re-exported as MixtureDensityLoss) mdn.py tests/losses/test_mdn.py (per-class) Full-cov Cholesky backward finite & differentiable
SLSLoss sls.py tests/losses/test_sls.py + consistency suite (top-level test_sls_loss_warmup_and_forward, etc.) Step-counter monotonic advance; warmup window; K>1 unfreeze gating
VolumePreservingFlow sls.py tests/losses/test_sls.py (round-trip) + tests/losses/test_sls_internals.py TestVolumePreservingFlow Invertibility: flow.inverse(flow(y)) == y; alternating half-mask per layer
MahalanobisFrontier sls.py tests/losses/test_sls_internals.py TestMahalanobisFrontierFull, TestMahalanobisFrontierLowRank Full-mode num_L_params = d(d+1)/2; low-rank default rank = ⌈√d⌉; G ≥ 0 invariant
UnionFrontier sls.py tests/losses/test_sls_internals.py TestUnionFrontier K-component MahalanobisFrontier list; freeze/unfreeze gating; mixture weights sum to 1
NormalizingFlowLoss nflows.py tests/losses/test_nflows.py (per-class) zuko-backed wrapper; loss wiring
ContrastiveFlowLoss nflows.py tests/losses/test_contrastive_nflows.py (per-class) Contrastive term
create_flow_model nflows.py (INDIRECT inside test_nflows.py) — Build flow from config
create_flow_loss nflows.py (INDIRECT inside test_nflows.py) — Build flow loss from config
create_contrastive_flow_loss nflows.py (INDIRECT — special optional) — Build contrastive flow loss
OrdinalCrossEntropyLoss ordinal.py tests/losses/test_ordinal.py (per-class) Label-smoothed ordinal CE
CumulativeLinkLoss ordinal.py tests/losses/test_ordinal.py (per-class) Cumulative-link logistic loss
NegativeBinomialNLLLoss poisson.py tests/losses/test_poisson.py (per-class) NB NLL with dispersion parameter
PoissonDevianceLoss poisson.py tests/losses/test_poisson.py (per-class) Poisson deviance residual
PoissonLikelihoodRatioLoss poisson.py tests/losses/test_poisson.py (per-class) LR loss vs. Poisson mean
ZeroInflatedPoissonNLLLoss poisson.py tests/losses/test_poisson.py (per-class) ZIP NLL with mixing parameter
PoissonGaussianLoss poisson_gaussian.py tests/losses/test_poisson_gaussian_convolution.py oracle + limits + gradcheck Poisson-Gaussian convolution (detector) NLL
PoissonGaussianContaminationMixtureLoss poisson_gaussian.py tests/losses/test_poisson_gaussian.py (per-class) + consistency Poisson+Gaussian NLL mixture
EnhancedPoissonGaussianContaminationMixtureLoss poisson_gaussian.py tests/losses/test_poisson_gaussian.py (per-class) + consistency Gain-offset mixture w/ learnable params
PoissonGaussianLikelihoodRatioLoss poisson_gaussian.py tests/losses/test_poisson_gaussian.py + consistency (per-class) LR mixture NLL
MultiQuantileLoss quantile.py tests/losses/test_quantile.py + tests/losses/test_non_gaussian_consistency.py TestMultiQuantileLoss Average across multiple quantiles per sample
QuantileCrossoverLoss quantile.py tests/losses/test_quantile.py + consistency TestQuantileLoss::test_quantile_crossover_constraint Crossover penalty Σᵢ max(fᵢ - fᵢ₊₁, 0)
QuantileLoss quantile.py tests/losses/test_quantile.py + tests/losses/test_functional_wrappers.py TestQuantileLoss, TestQuantileLossWrapper Asymmetric pinball; q=0.5 recovers MAE
quantile_loss quantile.py tests/losses/test_functional_wrappers.py TestQuantileLossWrapper Parity with QuantileLoss class
PseudoHuberLoss robust.py tests/losses/test_robust.py + consistency (per-class) Smooth L1 alternative
LogCoshLoss robust.py tests/losses/test_robust.py + consistency (per-class) Log-cosh residual
CharbonnierLoss robust.py tests/losses/test_robust.py + consistency (per-class) √(r²+ε²) stem
TukeyBiweightLoss robust.py tests/losses/test_robust.py + consistency (per-class) Biweight ψ-function
CauchyLoss robust.py tests/losses/test_robust.py + consistency (per-class) log(1+(r/c)²)
BarronLoss robust.py tests/losses/test_robust.py + consistency (per-class) Continuously-interpolated L2/L1 shape via α
AdaptiveRobustLoss robust.py tests/losses/test_robust.py + consistency (per-class) Learnable α/β/scale
CVaRLoss robust.py tests/losses/test_cvar.py (per-class) Tail-risk expectation above α
BoxCoxTransformLoss transforms.py tests/losses/test_transforms.py (per-class) Box-Cox transform + base loss
LogTransformLoss transforms.py tests/losses/test_transforms.py (per-class) log + base loss
SqrtTransformLoss transforms.py tests/losses/test_transforms.py (per-class) √ + base loss
TransformedTargetLoss transforms.py tests/losses/test_transforms.py (per-class) Generic transform wrapper
YeoJohnsonTransformLoss transforms.py tests/losses/test_transforms.py (per-class) Yeo-Johnson (handles non-positive targets)
CompoundPoissonLoss tweedie.py tests/losses/test_tweedie.py (per-class) Compound Poisson-Gamma (1 < p < 2)
GammaLoss tweedie.py tests/losses/test_tweedie.py (per-class) Gamma loss (p=2)
InverseGaussianLoss tweedie.py tests/losses/test_tweedie.py (per-class) IG loss (p=3)
TweedieLoss tweedie.py tests/losses/test_tweedie.py + tests/losses/test_functional_wrappers.py TestTweedieLoss, TestTweedieLossWrapper Routing by p: 0→normal, 1→Poisson, 2→gamma, 3→IG, 1<p<2→compound
tweedie_loss tweedie.py tests/losses/test_functional_wrappers.py TestTweedieLossWrapper Wrapper parity
ConsistencyRegLoss uncertain_gt.py tests/losses/test_uncertain_gt.py (per-class) EMA-style consistency penalty
NoisyTargetGaussianNLL uncertain_gt.py tests/losses/test_uncertain_gt.py (per-class) Label-noise-aware Gaussian NLL
PseudoLabelConsistencyLoss uncertain_gt.py tests/losses/test_uncertain_gt.py (per-class) Pseudo-label agreement penalty
PseudoLabelNLL uncertain_gt.py tests/losses/test_uncertain_gt.py (per-class) NLL under pseudo-label distribution
low_rank_output_dim utils/gaussian_output.py tests/losses/test_indirect_utilities.py TestLowRankOutputDim 2F + F·R formula; monotonicity; ValueError on n_features<=0 or rank<=0
split_low_rank_gaussian_output utils/gaussian_output.py tests/losses/test_indirect_utilities.py TestSplitLowRankGaussianOutput Round-trip [mean \| factor \| diag]; unbatched shape; ValueError on wrong out_dim

Supplementary symbol coverage

The matrix above covers the core loss surface; these additional public symbols are exercised by the tests listed here. Status follows the same conventions: DEDICATED when a Test* class targets the symbol, DIRECT-LIGHT when a focused test function exists in the per-symbol suites, and INDIRECT otherwise (a refactor should add a direct test).

Symbol Module Test entry point Coverage
balanced_mse_bmc_loss balanced_mse_bmc.py tests/losses/test_balanced_mse_bmc.py::TestHandFormula DIRECT-LIGHT
CVPlus conformal.py tests/losses/test_conformal.py::TestCVPlus DEDICATED
ConformalizedDensity conformal.py tests/losses/test_conformalized_density.py::test_conformalized_density_scalar_coverage DEDICATED
ContrastiveFlowConformal conformal.py tests/losses/test_conformalized_density.py::test_contrastive_flow_conformal_level_set DEDICATED
EnsembleBatchCP conformal.py tests/losses/test_conformal.py::TestEnsembleBatchCP DEDICATED
MultivariateScoreConformal conformal.py tests/test_multivariate_score_cp.py::test_covariance_shape_flexibility_and_errors DIRECT-LIGHT
NonExchangeableConformalRegressor conformal.py tests/test_nexc_conformal.py::test_uniform_weights_recover_finite_sample_quantile DIRECT-LIGHT
RankNContrastLoss contrastive.py tests/losses/test_rank_n_contrast.py::test_gradients_and_degenerate_batches DIRECT-LIGHT
rank_n_contrast_loss contrastive.py tests/losses/test_rank_n_contrast.py::test_perfectly_ordered_features_score_lower_than_shuffled DIRECT-LIGHT
InputNoiseAugmentationLoss eiv.py tests/losses/test_losses_regression_guards.py::test_a10_input_noise_augmentation_does_not_forward_weights DIRECT-LIGHT
AsymmetricLaplaceNLLLoss families.py tests/losses/test_families.py::test_asymmetric_laplace_unconstrained_inputs_flag DIRECT-LIGHT
BetaRegressionNLLLoss families.py tests/losses/test_families.py::test_beta_regression_registered DIRECT-LIGHT
GEVNLLLoss families.py tests/losses/test_families.py::test_gev_unconstrained_inputs_flag DIRECT-LIGHT
JohnsonSUNLLLoss families.py tests/losses/test_families.py::test_johnson_su_unconstrained_inputs_flag DIRECT-LIGHT
SQRLoss families.py tests/losses/test_families.py::test_sqr_level_count_validated_and_registered DIRECT-LIGHT
SinhArcsinhNLLLoss families.py tests/losses/test_families.py::test_sinh_arcsinh_registered DIRECT-LIGHT
SkewNormalNLLLoss families.py tests/losses/test_families.py::test_skew_normal_class_functional_and_registry DIRECT-LIGHT
SkewTLoss families.py tests/losses/test_families.py::test_skew_t_unconstrained_inputs_flag DIRECT-LIGHT
asymmetric_laplace_nll families.py tests/losses/test_families.py::test_asymmetric_laplace_kappa_one_is_symmetric_laplace DIRECT-LIGHT
beta_regression_nll families.py tests/losses/test_families.py::test_none_reduction_preserves_shape DIRECT-LIGHT
gev_nll families.py tests/losses/test_families.py::test_gev_gumbel_limit_matches_general_formula_at_small_xi DIRECT-LIGHT
johnson_su_nll families.py tests/losses/test_families.py::test_johnson_su_density_integrates_to_one DIRECT-LIGHT
sinh_arcsinh_nll families.py tests/losses/test_families.py::test_none_reduction_preserves_shape DIRECT-LIGHT
skew_normal_nll families.py tests/losses/test_families.py::test_skew_normal_class_functional_and_registry DIRECT-LIGHT
skew_t_nll families.py tests/losses/test_families.py::test_none_reduction_preserves_shape DIRECT-LIGHT
sqr_loss families.py tests/losses/test_families.py::test_sqr_constant_predictions_equal_mean_pinball DIRECT-LIGHT
FeatureDistributionSmoother imbalanced.py tests/losses/test_imbalanced.py::TestFeatureDistributionSmoother DEDICATED
recommended_tail_bound nflows.py tests/losses/test_nflows_tail_bound.py::test_recommended_tail_bound_is_data_range_with_margin_clipped DEDICATED
BinnedDensityLoss noise_aware_density.py tests/losses/test_noise_density_contract_regressions.py::test_binned_uniform_sampling_density_and_cdf_agree DIRECT-LIGHT
JointBinnedDensityLoss noise_aware_density.py tests/losses/test_binned_joint.py::test_joint_validation DIRECT-LIGHT
NoiseAwareDensityLoss noise_aware_density.py tests/losses/test_noise_aware_density.py::test_noise_aware_flow_gradient_and_contamination DIRECT-LIGHT
NeuralRatioLoss nre.py tests/losses/test_nre.py::_train_gaussian_ratio_estimator DIRECT-LIGHT
build_ratio_classifier nre.py tests/losses/test_nre.py::test_build_ratio_classifier_validation_errors DEDICATED
neural_ratio_logits nre.py tests/losses/test_nre.py::test_neural_ratio_logits_validation_errors DEDICATED
neural_ratio_loss nre.py tests/losses/test_nre.py::test_functional_helper_matches_class DIRECT-LIGHT
ConR prime.py tests/losses/test_prime_conr.py::test_conr_permutation_invariance DIRECT-LIGHT
PrimeLoss prime.py tests/losses/test_prime_conr.py::test_label_range_pins_grid_and_allows_forward_without_fit DIRECT-LIGHT
UncertaintyAwareConR prime.py tests/losses/test_noise_aware_density.py::test_uncertainty_aware_conr DIRECT-LIGHT
conr_loss prime.py tests/losses/test_prime_conr.py::test_conr_mask_reduction_and_weights DIRECT-LIGHT
uniform_proxy_targets prime.py tests/losses/test_prime_conr.py::test_uniform_proxy_targets_are_equal_width_and_exclude_endpoints DEDICATED
rank_sim_regularizer rank_sim.py tests/losses/test_rank_sim.py::test_invalid_inputs_raise DIRECT-LIGHT
CumulativeCDFLoss cdf.py tests/losses/test_cdf.py::test_cumulative_cdf_class DIRECT-LIGHT
cumulative_cdf_loss cdf.py tests/losses/test_cdf.py::test_cumulative_cdf_loss_zero_for_perfect_step DEDICATED
CorrectedScoreEIVLoss split_eiv.py tests/losses/test_split_eiv.py::test_corrected_score_decreases_on_small_mlp DIRECT-LIGHT
SplitMeasurementLoss split_eiv.py tests/losses/test_split_eiv.py::test_split_loss_nonlinear_is_finite_and_differentiable_to_second_order DIRECT-LIGHT
corrected_score_eiv_loss split_eiv.py tests/losses/test_split_eiv.py::test_helpers_match_classes_and_forward_sigma_override DIRECT-LIGHT
split_measurement_loss split_eiv.py tests/losses/test_split_eiv.py::test_helpers_match_classes_and_forward_sigma_override DIRECT-LIGHT
StudentTLoss student_t.py tests/losses/test_student_t.py::test_extreme_residuals DIRECT-LIGHT
WaldoConformal waldo.py tests/losses/test_waldo.py::test_waldo_conformal_with_regressor_coverage DEDICATED
WaldoCriticalValueRegressor waldo.py tests/losses/test_waldo.py::test_waldo_critical_value_regressor_fit_predict DEDICATED
WaldoDensityConformal waldo.py tests/losses/test_waldo.py::test_waldo_density_conformal DEDICATED
WaldoPosteriorCalibrator waldo.py tests/losses/test_waldo.py::test_waldo_posterior_calibrator DEDICATED
waldo_statistic waldo.py tests/losses/test_waldo.py::test_waldo_statistic_shapes DEDICATED
DiscreteWasserstein1Loss wasserstein1d.py tests/losses/test_wasserstein1d.py::test_default_unit_bins_and_validation DIRECT-LIGHT
discrete_wasserstein1 wasserstein1d.py tests/losses/test_wasserstein1d.py::test_metric_properties DIRECT-LIGHT

Internal helpers in utils/gaussian_output.py

The three helpers below are not in __all__ — they remain internal contract helpers outside the public losses API. They are exercised indirectly by their BetaNLLLoss/GaussianNLLLoss/FaithfulGaussianLoss callers but have no dedicated test class. Treat any change as a cross-module refactor that should land alongside a direct test in tests/losses/test_indirect_utilities.py.

  • parse_heteroscedastic_output — tuple/dict/concat-2D routing
  • split_mean_log_variance — tuple/dict/concat routing; ValueError on odd dims
  • variance_from_logvar — clamp + exp signing

Per-class test surface (consistency / cross-family)

File Purpose
test_gaussian_consistency.py Cross-family Gaussian invariants (input formats, mask/weights contracts, gradient contracts, CRPS stability, Wasserstein relationships). Locks every variant of the Gaussian loss family to the same input contract.
test_non_gaussian_consistency.py Cross-family contracts for Poisson-Gaussian, censored, Tweedie, quantile, ordinal, conformal, EIV, expectile, evidential, robust, balanced-MSE families.
test_loss_fixes.py Regression tests for documented loss bugs — SLSLoss.step_counter, WeightedLossWrapper.reduction, MixtureDensityLoss.full-cov Cholesky backward, LocalConformal.predict_interval sentinel, plus CQR calibration invariants (alpha not mutated; empty/all-masked raises). Use this file first when investigating these invariants.
test_sls_internals.py SLS internal modules — VolumePreservingFlow / MahalanobisFrontier (full + low-rank) / UnionFrontier / QuantileNetwork.
test_eiv_internals.py EIV internal modules — NoisyInputPredictor / BaseEIVLoss._prepare_covariance_from_sigma.
test_functional_wrappers.py Functional wrappers (quantile_loss, expectile_loss, beta_nll_loss, tweedie_loss, gaussian_wasserstein_bound_loss).
test_indirect_utilities.py Public indirect utilities — low_rank_output_dim, split_low_rank_gaussian_output, symmetric_spd_matrix_sqrt, create_gaussian_nll.
test_loss_registry.py get_regression_loss / list_regression_losses / create_loss_from_config.

Discriminator invariants: where to look when refactoring

Invariant category Canonical test entrance Module-level fallback
NLL formula and reduction test_gaussian.py::TestGaussianLosses + test_gaussian_consistency.py::TestMaskContract test_beta_nll.py, test_poisson_gaussian.py
Pinball / quantile formulation test_quantile.py::TestQuantileLoss + tests/losses/test_functional_wrappers.py::TestQuantileLossWrapper test_non_gaussian_consistency.py
CQR calibration invariants test_loss_fixes.py::TestCQRCalibrationInvariants test_conformal.py::TestCQR
Determinism across dataloader calls (sentinel underflow) test_loss_fixes.py::TestLocalConformalSentinelFallback test_conformal.py::TestLocalConformal
Volume-preserving flow invertibility test_sls.py::test_volume_preserving_* + test_sls_internals.py::TestVolumePreservingFlow test_sls_internals.py
Mahalanobis frontier shape & rank default test_sls_internals.py::TestMahalanobisFrontier{LowRank,Full} test_sls.py::test_mahalanobis_frontier_full_and_low_rank
K>1 union mixture weights test_sls_internals.py::TestUnionFrontier::test_unfrozen_mixture_weights_sum_to_one_per_sample test_sls.py::test_union_frontier
MDN Cholesky backward (no leaf-tensor in-place write) test_loss_fixes.py::TestMixtureDensityLossFullCovBackward test_mdn.py
Wrapper preserves caller-set reduction test_loss_fixes.py::TestWeightedLossWrapperPreservesReduction test_base.py::TestWeightedLossWrapper
SLS curriculum monotonic advance test_loss_fixes.py::TestSLSLossStepCounterAdvances test_sls.py::test_sls_loss_warmup_and_forward
Functional-wrapper parity (loss vs class) All Test*Wrapper classes in test_functional_wrappers.py + test_indirect_utilities.py per-class suite
Gaussian Wasserstein bound 4-mode parity test_functional_wrappers.py::TestGaussianWassersteinBoundWrapper::test_*_mode test_gaussian_wasserstein.py

INDIRECT-only symbols (refactor risk)

The authoritative list is the Coverage column of the supplementary symbol coverage table: symbols marked DIRECT-LIGHT or INDIRECT have no dedicated Test* class. The zuko-dependent flow factories (create_flow_model, create_flow_loss, create_contrastive_flow_loss) remain the canonical example: optional dependency, covered indirectly.

Any non-trivial change to these symbols should land alongside a small direct test in tests/losses/test_indirect_utilities.py (or specific file) so their behaviour doesn't drift silently.

Per-class test surfaces

For matrix rows citing (per-class suite), the dedicated Test* classes live in the file under Test file. Use grep '^class Test' <test_file> to list the exact class names — the names change frequently and the matrix does not attempt to enumerate them. Cross-consistency coverage is documented per file in test_gaussian_consistency.py and test_non_gaussian_consistency.py.

Known silent regressions

The following invariants are documented. Pre-fix code raises the listed error under older PyTorch but is silently absorbed under modern PyTorch's version-counter autograd; the listed regression test now discriminates both states at runtime, so the original caveat no longer applies:

  • MixtureDensityLoss H2 in-place scatter. Post-fix code composes the full-cov Cholesky factor functionally via torch.where(diag_mask, L_diag, L_offdiag), yielding a brand-new L_matrices tensor with _version == 0 at forward-return time. Pre-fix code derived L_matrices via two in-place __setitem__ writes onto L_offdiag, bumping its version to >= 2 by the time it was returned.The discriminator tests/losses/test_loss_fixes.py::TestMixtureDensityLossFullCovBackward::test_full_covariance_L_version_zero wraps _extract_distribution_parameters to capture L_matrices._version immediately after forward and asserts it equals 0, surviving PyTorch's silent absorption of the in-place pattern.

Coverage invariants: what test authors MUST pin

Future test authors must follow this discipline when introducing any ad-hoc reference to a covariance, sigma, stddev, or Cholesky factor in a test fixture. Ad-hoc torch.eye(...) / torch.diag(...) / torch.diag_embed(...) literals MUST pin device and dtype so the fixture does not silently rely on the loss module handling dtype/device of input fixtures internally. Two accepted forms depending on whether the literal is on the result side or the input side of the comparison:

  • Result comparison (the literal is the reference for a tensor returned by a loss module). Pin the literal to the result's metadata:
    ref = torch.eye(n_features, device=cov.device, dtype=cov.dtype) * 0.25
    self.assertTrue(torch.allclose(cov, ref))
    
  • Input builder (the literal is part of a fixture fed into a loss module — e.g. A @ A.T + torch.eye(dim) * jitter). Pin to the co-built anchor tensor that's already on the right device/dtype:
    A = torch.randn(dim, dim)
    base = A @ A.T + torch.eye(dim, device=A.device, dtype=A.dtype) * 1e-3
    

The legacy .to(cov.device, dtype=cov.dtype) cast on the literal is accepted as a fallback when the torch.eye(...) / torch.diag(...) form would change the literal's mathematical meaning (e.g. when the literal is a hand-built third-party reference like torch.tensor([...]) the test materials outside an obvious anchor).

Why this discipline matters

torch.allclose and torch.testing.assert_close are dtype/device-tied at the framework level. torch.eye(3) silently defaults to float32/CPU; if a future loss module grows a device-dispatching code path (e.g. CUDA NLL, autograd-double NLL, the to("cuda") migration in test_gaussian.py's setUp) the test would silently pass under old builds while passing against mismatched metadata under new builds — a covered-by-follow-up symptom of implicit fixture metadata rather than a single-step failure flagged by CI.

Concretely: under a dtype/device mismatch, torch.allclose raises a RuntimeError rather than returning the comparison result. CI fails with an unrelated-looking error message (e.g. Found dtype Float but expected Double), masking the real loss-graph regression behind a metadata mismatch — the developer fixes the missing dtype pin rather than the actual loss bug the test was guarding.

Canonical examples for reference while authoring new tests

  • tests/losses/test_eiv_internals.py::TestBaseEIVLossInternals::test_prepare_covariance_* — the canonical result-comparison form. Pin the reference to cov after _prepare_covariance_from_sigma: torch.eye(n_features, device=cov.device, dtype=cov.dtype) * 0.25.
  • tests/losses/test_functional_wrappers.py::TestGaussianWassersteinBoundWrapper.setUp — the canonical input-builder form. Pin the SPD builder's eye to the co-built A: A @ A.T + torch.eye(self.d, device=A.device, dtype=A.dtype).
  • All _make_spd_cov-style helpers in tests/losses/test_gaussian_consistency.py and the _psd_matrix helper in tests/losses/test_indirect_utilities.py reproduce the input-builder form on the helper's anchor A.
  • tests/losses/test_gaussian.py::TestGaussianLosses.setUp — adds a dtype= pin on top of an existing device= pin for the SPD jitter term.

Cross-cutting rule for code review

When reviewing or extending any test in tests/losses/, tests/, notebooks/, or examples/, re-grep torch.eye and torch.diag / torch.diag_embed. Any unpinned site that - constructs an input fixture (an A @ A.T + eye(dim) * jitter builder, an eye-in-a-list literal passed as a sigma parameter, etc.), or - compares against a result tensor in torch.allclose / torch.testing.assert_close,

is a coverage-invariance violation under this rule. Fix before merging, exactly per the patterns above.

Mechanical enforcement (TOR001 + TOR002 + TOR003)

Pin-rollout drift doctor

A second local hook, scripts/check_pin_rollout_drift.py, complements the enforcer above by auditing every# noqa: TORxxxopt-out in thetests/,examples/,notebooks/, andsrc/ trees. Three severity classes are reported:

  • [error] — the noqa is orphaned (no torch.eye / torch.diag / torch.diag_embed call on that line). The opt-out is attached to nothing; remove it.
  • [warning] — the noqa is redundant: the call on that line already pins device= / dtype= (or chains .to(device=..., dtype=...)), so the noqa silences nothing. This typically follows a successful pin rollout -- remove the now-defunct opt-out to keep the source clean.
  • [hint] -- advisory only (does NOT cause a non-zero exit): the cited rule ID does not match the file's path-resolved rule, or the rule ID is not in _RULE_PREFIXES (typo). The enforcer ignores cross-rule noqa already; the hint surfaces the stale scope assumption so a contributor can verify which rule the file actually lives in.

.pre-commit-config.yaml registers the doctor as a separate repos: local hook entry (pin-rollout-drift-doctor) so its diagnostics are distinct from the enforcer's TORxx output in pre-commit logs.

Mechanical enforcement (TOR001 + TOR002 + TOR003)

A local pre-commit hook at scripts/check_test_fixture_pin_discipline.py AST-scans every staged tests/**.py / examples/**.py / notebooks/**.py / src/**.py file for un-pinned torch.eye(...) / torch.diag(...) / torch.diag_embed(...) literals. The rule ID is resolved per file path via POSIX path-component matching (_rule_id_for_path in the script), so a file like examples/tests/helper.py lands under TOR002 (the examples directory component is the first match), not TOR001:

  • TOR001 — files under tests/ (the original tests-only scope).
  • TOR002 — files under examples/ or notebooks/.
  • TOR003 — files under src/ (production loss fixtures plus the algorithms/, metrics/, ensemble/, utils/, losses/ helpers that emit the same fixtures internally; .pre-commit-config.yaml registers a third hook entry with files: '^src/.*\.py\$').

# noqa precedence contract: a # noqa: TOR00x comment on a line silences only the matching rule ID — # noqa: TOR001 does NOT silence a violation routed to TOR002 or TOR003. The order in _RULE_PREFIXES matters: the script iterates path components in order and returns the first component whose name matches (so a relative path examples/tests/helper.py lands under TOR002, not via nested tests substring). An absolute path with a pre-project-root src/ segment (/home/user/src/torchregress/tests/foo.py) WILL route to TOR003 because src is matched first by the ABS path-component walk; callers should normalize absolute paths to project-relative before relying on the rule ID.

.pre-commit-config.yaml registers three repos: local: hook entries, each with its own rule ID, so pre-commit output surfaces which scope each violation belongs to. The script emits filename:lineno: torch.<func>() missing device= or dtype= kwarg violations to stderr and exits with status 1; the message body embeds the resolved rule ID so # noqa opt-outs must match (# noqa: TOR001, # noqa: TOR002, or # noqa: TOR003).

Recognised canonical pin patterns: - Direct kwarg (works for torch.eye, which natively supports the kwargs): torch.eye(N, device=A.device, dtype=A.dtype) - Chained .to(...) cast (the documented fallback for torch.diag and torch.diag_embed, which do NOT accept those kwargs natively): torch.diag(matrix).to(device=matrix.device, dtype=matrix.dtype)

Inline opt-out: a trailing # noqa: TOR001 (under tests/) or # noqa: TOR002 (under examples/ or notebooks/) comment on the offending line. Signature scope is intentionally narrow — only direct torch.<func>(...) attribute access is scanned. Aliases (t.eye(...)), imports (from torch import eye; eye(...)), and **kwargs splats are flagged as unverifiable; opt-out with the appropriate # noqa: TORxxx for the splat case if it provably carries the kwargs.

Why ast rather than a custom ruff plugin: ruff is a Rust CLI and is not importable as a Python module for plugin code; AST-based analysis covers the rule completely without spawning an extra Rust tool. Unit-tested in tests/utils/test_check_test_fixture_pin_discipline.py (24 cases covering direct-kwarg pin, chained .to(), scope filters, walk depth, and rule-ID stability).

TL;DR for code review

When reviewing a loss change, look for:

  1. The matrix row for the changed symbol — confirm the test class actually enforces the changed invariant (not just instantiates the loss).
  2. If you can't find a row, add a dedicated test before merging; the INDIRECT-only section flags where the gap lives.
  3. Re-running torchregress/scripts/revert_verify.py after a change gives empirical evidence the test discriminates the bug class the change risks.