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, EnbPIEnsemble is 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 new X. 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-adaptive aci_halfwidths() / nexcp_quantile(). enbpi_intervals() and fit_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: object

Fit/predict EnbPI ensemble: retain the bootstrap clones, calibrate on demand.

fit bootstraps the row indices with an observation-resampling method, fits a clone of estimator on 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_interval then 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 approximately 1 - alpha under 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-sample predict_interval(); set False to 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 on X_new (requires the ensemble to have been fitted with store_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 global 1 - alpha quantile for every row.

    • 'sliding_window', rolling 1 - alpha quantile (time-local EnbPI); accepts window (default min(len, 50)).

    • 'aci', Adaptive Conformal Inference; requires test_scores (the time-ordered realized |y_t - prediction_t|, one per row) and accepts gamma (default 0.05).

    • 'nexcp', recency-weighted quantile; accepts decay (default 0.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 get nan.

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 - alpha quantile of the out-of-bag absolute residuals. Coverage is approximately 1 - alpha under 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, use EnbPIEnsemble directly.

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 horizon steps past the data n_bootstraps times 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 = 0 recovers static conformal.

Returns:

  • halfwidths (ndarray, shape (T,)) – Interval half-width q_t to 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 - alpha regardless 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) by decay ** (n - 1 - i) and returns the smallest score whose normalized weighted CDF reaches 1 - alpha. With decay = 1 this is the ordinary empirical quantile; smaller decay puts 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 - alpha quantile, broadcast to n_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 - alpha quantile 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 - alpha quantile of the residuals.

For row t the width is the 1 - alpha quantile of the most recent window residuals ending at t (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 t uses the window of residuals ending at min(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,)