Venn-Abers predictors: calibrated probability intervals.
Classes
Probability intervals with a validity guarantee, not point estimates.
__init__( self, increasing: bool = True) -> None, )
Overview
- For a test score s, hypothetically append it to the calibration
- Run isotonic regression on each augmented set.
- The two fitted values at s are p_0 and p_1.
- The true calibrated probability is guaranteed to lie between them.
Theory
Under exchangeability, the multiprobability prediction \{p_0, p_1\} is valid: one of the two is the perfectly calibrated probability of the test label. The width p_1 - p_0 shrinks as O(1/n) in the calibration size, so it doubles as a diagnostic — a wide interval says the calibration set does not pin the probability down in that score region.
For a single actionable number, the standard summary is
which transform returns; predict_proba_interval returns the pair itself.
Each hypothesis needs its own isotonic fit, so the implementation runs one PAVA pass per distinct insertion position per direction, using the shared C++ kernel and caching by position. Test points are deliberately not batched into a single fit: a batch of identical hypothesised labels perturbs the isotonic regression far more than the one point the definition adds, which inflates the interval.
Parameters
increasing
Attributes
calibration_scores_
calibration_labels_
calibration_scores_.
classes_
fit.
fitted_
fit has been called.
Notes
Complexity. Fitting is O(n \log n) — just a sort. Predicting is O(u n) for u distinct insertion positions among the m test scores, since each needs its own PAVA pass; repeated positions are cached. The O(n \log n) GCM formulation of Vovk et al. would remove the linear factor and is the natural next optimisation.
When to use. Reach for Venn-Abers when a miscalibrated probability is expensive and you need to know how much to trust the calibration itself — medical triage, pricing, any decision with an asymmetric cost. For a plain point probability with less machinery, use IsotonicCalibrator.
References
See Also
>>> import numpy as np
>>> from tuiml.uncertainty import VennAbersCalibrator
>>> rng = np.random.default_rng(0)
>>> scores = rng.uniform(0, 1, 400)
>>> y = (rng.uniform(0, 1, 400) < scores).astype(int)
>>> va = VennAbersCalibrator().fit(scores, y)
>>> p0, p1 = va.predict_proba_interval(np.array([0.2, 0.8]))
>>> bool(np.all(p0 <= p1))
True
>>> proba = va.transform(np.array([0.2, 0.8]))
>>> bool(proba[0] < proba[1])
True
Methods
fit
(self, scores: np.ndarray, y: np.ndarray) -> 'VennAbersCalibrator'
fit
(self, scores: np.ndarray, y: np.ndarray) -> 'VennAbersCalibrator'
Store the calibration set that later hypotheses are appended to.
Parameters
scores
y
Returns
self
predict_proba_interval
(self, scores: np.ndarray) -> tuple
predict_proba_interval
(self, scores: np.ndarray) -> tuple
Return the Venn-Abers probability interval for each score.
Parameters
scores
Returns
p0
p1
p0; the width reports calibration uncertainty.
transform
(self, scores: np.ndarray) -> np.ndarray
transform
(self, scores: np.ndarray) -> np.ndarray
Collapse the probability interval to a single calibrated value.
Parameters
scores
Returns
proba
p1 / (1 - p0 + p1) summary of the interval.