Repository: scikit-learn/scikit-learn
File: examples/release_highlights/plot_release_highlights_1_8_0.py (Python)

Code before:
# everything is running smoothly when doing so is still an ongoing effort and that
# there are open issues to fix before considering making this the default.

# %%
# Temperature scaling in `CalibratedClassifierCV`
# -----------------------------------------------
# Probability calibration of classifiers with temperature scaling is available in
# :class:`calibration.CalibratedClassifierCV` by setting `method = "temperature"`.
# This method is particularly well suited for multiclass problems because it provides
# (better-) calibrated probabilities with just one free parameter, in contrast
# to using a "One-vs-Rest" scheme that adds more parameters for each class.

from sklearn.calibration import CalibratedClassifierCV
from sklearn.datasets import make_classification
from sklearn.frozen import FrozenEstimator
from sklearn.model_selection import train_test_split
from sklearn.svm import LinearSVC

X, y = make_classification(random_state=42)
X_train, X_calib, y_train, y_calib = train_test_split(X, y, random_state=42)
clf = LinearSVC(random_state=42)
clf.fit(X_train, y_train)
ts = CalibratedClassifierCV(FrozenEstimator(clf), method="temperature", ensemble=False)
ts.fit(X_calib, y_calib)
beta = ts.calibrated_classifiers_[0].calibrators[0].beta_
print(f"Optimal temperature = {1 / beta:.3}")

# %%
# Linear models improvements
# --------------------------
# There are two main developments going on for linear models: efficiency and API
# changes.
#
# Efficiency of squared error based models with L1 penalty
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# The first one is a massive improvement of efficiency, in particular a reduced fit
# time, for squared error based estimators with L1 penalty: `ElasticNet`, `Lasso`,
# `MultiTaskElasticNet`, `MultiTaskLasso` and their CV variants. The fit time
# improvement is mainly achieved by **gap safe screening rules**. They enable the
# coordinate descent solver to set feature coefficients to 0 early and not look at them
# again. The stronger the L1 penalty the earlier features can be excluded from further
# updates.

from time import time

from sklearn.datasets import make_regression
from sklearn.linear_model import ElasticNetCV

X, y = make_regression(n_features=5000)
model = ElasticNetCV()
tic = time()

Review comment (suggestion):
```suggestion

from sklearn.calibration import CalibratedClassifierCV
from sklearn.datasets import make_classification
from sklearn.naive_bayes import GaussianNB

X, y = make_classification(n_classes=3, n_informative=8, random_state=42)
clf = GaussianNB()
sig = CalibratedClassifierCV(clf, method="sigmoid", ensemble=False).fit(X, y)  # old
ts = CalibratedClassifierCV(clf, method="temperature", ensemble=False).fit(X, y)  # new

# %%
# The following example shows that temperature scaling can produce better-calibrated
# probabilities than sigmoid calibration in multi-class classification problem
# (3 classes).

import matplotlib.pyplot as plt
from sklearn.calibration import CalibrationDisplay

fig, axes = plt.subplots(
    figsize=(8, 4.5),
    ncols=3,
    sharey=True,
)
for i, c in enumerate(ts.classes_):
    CalibrationDisplay.from_predictions(
        y == c,
        ts.predict_proba(X)[:, i],
        name="Temperature scaling",
        ax=axes[i],
    )
    CalibrationDisplay.from_predictions(
        y == c,
        sig.predict_proba(X)[:, i],
        name="Sigmoid",
        ax=axes[i],
    )
    axes[i].set_title(f"Class {c}")
    axes[i].set_xlabel(None)
    axes[i].set_ylabel(None)
    axes[i].get_legend().remove()
fig.suptitle("Reliability Diagrams per Class")
fig.supxlabel("Mean Predicted Probability")
fig.supylabel("Fraction of Class")
fig.legend(*axes[0].get_legend_handles_labels(), loc=(0.72, 0.5))
plt.subplots_adjust(right=0.7)
_ = fig.show()
```

A preview of the visual:

<img width="800" height="450" alt="sphx_glr_plot_release_highlights_1_8_0_001" src="https://github.com/user-attachments/assets/30bd1244-acc6-4f37-b816-7af1b82d8ffc" />



Code after:
#
# We would be very interested by user feedback. Here are a few things you can
# try:
#
# - install free-threaded CPython 3.14, run your favourite
#   scikit-learn script and check that nothing breaks unexpectedly.
#   Note that CPython 3.14 (rather than 3.13) is strongly advised because a
#   number of free-threaded bugs have been fixed since CPython 3.13.
# - if you use some estimators with a `n_jobs` parameter, try changing the
#   default backend to threading with `joblib.parallel_config` as in the
#   snippet below. This could potentially speed-up your code because the
#   default joblib backend is process-based and incurs more overhead than
#   threads.
#
#   .. code-block:: python
#
#       grid_search = GridSearchCV(clf, param_grid=param_grid, n_jobs=4)
#       with joblib.parallel_config(backend="threading"):
#           grid_search.fit(X, y)
#
# - don't hesitate to report any issue or unexpected performance behaviour by
#   opening a `GitHub issue <https://github.com/scikit-learn/scikit-learn/issues/new/choose>`_!
#
# Free-threaded (also known as nogil) CPython is a version of CPython that aims
# to enable efficient multi-threaded use cases by removing the Global
# Interpreter Lock (GIL).
#
# For more details about free-threaded CPython see `py-free-threading doc
# <https://py-free-threading.github.io>`_, in particular `how to install a
# free-threaded CPython <https://py-free-threading.github.io/installing-cpython/>`_
# and `Ecosystem compatibility tracking <https://py-free-threading.github.io/tracking/>`_.
#
# In scikit-learn, one hope with free-threaded Python is to more efficiently
# leverage multi-core CPUs by using thread workers instead of subprocess
# workers for parallel computation when passing `n_jobs>1` in functions or
# estimators. Efficiency gains are expected by removing the need for
# inter-process communication. Be aware that switching the default joblib
# backend and testing that everything works well with free-threaded Python is an
# ongoing long-term effort.

# %%
# Temperature scaling in `CalibratedClassifierCV`
# -----------------------------------------------
# Probability calibration of classifiers with temperature scaling is available in
# :class:`calibration.CalibratedClassifierCV` by setting `method="temperature"`.
# This method is particularly well suited for multiclass problems because it provides
# (better) calibrated probabilities with a single free parameter. This is in
# contrast to all the other available calibrations methods
# which use a "One-vs-Rest" scheme that adds more parameters for each class.

from sklearn.calibration import CalibratedClassifierCV