Why optimise for calibration if I can recalibrate later?


Welcome!

Every Monday, I’ll drop a no-fluff, straight-to-the-point tip on a data science skill, tool, or
method to help you stay sharp in the field. I hope you find it useful!


Machine Learning Interpretability course has been updated!

I’ve recently finished updating my Machine Learning Interpretability course. 🎉

I’ve refreshed the course notebooks, replacing outdated libraries with practical alternatives and adding fixes to keep examples running as Python evolves. You’ll explore the same powerful interpretability methods with updated code to follow along.

Already learning with me? Jump back in! New to the course? Discover what drives your models’ predictions.

Why optimise for calibration if I can recalibrate later?

If a model produces poorly calibrated probabilities, we can fix them afterwards. Fit the model, pass its outputs through Platt scaling or isotonic regression, and carry on.

So why should we care about calibration while choosing and training the original model?

Well here’s the thing: Recalibration is another modelling problem, with another model, another dataset, and another evaluation procedure.

Sometimes that extra work is justified. But it should not be the default solution to a problem we can easily avoid.

Recalibration involves fitting a new model

Suppose our classifier returns a score of 0.8 for a group of customers, but only 50% of them actually default. A recalibration model learns a mapping from 0.8 to something closer to 0.5.

Platt scaling does this by fitting a sigmoid. Isotonic regression learns a more flexible monotonic mapping. In both cases, we fit parameters from data. In other words, we train another model on top of the first one. Hence, we need to evaluate it properly.

The calibrator becomes part of the system. We need to version it, deploy it, monitor it and retrain it when necessary, alongside the main model. Too much work. And too much room for things going wrong.

The calibrator needs its own data

We cannot fit the calibrator on the same predictions the base model used for training. We need a dedicated calibration set.

In the cleanest setup, we need three datasets:

  • a training set to fit the base model,
  • a calibration set to fit the recalibration model, and
  • an untouched test set to evaluate the complete pipeline.

When data is limited, cross-validation can generate out-of-fold predictions for the calibrator. But it turns out that to evaluate calibration properly, we do need a lot of data. So we are making our lives harder if we now need to split however much data we have into additional sets.

All in all, “I’ll recalibrate later” commits us to training, selecting and evaluating two models instead of one.

The good news is: we don’t have to.

A simpler starting point

If probabilities matter, make them part of model selection from the beginning. Train on the natural class distribution when possible. Choose models that are capable of producing sensible probabilities. Logistic regression and modern gradient boosting methods such as XGBoost, LightGBM and CatBoost optimise log loss, which encourages useful probability estimates.

During hyperparameter tuning and feature selection, evaluate candidates with proper scoring rules such as log loss or Brier score.

Then inspect calibration curves on a sufficiently large, independent test set. The curve is part of deciding which model should reach production.

None of this guarantees perfect calibration. No algorithm does. But it makes poorly calibrated probabilities less likely. And it saves you a ton of work afterwards.

If you liked this article, you’ll also enjoy my new book: Imbalanced Data: Myths, Mistakes and Modern Solutions.

I hope this information was useful!

Wishing you a successful week ahead - see you next Monday! 👋🏻

Sole


Ready to enhance your skills?

Our specializations, courses and books are here to assist you:


Hi…I’m Sole
​
I’m a Python developer, AI educator, and developer advocate. I’m the creator and maintainer of Feature-engine and the main instructor at Train in Data.
​
I share practical Python lessons, open-source insights, and ideas to help our community build better software and grow as developers and data scientists.

You are receiving this email because you subscribed to our newsletter, signed up on our website, purchased or downloaded any products from us.


Follow us on social media

Copyright (C) 2026 Train in Data. All rights reserved.

​
​Unsubscribe · Preferences​

Train in Data

by Soledad Galli, PhD | Data scientist | Python Developer | Best-selling instructor | Book author | 👉 www.trainindata.com

Read more from Train in Data
AI-generated pull requests won't land you that data science job

Welcome! Every Monday, I’ll drop a no-fluff, straight-to-the-point tip on a data science skill, tool, ormethod to help you stay sharp in the field. I hope you find it useful! Three proof copies of my books looking for a new home While I was working on making the physical copies of my books available through different providers, I ended up with three proof copies. They are not perfect: one has the "not for sale" band, and one of the feature selection copies has a few typos here and there....

How to Choose the Right Hyperparameter Search

Welcome! Every Monday, I’ll drop a no-fluff, straight-to-the-point tip on a data science skill, tool, ormethod to help you stay sharp in the field. I hope you find it useful! My new focused machine learning courses are now on Udemy I know many of you already use—and love—Udemy, so I’m back with a new series of short, focused courses designed to help you learn one valuable machine learning skill at a time. The Complete SHAP and Shapley Values Masterclass Master Hyperparameter Tuning with Grid...

TunedThresholdClassifierCV: the good, the bad, the ugly

Welcome! Every Monday, I’ll drop a no-fluff, straight-to-the-point tip on a data science skill, tool, ormethod to help you stay sharp in the field. I hope you find it useful! TunedThresholdClassifierCV: the good, the bad, the ugly For years, scikit-learn classifiers made one decision for us: predict() converted probabilities into class labels using a de facto cut-off of 0.5. That number seems obvious from stats classes. But in practice, it’s rarely the right one. A threshold is not a property...