Примечание
Перейти в конец, чтобы скачать полный код примера или запустить этот пример в браузере через JupyterLite или Binder.
Основные нововведения в scikit-learn 1.5
Мы рады объявить о выпуске scikit-learn 1.5! В него вошли многочисленные исправления ошибок и улучшения, а также несколько важных новых функций. Ниже мы подробно рассмотрим основные нововведения этого выпуска. Полный список всех изменений см. в примечаниях к выпуску.
Чтобы установить последнюю версию с помощью pip:
pip install --upgrade scikit-learn
или с помощью conda:
conda install -c conda-forge scikit-learn
FixedThresholdClassifier: настройка порога принятия решения бинарного классификатора
Все бинарные классификаторы scikit-learn используют фиксированный порог принятия решения 0.5 для преобразования оценок вероятности (то есть результатов predict_proba) в предсказания классов. Однако порог 0.5 почти никогда не подходит для конкретной задачи. FixedThresholdClassifier позволяет обернуть любой бинарный классификатор и задать пользовательский порог принятия решения.
from sklearn.datasets import make_classification from sklearn.linear_model import LogisticRegression from sklearn.metrics import ConfusionMatrixDisplay from sklearn.model_selection import train_test_split X, y = make_classification(n_samples=10_000, weights=[0.9, 0.1], random_state=0) X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0) classifier_05 = LogisticRegression(C=1e6, random_state=0).fit(X_train, y_train) _ = ConfusionMatrixDisplay.from_estimator(classifier_05, X_test, y_test)

Снижение порога, то есть возможность классифицировать больше объектов как принадлежащие к положительному классу, увеличивает число истинно положительных результатов ценой увеличения числа ложноположительных результатов (что хорошо известно из вогнутости ROC-кривой).
from sklearn.model_selection import FixedThresholdClassifier classifier_01 = FixedThresholdClassifier(classifier_05, threshold=0.1) classifier_01.fit(X_train, y_train) _ = ConfusionMatrixDisplay.from_estimator(classifier_01, X_test, y_test)

TunedThresholdClassifierCV: подбор порога принятия решения бинарного классификатора
Порог принятия решения бинарного классификатора можно подобрать для оптимизации заданной метрики с помощью TunedThresholdClassifierCV.
Это особенно полезно, когда нужно найти оптимальный порог принятия решения для модели, предназначенной для применения в конкретном контексте, где можно назначить разные выгоды или издержки истинно положительным, истинно отрицательным, ложноположительным и ложноотрицательным результатам.
Рассмотрим произвольный пример, в котором:
- каждый истинно положительный результат приносит 1 единицу прибыли, например евро, год жизни в добром здравии и т. д.;
- истинно отрицательные результаты не приносят ни прибыли, ни убытка;
- каждый ложноотрицательный результат обходится в 2 единицы;
- каждый ложноположительный результат обходится в 0.1 единицы.
Наша метрика оценивает среднюю прибыль на один объект и определяется следующей функцией Python:
from sklearn.metrics import confusion_matrix
def custom_score(y_observed, y_pred):
tn, fp, fn, tp = confusion_matrix(y_observed, y_pred, normalize="all").ravel()
return tp - 2 * fn - 0.1 * fp
print("Untuned decision threshold: 0.5")
print(f"Custom score: {custom_score(y_test, classifier_05.predict(X_test)):.2f}")
Untuned decision threshold: 0.5 Custom score: -0.12
Интересно отметить, что средняя прибыль на одно предсказание отрицательна, то есть эта система принятия решений в среднем приносит убыток.
Подбор порога для оптимизации этой пользовательской метрики позволяет получить более низкий порог, при котором больше объектов классифицируются как принадлежащие к положительному классу. В результате средняя прибыль на одно предсказание увеличивается.
from sklearn.metrics import make_scorer
from sklearn.model_selection import TunedThresholdClassifierCV
custom_scorer = make_scorer(
custom_score, response_method="predict", greater_is_better=True
)
tuned_classifier = TunedThresholdClassifierCV(
classifier_05, cv=5, scoring=custom_scorer
).fit(X, y)
print(f"Tuned decision threshold: {tuned_classifier.best_threshold_:.3f}")
print(f"Custom score: {custom_score(y_test, tuned_classifier.predict(X_test)):.2f}")
Tuned decision threshold: 0.071 Custom score: 0.04
Мы видим, что подбор порога принятия решения может превратить систему на основе машинного обучения, которая в среднем приносит убыток, в систему, приносящую пользу.
На практике определение значимой метрики для конкретной задачи может потребовать, чтобы издержки за ошибочные предсказания и выгоды за правильные зависели от дополнительных метаданных, относящихся к каждой отдельной точке данных, например от суммы транзакции в системе обнаружения мошенничества.
Для этого TunedThresholdClassifierCV использует поддержку маршрутизации метаданных (Руководство пользователя по маршрутизации метаданных), что позволяет оптимизировать сложные бизнес-метрики, как описано в примере Настройка порога принятия решения для обучения с учетом издержек.
Улучшение производительности PCA
В PCA появился новый решатель — "covariance_eigh". Для наборов данных с большим числом объектов и небольшим числом признаков он работает до десяти раз быстрее и требует меньше памяти, чем другие решатели.
from sklearn.datasets import make_low_rank_matrix
from sklearn.decomposition import PCA
X = make_low_rank_matrix(
n_samples=10_000, n_features=100, tail_strength=0.1, random_state=0
)
pca = PCA(n_components=10, svd_solver="covariance_eigh").fit(X)
print(f"Explained variance: {pca.explained_variance_ratio_.sum():.2f}")
Explained variance: 0.88
Новый решатель также принимает разреженные входные данные:
from scipy.sparse import random
X = random(10_000, 100, format="csr", random_state=0)
pca = PCA(n_components=10, svd_solver="covariance_eigh").fit(X)
print(f"Explained variance: {pca.explained_variance_ratio_.sum():.2f}")
Explained variance: 0.13
Решатель "full" также был улучшен: теперь он использует меньше памяти и позволяет быстрее выполнять преобразование. Параметр svd_solver="auto" по умолчанию использует преимущества нового решателя и теперь может выбирать подходящий решатель для разреженных наборов данных.
Как и большинство других решателей PCA, новый решатель "covariance_eigh" может использовать вычисления на GPU, если входные данные переданы в виде массива PyTorch или CuPy и включена экспериментальная поддержка Array API.
К ColumnTransformer теперь можно обращаться по индексу
Теперь к преобразователям ColumnTransformer можно обращаться напрямую по имени с помощью индексирования.
import numpy as np
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder, StandardScaler
X = np.array([[0, 1, 2], [3, 4, 5]])
column_transformer = ColumnTransformer(
[("std_scaler", StandardScaler(), [0]), ("one_hot", OneHotEncoder(), [1, 2])]
)
column_transformer.fit(X)
print(column_transformer["std_scaler"])
print(column_transformer["one_hot"])
StandardScaler() OneHotEncoder()
Пользовательские стратегии импутации для SimpleImputer
Теперь SimpleImputer поддерживает пользовательские стратегии импутации с помощью вызываемого объекта, который вычисляет скалярное значение по непустым значениям вектора-столбца.
from sklearn.impute import SimpleImputer
X = np.array(
[
[-1.1, 1.1, 1.1],
[3.9, -1.2, np.nan],
[np.nan, 1.3, np.nan],
[-0.1, -1.4, -1.4],
[-4.9, 1.5, -1.5],
[np.nan, 1.6, 1.6],
]
)
def smallest_abs(arr):
"""Return the smallest absolute value of a 1D array."""
return np.min(np.abs(arr))
imputer = SimpleImputer(strategy=smallest_abs)
imputer.fit_transform(X)
array([[-1.1, 1.1, 1.1],
[ 3.9, -1.2, 1.1],
[ 0.1, 1.3, 1.1],
[-0.1, -1.4, -1.4],
[-4.9, 1.5, -1.5],
[ 0.1, 1.6, 1.6]])
Попарные расстояния для нечисловых массивов
Теперь pairwise_distances может вычислять расстояния между нечисловыми массивами с помощью вызываемой метрики.
from sklearn.metrics import pairwise_distances
X = ["cat", "dog"]
Y = ["cat", "fox"]
def levenshtein_distance(x, y):
"""Return the Levenshtein distance between two strings."""
if x == "" or y == "":
return max(len(x), len(y))
if x[0] == y[0]:
return levenshtein_distance(x[1:], y[1:])
return 1 + min(
levenshtein_distance(x[1:], y),
levenshtein_distance(x, y[1:]),
levenshtein_distance(x[1:], y[1:]),
)
pairwise_distances(X, Y, metric=levenshtein_distance)
array([[0., 3.],
[3., 2.]])
Общее время выполнения скрипта: (0 минут 0.892 секунды)
Связанные примеры
© 2007–2026 The scikit-learn developers
Licensed under the 3-clause BSD License.
https://scikit-learn.org/1.9/auto_examples/release_highlights/plot_release_highlights_1_5_0.html