使用 Python 和 scikit-learn 中的 Pipeline 自动化机器学习工作流

在机器学习项目中存在可以自动化的标准工作流。

在 Python scikit-learn 中,Pipelines 有助于清晰地定义和自动化这些工作流。

在本文中,您将了解 scikit-learn 中的 Pipelines 以及如何自动化常见的机器学习工作流。

通过我的新书《Python 机器学习精通》,逐步教程和所有示例的Python 源代码文件,来启动您的项目

让我们开始吧。

  • 2017年1月更新:更新以反映 scikit-learn 0.18 版本中的 API 变化。
  • 2018年3月更新:添加了替代链接以下载数据集,因为原始链接似乎已被删除。
Automate Machine Learning Workflows with Pipelines in Python and scikit-learn

使用 Python 和 scikit-learn 中的 Pipeline 自动化机器学习工作流
照片作者:Brian Cantoni,部分权利保留。

用于自动化机器学习工作流的 Pipelines

应用机器学习中存在标准工作流。之所以标准,是因为它们解决了常见问题,例如测试中的数据泄露。

Python scikit-learn 提供了一个 Pipeline 工具来帮助自动化机器学习工作流。

Pipelines 的工作方式是允许将线性数据转换序列链接在一起,最终形成一个可以进行评估的建模过程。

目标是确保管道中的所有步骤都约束在用于评估的数据范围内,例如训练数据集或交叉验证过程的每个折叠。

您可以阅读用户指南中的 Pipeline 部分,以了解更多关于 scikit-learn 中 Pipelines 的信息。您还可以查看 pipeline 模块中 Pipeline 和 FeatureUnion 类的 API 文档。

需要 Python 机器学习方面的帮助吗?

参加我为期 2 周的免费电子邮件课程,探索数据准备、算法等等(附带代码)。

立即点击注册,还将免费获得本课程的 PDF 电子书版本。

Pipeline 1:数据准备和建模

应用机器学习中容易陷入的一个陷阱是将训练数据集中的数据泄露到测试数据集中。

为了避免此陷阱,您需要一个具有严格训练和测试分离的健壮测试框架。这包括数据准备。

数据准备是向算法泄露整个训练数据集知识的一种简单方式。例如,在学习之前使用整个训练数据集进行归一化或标准化来准备数据将不是一个有效的测试,因为训练数据集会受到测试集数据规模的影响。

Pipelines 通过确保标准化等数据准备过程约束在交叉验证过程的每个折叠中,来帮助您防止测试中的数据泄露。

下面的示例演示了这种重要的数据准备和模型评估工作流。管道定义了两个步骤:

  1. 标准化数据。
  2. 学习线性判别分析模型。

然后使用 10 折交叉验证来评估管道。

注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。可以尝试运行该示例几次,并比较平均结果。

运行该示例将提供该设置在数据集上的准确性摘要。

Pipeline 2:特征提取和建模

特征提取是另一个容易发生数据泄露的过程。

与数据准备一样,特征提取过程必须限于训练数据集中的数据。

Pipeline 提供了一个名为 FeatureUnion 的便捷工具,该工具允许将多个特征选择和提取过程的结果合并到一个更大的数据集上,然后可以在该数据集上训练模型。重要的是,所有特征提取和特征联合都发生在交叉验证过程的每个折叠中。

下面的示例演示了定义了四个步骤的管道:

  1. 使用主成分分析进行特征提取(3 个特征)
  2. 使用统计选择进行特征提取(6 个特征)
  3. 特征联合
  4. 学习逻辑回归模型

然后使用 10 折交叉验证来评估管道。

注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。可以尝试运行该示例几次,并比较平均结果。

运行该示例将提供管道在数据集上的准确性摘要。

总结

在本文中,您了解了应用机器学习中数据泄露的困难。

您了解了 Python scikit-learn 中的 Pipeline 工具以及如何使用它们来自动化标准的机器学习工作流。

您学会了如何在两个重要用例中使用 Pipelines:

  1. 数据准备和建模约束在交叉验证过程的每个折叠中。
  2. 特征提取和特征联合约束在交叉验证过程的每个折叠中。

您对数据泄露、Pipelines 或本文有任何疑问吗?在评论中提问,我会尽力回答。

发现 Python 中的快速机器学习!

Master Machine Learning With Python

在几分钟内开发您自己的模型

...只需几行 scikit-learn 代码

在我的新电子书中学习如何操作
精通 Python 机器学习

涵盖自学教程端到端项目,例如
加载数据可视化建模调优等等...

最终将机器学习带入
您自己的项目

跳过学术理论。只看结果。

查看内容

84 回复“使用 Python 和 scikit-learn 中的 Pipeline 自动化机器学习工作流”

  1. Ebrahimi 2016 年 9 月 23 日上午 6:47 #


    谢谢你的好帖子!
    当我们使用 pipeline 时,训练数据(9 个折叠)会被标准化,然后用于标准化训练数据的参数会被用来标准化测试数据吗?这篇帖子是这样建议的
    http://stats.stackexchange.com/questions/174823/how-to-apply-standardization-normalization-to-train-and-testset-if-prediction-I

    谢谢

  2. Ebrahimi 2016 年 9 月 23 日上午 6:52 #

    您能否为我们提供一个使用 pipeline 进行数据准备和特征选择的示例?过采样(ADASYN)也应该仅在训练数据上进行。可以同时进行这三者吗?

    非常感谢

  3. Ebrahimi 2016 年 9 月 23 日上午 7:15 #

    谢谢
    我在这里找到了答案
    http://stats.stackexchange.com/questions/228774/cross-validation-of-a-machine-learning-pipeline

  4. Chaks 2016 年 10 月 5 日下午 6:48 #

    当 Y 有多于一列数据时(替换 Y = array[:,8]),会发生什么?以及如何使用你的方法来做?谢谢 & 此致,Chaks

    • Jason Brownlee 2016 年 10 月 6 日上午 9:32 #

      好问题,预测多个输出的想法。

      我没有任何示例,也不确定 sklearn 是否支持此行为。我知道单个算法支持此功能,例如神经网络。

  5. Chaks 2016 年 10 月 6 日上午 12:05 #

    如何在 pipeline 中获取精确率和召回率值?

  6. Pratik Patil 2017 年 2 月 1 日晚上 9:39 #

    嗨,Jason,
    在使用 Keras/Scikit-wrapper 和 Pipeline 进行标准化以获得最佳拟合后,如何访问 Pipeline 中 Keras regressor/classifier 的权重?我想将这些权重打印到文本或 CSV 文件中。但我难以访问这些权重。

    • Jason Brownlee 2017 年 2 月 2 日下午 1:56 #

      Pratik,我不太确定。

      您可能需要单独转换数据,并使用独立的 Keras 模型,这样您就可以直接访问权重。

  7. Dan 2017 年 3 月 6 日凌晨 1:17 #

    感谢 Jason 的精彩帖子。

    为了我的理解。Feature Union 允许我们将两种特征提取方法放入 pipeline 中,它们保持独立,对吗?因为使用 PCA 获取 3 个特征然后选择最好的 6 个特征是没有意义的。但它们是如何组合在一起的?你能详细说明一下,或者推荐一个好的来源吗?

    附注:Keras vs tflearn vs Tensorflow?我觉得 Keras 对我这样的初学者来说是最简单的!
    谢谢

    • Jason Brownlee 2017 年 3 月 6 日上午 10:59 #

      嗨 Dan,

      特征的联合只是将它们添加到一个大的数据集中,作为新的列供您稍后在 pipeline 中使用/处理。

  8. Dror Atariah 2017 年 7 月 24 日下午 4:39 #

    在第二个示例中,为什么不将归一化步骤添加到 pipeline 中;例如

    estimators.append(('standardize', StandardScaler()))

    从第一个例子中?

    • Jason Brownlee 2017 年 7 月 25 日上午 9:34 #

      当然可以。在第二个示例中,我尝试演示一些除了缩放之外的其他内容。

      • Cray 2018 年 7 月 5 日晚上 10:09 #

        缩放器是否应该在特征联合之后?

        • Jason Brownlee 2018 年 7 月 6 日上午 6:42 #

          听起来不错。

  9. Jan 2017 年 9 月 8 日晚上 7:09 #

    嗨,Jason!

    感谢这篇文章。再一次,这是解开谜题的缺失部分!

    您写道“在学习之前使用整个训练数据集进行归一化或标准化在训练之前,不应该是一个有效的测试”。您指的是在分割训练/验证和独立测试集之前对整个数据集进行标准化,是吗?

    关于何时何地在监督学习任务中进行数据标准化,是否有更多信息——关于如何避免最常见工作流中的数据泄露的某种流程图?

    此致!

  10. Franco Arda 2017 年 11 月 1 日下午 6:39 #

    Jason 的又一篇精彩文章!“预处理或特征提取期间的数据泄露”是一个很少在 ML 课程中涵盖的棘手陷阱……

    • Jason Brownlee 2017 年 11 月 2 日上午 5:08 #

      谢谢你,Franco。

  11. Duccio A 2017 年 11 月 28 日上午 6:10 #

    感谢您的精彩帖子和书籍!
    如果你要尝试多种模型(例如 LinearRegression、Lasso 和 Ridge),你会为要测试的每个模型重复第一个示例中的第 16-24 行吗?

    谢谢你

    • Jason Brownlee 2017 年 11 月 28 日上午 8:42 #

      是的,正是如此。

  12. Leon C 2018 年 2 月 7 日上午 8:51 #

    我对于组合 PC 和选定的最佳特征进行预测感到困惑。主成分是原始特征的组合。对 PCA 和核 PCA 进行特征联合,或者在某些情况下,对逐步和向后选择进行特征联合,是否明智?

    • Jason Brownlee 2018 年 2 月 7 日上午 9:33 #

      这只是一个示例。它可能对您的数据没有意义。

  13. Laura 2018 年 2 月 15 日晚上 9:42 #

    我爱你!(说真的,我是初学者,每次我查找东西时,您的博客都会弹出,并且我都能以令人难以置信的清晰度找到我想要的东西!)

    • Jason Brownlee 2018 年 2 月 16 日上午 8:33 #

      很高兴听到这些材料对 Laura 有帮助。

  14. Marko Dinic 2018 年 3 月 3 日凌晨 12:34 #

    你好 Jason,很棒的文章。不过我有几个问题。

    1) 在文本分类中也适用吗?例如,创建词袋模型,或者更优的 tf-idf 特征,高度依赖于语料库中的所有文档。我的理解是,我们会拟合类似 tf-idf transformer 的模型到训练集上,基于训练数据“学习”idf,并使用相同的 transformer 来转换测试数据(现在使用来自具体测试文档的 tf 和来自训练语料库的“学习”的 idf)来确定准确性。这同样适用于实时进入的新数据。我的理解正确吗?

    2) 如果您有训练/测试/验证集划分,您是否仅根据训练数据集确定转换参数,并以相同的方式将其应用于测试集和验证集?

    3) 如何将 k 折交叉验证与训练/测试/验证的概念结合起来?您是否只在训练数据集上进行交叉验证,并“减少一个数据集”,例如在训练集(80%)上进行 k 折交叉验证,验证集(20%)用于超参数调优,测试集(20%)用于最终检查?

    我希望问题足够清晰,而且数量不多 🙂 再次感谢,这是一篇很棒的文章。

  15. Navin 2018 年 3 月 21 日上午 7:12 #

    你好,很棒的文章,
    将模型摘要(系数、截距等)包含在 pipeline 中的最佳方法是什么?
    即使它没有包含在 pipeline 中,您如何访问单个 pipeline 元素以提取相关信息?

    • Jason Brownlee 2018 年 3 月 21 日下午 3:04 #

      好问题。

      您可以在将模型添加到 pipeline 使用的列表中之前保留对其的引用。

      • Venkatesh Gandi 2020 年 1 月 20 日下午 5:09 #

        您能给一个例子以便更好地理解吗?

        • Jason Brownlee 2020 年 1 月 21 日上午 7:07 #

          没有,抱歉。

  16. Neha 2018 年 5 月 1 日上午 8:11 #

    嗨,Jason,

    再次感谢您的所有帖子。它们已经成为我不可或缺的资源。我有一个关于 Pipeline 2:特征提取和建模第 19 行的问题;我们是否遗漏了提及随机状态的种子?我应该用以下内容替换这一行吗?
    features.append((‘pca’, PCA(n_components=3, random_state=7)))

  17. Abhilash Srivastava 2018 年 5 月 16 日上午 11:00 #

    Jason,写得太棒了。谢谢!

    • Jason Brownlee 2018 年 5 月 17 日上午 6:22 #

      谢谢,很高兴对您有帮助。

  18. kern 2018 年 8 月 20 日下午 5:55 #

    嗨 Jason

    我对评分方面感到困惑。如何在使用 pipeline + 交叉验证后对新数据集进行评分?

    这是我的例子

    estimators = []
    estimators.append(('standardize', StandardScaler()))
    estimators.append(('mlp', KerasClassifier(build_fn=create_large_model, nb_epoch=250,
    validation_split=0.15,batch_size=25, verbose=2)))

    pipeline = Pipeline(estimators)
    kfold = StratifiedKFold(n_splits=3, shuffle=True, random_state=108)
    results = cross_val_score(pipeline, X_train, y_train, cv=kfold)

    这可以正常训练模型,但如果我运行以下代码

    print(accuracy_score(y_train, pipeline.predict(X_train)))

    我收到一个错误
    “NotFittedError: 这个 StandardScaler 实例还没有拟合。在使用此方法之前,请先使用适当的参数调用‘fit’。”

    • Jason Brownlee 2018 年 8 月 21 日上午 6:13 #

      我们不对新数据进行评分。

      一旦我们选择了模型,我们就可以用所有训练数据拟合一个新模型,然后使用该模型对新数据进行预测。

      也许这篇文章会有所帮助
      https://machinelearning.org.cn/make-predictions-scikit-learn/

      • Kern 2018 年 8 月 21 日晚上 9:17 #

        感谢您的快速回复。我错误地使用了“score”这个词。我的意思是,使用交叉验证后的模型在训练集上对新数据进行预测。

        据我目前对 pipelining 的理解,任何预处理步骤(如缩放/归一化等)都使用训练数据上的 fit_transform 方法,并保存转换参数,以便在预测新数据(使用 transform 方法)时可以重用它们,或者我是否完全误解了?

        我的困惑源于这样一个事实:当我使用了一些预处理步骤在训练数据上,然后将其与 pipeline 中的交叉验证结合使用时,模型权重或参数将在我上面示例的“pipeline”对象中可用,因此它们可以进一步使用。

        如果我删除了交叉验证步骤,我就可以使用 pipeline.predict 来获取新数据集的预测。

  19. Kyriacos 2018年11月7日上午2:11 #

    Jason你好。首先,感谢您提供的信息丰富的博文,我有一个问题。

    假设我们在工作流程中有一些特征缩放。我按照您在这篇文章中描述的那样,使用管道进行交叉验证。最后,我找到了一个让我满意的模型,并用所有训练数据来训练它。

    现在,假设我有了新的、从未见过的数据,我想进行一些预测。在进行预测之前,我必须对新数据进行特征缩放。

    为了缩放新数据,我应该在我的缩放器中使用什么数据?只使用新数据?训练数据和新数据?还是只使用训练数据?

    • Jason Brownlee 2018年11月7日上午6:09 #

      最好在交叉验证过程的每个折叠中执行特征缩放。

      一旦选择了模型,最终模型就会在所有可用数据上拟合,包括为所有可用数据准备缩放转换。当新数据进来时,可以使用相同的转换对象/系数。

  20. Daniel Penalva 2019年1月21日上午5:36 #

    建议

    编辑以将“...整个训练数据集...”替换为“整个数据集”,否则会让人们混淆,认为训练数据集等同于整个数据集,而事实并非如此,前者包含了测试数据集。

    • Daniel Penalva 2019年1月21日上午5:42 #

      抱歉,我的意思是最后一个也包含了测试数据集。

    • Jason Brownlee 2019年1月21日上午11:57 #

      感谢Daniel的建议。

  21. Sneha 2019年2月11日下午2:55 #

    你好,
    很棒的帖子,Json。
    我想知道管道的目的是什么,如果我们先将整个数据集进行训练和测试分割,然后对训练集应用预处理步骤,生成的编码器或缩放器对象可以被pickle,然后可以为测试数据集反pickle?

    • Sneha 2019年2月11日下午3:00 #

      *Jason,非常抱歉拼写错误。

    • Jason Brownlee 2019年2月12日上午7:51 #

      为了自动化数据在建模前正确排序/应用数据转换。

      如果您愿意,也可以手动完成。

  22. Sagar Gori 2019年2月12日下午4:59 #

    Jason,正如您提到的“重要的是,所有特征提取和特征联合都发生在交叉验证过程的每个折叠中。”

    您能否通过示例来详细说明这一点?因为我正在尝试了解如果我使用5折交叉验证方法,特征提取和特征联合将如何进行?

    这是否意味着在K折交叉验证的每次迭代中,您都会获得训练数据的特征列表?这个过程会继续进行其余的迭代,然后您将每个迭代的所有特征组合起来,最终列表是所有特征的联合?

  23. Nandini Nuthalapati 2019年3月31日上午6:38 #

    Jason你好,很棒的文章!如果数据中包含一些分类特征,或者我们不想标准化某些数值特征,我们仍然可以在管道中包含StandardScalar吗?还是我们需要单独对所需的特征进行标准化?

  24. Prem Alphonse 2019年6月7日下午5:32 #

    Jason你好,如果我们保存了管道(包含预处理+标准化+模型),未来是否可以使用它对单个测试记录进行相同的步骤处理?

  25. Prem 2019年6月12日上午8:05 #

    嗨,Jason,
    我已经在原始数据上进行了训练测试分割,

    使用Xtrain进行了数据预处理并构建了模型,然后保存了管道,

    当我将Xtest传递给管道时,出现错误,提示训练集列中的所有类别都不存在于测试集中。

    是否应该先进行预处理,然后再构建管道?

    谢谢

    • Jason Brownlee 2019年6月12日上午8:09 #

      也许您的测试集与训练数据集不同?

      您必须确保训练数据集包含模型在测试/预测中预期会遇到的所有情况。

      • Prem 2019年6月12日上午8:17 #

        谢谢Jason,非常感谢您快速回复。

  26. Prem Alphonse 2019年6月12日上午9:10 #

    嗨,Jason,

    在某个类别列中,例如婚姻状况,我们有级别(已婚、单身、离婚、分居),当我执行get_dummies时,我得到4个虚拟列,使用这些列,我从X_train构建数据预处理和模型管道。

    假设在X_test中,婚姻状况只有2种(已婚、单身),当我将它传递给同一个上述管道时,在数据预处理过程中,get_dummies只创建2列,所以模型显示形状错误(因为我们没有其他两列类别)。

    请问我该如何处理这个问题?

    谢谢

    • Jason Brownlee 2019年6月12日下午2:22 #

      我建议使用标签编码器或独热编码器,并在训练数据集上拟合编码器。

  27. bob zigon 2019年7月19日上午9:23 #

    Jason
    在您的其他课程中,您提到了在执行线性回归时对输入和目标进行缩放。我可以想象将2个缩放器放入管道,但是如何将一个缩放器应用于输入,而另一个应用于目标?

    • Jason Brownlee 2019年7月19日上午9:28 #

      好问题。我认为它们要么全应用,要么都不应用。

      您需要手动对数据的子集执行操作。

  28. Venkatesh Gandi 2020年1月20日下午5:25 #

    Jason你好,感谢您的详细解释。

    您能否告诉我ColumnTransformer()和FeatureUnion()方法有什么区别?

    • Jason Brownlee 2020年1月21日上午7:08 #

      FeatureUnion组合列,就像hstack一样。

      Column Transformer将对特征子集应用任何任意操作,然后将结果进行hstack。

  29. Venkatesh Gandi 2020年1月22日上午6:25 #

    好的,感谢您的澄清。

  30. MF 2020年3月13日凌晨1:04 #

    嗨,Jason,

    是否可以将管道用于创建导入和从URL加载数据集的第一步?
    请告知。谢谢。

    • Jason Brownlee 2020年3月13日上午8:18 #

      也许可以,如果你自己编写代码的话。

      • MF 2020年3月13日晚上11:39 #

        嗨,Jason,

        谢谢您的回复。
        你能展示一下如何在管道中编写吗?
        我很感谢您的帮助。真的。

        • Jason Brownlee 2020年3月14日上午8:12 #

          抱歉,不行。

          • MF 2020年3月14日下午3:37 #

            您是否有任何可以参考的URL来指导我?谢谢。

          • Jason Brownlee 2020年3月15日上午6:11 #

            也许可以尝试在stackoverflow上发布您的问题。

  31. Shiyun Jiang 2020年4月30日上午2:20 #

    嗨 Jason

    我不太明白为什么要在FeatureUnion中使用两个特征提取?PCA的3个分量与SelectKBest的6个选定特征中的3个相同?这是否意味着我们在重复工作?还是模型会先在PCA上训练,然后根据SelectKBest训练?之后它们会相互比较,看看哪个更好?另外,为什么在应用选择方法的组件数量时不选择相等的数量?谢谢

    • Jason Brownlee 2020年4月30日上午6:50 #

      我们不这样做,这只是一个关于如何使用管道的示例。

      • Shiyun Jiang 2020年4月30日上午7:16 #

        那么,我们通常应该选择相等的数量吗?

        • Jason Brownlee 2020年4月30日上午11:35 #

          不,您应该选择能够为您的测试评估带来最佳性能的特征数量。

          • Shiyun Jiang 2020年5月1日晚上9:30 #

            好的,太好了。那么SelectKBest中的6个特征和PCA中的3个特征可能都很好?

          • Jason Brownlee 2020年5月2日上午5:44 #

            您必须使用受控的实验来发现对给定数据集最有效的方法。

  32. JG 2021年4月19日上午4:56 #

    嗨,Jason,

    Sklearn Pipeline绝对是一个强大的模块!感谢这次介绍。

    我根据您的代码进行了一些实验,在此分享我的结果

    – 我认为不需要使用FeatureUnion。现有的特征列表可以直接使用。

    – 从Pipeline步骤列表中删除FeatureUnion,对logisticRegression模型的得分结果是相同的。因此,我看不出包含这种特征联合的目的是什么……

    – 如果在KFold函数中未将shuffle设置为True(如您的情况),则random_state参数将没有意义。

    非常感谢您的教程

    我的问题

    1) Pipeline被用作整个流程的集合,并准备好实现kfold、cross_val_score等。OK。
    但是,如果我对了解任何步骤的中间结果(PCA、SelectKbest、ColumnTransformer……的特定结果)感兴趣,我不知道如何从管道中提取它们,我猜这是不可能的。

    2) 使用keras模型时,对于单一的回归和分类模型,我不知道如何应用keras包装器来使用例如Pipeline。

    关于您的代码
    I

    • Jason Brownlee 2021年4月19日上午5:54 #

      如果您对每个转换的中间输出感兴趣,您将不会使用管道。

      keras模型通过包装器可以作为管道的最后一步。

  33. JG 2021年4月19日下午5:19 #

    谢谢 Jason

  34. Muhammad Usama Zahid 2022年5月2日上午5:01 #

    您是我的灵感。您优雅地解释了主题,现在概念非常清晰。谢谢Jason!

  35. Hasti 2023年1月9日上午3:40 #

    大家好,我使用了这段代码进行管道设置,我遇到了这个错误,请帮帮我

    pipe = Pipeline([(‘scaler’, StandardScaler()),
    (‘Logestic’,LogisticRegression()),
    (‘SVM’,SVC())])
    错误
    所有中间步骤都应该是转换器并且实现fit和transform,或者应该是字符串‘passthrough’‘LogisticRegression()’(类型)不应该。

Leave a Reply

Machine Learning Mastery 是 Guiding Tech Media 的一部分,Guiding Tech Media 是一家领先的数字媒体出版商,专注于帮助人们了解技术。访问我们的公司网站以了解更多关于我们的使命和团队的信息。