ml-models / Data and evaluation / Calibration core

Calibration

A model that says "90%" should be right about nine times in ten. This page defines what a calibrated probability is, how to see miscalibration in a reliability diagram and measure it with ECE and the Brier score, how Platt scaling, isotonic regression and temperature scaling repair it after training, and why modern neural networks tend to be overconfident, all worked on one small set of predictions.

On this page
  1. Problem
  2. Intuition
  3. Mechanics
  4. What calibrated means
  5. Reliability diagrams and ECE
  6. Proper scoring rules: Brier score and log loss
  7. Recalibration: Platt, isotonic and temperature
  8. Why modern networks are overconfident
  9. Worked example
  10. Twenty held-out predictions
  11. Three recalibrators on the same predictions
  12. What a larger logit buys
  13. Implementation
  14. Tradeoffs
  15. Connections
  16. Read first
  17. Read next
  18. References

Problem

Classification metrics like accuracy and AUC judge a model's decisions and its ranking. Many uses need more: the probability itself. A doctor weighs a 3% risk differently from a 30% one; an ad system multiplies click probability by bid; a fraud team sets its review threshold from the expected cost of each case; a language model decides when to say "I'm not sure". All of these read the number as a frequency.

Most models are not trained to make that reading true. A support vector machine outputs a margin, not a probability. Boosted trees and random forests output averages that are systematically pulled away from, or toward, the extremes. A deep network trained with cross-entropy can be highly accurate and still say 99% on cases it gets wrong a quarter of the time. Calibration is the property that the probabilities mean what they say, and the post-processing that restores it without retraining the model.

Intuition

Take every case where a weather forecaster said "70% chance of rain" and count how often it rained. If it rained on about 70% of them, and the same holds for every other number the forecaster uses, the forecaster is calibrated. Calibration says nothing about how useful the forecasts are: someone who says "it rains on 30% of days" every single day is perfectly calibrated and tells you nothing. A good probabilistic model is both calibrated and sharp, or discriminating: its numbers spread out and separate the cases that happen from the ones that don't.

This split suggests the fix. A model that ranks cases well but uses the wrong numbers can be repaired by a monotone function that relabels its outputs: "when you say 95%, that really means 75%". Learning that function needs only held-out predictions and labels, and since it is monotone it leaves the ranking, and so the AUC, as it was.

Mechanics

What calibrated means

A binary classifier with predicted probability p̂ = f(x) is calibrated if, for every value p it outputs,

P(Y = 1 | p̂ = p) = p

For K classes the strict version requires the whole predicted vector to match the conditional class frequencies; the version usually measured is confidence calibration, where the probability of the predicted class should equal the accuracy on cases with that confidence. The condition is about a population, never about one prediction: a single 70% forecast is neither right nor wrong.

Reliability diagrams and ECE

Since p̂ is continuous, the condition is checked in bins. Split [0, 1] into B intervals, put each prediction in its bin, and compare each bin's mean predicted probability (its confidence) with the fraction of positives in it (its accuracy, or observed frequency). Plotting accuracy against confidence gives a reliability diagram; a calibrated model lies on the diagonal, and points below it are overconfident on the positive side. scikit-learn's calibration_curve returns exactly these two arrays, with uniform bins by default (n_bins=5) or quantile bins that hold equal numbers of predictions.

The expected calibration error summarizes the diagram as the bin-size-weighted gap, and the maximum calibration error as the worst bin:

ECE = Σb (nb / N) · |acc(b) − conf(b)|, MCE = maxb |acc(b) − conf(b)|

ECE is easy to read but depends on the binning: few bins hide errors, many bins leave few cases per bin and add noise, so an ECE should always be reported with its bin scheme. It is a diagnostic, not a training objective; scikit-learn provides the curve but no ECE function.

Proper scoring rules: Brier score and log loss

A proper scoring rule is one whose expected value is optimized by reporting your true belief, so no model can gain by shading its probabilities. Two are standard:

Brier = (1/N) Σi (p̂i − yi)², log loss = −(1/N) Σi [yi log p̂i + (1 − yi) log(1 − p̂i)]

Both reward calibration and sharpness together (the Brier score splits exactly into a reliability term minus a resolution term plus the irreducible uncertainty of the labels, when predictions are grouped by value). The Brier score is bounded and forgiving; log loss punishes confident mistakes without limit, which makes it the one models are trained on and the one temperature scaling minimizes. Neither tells you whether the problem is calibration, which is why they are reported next to a reliability diagram.

Recalibration: Platt, isotonic and temperature

All three methods fit a monotone map g from the model's output to a new probability, on data the model was not trained on. Fitting it on the training set learns nothing useful, since the model's training predictions are more confident than its predictions on new data.

  • Platt scaling (Platt, 2000, for SVMs) is a one-feature logistic regression on the model's score s: g(s) = σ(a·s + b). Two parameters, so it needs little data, but it can only produce sigmoid-shaped corrections. To avoid overfitting small sets, Platt replaced the 0/1 labels with targets (N+ + 1)/(N+ + 2) and 1/(N− + 2), and scikit-learn does the same.
  • Isotonic regression (Zadrozny and Elkan, 2002) fits the best non-decreasing step function in squared error. The pool-adjacent-violators algorithm sorts by score, walks left to right, and whenever a block's mean is not below the next block's, merges them into their weighted mean, repeating backwards until the sequence is monotone. It can fix any monotone distortion but has as many parameters as steps, so it overfits small calibration sets; scikit-learn's documentation advises against it well below about a thousand samples.
  • Temperature scaling (Guo et al., 2017) divides the logits by one number T > 0 before the softmax: p̂ = softmax(z / T). T is fitted by minimizing log loss on a validation set. T > 1 softens overconfident outputs. One parameter, no change to the argmax, and it works for any number of classes directly; for binary models it is Platt scaling with the intercept fixed at zero.
ComponentShape/ParamsMeaningSource
CalibratedClassifierCVmethod="sigmoid", cv=None, ensemble="auto"Wraps a classifier and fits a calibrator on held-out foldscalibration.py
method'sigmoid', 'isotonic' or 'temperature'Platt scaling, isotonic regression, or temperature scaling (added in 1.8)calibration.py
_sigmoid_calibrationreturns slope a, intercept bPlatt's fit with smoothed targets, by L-BFGS; predicts σ(−(a·s + b)), so a is negative for a good modelcalibration.py
_TemperatureScalingbeta_ = 1/TMinimizes multinomial log loss over log β in [−10, 10]; probabilities are first turned back into logits with logcalibration.py
IsotonicRegression(out_of_bounds="clip")step thresholds X_thresholds_, y_thresholds_The isotonic calibrator; interpolates linearly between stepscalibration.py
_inplace_contiguous_isotonic_regressiony, w of length nPool-adjacent-violators in one pass with backtracking_isotonic.pyx
calibration_curven_bins=5, strategy="uniform"Returns per-bin accuracy and confidence, dropping empty binscalibration.py
brier_score_lossscalarMean squared error of the probabilities_classification.py
log_lossscalarMean negative log-likelihood_classification.py

Why modern networks are overconfident

Guo et al. (2017) found that a 1998 LeNet was well calibrated on CIFAR-100, while a 2016 ResNet, far more accurate, was overconfident: their average confidence exceeds their accuracy. They linked the change to greater depth and width, batch normalization, and training with less weight decay, and observed that test log loss starts to rise while test error keeps falling: the network overfits the loss, not the labels.

The loss explains the incentive. Once a training example is classified correctly, cross-entropy can still be lowered by making its logit larger, without changing any decision. Scaling every logit up shrinks the loss on correct examples toward zero and grows it on wrong ones only linearly, so on a training set the network mostly gets right, growing its logits pays. The result carries over to test data, where more examples are wrong. Temperature scaling undoes exactly this uniform inflation, which is why one parameter fixes so much of it.

Worked example

Twenty held-out predictions

A classifier makes 20 predictions on held-out data; 11 of the cases are positive (base rate 0.55). Grouped into calibration_curve's five uniform bins:

BinPredictionsPositivesConfidenceAccuracyGapWeight
(0.0, 0.2]0.05, 0.05, 0.1, 0.1, 0.151 of 50.0900.2000.1100.25
(0.2, 0.4]0.3, 0.351 of 20.3250.5000.1750.10
(0.4, 0.6]0.5, 0.551 of 20.5250.5000.0250.10
(0.6, 0.8]0.65, 0.7, 0.752 of 30.7000.6670.0330.15
(0.8, 1.0]0.85, 0.9, 0.9, 0.95, 0.95, 0.95, 0.99, 0.996 of 80.9350.7500.1850.40

The top bin is the problem: eight predictions averaging 0.935, of which only 6 were positive (0.75). The bottom bin is overconfident the other way, predicting 0.09 where 0.2 happened. ECE is 0.25·0.110 + 0.10·0.175 + 0.10·0.025 + 0.15·0.033 + 0.40·0.185 = 0.1265, and the worst bin's gap (MCE) is 0.185.

Compare a model that ignores its input and always says 0.55. Every prediction falls in one bin whose accuracy is exactly 0.55, so its ECE is 0.00: perfectly calibrated. Its AUC is 0.50, and the proper scoring rules see through it: Brier 0.2475 and log loss 0.6881, both worse than the real model's 0.2219 and 0.6705.

Reliability diagrams before and after temperature scaling Two panels with predicted confidence on the horizontal axis and observed frequency on the vertical axis, both from 0 to 1, and a dashed diagonal for perfect calibration. Bars show each bin's observed frequency and a marker shows its mean confidence. Before: the top bin's bar reaches 0.75 against confidence 0.935, well below the diagonal, and the bottom bin's bar is above it; ECE 0.127. After temperature scaling with T = 2.20, the predictions move inward, the bars sit close to the diagonal, and ECE is 0.033. before 0.2 n=5 0.4 n=2 0.6 n=2 0.8 n=3 1.0 n=8 1 0 confidence · ECE 0.127 after temperature scaling, T = 2.20 0.2 0.4 n=5 0.6 n=6 0.8 n=7 1.0 n=2 1 0 confidence · ECE 0.033 observed frequency mean confidence

Three recalibrators on the same predictions

Each method is fitted on the twenty predictions above and scored on them, to keep the arithmetic visible. In practice the calibrator is fitted on one held-out set and scored on another, and the in-sample numbers below flatter it, isotonic most of all.

Temperature. Turn each probability back into a logit, z = log(p / (1 − p)), so 0.99 becomes 4.595 and 0.05 becomes -2.944. Newton's method on the log loss of σ(β·z) converges to β = 0.4555, so T = 1/β = 2.195. Every logit is divided by 2.20: 0.99 becomes 0.890, 0.95 becomes 0.793, 0.05 becomes 0.207. Nothing crosses 0.5, so the decisions and the AUC are unchanged.

Platt. With 11 positives and 9 negatives, the targets are 12/13 = 0.923 and 1/11 = 0.091. Fitting σ(a·z + b) to them gives a = 0.3639 and b = -0.0173 (scikit-learn would store −a and −b). The intercept is almost zero, so this is nearly temperature scaling with T = 1/a = 2.75; the smoothed targets pull it a little further toward 0.5, and 0.99 becomes 0.840.

Isotonic. The 14 distinct scores, sorted, have positive rates 0.00, 0.50, 0.00, 1.00, 0.00, 1.00, 0.00, 1.00, 0.00, 1.00, 1.00, 0.50, 0.67, 1.00. That sequence rises and falls, so pool-adjacent-violators merges neighbours 9 times into 5 monotone steps:

ScoresCasesCalibrated probability
0.0520.000
0.1–0.1530.333
0.3–0.760.500
0.75–0.9570.714
0.9921.000

The result scores perfectly in-sample, ECE 0.00, because each step is the observed rate of its own cases. But it predicts exactly 0 and 1 at the ends, so a single new mistake there costs infinite log loss, and its ties change the ranking: AUC moves from 0.7475 to 0.7828. With twenty points isotonic is memorizing; it earns its flexibility only with thousands.

PredictionsECEMCEBrierLog lossAUCAccuracy at 0.5
Original0.12650.1850.22190.67050.747565%
Constant 0.550.00000.0000.24750.68810.500055%
Platt0.07200.1600.19950.58270.747565%
Temperature0.03290.1100.19890.57890.747565%
Isotonic (in-sample)0.00000.0000.17980.51280.782870%
The three calibration maps The model's original probability on the horizontal axis against the calibrated probability on the vertical axis. The dashed diagonal is no change. The temperature map, with T = 2.20, is a curve flattened toward 0.5 that passes through 0.5 at 0.5. The Platt map is almost the same curve, slightly flatter. The isotonic map is a staircase of 5 steps, from 0 at the lowest scores to 1 at 0.99. 0 0 0.5 0.5 1 1 original probability calibrated probability temperature, T = 2.20 Platt, a = 0.364, b = -0.017 isotonic, 5 steps no change all three are monotone, so they relabel the scores without reordering them (isotonic ties aside)

What a larger logit buys

Take an example with logit 2 and multiply the logit by k. Its loss if the label agrees, −log σ(kz), and if it doesn't, −log σ(−kz):

kLogitProbabilityLoss if rightLoss if wrong
120.8807971.27e-012.127
240.9820141.81e-024.018
480.9996653.35e-048.000
8161.0000001.13e-0716.000

The two losses always differ by exactly the logit. Doubling from k = 1 to 2 saves 0.109 on each correct example and costs 1.891 on each wrong one, so on a training set where more than about 95% of such examples are right, the larger logits lower the training loss. A network that fits its training set well is pushed toward confidence it cannot back up on new data.

Implementation

Calibrating a fitted classifier on a held-out set with scikit-learn, and checking it on a third split. Wrapping the model in FrozenEstimator tells CalibratedClassifierCV not to refit it, so ensemble="auto" resolves to False and the calibrator is fitted on all of the calibration data.

from sklearn.calibration import CalibratedClassifierCV, calibration_curve
from sklearn.frozen import FrozenEstimator
from sklearn.metrics import brier_score_loss, log_loss

model.fit(X_train, y_train)                       # any classifier

calibrated = CalibratedClassifierCV(FrozenEstimator(model), method="temperature")
calibrated.fit(X_cal, y_cal)                      # data the model never saw

for name, clf in [("raw", model), ("calibrated", calibrated)]:
    p = clf.predict_proba(X_test)[:, 1]
    frac_pos, mean_pred = calibration_curve(y_test, p, n_bins=10, strategy="quantile")
    ece = abs(frac_pos - mean_pred).mean()        # equal-count bins, so a plain mean
    print(name, brier_score_loss(y_test, p), log_loss(y_test, p), ece)

With quantile bins every bin holds about the same number of predictions, so the unweighted mean of the gaps is the ECE; with uniform bins it would need the bin counts. In PyTorch, temperature scaling is a single learnable scalar: collect validation logits once, then minimize F.cross_entropy(logits / T, labels) over T and divide by T at inference. Swap "temperature" for "sigmoid" on small calibration sets with a binary model that is biased toward one class, and for "isotonic" only with thousands of calibration examples.

Tradeoffs

  • Platt vs isotonic vs temperature. Platt and temperature scaling have one or two parameters and are hard to overfit, but can only apply a sigmoid-shaped correction. Isotonic fits any monotone distortion but needs much more data, produces ties, and can output exact 0 and 1. Temperature scaling is the default for neural networks and multiclass models; Platt's extra intercept helps when the model is biased toward one class.
  • Calibration data. Every example spent on calibration is one not spent on training. Cross-validated calibration (CalibratedClassifierCV with cv) reuses the data at the cost of fitting several models.
  • ECE vs proper scores. ECE isolates calibration but depends on the bins and can be zero for a useless model; Brier and log loss can't be gamed but mix calibration with discrimination. Report both.
  • Average vs subgroup calibration. A model can be calibrated overall and miscalibrated for a subgroup or a slice of the input space. Check reliability diagrams per important segment.
  • Shift. Calibration holds for the distribution it was fitted on. When inputs or the base rate change, it degrades first, often before accuracy does, so it needs monitoring and refitting.
  • Resampling and class weights. Training on rebalanced data (see class imbalance) deliberately shifts the probabilities toward the minority class; recalibrate on data with the real base rate.
A model predicts the base rate for everyone. What are its ECE and AUC?

ECE 0, since its one bin's accuracy equals its confidence, and AUC 0.5, since it can't rank. Calibration alone does not make a model useful; that is why Brier and log loss are reported alongside it.

Why does temperature scaling never change accuracy?

Dividing all logits by the same positive T keeps their order, so the argmax, and for binary models the side of 0.5, is the same. It only changes how confident the model is.

You fit isotonic calibration on 200 examples and its validation ECE is near zero. Should you trust it?

Not if that is the same data it was fitted on: isotonic matches its own data almost by construction. Score it on a separate split, and with 200 examples prefer Platt or temperature scaling.

A model was trained on data rebalanced to 50% positives; the real rate is 5%. What happens to its probabilities?

They are far too high for the real population, even though ranking is fine. Recalibrate on data with the real base rate, or correct the odds by the ratio of real to training prior odds.

Connections

Read first

Read next

References

  • Guo, Pleiss, Sun and Weinberger. On Calibration of Modern Neural Networks. ICML 2017. arXiv:1706.04599
  • Platt. Probabilistic Outputs for Support Vector Machines and Comparisons to Regularized Likelihood Methods. In Advances in Large Margin Classifiers, MIT Press, 2000.
  • Zadrozny and Elkan. Transforming Classifier Scores into Accurate Multiclass Probability Estimates. KDD 2002.
  • Niculescu-Mizil and Caruana. Predicting Good Probabilities with Supervised Learning. ICML 2005.
  • Brier. Verification of Forecasts Expressed in Terms of Probability. Monthly Weather Review, 1950.
  • scikit-learn 1.9.1: CalibratedClassifierCV, calibration_curve, IsotonicRegression, brier_score_loss.