Personalize this lesson
Adapt explanations and teaching visuals to your background and preferred voice.
A latency model predicts that the next request will finish in 40 milliseconds. That single number doesn't tell an on-call engineer whether a 50-millisecond deadline is safe. A prediction interval such as [32,48] makes the decision visible, but the range earns trust only when its coverage evidence comes from requests the model never saw during fitting.
Statistical Learning and Generalization established why untouched evidence matters. Here, conformal prediction uses a separate calibration split to turn those model errors into finite-sample prediction sets.[1]

Freeze the model before measuring its errors
Before calculating a radius, decide which rows are allowed to influence it. Three slices play different roles:
| Split | Role | Prohibited shortcut |
|---|---|---|
| Training | Fit the latency model | Report training residuals as independent calibration |
| Calibration | Measure errors from the already-frozen model | Tune the model repeatedly against calibration outcomes |
| Test or deployment | Check interval coverage on new requests | Include those outcomes in the original coverage claim |
For a 40-millisecond prediction, an observed 44 milliseconds gives an error of 4; an observed 53 gives an error of 13. A simple regression nonconformity score records that miss as the absolute residual . Larger scores mean the point prediction missed by more.

The diagram turns those held-out errors into one radius. Its guarantee needs exchangeable calibration and future examples: their joint distribution stays the same when their positions are swapped. Shuffling files doesn't repair a changed deployment distribution.
A model was repeatedly tuned using the same nine examples later labeled as its calibration split. Why can't their residuals support the ordinary split-conformal guarantee?
Answer
Those outcomes influenced the model before calibration, so their residuals are no longer held-out measurements of a frozen predictor. Their apparent errors can be optimistically small, and the ordinary exchangeability argument for fresh request outcomes no longer follows.
Let nine errors choose the radius
Nine held-out requests produce these sorted absolute errors, measured in milliseconds. The list gives us a small decision to make: which position should set the radius for the next request?
For target coverage and calibration size , split conformal selects a corrected residual quantile. Its order statistic, the value at a numbered position in the sorted sample, has rank:[1]
Rank eight points to a residual of 8 milliseconds. A new prediction of 40 milliseconds therefore gets:
The next cell repeats that arithmetic, checks that this calibration size can reach the requested coverage, and prints the interval. Predict its rank and bounds before running it.
1from math import ceil
2
3residuals = sorted([2, 3, 3, 4, 5, 6, 7, 8, 12])
4coverage = 0.80
5rank = ceil((len(residuals) + 1) * coverage)
6
7if rank > len(residuals):
8 raise ValueError("Calibration sample is too small for the requested finite interval")
9
10radius = residuals[rank - 1]
11prediction = 40
12
13print(f"corrected rank: {rank} of {len(residuals)}")
14print(f"calibration radius: {radius} ms")
15print(f"prediction interval: [{prediction - radius}, {prediction + radius}] ms")1corrected rank: 8 of 9
2calibration radius: 8 ms
3prediction interval: [32, 48] msNow raise the target to 95% while keeping nine calibration rows. The rank is , but no tenth observed residual exists. A distribution-free finite interval at that level isn't available from this tiny sample; gather more calibration data or explicitly admit an unbounded set.
Why does the example choose the eighth residual instead of simply multiplying nine by 0.8 and rounding down?
Answer
The finite-sample conformal rank is ceil((n+1)(1-alpha)). For nine calibration rows and 80% coverage, that is ceil(10 times 0.8), which selects the eighth order statistic.
Watch coverage appear in new requests
The interval [32,48] covers an actual 44-millisecond outcome and misses 53 milliseconds. That single request tells us what the rule does, not whether the rule is reliable. Coverage is measured across a stream of new comparable examples.
Keep radius 8 fixed and inspect four new request outcomes. Before running the cell, predict how many will land inside the interval.
1predictions = [40, 42, 38, 44]
2observed = [44, 48, 35, 55]
3
4covered = [abs(actual - guess) <= radius for guess, actual in zip(predictions, observed)]
5for guess, actual, is_covered in zip(predictions, observed, covered):
6 print(f"predicted={guess} actual={actual} covered={is_covered}")
7
8print(f"observed coverage: {sum(covered)}/{len(covered)}")1predicted=40 actual=44 covered=True
2predicted=42 actual=48 covered=True
3predicted=38 actual=35 covered=True
4predicted=44 actual=55 covered=False
5observed coverage: 3/4A four-row observed coverage of 75% doesn't contradict an 80% marginal coverage guarantee. Four requests are a noisy sample, so the observed fraction can move around the target.
The guarantee averages over repeated exchangeable draws and the calibration sample's randomness. It isn't an exact fraction in every short deployment window, and it isn't a guarantee conditional on one fixed realized calibration set.
Find the traffic the average hides
The 75% result is one population summary. Under the exchangeability condition above, standard split conformal provides marginal coverage over the overall population.[1][2]
That guarantee isn't conditional coverage for each subgroup or individual feature value. If short prompts receive 96% coverage while long prompts receive 54%, an aggregate passing threshold can hide unsafe long-request behavior.
An 80% conformal target passes across all traffic, but long requests are covered only 54% of the time. Does the population-wide guarantee refute the long-request measurement?
Answer
No. Standard split conformal guarantees marginal coverage across the exchangeable population, not equal conditional coverage for every prompt-length subgroup. A common well-covered group can keep the aggregate above target while a smaller long-request group remains unsafe.
The failure patterns below turn those distinctions into operational diagnoses:
| Failure | Symptom | Appropriate response |
|---|---|---|
| Model trained on calibration rows | Residuals look too small | Refit with a genuinely separate calibration split |
| Prompt lengths shift after launch | Recent interval misses cluster on long prompts | Recalibrate on representative recent traffic |
| Tenant-specific error differs | Overall coverage passes while one tenant fails | Measure per-tenant or group-conditional coverage |
| Noise grows with request size | Constant intervals are too narrow for large requests | Use a better nonconformity score or group-aware method |
| Calibration sample is tiny | Desired rank exceeds available observations | Gather more data or acknowledge an unbounded set |
Turn coverage into an operating check
A coverage number without interval width is incomplete. An interval spanning every plausible latency never misses, but it can't guide a 50-millisecond deadline.
Start the audit with one row per held-out request: frozen prediction, observed latency, absolute residual, sorted residual rank, and approved calibration-slice membership.
For the nine worked residuals, verify corrected rank eight, radius 8 milliseconds, and interval [32,48] for a 40-millisecond prediction. Then check overall coverage, long-request coverage, interval width, training/calibration separation, and the unsupported 95% target that would require a nonexistent tenth residual. Keep the deployment gate closed when exchangeability, subgroup safety, or a finite requested quantile isn't established.
For one final run, build a coverage scorecard from held-out rows. Verify each interval, calculate overall and long-request coverage, record interval width, and note whether exchangeability and the requested finite rank hold. Keep that scorecard with the deployment gate so a later traffic shift has evidence to trigger recalibration.