scikit-learn 1.10:IterativeImputer 正式“转正”——导入方式、实验特性开关与收敛警告的全面变化
【免费下载链接】scikit-learnscikit-learn: machine learning in Python项目地址: https://gitcode.com/gh_mirrors/sc/scikit-learn
本篇聚焦 scikit-learn 即将发布版本中IterativeImputer的三项 API 级变化:实验标记移除后的直接导入方式、sklearn.experimental.enable_iterative_imputer兼容层的行为(变为 no-op 并发出警告),以及达到max_iter未满足tol时不再抛出ConvergenceWarning的设计决策。读完后你将能够安全迁移旧版代码,理解迭代插补“不保证收敛”的底层原因,并据此选择合理的max_iter、tol与add_indicator配置组合。
变更全景:一次 changelog 里的三项改动
本次变更由 Guillaume Lemaitre 提出,记录在 34214.api.rst 中。它包含三个相互关联的要点:
IterativeImputer不再是实验特性,可以直接from sklearn.impute import IterativeImputer导入;- 继续导入
sklearn.experimental.enable_iterative_imputer不再是必需——这个导入现在会发出警告,且不再产生任何效果(no-op); - 当
max_iter耗尽但未满足tol停止条件时,IterativeImputer不再抛出ConvergenceWarning,因为轮转(round-robin)插补本身不保证收敛,未收敛属于预期行为;用户指南新增了对应的解释章节(iterative_imputer_convergence锚点)。
三项改动本质上是同一件事的不同侧面:IterativeImputer从一个“需要显式开关、收敛行为需要额外安抚”的实验组件,升级为一个“收敛性有明确文档承诺”的稳定组件。下面逐条结合源码展开。
直接导入:from sklearn.impute import IterativeImputer
在 1.10 之前,IterativeImputer属于 scikit-learn 的experimental特性:它虽然早已存在于 sklearn/impute/_iterative.py 中,但官方要求用户先导入enable_iterative_imputer以“启用”它,实验特性不受弃用周期保护,接口可以随时破坏性修改。
当前仓库中,sklearn/impute/init.py 已将其纳入sklearn.impute的公开导出:
from sklearn.impute._base import MissingIndicator, SimpleImputer from sklearn.impute._iterative import IterativeImputer from sklearn.impute._knn import KNNImputer __all__ = ["IterativeImputer", "KNNImputer", "MissingIndicator", "SimpleImputer"]同时,IterativeImputer的类文档字符串在 sklearn/impute/_iterative.py 中标注了.. versionchanged:: 1.10,说明该估计器“不再是实验特性,无需通过sklearn.experimental启用即可直接从sklearn.impute导入”。这意味着:
# 新代码(1.10+ 直接导入) from sklearn.impute import IterativeImputer imp = IterativeImputer(max_iter=10, random_state=0)从此,IterativeImputer与SimpleImputer、KNNImputer一样,受 scikit-learn 稳定的弃用周期(deprecation cycle)保护,可以安全用于生产管线。
典型用法回顾
用户指南 doc/modules/impute.rst 中的示例仍然有效:每个含缺失值的特征都被建模为其他特征的函数,以轮转方式迭代max_iter轮,返回最后一轮的结果:
import numpy as np from sklearn.impute import IterativeImputer imp = IterativeImputer(max_iter=10, random_state=0) imp.fit([[1, 2], [3, 6], [4, 8], [np.nan, 3], [7, np.nan]]) # 模型学到第二特征是第一个的两倍 X_test = [[np.nan, 2], [6, np.nan], [np.nan, 6]] print(np.round(imp.transform(X_test))) # [[ 1. 2.] # [ 6. 12.] # [ 3. 6.]]IterativeImputer还可以像SimpleImputer一样放入Pipeline与其他估计器组合,参考示例 plot_missing_values.py。
兼容层:enable_iterative_imputer变为 no-op 并发出警告
为了让既有代码在升级时不至于直接报错,sklearn.experimental下保留了 enable_iterative_imputer.py。文件头注释明确写道:“This is now a no-op and can be safely removed from your code”,并注明“不要删除此文件,我们不希望仅仅因为该特性不再是实验性就破坏用户代码”。其全部实现就是:
import warnings warnings.warn( "Since version 1.10, " "it is not needed to import enable_iterative_imputer anymore. " "IterativeImputer is now stable and can be normally imported from " "sklearn.impute." )也就是说,旧代码中的from sklearn.experimental import enable_iterative_imputer语句:
- 不会报错,
IterativeImputer依然可用(因为现在直接从sklearn.impute导入即可); - 会发出
UserWarning,提示自 1.10 起该导入已无必要,建议从代码中删除; - 不再产生任何“启用”副作用,它此前作为实验开关的意义已经消失。
这一行为由专门的回归测试 test_enable_iterative_imputer.py 固化下来:测试在子进程中执行from sklearn.experimental import enable_iterative_imputer,断言会抛出匹配"it is not needed to import"的UserWarning,且导入本身不产生其他输出。文件内还留有TODO(1.14)注释,讨论是否保留足够长的过渡期后可以启动完整弃用周期——可以推断,该兼容导入未来仍可能以正式弃用流程收尾,建议现在就清理相关语句。
收敛语义变化:不再抛出 ConvergenceWarning
旧版本中,当IterativeImputer跑满max_iter轮仍未满足tol停止条件时会抛出ConvergenceWarning,暗示“未收敛”是一件需要用户警惕的异常。新版本取消了这一警告,依据是:轮转插补在数学上不保证到达不动点,跑满迭代是常态而非故障。
从源码结构看,这一语义已经被写进参数文档与类注释中:
max_iter(默认 10)的文档说明停止条件为max(abs(X_t - X_{t-1})) / max(abs(X[known_vals])) < tol(默认tol=1e-3),且提前停止仅在sample_posterior=False时生效;- 类文档中的
note直接声明:“The stopping criterion of this imputer rarely improves the downstream predictive performance, and the imputed values are not guaranteed to converge with the number of iterations”(停止准则很少能提升下游预测性能,且插补值不保证随迭代次数收敛)。
也就是说,迭代次数应当被看作时间预算与插补质量的权衡,而不是一个需要“达成”的收敛目标。
用户指南在 doc/modules/impute.rst 中新增的“Convergence and diminishing returns”章节(即 changelog 引用的iterative_imputer_convergence锚点)进一步解释了原因与实践建议:
- 为什么不一定收敛:round-robin 方案不保证收敛到不动点,
IterativeImputer重复轮转插补max_iter轮,仅当两轮之间变化小于tol时才提前停止(且仅在sample_posterior=False时); - 为什么通常无所谓:Le Morvan 与 Varoquaux 的工作表明,当目标是预测时,提升插补精度的收益呈强烈递减——更准的插补只带来下游预测性能的微小增益,尤其在配合表达能力强的模型和缺失指示器(
add_indicator)时; - 实践建议:
- 以预测为目标时,优先选择较小且固定的
max_iter(如max_iter=10),配合缺失指示器(add_indicator=True)和表达能力强的下游模型,而不要在收敛上继续投入; - 以数据重建本身为目标(例如重建被缺失的数据)时,迭代次数(如
max_iter > 50)和插补器的选择才更关键,需要针对具体任务评估。
- 以预测为目标时,优先选择较小且固定的
这一建议与IterativeImputer的默认值是自洽的:max_iter=10、tol=1e-3、initial_strategy="mean"、默认回归器为BayesianRidge,并且基类参数中已包含add_indicator(False)与keep_empty_features(False),可直接用于“快速插补 + 指示特征”的推荐组合。
与 missForest、MICE 的关系
同一章节还说明了IterativeImputer的灵活性:R 生态中流行的 missForest 等序列插补算法,都可以通过向IterativeImputer传入不同的回归器来实现(missForest 对应随机森林回归器)。此外,虽然本实现受 R 的 MICE 包启发,但默认只做单次插补;如需多重插补,可在sample_posterior=True时用不同随机种子反复调用(此时estimator的predict必须支持return_std),且注意transform不允许改变样本数,因此不能通过一次transform调用完成多重插补。更多对比见示例 plot_iterative_imputer_variants_comparison.py。
迁移清单:升级时需要改什么
结合以上源码与文档证据,升级路径可以归纳为一张检查表:
| 旧代码 / 旧行为 | 1.10+ 的正确做法 | 依据 |
|---|---|---|
from sklearn.experimental import enable_iterative_imputer前置导入 | 删除该行,直接使用from sklearn.impute import IterativeImputer | sklearn/impute/init.py、sklearn/experimental/enable_iterative_imputer.py |
依赖ConvergenceWarning判断“插补未收敛”并做重试/告警 | 移除对该警告的处理逻辑;将max_iter视为时间预算参数而非收敛目标 | doc/modules/impute.rst(iterative_imputer_convergence章节)、34214.api.rst |
捕获enable_iterative_imputer导入以做特性开关 | 导入本身仍合法但会发UserWarning;测试环境注意该警告可能触发警告即失败的配置 | sklearn/experimental/tests/test_enable_iterative_imputer.py |
追求“更大max_iter提高精度” | 预测场景保持max_iter=10并启用add_indicator=True;重建场景再考虑max_iter > 50 | sklearn/impute/_iterative.py、doc/modules/impute.rst |
最后强调适用前提:以上行为均针对当前仓库(即将发布的 1.10 版本线);若你的环境仍在 1.9 或更早版本,IterativeImputer依旧需要通过实验开关导入,且跑满max_iter时可能收到ConvergenceWarning,迁移建议以实际安装的版本 changelog 为准。
【免费下载链接】scikit-learnscikit-learn: machine learning in Python项目地址: https://gitcode.com/gh_mirrors/sc/scikit-learn
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考