Prediction Intervals and Split Conformal Prediction
Build distribution-free prediction intervals and label sets with split conformal prediction, including finite-sample quantiles and marginal coverage guarantees.
Machine Learning from ScratchAll chapters Prediction Intervals and Split Conformal PredictionFull chapter · Sections in this chapter1 / 10 ↓
Reading tools Definitions, links & notes
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
Prediction Intervals and Split Conformal Prediction
A regression model hands us a single number: . If we are forecasting tomorrow's demand, pricing an insurance contract, or deciding whether a patient needs a follow-up test, that number alone does not describe how wrong the prediction might be. A prediction of 1,000 units that is usually off by 20 is a different business situation from one that is usually off by 400, even though both point predictions are 1,000.
Part II introduced confidence intervals for population quantities. In regression, a confidence interval for the conditional mean describes estimation uncertainty about that mean. A future observation has additional randomness around it. A prediction interval targets that future observation. The familiar Gaussian linear-model construction uses distributional and variance assumptions; split conformal takes a different route.
Split conformal prediction takes a fitted predictor, calibrates a score on examples held out from fitting and model selection, and returns an interval or label set. Its finite-sample guarantee requires the calibration and fresh test scores to be exchangeable, conditional on the fitting procedure. It guarantees marginal coverage over calibration and test draws. It does not guarantee coverage for each individual, subgroup, fixed calibration sample, or observed test batch.
The mechanism is simple. We measure how badly the model misses on the calibration set, take a particular quantile of those misses, and add that quantile as a margin around every future prediction. Almost all of the subtlety lives in exactly which quantile to take, and in understanding precisely what the resulting guarantee does and does not promise. That is where we will spend our time.
This chapter builds directly on Probability Calibration, where we asked whether a model's stated probabilities match observed frequencies. Conformal prediction asks a related but distinct question for regression: not whether the model is right, but how wide a band we must draw around it before a stated fraction of future observations fall inside.
Advantages
The coverage bound holds in finite samples under exchangeability of the held-out scores. It does not require a Gaussian error distribution or a correctly specified predictor. A fixed Gaussian margin can under-cover when its assumptions fail. Split conformal instead calibrates the chosen score, including an infinite threshold when the calibration sample is too small for a finite cutoff. The resulting sets can be wide or uninformative while remaining marginally valid.
Conformal prediction wraps a fitted model. Linear regression, a boosted ensemble, or another predictor can supply the score, provided fitting and selection are settled using fitting data only. The residual-score version needs predictions on calibration examples and a sort of scores, conventionally time for sorting. This extra work depends on the predictor and calibration size; it is not universally negligible.
Changing the score can change the shape and adaptivity of the output. Absolute residuals give constant-width regression intervals; positive input-dependent scaling can redistribute width; class-probability scores give label sets. All use the same marginal rank argument when their scores are fixed before calibration. Better probability calibration or a different score may improve set efficiency, but neither guarantees smaller sets or better subgroup coverage in every problem.
Interval width and set size can inform operational rules, such as routing broad intervals to human review. Such a rule is an additional selection step: marginal coverage of the original procedure does not imply the same coverage among automatically accepted cases. Evaluate the selected cases separately and distinguish a useful triage signal from a calibrated conditional error rate.
Disadvantages
The guarantee is marginal. It averages over calibration data and a fresh test point, rather than promising the target coverage at every input or within every subgroup. Constant-width intervals can over-cover low-noise regions and under-cover high-noise regions. A particular realized calibration set and finite test batch can also have coverage below nominal. None of these observations alone contradicts the marginal theorem.
Exchangeability can fail under distribution shift and ordinary serial dependence. A future regime can differ from the calibration period, and a sequence whose dependence changes with temporal lag is generally not invariant to arbitrary permutations. Dependence alone is not enough to rule out exchangeability: dependent exchangeable samples exist. A chronological split or rolling recalibration does not by itself restore the ordinary split-conformal guarantee.
Holding out calibration data leaves fewer observations for fitting. When data are scarce, related methods such as jackknife+ and CV+ reuse observations through additional model fits. Their constructions and finite-sample bounds differ from ordinary split conformal. Jackknife+ is the leave-one-out special case of CV+, obtained when each fold contains one observation. These methods should not be treated as interchangeable ways to preserve the split-conformal guarantee. This chapter keeps the separate fitting and calibration roles visible.
Conformal calibration does not improve the predictor itself. Large calibration errors can require a wide margin, and a constant margin can still leave a difficult subgroup under-covered. A finite calibration sample does not force the realized test fraction to meet nominal. Width is useful alongside coverage, but model choice, score choice and sampling variation all affect it.
Discrete scores and ties can make deterministic sets conservative. Classification sets can contain several labels or be empty. For the probability-threshold score, an empty set means that no class probability reaches the calibrated threshold. It does not by itself establish that the input is out of distribution. A downstream rule can add a label to an empty set, which only enlarges the set and therefore cannot reduce inclusion coverage.
Exchangeability, marginal coverage, and failure modes
Exchangeability is the assumption that the joint distribution of the points (the calibration points plus the test point) is invariant to permutation of their indices. In symbols, for any permutation of , the joint distribution of equals that of , where . Independent and identically distributed data are exchangeable. Exchangeable data need not be independent: a uniformly ordered sample without replacement from a fixed population is exchangeable but dependent. A calibration/test distinction that systematically changes the joint distribution lacks this permutation symmetry.
Write for the prediction set returned at input . Let be the target miscoverage level, so is the target inclusion probability.
Marginal coverage is , with probability over calibration and test draws. Conditional coverage would require at every relevant . For regression over unrestricted distributions with continuously varying covariates, exact distribution-free conditional coverage has strong impossibility results: nontrivial finite-length intervals cannot be guaranteed uniformly without additional restrictions (Vovk, 2012; Barber, Candès, Ramdas and Tibshirani, 2021). Group-conditional guarantees and assumptions about the conditional distribution are different, more restricted targets.
These distinctions give practical failure checks. Compare calibration and deployment populations; check whether temporal or clustered structure defeats exchangeability; and keep model fitting, preprocessing and selection outside the calibration and test outcomes. Training residuals can be optimistic because fitting used their responses. Reusing calibration outcomes for model selection can also destroy the held-out symmetry argument. Either practice removes the ordinary proof; it does not imply an identical numerical shortfall in every dataset.
Formula
We now build the machinery. The aim is to turn a bare point prediction into a band, and to do it in a way that comes with a guarantee we can state precisely. Three questions have to be answered along the way:
- What are we trying to cover? Not the regression surface, but the next observation. If the response retains nondegenerate noise, additional fitting data do not remove that noise.
- How do we measure a miss? We need a number that grows when a candidate observation becomes implausible under the fitted model, a nonconformity score.
- How do we convert finitely many measured misses into a margin that is valid for the next one? This is where exchangeability enters, and where a seemingly cosmetic turns out to carry the entire guarantee.
Notation throughout: fit the predictor and score on , then use a disjoint calibration set . A fresh test pair is . Conditional on the fitted score function, require these calibration and test scores to be exchangeable. Independent observations from one distribution, with an independent fitting split, are a sufficient setting. The separate test sample in the example evaluates the completed procedure.
Confidence intervals, prediction intervals, and prediction sets
Before building the procedure, distinguish three targets: a population quantity, a future observation, and a class label. The target determines which inclusion statement we need to establish.
A confidence interval targets a population quantity, such as a mean, coefficient or quantile. For example, an interval for aims to contain that fixed conditional mean across repeated fitting samples at the specified input. Its width can shrink under regular consistent estimation; shrinking is not an unconditional property of every confidence procedure.
A prediction interval targets a future observation and aims for a specified inclusion probability. It accounts for response variation as well as uncertainty in the fitted predictor. With persistent nondegenerate noise it can remain wide even when mean estimation is precise. For a symmetric noise distribution, a symmetric band around its center uses the quantile of the absolute noise as its half-width.
A prediction set is the classification analogue: a random subset with . Whereas an interval is an ordered range on the real line, a set is an unordered collection of labels, and its natural size measure is cardinality rather than length.
For comparison, consider the correctly specified linear model with fitting observations and nonconstant predictors plus an intercept. In this comparison only, denotes fitting size rather than calibration size. Assume , a fixed full-rank design, independent Gaussian errors with variance , and an independent future error with the same variance. At a fixed new design vector , the Gaussian prediction interval is
where:
- : the fitted value at the new input
- : the residual variance estimate (the sum of squared residuals divided by )
- : the full-rank training design matrix, including an intercept column and nonconstant predictors
- : the quantile of a distribution with degrees of freedom
- : the new-point leverage, with containing the intercept and the same predictors as the design matrix
The "" inside the square root reflects the additional noise of the future observation. It is there because the error of prediction decomposes as
Under these Gaussian-model assumptions, conditional on the fixed design and new input, the new observation error is independent of the fitting-sample estimation error. Their variances therefore add:
where:
- : the future observation whose value is not yet known
- : the fitted model's prediction at the future input
- : the true conditional mean
- : the noise variance
Under regular increasing-sample designs with a fixed number of predictors, mean-estimation uncertainty decreases. The mean confidence interval uses only the estimation term, while the prediction interval also contains the future-noise term. For a 95% Gaussian interval, its large-sample noise margin is approximately . This comparison explains the extra in the displayed square root.
The weakness of this construction is the assumption stack: Gaussian errors, constant variance, a correctly specified linear model, and independent observations. Split conformal keeps the same target, the observation, but replaces every one of those assumptions with exchangeability alone.
Calibration scores and finite-sample quantiles
The engine of conformal prediction is the nonconformity score. The idea is to condense each candidate pair and the fitted model into a single number, , that grows as the pair becomes less plausible under the model. A score is doing its job when it is small for observations the model explains well and large for observations it explains poorly.
For regression with a scalar response the standard choice is the absolute residual
where:
- : the nonconformity score for calibration point , measuring how far the model's prediction misses the observed response
- : the observed response for calibration point
- : the fitted model's prediction for calibration point
For classification with fitted class probabilities the standard choice is
where:
- : the nonconformity score for calibration point , equal to one minus the probability of the observed label
- : the fitted probability the model assigns to the observed label at input
- : the observed class label of calibration point
This score is small when the model assigns high probability to the observed label and large when it assigns low probability. Many other scores are possible; we will meet several. Choose and freeze the score function without using the calibration or test outcomes for fitting or selection. At prediction time, evaluate it for candidate labels or responses; the unknown true future response is not supplied to the procedure.
Given the scores , sort them and write the order statistics as
The conformal quantile at miscoverage level is the order statistic at index
For , set . If , set and return the full response space. Clipping to would lose the requested guarantee at small calibration sizes.
where:
- : the calibration set size
- : the miscoverage level, so is the nominal coverage
- : the ceiling index , which can equal ; that case uses an infinite threshold
- : the -th smallest calibration score
- : the conformal score threshold; for absolute-residual regression it is the interval half-width
This implementation selects an order statistic without interpolation. Other quantile conventions need to be checked against the stated finite-sample cutoff; an ordinary interpolating call is not generally equivalent.
The symbol denotes the ceiling function: the smallest integer greater than or equal to its argument. For and we get , so and .
To see the role of , first assume the exchangeable scores are almost surely distinct. The test score then has a uniform rank in . For , it falls below the th calibration score exactly when that rank is at most . Thus
where:
- : the nonconformity score of the future test point, an exchangeable draw from the same pool as the calibration scores
- : the -th smallest calibration score, used as the conformal quantile
- : the ceiling index , computed from the calibration size and miscoverage level
The equality holds because happens exactly when the rank of is one of the smallest.
The rank calculation behind the guarantee can be inspected directly. With and , we have , so . Under distinct exchangeable scores, the test score has eleven equally likely ranks, and ranks one through ten fall at or below the calibrated cutoff ; only the largest rank falls outside it. The cell below prepares the rank probabilities for the figure: it computes the ceiling index without clipping, builds uniform rank probabilities, and flags the ranks covered by the cutoff. This is an exact rank illustration, with no sampled data.
PythonIn [2]Expand
import numpy as np
n_rank = 10
alpha_rank = 0.10
k_rank = int(np.ceil((n_rank + 1) * (1 - alpha_rank)))
ranks = np.arange(1, n_rank + 2)
rank_prob = np.full(ranks.shape, 1.0 / (n_rank + 1))
covered_rank = (k_rank - ranks) >= 0VisualizationOut [3]Expand

Setting gives
The ceiling gives the lower bound in the distinct-score case, provided so the displayed finite order statistic is used. Below the finite-threshold cutoff, , so and the infinite threshold covers the full response space. With ties, independently randomizing the order within equal scores gives a uniform rank, and the deterministic event includes every rank-at-most- case. Its probability is therefore at least , although equality need not hold. If , the infinite threshold covers the full response space. Using or an ordinary interpolating quantile does not supply this general finite-sample guarantee; the values can coincide for some inputs, so the issue is the missing guarantee rather than universal under-coverage.
There is a matching upper bound. If the scores are almost surely distinct, then
so the guarantee is tight to within . For and , coverage lands between and roughly . This statement requires exchangeable scores, while leaving the response distribution otherwise unrestricted.
A finite threshold under this convention requires , equivalently . At least nine calibration observations permit a finite 90% threshold; at least 99 permit a finite 99% threshold. Smaller calibration samples still give valid sets through , but those sets are uninformative. These cutoffs do not guarantee stable or narrow finite thresholds.
The finite-threshold cutoff is only part of the story. At fixed , the guaranteed floor equals one while the infinite-threshold branch is active at small calibration sizes. Once a finite threshold exists, the ceiling index makes the floor vary nonmonotonically as grows. The figure below plots the rank-based floors for calibration sizes from 1 to 200. It evaluates the formula directly, with no sampled data.
PythonIn [4]Expand
n_grid = np.arange(1, 201)
def coverage_floor_for(nominal):
alpha_level = 1.0 - nominal
k = np.ceil((n_grid + 1) * (1.0 - alpha_level)).astype(int)
return np.where(k > n_grid, 1.0, k / (n_grid + 1))
coverage_floor_90 = coverage_floor_for(0.90)
coverage_floor_95 = coverage_floor_for(0.95)VisualizationOut [5]Expand

This bound arises because requires , equivalently since is an integer. Solving:
Split conformal regression and classification
Putting the pieces together, split conformal regression is a four-step procedure, sometimes called inductive conformal prediction (Papadopoulos et al., 2002). Notice how cleanly the steps separate the modelling from the calibration. The model is fit and frozen first, and only then does the conformal machinery measure its mistakes.
- Fit the point predictor on . Nothing about this step is special; use whatever model you like and whatever model selection procedure you like, as long as it never touches .
- Compute calibration scores for .
- Compute . Set if and otherwise.
- For a new input , return when is finite, and return the full response space when .
The interval is the point prediction plus or minus a constant margin. When is finite its width is exactly everywhere, independent of ; when the set is the full response space. Here is the conformal quantile computed from calibration scores, and there is no guarantee that averaging a realized test batch reproduces the nominal coverage. That is both its simplicity and its main weakness, and we will return to the consequence shortly.
Step 4 is worth reading backwards, because that is how the guarantee is usually proved. The event is the same as , which is the same as . Everything reduces to the rank argument in the previous subsection. The proof does not require a particular predictor family or parametric response law. Its sampling argument uses exchangeability of the held-out scores.
For classification, the same four steps apply with a different score, and step 4 becomes a set construction:
where:
- : a candidate class label in
- : the fitted probability the model assigns to label at input
- : the conformal quantile from the calibration scores, so is the probability threshold
For the score , classification keeps labels whose fitted probability is at or above . The calibration step chooses the threshold automatically, in such a way that the fraction of calibration points whose nonconformity score exceeds is at most . This uses held-out outcomes to calibrate set inclusion. It is different from Probability Calibration, which evaluates or adjusts probability reliability. Accurate class probabilities are useful, but are not required for this marginal set-coverage proof.
The threshold applies to each candidate label, so set size varies with the probability vector and the calibrated cutoff. Several labels may pass, or none may pass. The marginal guarantee controls overall inclusion under its sampling assumptions. For a proper nonempty subset of the class space, set size alone does not determine its conditional inclusion probability. Set size alone also does not establish an out-of-distribution interpretation.
Mathematical Properties
Several properties follow from the construction and are worth naming. Treat them as a checklist of what the formula does and does not give us.
- Coverage is finite-sample. Under the score-exchangeability condition, holds for every and , using the infinite-threshold branch when necessary. No asymptotic approximation is used.
- The guarantee is distribution-free over score distributions satisfying exchangeability. The predictor and score construction must be fixed before calibration; no correctly specified parametric response model is required.
- Monotonicity in . With the same calibration scores, decreasing cannot decrease or . The sets are nested, although the discrete index can stay unchanged over a range of levels.
- Invariance to monotone rescaling of scores. Replacing by any strictly increasing transform yields the same prediction sets, since the ranking is unchanged. The transform must be well-defined and the same for every calibration and candidate score. The small-calibration branch still returns the full response space; it does not require evaluating . Dividing by an input-dependent scale is a different score construction and can change the resulting sets.
- Width depends on the score distribution. With a fixed score and independent calibration samples growing in size, the empirical cutoff converges to its population score quantile at continuity and identifiability points. When the fitted score also changes, additional consistency assumptions are needed. Improving a predictor under one loss does not universally shrink every conformal cutoff.
- Ties can make deterministic inclusion conservative: may exceed . This removes the distinct-score upper slack bound; it does not by itself prove that an interval can be narrowed while keeping the same guarantee.
Example
A small numerical example makes the quantile convention concrete. Let us work through a complete split conformal calculation by hand with ten calibration points and a simple regression model, so that every index in the formula is visible.
We have fitted on a training set and evaluated it on a calibration set of points, obtaining absolute residuals. Sorted, they are
The largest residual is in the response units of this illustrative example. Suppose we want 90% coverage, so and . The index is
where:
- : the calibration set size
- : the miscoverage level, so is the nominal coverage
- : the ceiling index, which selects the -th smallest calibration score
Because , the conformal quantile is the largest observed residual, . A new input with gets the interval
If the realized value turns out to be , it is inside the interval and this particular point is covered. If , it is not; the interval width of is simply not enough to catch a miss that large. The marginal guarantee averages over calibration and fresh test draws; it does not certify this particular point.
With almost surely distinct exchangeable scores, the repeated-sample coverage for this rule is . With ties, that value is a lower bound. This is a statement about the procedure over calibration and test draws, not the conditional coverage of the particular ten residuals displayed above. At this level and calibration size, the rule selects the sample maximum.
Now compare an 80% interval, . Then
where:
- : the miscoverage level, so
- : the resulting index, so
- : the calibration set size, giving the rank lower bound ; equality holds for almost surely distinct exchangeable scores, while ties can, but need not, increase coverage
With , the same prediction becomes , narrower as expected, with guarantee .
The convention matters here. Suppose we had carelessly used instead. For that gives and , exactly the margin we should have used for the 80% interval. The reported interval would cover about of calibration points, matching the nominal level on the calibration data, yet its coverage of future points is only guaranteed at the lower level , not at the nominal . The shortfall comes from replacing with : the resulting index is too small by roughly one position, so at the effective guarantee falls below the nominal . The wrong index can appear correct on the data used to compute it.
Now the classification case. Suppose the same ten calibration points give scores , sorted:
At we again have
So , giving the probability threshold :
- : the resulting index, the tenth smallest calibration score
- : the conformal quantile, equal to
- : the calibrated probability threshold applied to each class
A new input with class probabilities yields the set : and clear the bar and does not. The set has size two. If the true label is , this set misses it. The marginal bound does not assign an error probability to this particular vector or set.
Consider a classifier that spreads its probability mass across all three labels. Suppose the probabilities for some input are . Since all three exceed , the prediction set is all three labels. That input is effectively unclassified, and the set says so. Conversely, an input with probabilities yields the singleton . Set size reports how many labels this score and calibrated threshold retain at that input. It does not supply a calibrated probability that a singleton is correct or prove that an empty set is out of distribution.
Implementation in NumPy and scikit-learn
We build the conformal quantile and interval arithmetic from NumPy primitives, using scikit-learn for the base predictors. Fitting and calibration data construct the intervals; untouched test data evaluate them. The example keeps all three roles disjoint and performs no model or score selection using calibration or test outcomes.
The data are one-dimensional and heteroscedastic, with the noise standard deviation growing quadratically away from the origin. This is a realistic situation where a constant-width interval will struggle, so it doubles as a stress test.
PythonIn [7]Expand
def make_data(n, rng, shift=0.0):
"""y = sin(x) + 0.5x + noise whose sd grows with |x|."""
x = rng.uniform(-3.0, 3.0, size=n) + shift
sigma = 0.30 + 0.25 * x**2 # heteroscedastic noise scale
y = np.sin(x) + 0.5 * x + rng.normal(0.0, 1.0, size=n) * sigma
return x, y
x_all, y_all = make_data(6000, rng)
# Three disjoint roles: fit, calibrate, evaluate.
x_tr, y_tr = x_all[:3000], y_all[:3000]
x_ca, y_ca = x_all[3000:4500], y_all[3000:4500]
x_te, y_te = x_all[4500:], y_all[4500:]We fit an ordinary least-squares line even though the synthetic mean is nonlinear. This makes model misspecification visible. The held-out calibration procedure still has its marginal coverage guarantee under the sampling assumptions, but the predictor and score can produce inefficient intervals or uneven local coverage.
PythonIn [8]Expand
X_tr, X_ca, X_te = (a.reshape(-1, 1) for a in (x_tr, x_ca, x_te))
model = LinearRegression().fit(X_tr, y_tr)
pred_ca = model.predict(X_ca)
pred_te = model.predict(X_te)conformal_quantile implements the explicit order-statistic rule and its infinite-threshold case. regression_intervals adds the calibrated margin to predictions. Sorting and indexing make the finite-sample convention visible; calling an ordinary interpolating quantile at is not generally equivalent.
PythonIn [9]Expand
def conformal_quantile(scores, alpha):
"""Finite-sample conformal quantile: the ceil((n+1)(1-alpha))-th smallest score."""
scores = np.asarray(scores, dtype=float)
if scores.ndim != 1 or scores.size == 0 or not np.all(np.isfinite(scores)):
raise ValueError(
"scores must be a nonempty finite one-dimensional array"
)
if not np.isscalar(alpha) or not np.isfinite(alpha) or not 0 < alpha < 1:
raise ValueError("alpha must lie strictly between zero and one")
n = scores.size
k = int(np.ceil((n + 1) * (1 - alpha)))
if k > n:
return np.inf, k
return float(np.sort(scores)[k - 1]), k
def regression_intervals(pred, q_hat, scale=1.0):
"""Symmetric conformal band; `scale` lets us plug in a local noise estimate."""
return pred - q_hat * scale, pred + q_hat * scale
# Small calibration samples must use the full-space branch rather than clipping.
assert np.isinf(conformal_quantile([0.5, 0.8, 1.2, 2.5], 0.10)[0])
assert conformal_quantile([0.5, 0.8, 1.2, 2.5], 0.20) == (2.5, 4)
assert conformal_quantile(np.arange(19), 0.10) == (17.0, 18)With those in hand, the entire method is six lines.
PythonIn [10]Expand
alpha = 0.10
scores_ca = np.abs(y_ca - pred_ca)
q_hat, k_ca = conformal_quantile(scores_ca, alpha)
lo, hi = regression_intervals(pred_te, q_hat)
covered = (y_te >= lo) & (y_te <= hi)ConsoleOut [11]Expand
n_cal = 1500, k = 1351, q_hat = 2.338 empirical test coverage = 0.909 (nominal target = 0.90) mean interval width = 4.675
The printed coverage describes this realized held-out sample. Constant-width intervals can cover more often near the low-noise center and less often in the noisy tails. The mean width alone does not reveal those local differences, and a result near nominal in this run is not proof of conditional or per-sample validity.
The sweep applies several nominal levels to the same calibration scores and test data. Each row changes the quantile cutoff and recomputes inclusion; for levels that require the infinite-threshold branch the row reports the full response space and its empirical coverage is one. The rows are related evaluations of one sample, not independent replications or a guarantee that every measured coverage exceeds nominal.
PythonIn [12]Expand
alphas = np.array([0.02, 0.05, 0.10, 0.20, 0.30, 0.40, 0.50])
rows = []
for a in alphas:
q, kk = conformal_quantile(scores_ca, a)
l, h = regression_intervals(pred_te, q)
rows.append(
{
"alpha": a,
"nominal": 1 - a,
"k": kk,
"q_hat": q,
"test_coverage": ((y_te >= l) & (y_te <= h)).mean(),
"mean_width": np.mean(h - l),
}
)
coverage_table = pd.DataFrame(rows)| alpha | nominal | k | q_hat | test_coverage | mean_width | |
|---|---|---|---|---|---|---|
| 0 | 0.02 | 0.98 | 1471 | 3.859 | 0.974 | 7.719 |
| 1 | 0.05 | 0.95 | 1426 | 3.083 | 0.957 | 6.167 |
| 2 | 0.10 | 0.90 | 1351 | 2.338 | 0.909 | 4.675 |
| 3 | 0.20 | 0.80 | 1201 | 1.550 | 0.817 | 3.100 |
| 4 | 0.30 | 0.70 | 1051 | 1.086 | 0.720 | 2.172 |
| 5 | 0.40 | 0.60 | 901 | 0.818 | 0.619 | 1.636 |
| 6 | 0.50 | 0.50 | 751 | 0.634 | 0.524 | 1.267 |
The interval width grows as nominal coverage rises. Empirical test coverage fluctuates around the target and can fall below it for a particular calibration sample and finite test set; the marginal theorem does not require every row of this table to exceed nominal.
Constants and Calibration Size
Three key design choices are the miscoverage level , the calibration size , and the score. Understanding their roles is what separates a working deployment from a mysterious one.
The level specifies the tolerated marginal miscoverage. Its choice depends on the decision, the cost of misses and the usefulness of the resulting sets. Calibration size constrains whether that level permits a finite cutoff, and the experiment uses as an illustrative choice.
The calibration size controls rank granularity. With distinct scores the coverage excess from rounding is less than ; this is a probability-scale bound, not a universal bound on excess interval width. For example, and give . Quantile variability also depends on the score distribution, especially its density near the cutoff, so there is no distribution-free sample count that guarantees a stable narrow interval.
The score is the main modelling lever. Absolute residuals give constant width. Normalized residuals give locally adaptive width. Signed residuals give one-sided bounds. We turn to the adaptive case next, because it is where the constant-width weakness becomes visible.
Normalized Scores
Absolute-residual scores use the same cutoff at every input. An input-dependent positive scale can redistribute width. Fix that scale using fitting data only, then calibrate . The same exchangeability proof applies, because the score is fixed before calibration. Here is an error-scale proxy, not a validated conditional standard deviation; the construction does not guarantee improved conditional coverage.
We build by regressing the training absolute residuals on , then clip it away from zero to avoid division blow-ups. This is a crude but honest noise model, and it is fitted only on training data, consistent with the requirement that the score function be frozen before calibration.
PythonIn [14]Expand
abs_res_tr = np.abs(y_tr - model.predict(X_tr))
scale_model = LinearRegression().fit(np.abs(x_tr).reshape(-1, 1), abs_res_tr)
def sigma_hat(x):
"""Local noise scale, fitted on TRAIN residuals only."""
return np.maximum(scale_model.predict(np.abs(x).reshape(-1, 1)), 1e-2)
scores_ca_n = np.abs(y_ca - pred_ca) / sigma_hat(x_ca)
q_norm, k_norm = conformal_quantile(scores_ca_n, alpha)
lo_n, hi_n = regression_intervals(pred_te, q_norm, sigma_hat(x_te))
covered_n = (y_te >= lo_n) & (y_te <= hi_n)ConsoleOut [15]Expand
constant-width coverage = 0.909, mean width = 4.675 normalized-score coverage = 0.898, mean width = 4.138
The printed results show how normalization changes both width and measured coverage. The normalized version allocates less width near the origin and more width at larger , but this crude scale model can still under-cover a region. Its empirical test coverage can also lie below nominal. Both score choices have the same type of marginal guarantee, rather than identical realized coverage or guaranteed local accuracy.
Next we demonstrate the failure mode. We keep the model and the calibrated quantile fixed, then evaluate on data drawn from a shifted input distribution. The input shift breaks exchangeability with calibration, so the ordinary coverage theorem no longer applies. The following evaluation measures what happens in this sample.
PythonIn [16]Expand
x_sh, y_sh = make_data(
1500, np.random.default_rng(99), shift=1.5
) # inputs pushed right
pred_sh = model.predict(x_sh.reshape(-1, 1))
lo_sh, hi_sh = regression_intervals(pred_sh, q_hat)
cov_sh = ((y_sh >= lo_sh) & (y_sh <= hi_sh)).mean()ConsoleOut [17]Expand
exchangeable test coverage = 0.909 shifted test coverage = 0.807 (nominal target = 0.90)
The shifted set is covered far less often than nominal. Nothing about the model or the quantile changed; only the assumption did. The guarantee depends on the specified set-valued procedure and the joint distribution of calibration and test scores. When the deployment distribution differs from the calibration distribution, coverage can fall below nominal and must be monitored empirically.
Classification follows the same recipe with a different score. We generate a three-class problem, fit a multinomial logistic regression, and conformalize it.
PythonIn [18]Expand
Xc, yc = make_classification(
n_samples=6000,
n_features=8,
n_informative=5,
n_redundant=0,
n_classes=3,
n_clusters_per_class=1,
class_sep=0.9,
random_state=0,
)
Xc_tr, yc_tr = Xc[:3000], yc[:3000]
Xc_ca, yc_ca = Xc[3000:4500], yc[3000:4500]
Xc_te, yc_te = Xc[4500:], yc[4500:]
clf = LogisticRegression(max_iter=1000).fit(Xc_tr, yc_tr)
p_ca = clf.predict_proba(Xc_ca)
p_te = clf.predict_proba(Xc_te)
# Nonconformity score: 1 minus the probability assigned to the true label.
s_cls = 1.0 - p_ca[np.arange(yc_ca.size), yc_ca]
q_cls, k_cls = conformal_quantile(s_cls, alpha)
threshold = 1.0 - q_cls
in_set = p_te >= threshold # (n_test, n_classes) boolean
set_sizes = in_set.sum(axis=1)
covered_cls = in_set[np.arange(yc_te.size), yc_te]ConsoleOut [19]Expand
n_cal = 1500, k = 1351, q_hat = 0.690 probability threshold = 0.310 empirical test coverage = 0.895 (nominal target = 0.90) mean prediction set size = 1.18 singleton sets = 0.819 empty sets = 0.000
The printed classification coverage can be slightly below nominal on this finite test sample. In this seeded run there are no empty sets: most inputs receive one label, some receive two, and one receives all three. A calibration-set check is different from a test-set guarantee: by construction, the fraction of calibration scores above the chosen cutoff is at most . None of these summaries gives conditional correctness for a specific singleton.
Key Parameters
The main parameters that govern the conformal procedure are the miscoverage level , the calibration size , and the choice of nonconformity score.
alpha: The miscoverage level, so is the nominal coverage. It specifies the target marginal miscoverage and determines the interval width through the quantile index. There is no universally correct value; this example uses .n(calibration size): Controls the rank grid and the probability-scale rounding bound. A finite threshold requires ; otherwise the full-space branch is valid. Stability and width also depend on the score distribution.scores(nonconformity score): The main modelling lever. Absolute residuals give constant-width intervals; scaled residuals (dividing by a training-only local noise estimate) give locally adaptive width; signed residuals give one-sided bounds. The same strictly increasing scalar transform applied to every score preserves the sets; an input-dependent normalization generally changes them.
Visualizing Split Conformal Prediction
The figures reuse the fitted models, calibration scores and test observations. Ordinary calculation cells prepare the additional cutoff, prediction grid, bin summaries and set-size counts; rendering cells do not refit the models or regenerate the data.
The histogram displays calibration absolute residuals and the cutoffs for two nominal levels. Scores to the right of a cutoff exceed that calibrated margin. The plot illustrates an empirical order statistic, not a promise that an identical fraction of every future batch will lie in the tail. It is a descriptive view of one synthetic calibration sample drawn once from the seeded generator, not a repeated-seed evaluation of variability in the cutoff.
PythonIn [20]Expand
q20, _ = conformal_quantile(scores_ca, 0.20)VisualizationOut [21]Expand

The calibration residuals have a long right tail in this synthetic example. The 90% cutoff exceeds the 80% cutoff, illustrating the width cost of the higher target on these same scores. The size of that increase depends on the score distribution.
The second figure shows the intervals themselves in input space. The band is the model plus and minus the fixed margin, and the points are test observations coloured by whether they fall inside.
PythonIn [22]Expand
grid = np.linspace(x_te.min(), x_te.max(), 200)
grid_pred = model.predict(grid.reshape(-1, 1))VisualizationOut [23]Expand

On this seeded test split, the uncovered points are more frequent at large absolute inputs, where the noise is larger. The band has the same vertical width everywhere, so it cannot adapt to that local noise. The binned coverage in the next figure measures the difference directly.
The third figure quantifies that gap. We split the test inputs into five bins by and compute coverage within each bin, for the constant-width and the normalized-score intervals. The horizontal line marks nominal coverage.
PythonIn [24]Expand
n_bins = 5
bin_edges = np.quantile(np.abs(x_te), np.linspace(0, 1, n_bins + 1))
bin_idx = np.clip(np.digitize(np.abs(x_te), bin_edges[1:-1]), 0, n_bins - 1)
centers, cov_const, cov_norm_b = [], [], []
for b in range(n_bins):
mask = bin_idx == b
centers.append(np.abs(x_te)[mask].mean())
cov_const.append(covered[mask].mean())
cov_norm_b.append(covered_n[mask].mean())VisualizationOut [25]Expand

Because the horizontal axis is , moving right means moving farther from the low-noise center. Constant-width coverage falls at larger . Normalization changes that pattern, but its crude scale estimate also under-covers the innermost bin. Similar overall coverage can therefore coexist with quite different local failures; neither score has a conditional-coverage guarantee.
The fourth figure shows coverage against nominal level for the sweep we computed, with the shifted-distribution result plotted as a single failing point.
VisualizationOut [26]Expand

The exchangeable evaluation lies near the diagonal and can cross it because calibration and test samples are finite. The shifted sample has coverage of about 0.807 at the same nominal 0.90 level. The predictor and calibrated margin are unchanged in that comparison; the input distribution was deliberately shifted. These are evaluations of one calibration sample and one shifted test draw, illustrating a failure mode when the original sampling assumption no longer applies.
The final figure summarizes the classification side. The distribution of prediction-set sizes tells us how much work the conformal threshold is doing.
PythonIn [27]Expand
sizes = np.arange(0, set_sizes.max() + 1)
counts = np.array([(set_sizes == s).sum() for s in sizes])VisualizationOut [28]Expand

Set size counts the labels retained by this particular probability score and calibrated cutoff. A larger set leaves more labels unresolved.
- An empty set necessarily misses the true label.
- A set containing all labels necessarily includes the true label, provided the declared class space is exhaustive.
- The size of a proper nonempty subset, including a singleton when , does not by itself determine an individual inclusion probability.
Set size alone does not identify an out-of-distribution input. Those conditional error-rate and out-of-distribution interpretations require separate evaluation. The displayed counts come from one seeded classification split, so the absence of empty sets is a conditional observation on that sample rather than a repeated-seed estimate of the empty-set rate.
Practical Implications
Split conformal is useful when a fitted predictor needs an additional marginal inclusion guarantee and an appropriate held-out calibration sample is available. Valuation or screening examples can use width to expose the limits of a point prediction. Classification sets can support routing or abstention rules, but those selected decisions need separate evaluation. Sequential demand forecasting additionally requires an argument for its dependence and deployment assumptions; ordinary split conformal is not automatically valid there.
Fit and select the predictor, preprocessing and score using fitting data only, then use held-out calibration outcomes to choose the cutoff. Keep evaluation outcomes outside those choices as well. Data-reuse alternatives such as jackknife+ and CV+ require their own refitting procedures and coverage results. Conformalized quantile regression, discussed in relation to Quantile Regression, calibrates a score built from fitted lower and upper quantile functions. It can redistribute width in heteroscedastic problems; neither the initial quantile fit nor its conformalized version automatically supplies distribution-free conditional coverage.
Plan calibration size against the desired level. A finite cutoff is available when ; otherwise the infinite threshold still gives valid but uninformative sets. The distinct-score rounding excess is below , while the sampling variability and width of the cutoff depend on the score distribution. Report observed coverage together with a width summary and the calibration and evaluation sample sizes.
Two implementation pitfalls are worth checking directly. An ordinary call to np.quantile(scores, 1-alpha) need not implement the required finite-sample index. Computing scores from data used to fit or select the predictor can also invalidate the held-out proof. Training errors can be optimistic, but the size and direction of a particular test-coverage change are not determined solely by model capacity. Use the specified cutoff and keep the data roles separate.
Monitor labeled deployment outcomes for changes in coverage and width. Refreshing calibration data can respond to a changing population, but it does not itself establish exchangeability. A chronological split, a blocked holdout trained on earlier observations, or a rolling-origin split supports honest temporal evaluation when fitting, preprocessing and feature construction use only information available at each forecast origin; it does not automatically provide conformal validity under serial dependence. Specialized online and dependent-data methods have their own assumptions and targets, such as long-run rather than per-step coverage. Their guarantees must be checked for the intended forecasting task.
When intervals are too wide for the intended decision, examine the predictor and the score as well as the data. Lowering asks for higher coverage and cannot narrow intervals built from the same scores. Improving one predictive loss does not universally reduce every conformal quantile, and a narrow interval alone does not establish useful individual coverage. Evaluate the tradeoff on an appropriate held-out population.
Summary
Confidence intervals target population quantities; prediction intervals target future observations. Split conformal constructs sets from a predictor and score fixed before calibration. Compute held-out scores, choose , use the th calibration score when , and use otherwise. Absolute-residual scores turn that cutoff into a symmetric margin around the prediction.
The guarantee averages over calibration and fresh test draws under score exchangeability. Almost surely distinct scores also give the upper slack bound ; ties can be more conservative. Using an ordinary uncorrected empirical quantile does not provide the same general lower-bound argument.
This marginal guarantee does not ensure conditional or subgroup coverage, nor nominal coverage for every realized test batch. Training-only positive normalization can redistribute width, but our crude scale proxy still has local failures. Classification uses the same rank mechanism to threshold candidate label scores. An empty classification set necessarily misses the true label; a set containing every label in an exhaustive class space necessarily includes it. For proper nonempty subsets, cardinality alone does not calibrate individual inclusion.
Check score construction and data roles before interpreting the guarantee. Distribution shift, ordinary serial dependence and reuse of calibration outcomes for model selection can remove its justification. Keep fitting, calibration and evaluation separate, handle the infinite-threshold case explicitly, and monitor labeled deployment outcomes. The coverage theorem is a precise probability statement under assumptions, not a promise that every reported interval or observed batch succeeds.
Quiz
Ready to test your understanding? Take this quick quiz to reinforce what you've learned about prediction intervals and split conformal prediction.
Prediction Intervals and Split Conformal Prediction
Join the discussionAsk a question or share what you learned.
Keep exploring
Reference
Citation details
Cite or share this article.


Comments
Add to the conversation
A question, a correction, or an example from your own work.
No comments yet. Be the first to share your thoughts!