Quick Start¶
← Installation | Core Concepts →
This page assembles the canonical workflows for the four most common regression regimes in torchregress. Each workflow is self-contained: copy a block, run it, and validate against the listed evaluation metrics before committing to a method.
Design intent
Every loss in this page is interchangeable in a standard PyTorch
training loop. The differences are semantic (what the loss
optimises) and contractual (what the model must output), not
procedural. Replace loss_fn and the head's final layer; the rest
of the loop is unchanged.
The sections progress from simplest (§1 — point regression) to most comprehensive (§7 — causal inference). Each builds on concepts from the previous ones.
1. Point regression with mask and sample-weight support¶
When you need a point prediction and your data has missing targets or
per-sample weights, use the weighted wrappers instead of torch.nn.MSELoss.
The wrappers also support reduction="none" for per-sample loss returns.
import torch
import torch.nn as nn
from torchregress.losses import WeightedMSELoss, WeightedHuberLoss
from torchregress.metrics import mean_absolute_error, r2_score, rmse
model = nn.Sequential(nn.Linear(10, 64), nn.ReLU(), nn.Linear(64, 1))
# Huber is a robust default for mild outliers; delta=1.0 transitions
# between quadratic and linear at |r| = 1.
loss_fn = WeightedHuberLoss(delta=1.0)
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
for x, y, mask, w in dataloader:
pred = model(x)
loss = loss_fn(pred, y, mask=mask, weights=w)
loss.backward(); optimizer.step(); optimizer.zero_grad()
# Evaluation: report RMSE + MAE + R² as secondary summaries
with torch.no_grad():
y_pred = model(x_test)
print(f"RMSE: {rmse(y_pred, y_test):.4f} "
f"MAE: {mean_absolute_error(y_pred, y_test):.4f} "
f"R²: {r2_score(y_pred, y_test):.4f}")
When not to use this: if your data is heteroscedastic (noise varies with \(x\)) or you need uncertainty intervals, use §2 instead.
→ API: WeightedHuberLoss, WeightedMSELoss; metrics rmse, mae, r2_score.
2. Heteroscedastic Gaussian regression¶
The model outputs a mean and a log-variance; the loss is the Gaussian negative log-likelihood, a proper scoring rule that admits gradient-based optimisation. This is the canonical aleatoric uncertainty head.
from torchregress.losses import GaussianNLLLoss
from torchregress.metrics import crps_gaussian, gaussian_nll
# Head: [mean, log_var] per example
model = nn.Sequential(nn.Linear(10, 64), nn.ReLU(), nn.Linear(64, 2))
loss_fn = GaussianNLLLoss()
for x, y in dataloader:
out = model(x) # [B, 2]
loss = loss_fn(out, y) # -log p(y | μ(x), σ²(x))
loss.backward(); optimizer.step(); optimizer.zero_grad()
# Inference + density-aware evaluation
with torch.no_grad():
out = model(x_test)
mu, logvar = out[:, 0], out[:, 1]
var = torch.exp(logvar)
std = torch.sqrt(var)
lower, upper = mu - 1.96 * std, mu + 1.96 * std
crps = crps_gaussian(mu, y_test, std) # proper scoring rule
gnll = gaussian_nll(mu, y_test, var) # NLL on test set
Caveat: Gaussian NLL can suffer from variance-collapse early in
training (the model predicts \(\sigma \to 0\) and exploits the NLL's density
peak). The BetaNLLLoss variant detaches the
variance term to mitigate this. Always inspect a
reliability diagram before trusting the
intervals.
For full epistemic decomposition, wrap this head in an ensemble or add a posterior approximation (see §5).
→ API: GaussianNLLLoss; evaluation: crps_gaussian, gaussian_nll.
3. Robust regression under contamination¶
When the data contains outliers or heavy-tailed noise, the \(L_2\) penalty in MSE / Gaussian NLL gives unbounded influence to a single bad example. Use an M-estimator with a bounded influence function.
from torchregress.losses import (
WeightedHuberLoss, CauchyLoss, TukeyBiweightLoss, AdaptiveRobustLoss
)
# Mild outliers (5–10%): Huber is a safe default
loss_fn = WeightedHuberLoss(delta=1.0)
# Moderate outliers (10–25%): Cauchy is more aggressive
loss_fn = CauchyLoss(c=1.0)
# Severe contamination (>25%): Tukey rejects outliers entirely
loss_fn = TukeyBiweightLoss(c=4.685)
# Unknown noise regime: learn the shape parameter
loss_fn = AdaptiveRobustLoss()
# IMPORTANT: when the loss has learnable parameters (AdaptiveRobust,
# Barron), pass them to the optimizer:
optimizer = torch.optim.Adam([
{"params": model.parameters(), "lr": 1e-3},
{"params": loss_fn.parameters(), "lr": 1e-2},
])
The choice of \(\rho(r)\) is not a hyperparameter to tune blindly — inspect the empirical influence function and the uncertainty vs. error diagnostic to validate that outliers are actually being down-weighted.
4. Conformal prediction for guaranteed coverage¶
Apply conformal prediction on top of any pre-trained model to obtain prediction intervals with distribution-free coverage guarantees under exchangeability.
from torchregress.losses import SplitConformal, CQR
# Split conformal: residuals |y - ŷ| on a held-out calibration set
cp = SplitConformal(alpha=0.1) # target 90% coverage
cp.calibrate(y_pred_cal, y_cal)
lower, upper = cp.predict_interval(y_pred_test)
# Conformalized Quantile Regression (CQR): adapt to heteroscedastic noise
cqr = CQR(alpha=0.1)
cqr.calibrate(quantile_preds_cal, y_cal) # quantile predictions
lower, upper = cqr.predict_interval(quantile_preds_test)
Important: conformal prediction provides coverage, not density estimation. The intervals can be wide if the underlying model is poor or the data has shifted; this is a feature, not a bug. If you also need aleatoric/epistemic decomposition, use a probabilistic model (§2) and conformal calibration.
5. Epistemic uncertainty via ensembles¶
For decomposable uncertainty, train an ensemble of likelihood heads and decompose the predictive variance via the Law of Total Variance:
from torchregress.ensemble import BaseEnsembleModel
from torchregress.metrics import uncertainty_decomposition
# A heteroscedastic head that outputs [mean, log_var]
def heteroscedastic_head():
return nn.Sequential(nn.Linear(10, 64), nn.ReLU(), nn.Linear(64, 2))
ens = BaseEnsembleModel(base_model=heteroscedastic_head(),
ensemble_size=5, base_seed=0)
ens.fit(train_loader, optimizer_factory=torch.optim.Adam, lr=1e-3)
# Per-member predictions
mu_per_member = torch.stack([m(x_test) for m in ens.models], dim=0) # [M, B]
var_per_member = ... # from each member's (mean, log_var) head
# Decomposition
decomp = uncertainty_decomposition(mu_per_member, var_per_member)
# decomp["epistemic_uncertainty"], decomp["aleatoric_uncertainty"], decomp["total_uncertainty"]
Tradeoff: training and inference costs scale linearly with ensemble
size. For a single-pass alternative, see
EvidentialRegressionLoss; for a cheaper posterior
approximation, see SWAG or
IVON.
6. Distribution shift at test time¶
When the target distribution at deployment differs from training (population shift, instrument drift, non-stationary process), use test-time adaptation primitives.
from torchregress.test_time import (
BayesianLinearHead, ScoreCDFReweighter, WeightedSplitConformalAdapter
)
# 1. Closed-form Bayesian last layer — adapts to a few labeled or
# unlabeled examples without backprop
head = BayesianLinearHead(in_features=64, out_features=1, noise_variance=0.1)
head.fit(features_train, y_train) # one-shot
head.partial_fit(features_stream, y_stream) # streaming with forgetting
# 2. OT-style conformal reweighting under non-exchangeable shift
rw = ScoreCDFReweighter().fit(cal_scores, target_scores)
adapter = WeightedSplitConformalAdapter(alpha=0.1).calibrate(cal_scores, rw.weights_)
mask = adapter.predict_from_test_scores(test_scores)
# 3. Full pipeline: prior transport + feature alignment + conformal
from torchregress.test_time import (
ShiftFactoredPredictiveTransport, ShiftFactoredTransportConfig
)
transport = ShiftFactoredPredictiveTransport(ShiftFactoredTransportConfig())
transport.fit_source(source_pb, source_targets=src_y, source_inputs=src_x)
adapted_pb = transport.adapt_unlabeled_target(target_pb, target_inputs=tgt_x)
7. Causal inference (ATE / CATE)¶
For treatment-effect estimation under confounding, use doubly-robust estimators with cross-fitting and overlap diagnostics.
from torchregress.causal import dr_ate, causal_overlap_report
ate = dr_ate(x, t, y,
outcome_model=lambda: GradientBoostingRegressor(n_estimators=50),
propensity_model=lambda: GradientBoostingClassifier(n_estimators=50),
folds=2, alpha=0.05, seed=42)
print(f"ATE = {ate['estimate']:.3f} CI = [{ate['ci_lower']:.3f}, {ate['ci_upper']:.3f}]")
# Always inspect overlap diagnostics — a low ESS in either arm means
# the estimate is dominated by a few influential points
print(f"min ESS: {ate['diagnostics']['min_group_ess']:.1f} "
f"overlap rate: {ate['diagnostics']['overlap_rate']:.3f}")
Decision aid: which workflow is right for you?¶
| Your situation | Start at | Why |
|---|---|---|
| Plain regression, complete data, no uncertainty needed | §1 | Smallest model, fastest to train |
| Noise varies with \(x\) or you need predictive intervals | §2 | Heteroscedastic head + proper scoring rule |
| Data has outliers or heavy-tailed noise | §3 | Bounded influence function |
| You need coverage guarantees on intervals | §4 | Distribution-free coverage under exchangeability |
| You need to know what the model doesn't know | §5 | Decomposition into aleatoric / epistemic |
| Test data is shifted from training | §6 | Test-time adaptation primitives |
| You need treatment-effect estimates under confounding | §7 | Doubly-robust estimation with diagnostics |
For the full task matrix, see Method Selection. For derivations of the scoring rules and decomposition formulas, see Mathematical Foundations.
References¶
| # | Reference |
|---|---|
| 1 | Kendall, A. & Gal, Y. (2017). What Uncertainties Do We Need in Bayesian Deep Learning for Computer Vision? NeurIPS. |
| 2 | Lakshminarayanan, B., Pritzel, A. & Blundell, C. (2017). Simple and Scalable Predictive Uncertainty Estimation using Deep Ensembles. NeurIPS. |
| 3 | Gneiting, T. & Raftery, A. E. (2007). Strictly Proper Scoring Rules, Prediction, and Estimation. JASA, 102(477), 359–378. |
| 4 | Vovk, V., Gammerman, A. & Shafer, G. (2005). Algorithmic Learning in a Random World. Springer. |
| 5 | Romano, Y., Patterson, E. & Candès, E. (2019). Conformalized Quantile Regression. NeurIPS. |
| 6 | Tibshirani, R. J., Foygel Barber, R., Candès, E. & Ramdas, A. (2019). Conformal Prediction Under Covariate Shift. NeurIPS. |
| 7 | Huber, P. J. (1964). Robust Estimation of a Location Parameter. Annals of Mathematical Statistics, 35(1), 73–101. |
| 8 | Carroll, R. J., Ruppert, D., Stefanski, L. A. & Crainiceanu, C. M. (2006). Measurement Error in Nonlinear Models (2nd ed.). Chapman & Hall. |
Next steps¶
-
Mathematical Foundations
- Derivations of NLL, CRPS, interval score, and decomposition formulas
- Mathematical Foundations
-
Method Selection
- Task-first guidance with capability matrices
- Method Selection Matrix
-
Diagnostics & Visualization
- Reliability diagrams, PIT histograms, residual plots
- Visualization Methods