Uncertainty quantification (tsbootstrap.uq)
The uncertainty-quantification surface is also re-exported at the top level, so
from tsbootstrap import EnbPIEnsemble works alongside from tsbootstrap.uq
import EnbPIEnsemble. scikit-learn (the uq extra) is imported lazily inside
the out-of-bag path, so importing these names on a core-only install is safe; it
is required only when an EnbPI ensemble is fitted.
Note
forecast_intervals() currently supports the
AR model only and raises
MethodConfigError for ARIMA or VAR. Out-of-sample
forecast intervals for ARIMA and VAR are tracked on the roadmap.
Uncertainty quantification built on the bootstrap.
Two task-appropriate paths (see the v0.2.0 design notes):
In-sample / out-of-sample regression,
EnbPIEnsembleis a MAPIE-style fit/predict object: it bootstraps the row indices, fits a clone of the estimator per resample, records the out-of-bag ensemble residuals (Xu & Xie 2021), and retains the fitted clones so intervals can be produced for newX. The half-width comes from a chosen calibrator over the residual buffer,static_halfwidths()(global quantile),sliding_window_halfwidths()(time-local EnbPI), or the drift-adaptiveaci_halfwidths()/nexcp_quantile().enbpi_intervals()andfit_predict_oob()are thin wrappers for the simple in-sample, static-width path.Forecasting,
forecast_intervals()simulates the fitted model forward and takes empirical path quantiles over the horizon.
These carry honest, assumption-appropriate coverage claims: approximate / asymptotic under temporal dependence, not finite-sample distribution-free.
- class tsbootstrap.uq.EnbPIEnsemble[source]
Bases:
objectFit/predict EnbPI ensemble: retain the bootstrap clones, calibrate on demand.
fitbootstraps the row indices with an observation-resampling method, fits a clone ofestimatoron each in-bag resample, and computes the out-of-bag ensemble prediction per row (the mean over the replicates in which the row was held out) and the out-of-bag absolute residuals|y - oob_pred|. The residuals are the raw calibration scores, decoupled from any particular calibrator.predict_intervalthen centers an interval at the out-of-bag prediction (in sample) or the retained-clone ensemble mean (out of sample) and applies the chosen calibrator to the residual buffer to get the half-width. Coverage is approximately1 - alphaunder a strong-mixing condition (Xu & Xie 2021), not finite-sample distribution-free.- fit(estimator: _SklearnLike, X: object, y: object, *, method: BaseMethodSpec, n_bootstraps: int = 100, random_state: int | Generator | SeedSequence | None = None, store_estimators: bool = True) EnbPIEnsemble[source]
Fit the bootstrap ensemble and record the out-of-bag calibration scores.
- Parameters:
estimator (object) – An unfitted, order-invariant sklearn-style regressor; cloned per replicate.
X (array-like) – Design matrix
(n, d)(1-D is treated as(n, 1)) and targets(n,).y (array-like) – Design matrix
(n, d)(1-D is treated as(n, 1)) and targets(n,).method (object) – An observation-resampling method (IID or a block method). Recursive model methods are rejected with
MethodConfigError.n_bootstraps (int) – Number of bootstrap replicates.
random_state (object) – Seed or generator forwarded to the bootstrap.
store_estimators (bool) – Retain the fitted clones on the instance (default
True). Required for out-of-samplepredict_interval(); setFalseto save memory when only in-sample intervals are needed.
- property oob_residuals: ndarray[tuple[int, ...], dtype[float64]]
The out-of-bag absolute residuals (calibration scores), in time order.
Raw and decoupled from calibration: every calibrator reads from this buffer.
- property oob_prediction: ndarray[tuple[int, ...], dtype[float64]]
The in-sample out-of-bag ensemble prediction, one per training row.
- predict_interval(X_new: object | None = None, *, alpha: float = 0.1, calibrator: str = 'static', **calibrator_kwargs: object) tuple[ndarray[tuple[int, ...], dtype[float64]], ndarray[tuple[int, ...], dtype[float64]], ndarray[tuple[int, ...], dtype[float64]]][source]
Prediction interval
(lower, upper, point)for the chosen calibrator.- Parameters:
X_new (array-like, optional) – New design matrix. If
None(default), returns in-sample intervals centered at the out-of-bag prediction. Otherwise the point prediction is the mean of the retained clones’ predictions onX_new(requires the ensemble to have been fitted withstore_estimators=True).alpha (float) – Target miscoverage; the interval target coverage is
1 - alpha.calibrator ({'static', 'sliding_window', 'aci', 'nexcp'}) –
How the residual buffer is turned into a half-width:
'static', one global1 - alphaquantile for every row.'sliding_window', rolling1 - alphaquantile (time-local EnbPI); acceptswindow(defaultmin(len, 50)).'aci', Adaptive Conformal Inference; requirestest_scores(the time-ordered realized|y_t - prediction_t|, one per row) and acceptsgamma(default0.05).'nexcp', recency-weighted quantile; acceptsdecay(default0.99).
**calibrator_kwargs – Calibrator-specific options as listed above.
- Returns:
(lower, upper, point), each shape(n_rows,).- Return type:
tuple of ndarray
- tsbootstrap.uq.fit_predict_oob(estimator: _SklearnLike, X: object, y: object, *, method: BaseMethodSpec, n_bootstraps: int = 100, random_state: int | Generator | SeedSequence | None = None) ndarray[tuple[int, ...], dtype[float64]][source]
Out-of-bag ensemble predictions, one per row.
Each in-bag resample fits a clone of
estimator; the held-out rows are predicted and averaged per row over the replicates in which the row was out-of-bag. Rows never held out getnan.A thin convenience wrapper over
EnbPIEnsemble; use the class directly when you also need calibrated intervals or out-of-sample prediction.
- tsbootstrap.uq.enbpi_intervals(estimator: _SklearnLike, X: object, y: object, *, method: BaseMethodSpec, alpha: float = 0.1, n_bootstraps: int = 100, random_state: int | Generator | SeedSequence | None = None) tuple[ndarray[tuple[int, ...], dtype[float64]], ndarray[tuple[int, ...], dtype[float64]], ndarray[tuple[int, ...], dtype[float64]]][source]
EnbPI prediction intervals:
(lower, upper, oob_prediction).The interval is centered at the out-of-bag ensemble prediction with half-width the
1 - alphaquantile of the out-of-bag absolute residuals. Coverage is approximately1 - alphaunder a strong-mixing condition (Xu & Xie 2021), not finite-sample distribution-free.A thin convenience wrapper for the simple in-sample, static-width path; equivalent to
EnbPIEnsemble().fit(...).predict_interval(calibrator="static"). For time-local widths, out-of-sample prediction, or the adaptive calibrators, useEnbPIEnsembledirectly.
- tsbootstrap.uq.forecast_intervals(X: object, *, model: object, horizon: int, alpha: float = 0.1, n_bootstraps: int = 999, random_state: int | Generator | SeedSequence | None = None) tuple[ndarray[tuple[int, ...], dtype[float64]], ndarray[tuple[int, ...], dtype[float64]], ndarray[tuple[int, ...], dtype[float64]]][source]
Bootstrap forecast intervals:
(lower, upper, median), each(horizon,).The fitted model is simulated
horizonsteps past the datan_bootstrapstimes with resampled, centered innovations; the per-step quantiles form the interval.
- tsbootstrap.uq.aci_halfwidths(calibration_scores: object, test_scores: object, *, alpha: float = 0.1, gamma: float = 0.05) tuple[ndarray[tuple[int, ...], dtype[float64]], ndarray[tuple[int, ...], dtype[float64]]][source]
Adaptive Conformal Inference: online-adapted interval half-widths.
- Parameters:
calibration_scores (array-like, shape (m,)) – Nonconformity scores (e.g.
|residual|) from the bootstrap calibration set.test_scores (array-like, shape (T,)) – Realized scores
|y_t - prediction_t|over the test sequence, in time order.alpha (float) – Target miscoverage (interval target coverage is
1 - alpha).gamma (float) – Adaptation step size.
gamma = 0recovers static conformal.
- Returns:
halfwidths (ndarray, shape (T,)) – Interval half-width
q_tto use at each step (prediction_t ± q_t).alphas (ndarray, shape (T,)) – The adapted miscoverage level used at each step.
The update is
alpha_{t+1} = alpha_t + gamma * (alpha - err_t)with``err_t = 1`` when step ``t`` is miscovered (a miss shrinks the level and widens the)
next interval. Coverage converges to
1 - alpharegardless of how the scores drift.
- tsbootstrap.uq.nexcp_quantile(scores: object, *, alpha: float = 0.1, decay: float = 0.99) float[source]
Recency-weighted (nonexchangeable) conformal quantile of the scores.
Weights score
i(0 = oldest, last = most recent) bydecay ** (n - 1 - i)and returns the smallest score whose normalized weighted CDF reaches1 - alpha. Withdecay = 1this is the ordinary empirical quantile; smallerdecayputs more weight on recent residuals, widening the interval when recent volatility rises.
- tsbootstrap.uq.static_halfwidths(residuals: ndarray[tuple[int, ...], dtype[float64]], n_rows: int, *, alpha: float = 0.1) ndarray[tuple[int, ...], dtype[float64]][source]
Constant half-width: the global
1 - alphaquantile, broadcast ton_rows.- Parameters:
residuals (ndarray, shape (m,)) – Time-ordered out-of-bag absolute residuals (the calibration scores).
n_rows (int) – Number of prediction rows to emit a width for.
alpha (float) – Target miscoverage; the interval target coverage is
1 - alpha.
- Returns:
The same scalar
1 - alphaquantile repeated for every row.- Return type:
ndarray, shape (n_rows,)
- tsbootstrap.uq.sliding_window_halfwidths(residuals: ndarray[tuple[int, ...], dtype[float64]], n_rows: int, *, alpha: float = 0.1, window: int | None = None) ndarray[tuple[int, ...], dtype[float64]][source]
Time-local half-widths: a rolling
1 - alphaquantile of the residuals.For row
tthe width is the1 - alphaquantile of the most recentwindowresiduals ending att(the trailing window shrinks at the start of the series, where fewer residuals are available). The width therefore widens in high-volatility stretches and tightens in calm ones, which is the defining time-local mechanism of EnbPI (Xu & Xie 2021) and the static calibrator’s missing piece.- Parameters:
residuals (ndarray, shape (m,)) – Time-ordered out-of-bag absolute residuals (the calibration scores).
n_rows (int) – Number of prediction rows to emit a width for. Each row
tuses the window of residuals ending atmin(t, m - 1), so out-of-sample rows beyond the calibration set reuse the final trailing window.alpha (float) – Target miscoverage; the interval target coverage is
1 - alpha.window (int, optional) – Trailing window length. Defaults to
min(len(residuals), 50).
- Returns:
Per-row half-width; non-constant whenever local volatility varies.
- Return type:
ndarray, shape (n_rows,)