scikit-learn 1.9.1 是一次以修复和兼容性改进为主的版本更新。本次更新覆盖 Array API 支持、元数据路由、回调机制、聚类、数据集下载、判别分析、指标评分、近邻算法、预处理、支持向量机以及工具层等多个模块。
虽然本版本没有引入大量全新的公开功能,但针对跨数组命名空间、Pipeline 中的元数据传递、稀疏预计算距离矩阵、并行执行、模型 HTML 展示和无障碍访问等场景进行了细致修复。对于正在使用元数据路由、Array API、稀疏数据、Polars 输出或并行训练流程的用户而言,这些改动尤其值得关注。
一、Array API 支持改进:跨命名空间与跨设备的分类指标更稳定
在 Array API 支持方面,scikit-learn 1.9.1 修复了分类指标计算中的一个兼容性问题。
此前,当启用 Array API 分发机制时,如果真实标签来自 pandas,而预测结果来自不同的 Array API 命名空间或不同设备,固定分类指标可能无法正常接受这些标签。这里的关键场景包括:
- 真实标签使用 pandas 标签对象;
- 预测值来自另一种数组实现;
- 真实标签与预测值位于不同设备;
- 启用了 Array API 分发机制。
在 1.9.1 中,这类固定分类指标已经能够正确处理 pandas 标签与不同数组命名空间、不同设备上的预测结果组合。
这一修复使分类评估流程在混合数组生态中更加一致。对于同时涉及 pandas 标签、不同数组后端以及不同计算设备的任务,指标计算的兼容性得到了改善。
二、元数据路由修复:Pipeline 与元估计器中的元数据不再被静默丢弃
元数据路由是本次更新的重点之一。
元数据通常指不属于特征矩阵和目标值本身、但需要在训练或预测过程中传递的信息,例如sample_weight。在复杂的 Pipeline、元估计器和组合模型结构中,元数据是否能够准确传递到真正需要它的子估计器,会直接影响训练流程的正确性。
本版本继续完善元数据路由行为,并针对多个容易出现问题的组合场景进行了修复。
对于元数据路由的完整使用方式,可以参考 Metadata Routing User Guide。
三、Pipeline 中作为中间步骤使用的元估计器,现可正确接收元数据
在此前的行为中,一些元估计器作为pipeline.Pipeline的中间步骤使用时,可能出现元数据被静默丢弃的问题。
受影响的元估计器包括:
feature_selection.SelectFromModelfeature_selection.RFEfeature_selection.RFECVfeature_selection.SequentialFeatureSelectorimpute.IterativeImputer
问题出现的典型条件是:
- 这些元估计器被放在 Pipeline 的中间步骤;
- Pipeline 调用组合式的
fit_transform; - 该
fit_transform成为元数据路由的目标; - 用户传入了诸如
sample_weight之类的元数据。
此前,在这种场景中,元数据可能不会继续传递给元估计器内部的子估计器,而是被静默丢弃。所谓“静默丢弃”,意味着流程不一定会显式报错,但子估计器实际并没有收到应当传递的数据。
scikit-learn 1.9.1 修复后,这些元估计器在作为 Pipeline 中间步骤时,可以将元数据正确路由到内部子估计器。这样一来,Pipeline 的组合训练流程与元数据路由机制能够更好地协同工作。
四、BaggingClassifier 的预测元数据路由行为得到修复
ensemble.BaggingClassifier在predict和predict_proba阶段的元数据路由也得到了修正。
此前,预测过程中的元数据路由可能无法根据底层子估计器真正对应的方法进行动态分发。不同子估计器可能支持不同的预测相关接口,因此路由时需要根据具体调用的方法进行匹配。
在 1.9.1 中,BaggingClassifier现在能够通过predict和predict_proba,动态地将元数据路由到子估计器上相应的方法。
这一调整使 Bagging 分类器在预测和概率预测阶段的元数据传递更加准确,也使组合模型与底层估计器的方法对应关系更加一致。
五、Pipeline 的 fit_transform 与 fit_predict 现可正确应用 transform_input
pipeline.Pipeline的fit_transform与fit_predict也获得了元数据路由修复。
此前,Pipeline 的fit已经能够对路由到中间步骤的元数据应用transform_input。但是,fit_transform和fit_predict的行为并不完全一致,可能未能以同样的方式处理这些元数据。
在 1.9.1 中:
Pipeline.fit_transform可以正确对路由到中间步骤的元数据应用transform_input;Pipeline.fit_predict也可以正确对路由到中间步骤的元数据应用transform_input;- 两者的行为现在与
Pipeline.fit保持一致。
这意味着,当 Pipeline 需要在中间步骤中变换元数据时,三种常见训练入口的行为更加统一:
fitfit_transformfit_predict
对于依赖元数据路由和transform_input的复杂 Pipeline,训练方式之间的差异得到消除。
六、TransformedTargetRegressor 可向默认回归器传递元数据
compose.TransformedTargetRegressor也修复了元数据传递问题。
当启用元数据路由时,TransformedTargetRegressor现在可以正确将诸如sample_weight的元数据传递给其默认回归器,即LinearRegression。
这一改动解决了目标变量转换场景中的元数据传递问题。也就是说,当回归模型通过TransformedTargetRegressor包装,并使用默认回归器时,启用元数据路由后,训练所需的权重信息能够准确到达底层回归器。
七、回调与多进程并行:ScoringMonitor 的序列化问题修复
在回调机制方面,1.9.1 修复了一个与多进程并行后端相关的问题。
此前,如果使用callback.ScoringMonitor对估计器拟合过程进行监控,同时使用基于多进程的并行后端,训练过程可能失败,并出现无法将任务序列化后发送给工作进程的错误。
问题的核心在于,多进程并行需要将任务传递给工作进程,而传递过程涉及对象的序列化。如果回调对象或其相关任务无法正确序列化,就可能导致拟合任务无法执行。
修复后,带有ScoringMonitor回调的估计器拟合流程可以更好地适配多进程并行后端,避免此前可能出现的任务无法发送到工作进程的问题。
八、聚类模块修复:预计算稀疏距离矩阵不再触发错误警告
聚类模块针对预计算稀疏距离矩阵的警告行为进行了修正。
首先,cluster.DBSCAN和cluster.dbscan在输入预计算稀疏距离矩阵时,不再错误地抛出EfficiencyWarning。
其次,cluster.OPTICS在使用预计算稀疏距离矩阵进行拟合时,也不再抛出EfficiencyWarning。
这两项改动分别覆盖:
cluster.DBSCANcluster.dbscancluster.OPTICS
共同场景是:输入数据为预计算的稀疏距离矩阵。
此前出现的EfficiencyWarning属于不应触发的警告。修复后,在这一输入条件下,用户不会再受到无关警告的干扰,聚类流程的反馈更符合实际行为。
九、datasets 模块:下载损坏可恢复,文件名参数校验更明确
数据集获取功能在本次版本中有两项修复。
第一项涉及datasets.fetch_openml。
此前,如果下载过程得到的内容损坏,fetch_openml可能直接报错,而不会尝试重新下载。在 1.9.1 中,当检测到下载内容损坏时,fetch_openml能够重新下载数据,而不是立即抛出错误。
这一修复改善了下载异常场景下的恢复行为。对于下载结果损坏的情况,函数现在会尝试通过重新下载恢复正常流程。
第二项涉及datasets.fetch_file。
在 1.9.1 中,如果local_filename参数传入的是一个路径,而不是一个普通文件名,fetch_file现在会抛出ValueError。
这意味着,local_filename的参数约束更加明确:
- 可以传入普通文件名;
- 不应传入文件路径;
- 若传入路径,将得到
ValueError。
这一变化使参数错误能够更早、更明确地暴露出来。
十、判别分析模块:svd 与 eigen 求解器的结果更加一致
discriminant_analysis.LinearDiscriminantAnalysis和discriminant_analysis.QuadraticDiscriminantAnalysis在求解器结果一致性方面得到修复。
本次更新后,当使用:
solver="svd"solver="eigen"
时,这两个判别分析估计器将返回相同的结果。
为了实现这一一致性,solver="svd"的归一化方式发生了调整。
对于线性判别分析,归一化从:
1 / (n_samples - n_classes)
调整为:
1 / n_samples
对于二次判别分析,归一化从:
1 / (n_samples - 1)
调整为:
1 / n_samples
调整后的方式与最大似然协方差估计器保持一致,也与solver="eigen"的默认行为一致。
这一修复的重点不在于新增求解器,而在于消除不同求解器之间不必要的结果差异。现在,svd与eigen在对应场景下可以给出一致结果,归一化逻辑也统一到最大似然协方差估计的标准上。
十一、metrics 模块:make_scorer 减少重复深拷贝,降低模型选择中的内存消耗
在sklearn.metrics中,通过make_scorer创建的评分器优化了元数据参数的处理方式。
此前,这类评分器在每次调用时都会对元数据关键字参数进行深拷贝。深拷贝会创建完整的新对象副本,在模型选择和交叉验证中,评分器往往被重复调用,因此可能带来额外内存消耗。
在 1.9.1 中,使用make_scorer创建的评分器不再在每次调用时深拷贝元数据关键字参数。
这一优化带来的直接效果是:
- 减少评分过程中的重复内存分配;
- 降低模型选择时的内存使用;
- 降低交叉验证时的内存使用。
改动聚焦于评分器内部的元数据参数处理,不改变评分器所承担的评估职责。
十二、近邻模块:radius_neighbors 支持并行条件下的数组半径
neighbors.NearestNeighbors.radius_neighbors修复了一个与数组形式半径和并行执行相关的问题。
此前,当半径参数以数组形式提供,并且设置n_jobs > 1使用并行计算时,若采用以下算法:
ball_treekd_tree
则radius_neighbors可能无法正确处理数组形式的半径。
在 1.9.1 中,这一问题已被修复。现在,当满足以下条件时,函数可以正确工作:
- 半径是数组形式;
n_jobs > 1;- 使用
ball_tree算法,或使用kd_tree算法。
这一修复提升了近邻半径查询在并行树结构算法下的正确性。
十三、预处理模块:QuantileTransformer 修复稀疏数据分位数退化问题
preprocessing.QuantileTransformer修复了一个与稀疏数据、隐式零值处理和子采样同时相关的问题。
受影响的场景包括:
- 输入数据为稀疏数据;
- 设置
ignore_implicit_zeros=True; - 拟合过程使用子采样。
此前,在这些条件组合下,部分特征可能计算出退化的分位数。也就是说,分位数结果在某些特征上可能出现不正常或失去有效区分能力的情况。
在 1.9.1 中,这个问题已经得到修复。对于稀疏数据、忽略隐式零值以及子采样共同出现的拟合流程,QuantileTransformer可以避免为部分特征计算出退化分位数。
十四、支持向量机模块:LinearSVR 内存泄漏与 LinearSVC 越界写入修复
支持向量机模块包含两项重要修复。
第一项涉及svm.LinearSVR。
此前,调用LinearSVR.fit方法时存在内存泄漏问题。内存泄漏意味着在拟合过程结束后,部分不再需要的内存未能正确释放。
在 1.9.1 中,LinearSVR.fit的这一内存泄漏问题已被修复。
第二项涉及svm.LinearSVC。
当使用:
multi_class="crammer_singer"
时,LinearSVC.fit存在越界写入问题。越界写入意味着程序可能写入超出预期边界的内存区域。
在 1.9.1 中,LinearSVC.fit在multi_class="crammer_singer"配置下的越界写入问题已被修复。
这两项修复分别改善了:
LinearSVR.fit的内存管理;LinearSVC.fit在特定多分类配置下的内存安全性。
十五、工具层与 HTML 展示:大量输出特征、跨设备传输和无障碍体验同步改进
sklearn.utils及相关展示功能在本版本中包含多项修复,涉及 HTML 渲染性能、数组传输稳定性、键盘可访问性以及 Polars 输出兼容性。
十六、估计器 HTML 表示最多展示 100 个输出特征
对于具有大量输出特征的估计器,HTML 表示可能需要渲染非常长的输出特征列表,从而影响展示性能。
在 1.9.1 中,估计器的 HTML 表示会将输出特征列表截断为最多 100 项。
这一调整的目的,是改善具有大量输出特征时的渲染性能。
更新后的行为是:
- 输出特征列表不会无限扩展;
- HTML 表示最多显示 100 个输出特征;
- 大量输出特征场景下的渲染负担得到降低。
十七、负步长 NumPy 数组传递至 PyTorch 时不再导致进程中止
支持 Array API 的函数和估计器,在处理混合输入命名空间时也得到了稳定性修复。
此前,如果输入中包含负步长的 NumPy 数组,并且该数组需要通过 DLPack 传递到 PyTorch,可能触发torch.from_dlpack导致 Python 进程中止。
在 1.9.1 中,支持 Array API、且能够处理混合输入命名空间的函数和估计器,会在通过 DLPack 将负步长 NumPy 数组传递给 PyTorch 之前,先将该数组转换为连续内存布局。
调整后的流程可以概括为:
- 检测到负步长 NumPy 数组;
- 在传递前使数组变为连续布局;
- 再通过 DLPack 传递到 PyTorch;
- 避免
torch.from_dlpack引发 Python 进程中止。
这一修复面向数组命名空间混用以及 NumPy 与 PyTorch 之间的数据传递场景。
十八、HTML 复制图标升级为可访问按钮
估计器 HTML 表示中的复制到剪贴板图标,也进行了无障碍访问改进。
此前,复制图标使用的是非交互式的<i>元素。此类元素不具备完整的交互语义,在键盘操作和屏幕阅读器访问方面存在不足。
在 1.9.1 中,这些复制图标改为使用<button>元素,并具备以下特性:
- 包含
aria-label; - 具有可见的焦点轮廓;
- 可以通过键盘访问;
- 可以被屏幕阅读器识别和使用。
这一改动使复制到剪贴板功能不再仅依赖鼠标操作,也改善了 HTML 表示的可访问性。
十九、Polars 输出不再触发弃用警告
在set_output(transform="polars")场景中,scikit-learn 1.9.1 修复了与较新 Polars 版本的兼容性问题。
此前,当使用 Polars 版本不低于 1.42.1 时,拼接 Polars DataFrame 的过程可能产生DeprecationWarning。原因是使用了已经弃用的:
how="horizontal"
在 1.9.1 中,拼接 Polars DataFrame 时改为使用:
how="horizontal_extend"
因此,当使用:
set_output(transform="polars")
并且 Polars 版本不低于 1.42.1 时,不再产生此前的弃用警告。
这一修复使 scikit-learn 的 Polars 输出模式与新版 Polars 的接口变化保持兼容。
二十、版本更新内容总结
代码地址:github.com/scikit-learn/scikit-learn
scikit-learn 1.9.1 的更新重点可以归纳为以下几个方向:
- 改善 Array API 场景下 pandas 标签与跨命名空间预测结果的分类指标兼容性;
- 修复 Pipeline、元估计器、BaggingClassifier 和 TransformedTargetRegressor 中的元数据路由问题;
- 统一 Pipeline 的
fit、fit_transform与fit_predict在transform_input上的行为; - 修复带
ScoringMonitor回调时多进程并行可能出现的序列化失败; - 消除 DBSCAN、dbscan 和 OPTICS 使用预计算稀疏距离矩阵时不应出现的效率警告;
- 提升 OpenML 下载损坏后的恢复能力,并明确
fetch_file的文件名参数校验; - 让判别分析中的
svd与eigen求解器结果保持一致; - 降低
make_scorer在模型选择和交叉验证中的内存使用; - 修复近邻查询、稀疏分位数变换、线性支持向量机训练中的问题;
- 改进估计器 HTML 表示的渲染性能、无障碍访问能力和复制操作体验;
- 修复负步长 NumPy 数组经 DLPack 传递到 PyTorch 时可能导致的进程中止;
- 消除新版 Polars 环境下的弃用警告。
总体来看,scikit-learn 1.9.1 主要强化了复杂工作流中的稳定性与一致性,特别是在元数据路由、数组后端兼容、稀疏数据处理、并行执行以及展示层细节方面进行了集中修复。