scikit-learn 1.8 发布亮点#

我们很高兴地宣布 scikit-learn 1.8 发布!新增了许多错误修复和改进,以及一些关键的新功能。下面我们详细介绍了本次发布的亮点。有关所有更改的详尽列表,请参阅发布说明

要安装最新版本(使用 pip)

pip install --upgrade scikit-learn

或使用 conda

conda install -c conda-forge scikit-learn

Array API 支持(启用 GPU 计算)#

scikit-learn 中逐步采用 Python array API 标准意味着可以直接使用 PyTorch 和 CuPy 输入数组。这意味着在 scikit-learn 估计器和函数中,非 CPU 设备(例如 GPU)可用于执行计算。因此,性能得到改善,并且与这些库的集成更加容易。

在 scikit-learn 1.8 中,一些估计器和函数已更新以支持 array API 兼容输入,例如 PyTorch 张量和 CuPy 数组。

以下估计器添加了 Array API 支持:preprocessing.StandardScalerpreprocessing.PolynomialFeatureslinear_model.RidgeCVlinear_model.RidgeClassifierCVmixture.GaussianMixturecalibration.CalibratedClassifierCV

Array API 支持也已添加到 sklearn.metrics 模块中的多个指标,有关更多详细信息,请参阅支持 Array API 兼容输入

有关使用 scikit-learn 和 PyTorch 或 CuPy 等 array API 兼容库的说明,请参阅array API 支持页面。注意:Array API 支持是实验性的,必须在 SciPy 和 scikit-learn 中显式启用。

下面是使用 PyTorch 在 CPU 上使用特征工程预处理器,然后将 calibration.CalibratedClassifierCVlinear_model.RidgeCV 一起在 GPU 上使用的摘录

ridge_pipeline_gpu = make_pipeline(
    # Ensure that all features (including categorical features) are preprocessed
    # on the CPU and mapped to a numerical representation.
    feature_preprocessor,
    # Move the results to the GPU and perform computations there
    FunctionTransformer(
        lambda x: torch.tensor(x.to_numpy().astype(np.float32), device="cuda"))
    ,
    CalibratedClassifierCV(
        RidgeClassifierCV(alphas=alphas), method="temperature"
    ),
)
with sklearn.config_context(array_api_dispatch=True):
    cv_results = cross_validate(ridge_pipeline_gpu, features, target)

有关更多详细信息,请参阅 Google Colab 上的完整笔记本。在这个特定示例中,使用 Colab GPU 与使用单个 CPU 核心相比,速度提高了 10 倍,这对于此类工作负载来说非常典型。

支持自由线程 CPython 3.14#

scikit-learn 支持自由线程 CPython,特别是对于 Python 3.14 上所有受支持的平台,均提供自由线程 wheel。

我们非常希望得到用户反馈。您可以尝试以下几项:

  • 安装自由线程 CPython 3.14,运行您喜欢的 scikit-learn 脚本并检查是否没有意外中断。请注意,强烈建议使用 CPython 3.14(而不是 3.13),因为自 CPython 3.13 以来已修复了许多自由线程错误。

  • 如果您使用带 n_jobs 参数的估计器,请尝试使用 joblib.parallel_config 将默认后端更改为线程,如以下代码片段所示。这可能会加快您的代码速度,因为默认的 joblib 后端是基于进程的,并且比线程产生更多的开销。

    grid_search = GridSearchCV(clf, param_grid=param_grid, n_jobs=4)
    with joblib.parallel_config(backend="threading"):
        grid_search.fit(X, y)
    
  • 请通过打开 GitHub issue 毫不犹豫地报告任何问题或意外的性能行为!

自由线程(也称为 nogil)CPython 是 CPython 的一个版本,旨在通过删除全局解释器锁 (GIL) 来实现高效的多线程用例。

有关自由线程 CPython 的更多详细信息,请参阅 py-free-threading doc,特别是如何安装自由线程 CPython生态系统兼容性跟踪

在 scikit-learn 中,对于自由线程 Python,希望通过在函数或估计器中传递 n_jobs>1 时使用线程工作器而不是子进程工作器进行并行计算,从而更有效地利用多核 CPU。通过消除对进程间通信的需求,有望提高效率。请注意,切换默认的 joblib 后端并测试所有功能在自由线程 Python 中是否正常运行是一项正在进行的长期努力。

CalibratedClassifierCV 中的温度缩放#

通过设置 method="temperature",可以在 calibration.CalibratedClassifierCV 中使用温度缩放对分类器进行概率校准。此方法特别适用于多类问题,因为它使用单个自由参数提供(更好)校准的概率。这与所有其他可用的校准方法形成对比,后者使用“一对多”方案,为每个类添加更多参数。

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().fit(X, y)
sig = CalibratedClassifierCV(clf, method="sigmoid", ensemble=False).fit(X, y)
ts = CalibratedClassifierCV(clf, method="temperature", ensemble=False).fit(X, y)

以下示例显示,在具有 3 个类的多类分类问题中,温度缩放可以产生比 sigmoid 校准更好的校准概率。

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, clf.predict_proba(X)[:, i], name="Uncalibrated", ax=axes[i], marker="s"
    )
    CalibrationDisplay.from_predictions(
        y == c,
        ts.predict_proba(X)[:, i],
        name="Temperature scaling",
        ax=axes[i],
        marker="o",
    )
    CalibrationDisplay.from_predictions(
        y == c, sig.predict_proba(X)[:, i], name="Sigmoid", ax=axes[i], marker="v"
    )
    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()
Reliability Diagrams per Class, Class 0, Class 1, Class 2

线性模型中的效率改进#

对于基于平方误差且带有 L1 惩罚的估计器,拟合时间已大大减少:ElasticNetLassoMultiTaskElasticNetMultiTaskLasso 及其 CV 变体。拟合时间改进主要通过安全间隙筛选规则实现。它们使坐标下降求解器能够尽早将特征系数设置为零,并且不再查看它们。L1 惩罚越强,特征就可以越早地从进一步更新中排除。

from time import time

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

X, y = make_regression(n_features=10_000, random_state=0)
model = ElasticNetCV()
tic = time()
model.fit(X, y)
toc = time()
print(f"Fitting ElasticNetCV took {toc - tic:.3} seconds.")
Fitting ElasticNetCV took 12.9 seconds.

估计器的 HTML 表示#

HTML 表示的下拉表格中的超参数现在包含指向在线文档的链接。将鼠标悬停在上面时,文档字符串描述也会显示为工具提示。

from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler

clf = make_pipeline(StandardScaler(), LogisticRegression(random_state=0, C=10))

通过点击“LogisticRegression”然后点击“Parameters”来展开下面的估计器图。

clf
Pipeline(steps=[('standardscaler', StandardScaler()),
                ('logisticregression',
                 LogisticRegression(C=10, random_state=0))])
在 Jupyter 环境中,请重新运行此单元格以显示 HTML 表示形式或信任 notebook。
在 GitHub 上,HTML 表示形式无法渲染,请尝试使用 nbviewer.org 加载此页面。


带有 criterion="absolute_error" 的 DecisionTreeRegressor#

带有 criterion="absolute_error"tree.DecisionTreeRegressor 现在运行速度快得多。现在它具有 O(n * log(n)) 复杂度,而之前是 O(n**2),这使得它可以扩展到数百万个数据点。

作为一个例证,在包含 100,000 个样本和 1 个特征的数据集上,进行一次拆分大约需要 100 毫秒,而之前需要约 20 秒。

import time

from sklearn.datasets import make_regression
from sklearn.tree import DecisionTreeRegressor

X, y = make_regression(n_samples=100_000, n_features=1)
tree = DecisionTreeRegressor(criterion="absolute_error", max_depth=1)

tic = time.time()
tree.fit(X, y)
elapsed = time.time() - tic
print(f"Fit took {elapsed:.2f} seconds")
Fit took 0.13 seconds

ClassicalMDS#

Classical MDS,也称为“主坐标分析”(PCoA)或“Torgerson's scaling”,现在可在 sklearn.manifold 模块中使用。Classical MDS 接近 PCA,它不是近似距离,而是近似成对标量积,这在特征分解方面具有精确的解析解。

让我们通过在 S 曲线数据集上使用它来获得数据的低维表示,从而说明这一新增功能。

import matplotlib.pyplot as plt
from matplotlib import ticker

from sklearn import datasets, manifold

n_samples = 1500
S_points, S_color = datasets.make_s_curve(n_samples, random_state=0)
md_classical = manifold.ClassicalMDS(n_components=2)
S_scaling = md_classical.fit_transform(S_points)

fig = plt.figure(figsize=(8, 4))
ax1 = fig.add_subplot(1, 2, 1, projection="3d")
x, y, z = S_points.T
ax1.scatter(x, y, z, c=S_color, s=50, alpha=0.8)
ax1.set_title("Original S-curve samples", size=16)
ax1.view_init(azim=-60, elev=9)
for axis in (ax1.xaxis, ax1.yaxis, ax1.zaxis):
    axis.set_major_locator(ticker.MultipleLocator(1))

ax2 = fig.add_subplot(1, 2, 2)
x2, y2 = S_scaling.T
ax2.scatter(x2, y2, c=S_color, s=50, alpha=0.8)
ax2.set_title("Classical MDS", size=16)
for axis in (ax2.xaxis, ax2.yaxis):
    axis.set_major_formatter(ticker.NullFormatter())

plt.show()
Original S-curve samples, Classical MDS

脚本总运行时间: (0 minutes 13.717 seconds)

相关示例

scikit-learn 1.6 发布亮点

scikit-learn 1.6 发布亮点

scikit-learn 1.7 发布亮点

scikit-learn 1.7 发布亮点

scikit-learn 1.0 发布亮点

scikit-learn 1.0 发布亮点

scikit-learn 1.2 发布亮点

scikit-learn 1.2 发布亮点

由 Sphinx-Gallery 生成的图库