Cross-validation-based conformal regression (CV+ and jackknife+).
Classes
CV+ prediction intervals that use every training sample twice.
__init__( self, estimator: Any, alpha: float = 0.1, cv: int = 5, aggregate: str = 'median', shuffle: bool = True, random_state: Optional[int] = None) -> None, )
Overview
-
Partition the training data into
cvfolds. - For each fold, fit a model on the other folds and record the absolute
- At prediction time, every fold model predicts the test point.
- The interval bounds are quantiles of the fold predictions shifted by
Theory
Let \hat{f}_{-k(i)} be the model fitted without the fold containing sample i, and R_i = |y_i - \hat{f}_{-k(i)}(x_i)| its out-of-fold residual. The CV+ interval is
where q^- and q^+ are the \lfloor \alpha(n+1) \rfloor smallest and largest order statistics. Unlike split conformal, the guarantee is the slightly weaker
in the worst case, though empirically CV+ achieves close to 1 - \alpha and is never observed to fall below it on real data. The factor-of-two slack is the cost of reusing the data.
Setting cv=n_samples recovers the jackknife+ — see JackknifePlusRegressor.
Parameters
estimator
alpha
cv
aggregate
predict. Interval bounds always use the order statistics above, independent of this choice.
shuffle
random_state
Attributes
estimators_
fold_index_
scores_
quantile_
fitted_
fit has been called.
Notes
Complexity. cv model fits at training time and cv predictions per test batch, plus O(n \log n) for the order statistics. This is cv times the cost of split conformal in both phases — the reason JackknifePlusRegressor is only practical on small data.
When to use. Use CV+ when data is scarce enough that holding out a calibration split visibly hurts the model, and when cv extra fits are affordable. On large data, split conformal gives a strictly stronger guarantee for a fraction of the compute.
References
See Also
>>> import numpy as np
>>> from tuiml.uncertainty import CVPlusRegressor
>>> from tuiml.algorithms.trees import DecisionTreeRegressor
>>> rng = np.random.default_rng(0)
>>> X = rng.normal(size=(200, 3))
>>> y = X[:, 0] * 2.0 + rng.normal(0, 0.5, 200)
>>> cp = CVPlusRegressor(DecisionTreeRegressor(max_depth=4), cv=5, random_state=0)
>>> cp.fit(X, y)
CVPlusRegressor(estimator=DecisionTreeRegressor(), alpha=0.1, cv=5)
>>> cp.predict_interval(X[:4]).shape
(4, 2)
Methods
fit
(self, X: np.ndarray, y: np.ndarray) -> 'CVPlusRegressor'
fit
(self, X: np.ndarray, y: np.ndarray) -> 'CVPlusRegressor'
Cross-fit the estimator and collect out-of-fold residuals.
Parameters
X
y
Returns
self
Jackknife+ intervals — the leave-one-out limit of CV+.
__init__( self, estimator: Any, alpha: float = 0.1, aggregate: str = 'median') -> None, )
Overview
- For each training sample, fit a model on all the others.
- Record that sample's leave-one-out absolute residual.
- Form the interval from the order statistics of the leave-one-out
Theory
Jackknife+ is CVPlusRegressor with cv = n_samples. It inherits the worst-case 1 - 2\alpha bound
but is provably at least as tight as CV+ with fewer folds, and in practice covers at very close to the nominal 1 - \alpha.
Note the distinction from the plain jackknife, which shifts a single model's prediction by leave-one-out residuals: that has no coverage guarantee at all and can fail badly when the fitting algorithm is unstable. The "+" is what pairs each residual with its own leave-one-out model.
Parameters
estimator
alpha
aggregate
Attributes
estimators_
scores_
fitted_
fit has been called.
Notes
CVPlusRegressor with cv=10, which is close in tightness and orders of magnitude cheaper.References
See Also
>>> import numpy as np
>>> from tuiml.uncertainty import JackknifePlusRegressor
>>> from tuiml.algorithms.linear import LinearRegression
>>> rng = np.random.default_rng(0)
>>> X = rng.normal(size=(60, 2))
>>> y = X[:, 0] * 2.0 + rng.normal(0, 0.3, 60)
>>> cp = JackknifePlusRegressor(LinearRegression(), alpha=0.1)
>>> cp.fit(X, y)
JackknifePlusRegressor(estimator=LinearRegression(), alpha=0.1)
>>> cp.predict_interval(X[:3]).shape
(3, 2)