如何在机器学习中使用折外预测

机器学习算法通常使用诸如k折交叉验证之类的重采样技术进行评估。

在k折交叉验证过程中,会对由未用于训练模型的数据组成的测试集进行预测。这些预测被称为折外预测,属于样本外预测的一种。

折外预测在机器学习中扮演着重要角色,既可以估计模型在未来对新数据进行预测时的性能(即模型的泛化性能),也可以用于开发集成模型。

在本教程中,您将了解到对机器学习中折外预测的初步介绍。

完成本教程后,您将了解:

  • 折外预测是样本外预测的一种,是在未用于训练模型的数据上进行的预测。
  • 折外预测最常用于估计模型在对未见过的数据进行预测时的性能。
  • 折外预测可用于构建一个称为堆叠泛化或堆叠集成的集成模型。

开始您的项目,阅读我的新书《Python集成学习算法》,其中包含分步教程和所有示例的Python源代码文件。

让我们开始吧。

  • **2020年1月更新**:已针对 scikit-learn v0.22 API 的变更进行更新。
How to Use Out-of-Fold Predictions in Machine Learning

如何在机器学习中使用折外预测
照片作者:Gael Varoquaux,部分权利保留。

教程概述

本教程分为三个部分;它们是:

  1. 什么是折外预测?
  2. 用于评估的折外预测
  3. 用于集成的折外预测

什么是折外预测?

通常,我们会使用诸如k折交叉验证之类的重采样技术来评估机器学习算法在数据集上的性能。

k折交叉验证过程涉及将训练数据集划分为k个组,然后使用这k个组中的每一组作为测试集,而其余组用作训练集。

这意味着会训练和评估k个不同的模型。模型性能的评估是基于模型在所有k折上进行的预测。

该过程可总结如下:

  • 1. 随机打乱数据集。
  • 2. 将数据集分成k个组。
  • 3. 对于每个唯一的组:
    • a. 将该组作为保留集或测试数据集。
    • b. 将其余组作为训练数据集。
    • c. 在训练集上拟合模型,并在测试集上对其进行评估。
    • d. 保留评估分数,并丢弃模型。
  • 4. 使用模型评估分数的样本总结模型的技能。

重要的是,数据样本中的每个观测值都会被分配到一个独立的组,并在该过程中一直保留在该组中。这意味着每个样本都有机会在保留集中使用1次,并在训练模型时使用k-1次。

有关k折交叉验证主题的更多信息,请参阅教程:

折外预测是k折交叉验证过程中模型进行的预测。

也就是说,折外预测是在重采样过程中在保留数据集上进行的预测。如果执行正确,则训练数据集中的每个示例都会有一个预测。

有时,折外会用缩写OOF来总结。

  • 折外预测:模型在k折交叉验证过程中对保留示例进行的预测。

折外预测的概念与样本外预测的概念直接相关,因为在这两种情况下,预测都是在未用于模型训练的示例上进行的,并且可以用于估计模型在用于预测新数据时的性能。

因此,折外预测是样本外预测的一种,尽管是在使用k折交叉验证的模型评估的上下文中描述的。

  • 样本外预测:模型在未用于模型训练的数据上进行的预测。

样本外预测也可能被称为保留预测。

折外预测主要有两个用途;它们是:

  • 估计模型在未见过的数据上的性能。
  • 拟合集成模型。

让我们仔细看看这两种情况。

想开始学习集成学习吗?

立即参加我为期7天的免费电子邮件速成课程(附示例代码)。

点击注册,同时获得该课程的免费PDF电子书版本。

用于评估的折外预测

折外预测最常见的用途是估计模型的性能。

也就是说,可以对模型在未用于训练的数据上进行的预测进行评分,并使用诸如错误率或准确率之类的评分指标进行评估。此指标提供了模型在用于预测新数据(例如,模型在实际中使用时)时的性能估计。

通常,在未用于训练模型的数据上进行的预测可以洞察模型如何泛化到新情况。因此,评估这些预测的分数被称为机器学习模型的泛化性能。

这两种方法都可以用于估计模型的性能。

第一种方法是对每个折的预测结果进行模型评分,然后计算这些分数的平均值。例如,如果我们正在评估一个分类模型,那么可以在每组折外预测上计算分类准确率,然后报告平均准确率。

  • 方法1:将性能估计为每个折外预测组上的平均得分。

第二种方法是考虑每个示例在每个测试集中只出现一次。也就是说,训练数据集中的每个示例在k折交叉验证过程中都进行了一次预测。因此,我们可以收集所有预测,并将它们与预期结果进行比较,并在整个训练数据集上直接计算一个得分。

  • 方法2:使用所有折外预测的聚合来估计性能。

这两种方法都是合理的,并且由此产生的分数应该近似相等。

计算每组样本外预测的平均值可能是最常见的方法,因为估计量的方差也可以通过标准差或标准误差来计算。

k个重采样性能估计被总结(通常是均值和标准误差)……

— 第70页,《应用预测建模》,2013年。

我们可以通过一个小型演示示例来展示这两种评估模型性能的方法(使用折外预测)之间的区别。

我们将使用scikit-learn的make_blobs()函数来创建一个二分类测试问题,该问题包含1000个示例,两个类别和100个输入特征。

以下示例准备了一个数据样本,并总结了数据集中输入和输出元素的形状。

运行该示例会打印输入数据的形状,显示1000行数据,其中包含100列或输入特征,以及相应的分类标签。

接下来,我们可以使用k折交叉验证来评估KNeighborsClassifier模型。

我们将使用k=10进行KFold对象,这是合理的默认值,在每个训练数据集上拟合模型,并在每个保留折上对其进行评估。

准确率分数将存储在列表中,跨越每次模型评估,并报告这些分数的均值和标准差。

完整的示例如下所示。

运行示例会报告每次迭代中模型在保留折上的分类准确率。

注意:由于算法或评估程序的随机性,或者数值精度的差异,您的结果可能有所不同。请考虑多次运行示例并比较平均结果。

运行结束后,将报告准确率分数的均值和标准差。

我们可以将其与将所有预测作为一个整体进行评估的替代方法进行对比。

在每个保留折上评估模型后,会进行预测并存储在一个列表中。然后,在运行结束时,会将预测与每个保留测试集的预期值进行比较,并在最后报告一个准确率分数。

完整的示例如下所示。

注意:由于算法或评估程序的随机性,或者数值精度的差异,您的结果可能有所不同。请考虑多次运行示例并比较平均结果。

运行示例会收集每个保留数据集的所有预期值和预测值,并在运行结束时报告一个单独的准确率分数。

同样,这两种方法都具有可比性,您使用哪种方法可能取决于您自己预测建模问题的偏好。

用于集成的折外预测

折外预测的另一个常见用途是将其用于集成模型的开发。

集成是一种机器学习模型,它将来自在同一训练数据集上准备的两个或多个模型的预测进行组合。

这是在机器学习竞赛中非常常用的过程。

折外预测的聚合提供了关于模型在训练数据集的每个示例上如何工作的信息,而没有被用于训练模型。这些信息可以用来训练一个模型来纠正或改进这些预测。

首先,对每个感兴趣的基本模型执行k折交叉验证,并收集所有折外预测。重要的是,对每个模型执行相同的训练数据拆分到k折。现在,我们为每个模型获得了一个聚合的样本外预测组,例如,针对训练数据集中的每个示例的预测。

  • 基本模型:使用k折交叉验证在训练数据集上进行评估,并保留所有折外预测的模型。

接下来,第二个高阶模型,称为元模型,是在其他模型进行的预测上进行训练的。此元模型在进行预测时,可能会或可能不会将每个示例的输入数据作为输入。此模型的任务是学习如何最好地结合和纠正其他模型通过其折外预测所做的预测。

  • 元模型:接收一个或多个模型进行的折外预测作为输入,并展示如何最好地组合和纠正预测的模型。

例如,我们可能有一个两类分类预测建模问题,并训练一个决策树和一个k近邻模型作为基本模型。每个模型通过折外预测为训练数据集中的每个示例预测0或1。然后,这些预测以及输入数据可以构成元模型的新输入。

  • 元模型输入:给定样本的输入部分,与每个基本模型进行的预测连接。
  • 元模型输出:给定样本的输出部分。

为什么使用折外预测来训练元模型?

我们可以将每个基本模型训练在整个训练数据集上,然后为训练数据集中的每个示例进行预测,并将预测用作元模型的输入。问题在于预测会过于乐观,因为样本被用于每个基本模型的训练。这种乐观的偏差意味着预测会比正常情况更好,并且元模型可能无法学会结合和纠正基本模型预测所需的知识。

通过使用基本模型的折外预测来训练元模型,元模型可以看到并利用每个基本模型在未见过数据上运行时预期的行为,正如集成在实际中用于对新数据进行预测时一样。

最后,基本模型都在整个训练数据集上进行训练,然后可以使用这些最终模型和元模型对新数据进行预测。该集成的性能可以在训练期间未使用的单独保留测试数据集上进行评估。

该过程可总结如下:

  • 1. 对于每个基本模型:
    • a. 使用k折交叉验证并收集折外预测。
    • b. 在所有模型的折外预测上训练元模型。
    • c. 在整个训练数据集上训练每个基本模型。

此过程称为堆叠泛化,简称堆叠。由于通常使用线性加权和作为元模型,因此此过程有时称为混合

有关堆叠主题的更多信息,请参阅教程:

我们可以通过一个实际示例来使此过程具体化,该示例使用上一节中使用的相同数据集。

首先,我们将数据分成训练集和验证集。训练集将用于拟合子模型和元模型,验证集将保留不用于训练,并在最后用于评估元模型和子模型。

在此示例中,我们将使用k折交叉验证来拟合DecisionTreeClassifierKNeighborsClassifier模型,并在每个交叉验证折上进行操作,并使用拟合的模型进行折外预测。

模型将预测概率而不是类标签,以尝试为元模型提供更有用的输入特征。这是一个好习惯。

我们还将跟踪折外数据的输入数据(100个特征)和输出数据(预期标签)。

运行结束后,我们可以构建一个由输入数据的100个输入特征以及kNN和决策树模型预测概率的两个列组成的分类器数据集。

下面的create_meta_dataset()函数实现了这一点,它将折外数据和跨折的预测作为输入,并构建元模型的输入数据集。

我们可以调用此函数来准备元模型的数据。

然后,我们可以将每个子模型拟合到整个训练数据集上,以准备在验证数据集上进行预测。

然后,我们可以在准备好的数据上拟合元模型,在本例中是 LogisticRegression 模型。

最后,我们可以使用元模型对保留数据集进行预测。

这需要数据首先通过子模型,输出用于构建元模型的数据集,然后使用元模型进行预测。我们将所有这些包装到一个名为 stack_prediction() 的函数中,该函数接受模型和要进行预测的数据。

然后,我们可以对保留数据集上的子模型进行评估以供参考,然后使用元模型对保留数据集进行预测并进行评估。

我们期望元模型在保留数据集上的性能与任何单个子模型一样好或更好。如果不是这种情况,则可以使用其他子模型或元模型来处理该问题。

将所有这些结合起来,完整的示例如下所示。

运行示例首先报告决策树和 kNN 模型的准确性,然后报告未在训练期间看到的元模型在保留数据集上的性能。

注意:由于算法或评估程序的随机性,或者数值精度的差异,您的结果可能有所不同。请考虑多次运行示例并比较平均结果。

在这种情况下,我们可以看到元模型优于两个子模型。

为了确认子模型的预测确实为元模型增加了价值,可以尝试进行消融研究,以仅使用模型1、仅使用模型2以及不使用模型1和模型2作为元模型的输入来重新运行示例。

进一步阅读

如果您想深入了解,本节提供了更多关于该主题的资源。

教程

书籍

文章

API

总结

在本教程中,您了解了机器学习中的“out-of-fold”预测。

具体来说,你学到了:

  • 折外预测是样本外预测的一种,是在未用于训练模型的数据上进行的预测。
  • 折外预测最常用于估计模型在对未见过的数据进行预测时的性能。
  • 折外预测可用于构建一个称为堆叠泛化或堆叠集成的集成模型。

你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。

掌握现代集成学习!

Ensemble Learning Algorithms With Python

在几分钟内改进您的预测

...只需几行python代码

在我的新电子书中探索如何实现
使用 Python 实现集成学习算法

它提供**自学教程**,并附有关于以下内容的**完整工作代码**:
堆叠、投票、提升、装袋、混合、超级学习器等等……

将现代集成学习技术带入
您的机器学习项目


查看内容

How to Use Out-of-Fold Predictions in Machine Learning 的 18 条回复

  1. Markus December 7, 2019 at 11:35 pm #

    这是您另一篇精彩的博文,谢谢!

    NIT
    我注意到您使用了 numpy 数组索引 [:, 0] 来将维度从 [LENGTH, 1] 减小到 [LENGTH,],然后在 create_meta_dataset 函数中将其重塑回 [LENGTH, 1] 维度。

    我从示例中删除了所有 [:, 0] 索引以及以下行:

    yhat1 = array(yhat1).reshape((len(yhat1), 1))
    yhat2 = array(yhat2).reshape((len(yhat2), 1))

    示例仍然以相同的方式工作。

    • Jason Brownlee December 8, 2019 at 6:11 am #

      谢谢,我很高兴它很有趣/有帮助。

      非常好!感谢分享。

  2. Ismalia December 19, 2019 at 2:10 am #

    感谢您的精彩教程。我想实现类似的东西,但收到以下错误:
    TypeError: array() argument 1 must be a unicode character, not list
    当我运行以下代码时,如何修复?

    # 创建元数据集
    import numpy as np
    from array import array
    # 创建元数据集
    def create_meta_dataset(data_x, yhat1, yhat2)
    # 转换为列
    yhat1 = array(yhat1).reshape((len(yhat1), 1))
    yhat2 = array(yhat2).reshape((len(yhat2), 1))
    # 堆叠为单独的列
    meta_X = hstack((data_x, yhat1, yhat2))
    return meta_X

    ## 这是我调用函数的地方,它产生了那个错误
    # 构建元数据集
    meta_X = create_meta_dataset(data_x, knn_yhat, cart_yhat)

    • Jason Brownlee December 19, 2019 at 6:33 am #

      抱歉,我不熟悉这个错误,也许可以尝试发布到 stackoverflow?

      • Ismalia December 19, 2019 at 9:42 pm #

        谢谢,我解决了这个问题,需要添加 np.array 和 np.hstack。确保导入 numpy 数组。其他读者可以从中受益。这是一个基本错误,但可能会令人沮丧。

  3. Ehsan March 23, 2020 at 7:20 pm #

    感谢这篇教程。
    据我所知,当我们在循环中放入“fit method”时,前一个结果会被丢弃,并在每次迭代后被新结果替换。这意味着模型仅根据训练数据的最后一个折叠进行拟合。这是真的吗?如果能为我解释一下,我将不胜感激。

    提前感谢

  4. Dan May 27, 2021 at 6:45 am #

    非常感谢!!!!!

  5. TLM August 2, 2021 at 4:39 am #

    嗨,Jason,

    喜欢这个网站,在过去的 18 个月里,我通过阅读您的文章学到了很多。

    我遵循了您关于进一步学习的建议,并修改了示例,使其不包含子模型在元模型中的预测。

    每次运行 100 次后

    无元特征结果
    Model1 Accuracy: 0.731, Model2 Accuracy: 0.929
    Meta Model Accuracy: 0.955

    有元特征结果
    Model1 Accuracy: 0.733, Model2 Accuracy: 0.926
    Meta Model Accuracy: 0.955

    看看这些结果,我认为这些子模型的预测并没有增加任何价值。对我来说,更可能的情况是,与决策树或 K-Neighbors 相比,Logistic Regression 只是这个问题的一个更好的模型。

  6. Braden August 28, 2021 at 6:52 am #

    嗨,Jason,

    很棒的教程,尤其是概念泛化!我确实有一个关于使用堆叠模型评估性能的问题。

    考虑到计算限制不是问题,是否可以合理地使用交叉验证来评估整个训练过程中的堆叠模型性能?也就是说,保留一个“元”的 out-of-fold 数据集,使用上面描述的进一步交叉验证所分解的所有“元” in-fold 数据来训练基础模型,然后在元 out-of-fold 数据集上评估元模型,并重复这个过程?

    • Adrian Tam
      Adrian Tam August 28, 2021 at 9:44 am #

      是的,这听起来是合理的。

  7. Alexander Adamov October 6, 2021 at 10:23 pm #

    感谢您提供清晰而富有洞察力的教程!

    • Adrian Tam
      Adrian Tam October 7, 2021 at 3:51 am #

      谢谢你。很高兴你喜欢。

留下回复

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