在 scikit-learn 管道中插入或删除步骤

Posted

技术标签:

【中文标题】在 scikit-learn 管道中插入或删除步骤【英文标题】:Insert or delete a step in scikit-learn Pipeline 【发布时间】:2021-08-15 20:27:51 【问题描述】:

是否可以在sklearn.pipeline.Pipeline 对象中删除或插入步骤?

我正在尝试在 Pipeline 对象中使用或不使用一步进行网格搜索。并且想知道我是否可以在管道中插入或删除一个步骤。我在Pipeline 源代码中看到,有一个self.steps 对象包含所有步骤。我们可以通过named_steps()获取步骤。在修改它之前,我想确定一下,我不会造成意想不到的影响。

这是一个示例代码:

from sklearn.pipeline import Pipeline
from sklearn.svm import SVC
from sklearn.decomposition import PCA
estimators = [('reduce_dim', PCA()), ('svm', SVC())]
clf = Pipeline(estimators)
clf 

我们是否有可能做类似steps = clf.named_steps() 的操作,然后在此列表中插入或删除?这会对 clf 对象造成不良影响吗?

【问题讨论】:

【参考方案1】:

我看到大家只提到了删除步骤。如果您还想在管道中插入一个步骤:

pipe.steps.append(['step name',transformer()])

pipe.steps 的工作方式与列表相同,因此您也可以将项目插入特定位置:

pipe.steps.insert(1,['estimator',transformer()]) #insert as second step

【讨论】:

感谢您的帮助!我认为appendinsert 应该使用tuple 而不是`list` 来完成,因为管道中的每个步骤都是tuple。如:pipe.steps.append(('step name',transformer()))pipe.steps.insert(1,('estimator',transformer()))【参考方案2】:

基于初步测试,您可以像处理任何列表项一样安全地从 scikit-learn 管道中删除一个步骤,只需一个简单的

clf_pipeline.steps.pop(n)

其中 n 是您尝试删除的单个估算器的位置。

【讨论】:

感谢您的回答。您能否扩展一下“基于基本测试”? 我有大约 500 个具有相同矢量化步骤的预训练管道。我使用这些管道之一的矢量化步骤转换了输入数据,然后在对预矢量化数据运行每个管道的 predict_proba 方法之前从所有管道中删除了此步骤。结果分数与我在没有预矢量化的情况下对原始数据运行每个未修改的管道一样,并且由于我没有一遍又一遍地执行相同的矢量化步骤,因此整体运行时间得到了改善。请注意,这只适用于无状态转换器,如散列矢量化器。 也许您可以通过设置管道的memory 参数来使用缓存?【参考方案3】:

只是插话,因为我觉得其他答案很好地回答了向管道添加步骤的问题,但并没有真正涵盖如何从管道中删除步骤。

但请注意我的方法。在这种情况下切片列表有点奇怪。

from sklearn.pipeline import Pipeline
from sklearn.svm import SVC
from sklearn.decomposition import PCA
from sklearn.preprocessing import PolynomialFeatures

estimators = [('reduce_dim', PCA()), ('poly', PolynomialFeatures()), ('svm', SVC())]
clf = Pipeline(estimators)

如果你想创建一个只有步骤 PCA/多项式的管道,你可以按索引对列表进行切片并将其传递给管道

clf1 = Pipeline(clf.steps[0:2])

只想使用步骤 2/3? 注意这些片段并不总是最有意义

clf2 = Pipeline(clf.steps[1:3])

只想使用步骤 1/3? 我似乎无法使用这种方法

clf3 = Pipeline(clf.steps[0] + clf.steps[2]) # errors

【讨论】:

clf3 = Pipeline([clf.steps[0], clf.steps[2]])【参考方案4】:

是的,这是可能的,但您必须满足 Pipeline 在初始化时要求的相同要求,即您不能在除最后一步之外的任何步骤中插入预测器,您应该在更新 Pipeline.steps 后调用 fit,因为在更新完所有步骤之后(可能是在之前的fit 调用中学到的)将失效,Pipeline 的最后一步也应该始终实现fit 方法,之前的所有步骤都应该实现fit_transform

所以是的,它可以在当前的代码库中工作,但我认为这不是你的任务的好解决方案,它使你的代码更加依赖于 Pipeline 的当前实现,我认为使用修改的步骤创建新的 Pipeline 更方便,因为 Pipeline 至少会验证您在初始化中的所有步骤,所以创建新的 Pipeline 在速度方面与修改现有管道的步骤不会有显着差异,但正如我刚才所说 - 在每次修改步骤后创建新的 Pipeline 更安全以防有人会显着改变 Pipeline 的实现。

【讨论】:

感谢您的 cmets。直接修改步骤的担忧也是我的担忧,这就是为什么我问是否有安全的方法来做到这一点。哦,关于为什么我要修改管道而不是创建新管道。原因是我想用不同的管道做一堆实验。因此在代码中修改它们是一种首选方式。我同意创建新的管道也是一个好方法。我可能会重新考虑这一点。谢谢。 (仍然希望有人有办法安全地修改步骤:)

以上是关于在 scikit-learn 管道中插入或删除步骤的主要内容,如果未能解决你的问题,请参考以下文章

相同数据和步骤的 Scikit-learn 管道无法分类

scikit-learn:应用任意函数作为管道的一部分

在管道中使用时带有 scikit-learn PLSRegression 的 ValueError

使用列操作步骤创建 sklearn 管道

使用 Scikit-Learn 在管道中包含预测器

如何创建一个应用 z-score 和交叉验证的 scikit-learn 管道?