Machine Learning Mastery 集成学习教程(六)
多类分类的一对一和一对剩余
最后更新于 2021 年 4 月 27 日
并非所有分类预测模型都支持多类分类。
感知器、逻辑回归和支持向量机等算法是为二进制分类而设计的,并不支持两类以上的分类任务。
将二进制分类算法用于多分类问题的一种方法是将多类别数据集分割成多个二进制类别数据集,并在每个二进制类别数据集上拟合二进制分类模型。这种方法的两个不同的例子是“一对一”和“一对一”策略。
在本教程中,您将发现多类分类的一对一和一对一策略。
完成本教程后,您将知道:
- 像逻辑回归和 SVM 这样的二分类模型本身不支持多类分类,需要元策略。
- One-vs-Rest 策略将多类分类拆分为每个类一个二分类问题。
- 一对一策略将多类分类分成每对类一个二进制分类问题。
用我的新书Python 集成学习算法启动你的项目,包括分步教程和所有示例的 Python 源代码文件。
我们开始吧。
如何使用一对一休息和一对一进行多类分类 图片由 Espen Sundve 提供,保留部分权利。
教程概述
本教程分为三个部分;它们是:
- 用于多类分类的二分类器
- 多类分类中的一对多
- 多类分类的一对一与一对一
用于多类分类的二分类器
分类是一个预测性的建模问题,包括给一个例子分配一个类标签。
二进制分类是那些例子被指定为两类中的一类的任务。多类分类是那些例子被指定为两个以上类中的一个的任务。
- 二分类:两类分类任务。
- 多类分类:两类以上的分类任务。
一些算法是为二进制分类问题设计的。例子包括:
- 逻辑回归
- 感知器
- 支持向量机
因此,它们不能用于多类分类任务,至少不能直接使用。
相反,启发式方法可以用于将多类分类问题分割成多个二进制类别数据集,并分别训练二进制分类模型。
这些启发式方法的两个例子包括:
- 一对一对多休息
- 一对一(OvO)
让我们仔细看看每一个。
多类分类中的一对多
One-vs-rest(简称 OvR,也称为 One-vs-All 或 OvA)是一种启发式方法,用于使用二进制分类算法进行多类分类。
它包括将多类数据集拆分成多个二进制分类问题。然后对每个二进制分类问题训练二进制分类器,并使用最有把握的模型进行预测。
例如,给定一个多类分类问题,其中每个类都有例子。这可以分为如下三个二元类别数据集:
- 二分类问题 1 :红色 vs【蓝色,绿色】
- 二分类问题 2 :蓝色 vs【红色,绿色】
- 二进制分类问题 3 :绿色 vs【红色,蓝色】
这种方法的一个可能的缺点是,它需要为每个类创建一个模型。例如,三个类需要三个模型。对于大型数据集(例如,数百万行)、慢速模型(例如,神经网络)或非常大量的类(例如,数百个类),这可能是一个问题。
显而易见的方法是使用一对其余的方法(也称为一对全部),其中我们训练 C 二进制分类器 fc(x),其中来自 C 类的数据被视为正,来自所有其他类的数据被视为负。
—第 503 页,机器学习:概率视角,2012 年。
这种方法要求每个模型预测一个类成员概率或类似概率的分数。然后使用这些分数的 argmax(分数最大的班级指数)来预测班级。
这种方法通常用于自然预测数值类成员概率或分数的算法,例如:
- 逻辑回归
- 感知器
因此,当使用这些算法进行多类分类时,Sklearn 库中这些算法的实现默认实现了 OvR 策略。
我们可以用一个使用物流分类算法的 3 类分类问题的例子来证明这一点。处理多类分类的策略可以通过“多类参数设置,一对多策略可以设置为“ ovr ”。
下面列出了使用内置的一对多策略拟合多类分类的逻辑回归模型的完整示例。
# logistic regression for multi-class classification using built-in one-vs-rest
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
# define dataset
X, y = make_classification(n_samples=1000, n_features=10, n_informative=5, n_redundant=5, n_classes=3, random_state=1)
# define model
model = LogisticRegression(multi_class='ovr')
# fit model
model.fit(X, y)
# make predictions
yhat = model.predict(X)
Sklearn 库还提供了一个单独的 OneVsRestClassifier 类,该类允许 one-vs-rest 策略用于任何分类器。
此类可用于使用二进制分类器(如逻辑回归或感知器)进行多类分类,或者甚至使用其他本身支持多类分类的分类器。
它非常容易使用,并且要求将用于二进制分类的分类器作为参数提供给 OneVsRestClassifier 。
下面的例子演示了如何使用 OneVsRestClassifier 类和作为二进制分类模型的物流分类类。
# logistic regression for multi-class classification using a one-vs-rest
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.multiclass import OneVsRestClassifier
# define dataset
X, y = make_classification(n_samples=1000, n_features=10, n_informative=5, n_redundant=5, n_classes=3, random_state=1)
# define model
model = LogisticRegression()
# define the ovr strategy
ovr = OneVsRestClassifier(model)
# fit model
ovr.fit(X, y)
# make predictions
yhat = ovr.predict(X)
多类分类的一对一与一对一
One-vs-One(简称 OvO)是另一种使用二进制分类算法进行多类分类的启发式方法。
与 one-vs-rest 类似,one-vs-one 将多类类别数据集拆分为二分类问题。与 one-vs-rest 为每个类将数据集拆分为一个二进制数据集不同,one-vs-one 方法为每个类将数据集拆分为一个数据集,而不是其他类。
例如,考虑一个包含四个类的多类分类问题:“红色、“蓝色、”和“绿色、“黄色”这可以分为六个二元类别数据集,如下所示:
- 二进制分类问题 1 :红色对蓝色
- 二进制分类问题 2 :红色对绿色
- 二进制分类问题 3 :红色对黄色
- 二进制分类问题 4 :蓝色对绿色
- 二进制分类问题 5 :蓝色对黄色
- 二进制分类问题 6 :绿色对黄色
这比上一节描述的一对多策略要多得多的数据集和模型。
计算二进制数据集以及模型数量的公式如下:
- (数字类别*(数字类别–1))/2
我们可以看到,对于四个类,这给了我们六个二分类问题的期望值:
- (数字类别*(数字类别–1))/2
- (4 * (4 – 1)) / 2
- (4 * 3) / 2
- 12 / 2
- six
每个二分类模型可以预测一个类别标签,并且通过一对一策略预测具有最多预测或投票的模型。
另一种方法是引入 K(k1)/2 二元判别函数,每一对可能的类对应一个。这就是所谓的一对一分类器。然后根据判别函数中的多数票对每个点进行分类。
—第 183 页,模式识别与机器学习,2006。
类似地,如果二进制分类模型预测数值类成员,例如概率,那么分数总和(具有最大总和分数的类)的 argmax 被预测为类标签。
经典地,这种方法被建议用于支持向量机(SVM)和相关的基于核的算法。这被认为是因为内核方法的表现与训练数据集的大小不成比例,使用训练数据的子集可能会抵消这种影响。
Sklearn 中的支持向量机实现由 SVC 类提供,支持多类分类问题的一对一方法。这可以通过将“ decision_function_shape ”参数设置为“ ovo 来实现。
下面的例子演示了 SVM 使用一对一方法进行多类分类。
# SVM for multi-class classification using built-in one-vs-one
from sklearn.datasets import make_classification
from sklearn.svm import SVC
# define dataset
X, y = make_classification(n_samples=1000, n_features=10, n_informative=5, n_redundant=5, n_classes=3, random_state=1)
# define model
model = SVC(decision_function_shape='ovo')
# fit model
model.fit(X, y)
# make predictions
yhat = model.predict(X)
Sklearn 库还提供了一个单独的 OneVsOneClassifier 类,允许一对一策略用于任何分类器。
该类可以与二进制分类器(如 SVM、逻辑回归或感知器)一起用于多类分类,甚至可以与其他本身支持多类分类的分类器一起使用。
它非常容易使用,并且要求将用于二进制分类的分类器作为参数提供给 OneVsOneClassifier 。
下面的例子演示了如何使用 OneVsOneClassifier 类和一个用作二进制分类模型的 SVC 类。
# SVM for multi-class classification using one-vs-one
from sklearn.datasets import make_classification
from sklearn.svm import SVC
from sklearn.multiclass import OneVsOneClassifier
# define dataset
X, y = make_classification(n_samples=1000, n_features=10, n_informative=5, n_redundant=5, n_classes=3, random_state=1)
# define model
model = SVC()
# define ovo strategy
ovo = OneVsOneClassifier(model)
# fit model
ovo.fit(X, y)
# make predictions
yhat = ovo.predict(X)
进一步阅读
如果您想更深入地了解这个主题,本节将提供更多资源。
书
蜜蜂
文章
摘要
在本教程中,您发现了多类分类的一对一和一对一策略。
具体来说,您了解到:
- 像逻辑回归和 SVM 这样的二分类模型本身不支持多类分类,需要元策略。
- One-vs-Rest 策略将多类分类拆分为每个类一个二分类问题。
- 一对一策略将多类分类分成每对类一个二进制分类问题。
你有什么问题吗? 在下面的评论中提问,我会尽力回答。
如何在机器学习中使用折外预测
最后更新于 2021 年 4 月 27 日
机器学习算法通常使用重采样技术进行评估,例如 k 倍交叉验证。
在 k 倍交叉验证过程中,对测试集进行预测,测试集由不用于训练模型的数据组成。这些预测被称为超差预测,一种样本外预测。
在未来对新数据进行预测时,所谓的模型的泛化表现,以及集成模型的开发中,超折叠预测在机器学习中都起着重要的作用。
在本教程中,您将发现一个关于机器学习中异常预测的温和介绍。
完成本教程后,您将知道:
- 超差预测是对未用于训练模型的数据进行的一种超差预测。
- 在对看不见的数据进行预测时,超差预测最常用于估计模型的表现。
- 叠外预测可以用来构建一个集合模型,称为叠化概化或叠化集合。
用我的新书Python 集成学习算法启动你的项目,包括分步教程和所有示例的 Python 源代码文件。
我们开始吧。
- 2020 年 1 月更新:针对 Sklearn v0.22 API 的变化进行了更新。
如何在机器学习中使用超折叠预测 图片由盖尔·瓦罗库提供,版权所有。
教程概述
本教程分为三个部分;它们是:
- 什么是异常预测?
- 用于评估的超范围预测
- 集成的异常预测
什么是异常预测?
使用重采样技术(如 k 倍交叉验证)来评估数据集上机器学习算法的表现是很常见的。
K 折交叉验证过程包括将训练数据集分成 k 组,然后在测试集上使用每组 k 示例,而剩余示例用作训练集。
这意味着 k 不同的模型被训练和评估。模型的表现是使用所有 k 倍模型的预测来估计的。
该程序可总结如下:
- 1.随机打乱数据集。
- 2.将数据集分成 k 个组。
- 3.对于每个唯一的组:
- a.将该组作为保持或测试数据集。
- b.将剩余的组作为训练数据集。
- c.在训练集上安装一个模型,并在测试集上对其进行评估。
- d.保留评估分数并放弃模型。
- 4.使用模型评估分数样本总结模型技巧。
重要的是,数据样本中的每个观察值被分配到一个单独的组,并在整个过程中保持在该组中。这意味着每个样本都有机会在保持设置中使用 1 次,并用于训练模型 k-1 次。
有关 k-fold 交叉验证主题的更多信息,请参见教程:
折外预测是模型在 k 折叠交叉验证过程中的预测。
也就是说,超倍预测是在重采样过程中对保持数据集进行的预测。如果执行正确,训练数据集中的每个示例都有一个预测。
有时,折外用缩写 OOF 概括。
- 折外预测:模型在保持示例的 k 折叠交叉验证过程中做出的预测。
超差预测的概念与超差预测的概念直接相关,因为这两种情况下的预测都是在模型训练期间没有使用的例子上进行的,当用于对新数据进行预测时,可以用来估计模型的表现。
因此,超越预测是一种样本外预测,尽管是在使用 k 倍交叉验证评估的模型环境中描述的。
- 样本外预测:模型对模型训练期间未使用的数据进行的预测。
样本外预测也可以称为保持预测。
超折叠预测有两个主要用途;它们是:
- 根据看不见的数据评估模型的表现。
- 适合整体模型。
让我们仔细看看这两个案例。
用于评估的超范围预测
无序预测最常见的用途是估计模型的表现。
也就是说,对未用于训练模型的数据的预测可以使用诸如误差或准确度的评分标准来进行和评估。当用于对新数据进行预测时,例如当模型将在实践中用于进行预测时,该度量提供了模型表现的估计。
一般来说,对不用于训练模型的数据所做的预测提供了模型如何推广到新情况的洞察力。因此,评估这些预测的分数被称为机器学习模型的广义表现。
这些预测可以使用两种主要方法来估计模型的表现。
第一种方法是根据每次折叠期间所做的预测对模型进行评分,然后计算这些评分的平均值。例如,如果我们正在评估一个分类模型,那么可以对每组超出范围的预测计算分类准确率,然后可以报告平均准确率。
- 方法 1 :将绩效评估为每组异常预测的平均得分。
第二种方法是考虑每个例子在每个测试集中只出现一次。也就是说,训练数据集中的每个示例在 k 倍交叉验证过程中都有一个预测。因此,我们可以收集所有预测,并将它们与预期结果进行比较,并直接在整个训练数据集中计算分数。
- 方法 2: 使用所有异常预测的总和来评估表现。
这两种方法都是合理的,每种方法得出的分数应该大致相等。
从每组样本外预测中计算平均值可能是最常见的方法,因为估计的方差也可以计算为标准偏差或标准误差。
对重新采样的表现估计值进行了总结(通常带有平均值和标准误差)…
—第 70 页,应用预测建模,2013 年。
我们可以用一个小的工作实例来说明这两种方法之间的差异,这两种方法使用不同的预测来评估模型。
我们将使用 make_blobs() Sklearn 函数创建一个包含 1000 个示例、两个类和 100 个输入特征的测试二进制分类问题。
下面的示例准备了一个数据示例,并总结了数据集的输入和输出元素的形状。
# example of creating a test dataset
from sklearn.datasets import make_blobs
# create the inputs and outputs
X, y = make_blobs(n_samples=1000, centers=2, n_features=100, cluster_std=20)
# summarize the shape of the arrays
print(X.shape, y.shape)
运行该示例会打印输入数据的形状,显示 1000 行数据、100 列或输入要素以及相应的分类标签。
(1000, 100) (1000,)
接下来,我们可以使用 k 折叠交叉验证来评估一个kneighgborksclassifier模型。
我们将使用 k =10 作为 KFold 对象,合理的默认值,在每个训练数据集上拟合一个模型,并在每个保持折叠上评估它。
准确性分数将存储在每个模型评估的列表中,并将报告这些分数的平均值和标准偏差。
下面列出了完整的示例。
# evaluate model by averaging performance across each fold
from numpy import mean
from numpy import std
from sklearn.datasets import make_blobs
from sklearn.model_selection import KFold
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
# create the inputs and outputs
X, y = make_blobs(n_samples=1000, centers=2, n_features=100, cluster_std=20)
# k-fold cross validation
scores = list()
kfold = KFold(n_splits=10, shuffle=True)
# enumerate splits
for train_ix, test_ix in kfold.split(X):
# get data
train_X, test_X = X[train_ix], X[test_ix]
train_y, test_y = y[train_ix], y[test_ix]
# fit model
model = KNeighborsClassifier()
model.fit(train_X, train_y)
# evaluate model
yhat = model.predict(test_X)
acc = accuracy_score(test_y, yhat)
# store score
scores.append(acc)
print('> ', acc)
# summarize model performance
mean_s, std_s = mean(scores), std(scores)
print('Mean: %.3f, Standard Deviation: %.3f' % (mean_s, std_s))
运行该示例会报告每次迭代中保持折叠的模型分类准确率。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
运行结束时,报告准确度分数的平均值和标准偏差。
> 0.95
> 0.92
> 0.95
> 0.95
> 0.91
> 0.97
> 0.96
> 0.96
> 0.98
> 0.91
Mean: 0.946, Standard Deviation: 0.023
我们可以用另一种方法来对比这一点,这种方法将所有预测作为一个整体来评估。
不是在每个保持折叠上评估模型,而是进行预测并存储在列表中。然后,在运行结束时,将预测值与每个保持测试集的期望值进行比较,并报告单个准确度分数。
下面列出了完整的示例。
# evaluate model by calculating the score across all predictions
from sklearn.datasets import make_blobs
from sklearn.model_selection import KFold
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
# create the inputs and outputs
X, y = make_blobs(n_samples=1000, centers=2, n_features=100, cluster_std=20)
# k-fold cross validation
data_y, data_yhat = list(), list()
kfold = KFold(n_splits=10, shuffle=True)
# enumerate splits
for train_ix, test_ix in kfold.split(X):
# get data
train_X, test_X = X[train_ix], X[test_ix]
train_y, test_y = y[train_ix], y[test_ix]
# fit model
model = KNeighborsClassifier()
model.fit(train_X, train_y)
# make predictions
yhat = model.predict(test_X)
# store
data_y.extend(test_y)
data_yhat.extend(yhat)
# evaluate the model
acc = accuracy_score(data_y, data_yhat)
print('Accuracy: %.3f' % (acc))
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
运行该示例会收集每个保持数据集的所有预期值和预测值,并在运行结束时报告一个准确度分数。
Accuracy: 0.930
同样,这两种方法是可比较的,这可能是你在自己的预测建模问题上使用的方法的品味问题。
集成的异常预测
超折叠预测的另一个常见用途是在集合模式的开发中使用它们。
集成是一种机器学习模型,它结合了在同一训练数据集上准备的两个或多个模型的预测。
这是在进行机器学习竞赛时非常常用的程序。
当不用于训练模型时,折外预测总体上提供了关于模型如何在训练数据集中的每个示例上执行的信息。这些信息可以用来训练模型来修正或改进这些预测。
首先,对每个感兴趣的基础模型执行 k 折叠交叉验证程序,并收集所有的折外预测。重要的是,对每个模型执行训练数据到 k 折叠的相同分割。现在,我们为每个模型都有一组聚合的样本外预测,例如训练数据集中每个示例的预测。
- 基础模型:使用 k 评估的模型在训练数据集上进行多重交叉验证,并且保留所有不符合的预测。
接下来,第二个更高阶的模型,称为元模型,在其他模型的预测上进行训练。当进行预测时,该元模型可以也可以不将每个示例的输入数据作为输入。这个模型的工作是学习如何最好地结合和纠正其他模型使用他们的超折叠预测所做的预测。
- 元模型:将一个或多个模型做出的超差预测作为输入,并展示如何最好地组合和校正预测的模型。
例如,我们可能有一个两类分类预测建模问题,并训练决策树和 k-最近邻模型作为基础模型。每个模型通过超范围预测为训练数据集中的每个示例预测 0 或 1。这些预测以及输入数据可以形成元模型的新输入。
- 元模型输入:给定样本的输入部分与每个基础模型所做的预测相连接。
- 元模型输出:给定样本的输出部分。
为什么要用出格的预测来训练元模型?
我们可以在整个训练数据集上训练每个基础模型,然后对训练数据集中的每个示例进行预测,并将预测用作元模型的输入。问题是预测将是乐观的,因为样本用于每个基础模型的训练。这种乐观的偏差意味着预测会比正常情况下更好,元模型可能不会从基础模型中学习到组合和校正预测所需的东西。
通过使用来自基础模型的折外预测来训练元模型,元模型可以在对看不见的数据进行操作时看到并利用每个基础模型的预期行为,正如在实践中使用集成对新数据进行预测时的情况一样。
最后,在整个训练数据集上训练每个基础模型,并且这些最终模型和元模型可以用于对新数据进行预测。这种集成的表现可以在单独的保持测试数据集上进行评估,该数据集在训练期间不使用。
该程序可总结如下:
- 1.对于每个基础模型:
- a.使用 k 倍交叉验证并收集不一致的预测。
- b.根据所有模型的不一致预测训练元模型。
- c.在整个训练数据集上训练每个基础模型。
这个过程被称为堆叠一般化,简称堆叠。因为通常使用线性加权和作为元模型,这个过程有时被称为 混合 。
有关堆叠主题的更多信息,请参见教程:
我们可以使用上一节中使用的相同数据集,通过一个工作示例来具体实现这个过程。
首先,我们将数据分成训练和验证数据集。训练数据集将用于拟合子模型和元模型,验证数据集将从训练中保留下来,并在最后用于评估元模型和子模型。
...
# split
X, X_val, y, y_val = train_test_split(X, y, test_size=0.33)
在这个例子中,我们将使用 k 倍交叉验证来拟合一个决策树分类器和 KNeighborsClassifier 模型每个交叉验证折叠,并使用拟合模型来进行超折叠预测。
这些模型将预测概率而不是类别标签,试图为元模型提供更有用的输入特征。这是一个很好的做法。
我们还将跟踪折叠数据的输入数据(100 个特征)和输出数据(预期标签)。
...
# collect out of sample predictions
data_x, data_y, knn_yhat, cart_yhat = list(), list(), list(), list()
kfold = KFold(n_splits=10, shuffle=True)
for train_ix, test_ix in kfold.split(X):
# get data
train_X, test_X = X[train_ix], X[test_ix]
train_y, test_y = y[train_ix], y[test_ix]
data_x.extend(test_X)
data_y.extend(test_y)
# fit and make predictions with cart
model1 = DecisionTreeClassifier()
model1.fit(train_X, train_y)
yhat1 = model1.predict_proba(test_X)[:, 0]
cart_yhat.extend(yhat1)
# fit and make predictions with cart
model2 = KNeighborsClassifier()
model2.fit(train_X, train_y)
yhat2 = model2.predict_proba(test_X)[:, 0]
knn_yhat.extend(yhat2)
在运行结束时,我们可以为元分类器构建一个数据集,该数据集由输入数据的 100 个输入特征和来自 kNN 和决策树模型的两列预测概率组成。
下面的 create_meta_dataset() 函数实现了这一点,将折外的数据和跨折叠的预测作为输入,并为元模型构建输入数据集。
# create a meta dataset
def create_meta_dataset(data_x, yhat1, yhat2):
# convert to columns
yhat1 = array(yhat1).reshape((len(yhat1), 1))
yhat2 = array(yhat2).reshape((len(yhat2), 1))
# stack as separate columns
meta_X = hstack((data_x, yhat1, yhat2))
return meta_X
然后我们可以调用这个函数为元模型准备数据。
...
# construct meta dataset
meta_X = create_meta_dataset(data_x, knn_yhat, cart_yhat)
然后,我们可以在整个训练数据集中拟合每个子模型,以便在验证数据集中进行预测。
...
# fit final submodels
model1 = DecisionTreeClassifier()
model1.fit(X, y)
model2 = KNeighborsClassifier()
model2.fit(X, y)
然后,我们可以在准备好的数据集上拟合元模型,在这种情况下,是物流配送模型。
...
# construct meta classifier
meta_model = LogisticRegression(solver='liblinear')
meta_model.fit(meta_X, data_y)
最后,我们可以使用元模型对保持数据集进行预测。
这要求数据首先通过子模型,即用于构建元模型数据集的输出,然后元模型用于进行预测。我们将把所有这些装袋成一个名为 stack_prediction() 的函数,该函数获取将要进行预测的模型和数据。
# make predictions with stacked model
def stack_prediction(model1, model2, meta_model, X):
# make predictions
yhat1 = model1.predict_proba(X)[:, 0]
yhat2 = model2.predict_proba(X)[:, 0]
# create input dataset
meta_X = create_meta_dataset(X, yhat1, yhat2)
# predict
return meta_model.predict(meta_X)
然后,我们可以评估保持数据集上的子模型以供参考,然后使用元模型对保持数据集进行预测并进行评估。
我们预计,元模型在保持数据集上的表现将与任何单个子模型一样好或更好。如果不是这种情况,可以使用替代子模型或元模型来解决问题。
...
# evaluate sub models on hold out dataset
acc1 = accuracy_score(y_val, model1.predict(X_val))
acc2 = accuracy_score(y_val, model2.predict(X_val))
print('Model1 Accuracy: %.3f, Model2 Accuracy: %.3f' % (acc1, acc2))
# evaluate meta model on hold out dataset
yhat = stack_prediction(model1, model2, meta_model, X_val)
acc = accuracy_score(y_val, yhat)
print('Meta Model Accuracy: %.3f' % (acc))
将这些结合在一起,完整的示例如下所示。
# example of a stacked model for binary classification
from numpy import hstack
from numpy import array
from sklearn.datasets import make_blobs
from sklearn.model_selection import KFold
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
# create a meta dataset
def create_meta_dataset(data_x, yhat1, yhat2):
# convert to columns
yhat1 = array(yhat1).reshape((len(yhat1), 1))
yhat2 = array(yhat2).reshape((len(yhat2), 1))
# stack as separate columns
meta_X = hstack((data_x, yhat1, yhat2))
return meta_X
# make predictions with stacked model
def stack_prediction(model1, model2, meta_model, X):
# make predictions
yhat1 = model1.predict_proba(X)[:, 0]
yhat2 = model2.predict_proba(X)[:, 0]
# create input dataset
meta_X = create_meta_dataset(X, yhat1, yhat2)
# predict
return meta_model.predict(meta_X)
# create the inputs and outputs
X, y = make_blobs(n_samples=1000, centers=2, n_features=100, cluster_std=20)
# split
X, X_val, y, y_val = train_test_split(X, y, test_size=0.33)
# collect out of sample predictions
data_x, data_y, knn_yhat, cart_yhat = list(), list(), list(), list()
kfold = KFold(n_splits=10, shuffle=True)
for train_ix, test_ix in kfold.split(X):
# get data
train_X, test_X = X[train_ix], X[test_ix]
train_y, test_y = y[train_ix], y[test_ix]
data_x.extend(test_X)
data_y.extend(test_y)
# fit and make predictions with cart
model1 = DecisionTreeClassifier()
model1.fit(train_X, train_y)
yhat1 = model1.predict_proba(test_X)[:, 0]
cart_yhat.extend(yhat1)
# fit and make predictions with cart
model2 = KNeighborsClassifier()
model2.fit(train_X, train_y)
yhat2 = model2.predict_proba(test_X)[:, 0]
knn_yhat.extend(yhat2)
# construct meta dataset
meta_X = create_meta_dataset(data_x, knn_yhat, cart_yhat)
# fit final submodels
model1 = DecisionTreeClassifier()
model1.fit(X, y)
model2 = KNeighborsClassifier()
model2.fit(X, y)
# construct meta classifier
meta_model = LogisticRegression(solver='liblinear')
meta_model.fit(meta_X, data_y)
# evaluate sub models on hold out dataset
acc1 = accuracy_score(y_val, model1.predict(X_val))
acc2 = accuracy_score(y_val, model2.predict(X_val))
print('Model1 Accuracy: %.3f, Model2 Accuracy: %.3f' % (acc1, acc2))
# evaluate meta model on hold out dataset
yhat = stack_prediction(model1, model2, meta_model, X_val)
acc = accuracy_score(y_val, yhat)
print('Meta Model Accuracy: %.3f' % (acc))
运行该示例首先报告决策树和 kNN 模型的准确性,然后报告元模型在保持数据集上的表现,这在训练期间是看不到的。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
在这种情况下,我们可以看到元模型在两个子模型上都表现出色。
Model1 Accuracy: 0.670, Model2 Accuracy: 0.930
Meta-Model Accuracy: 0.955
尝试一项消融性研究,仅用模型 1、模型 2 重新运行该示例,并且模型 1 和模型 2 都不作为元模型的输入,以确认来自子模型的预测实际上正在为元模型增加价值,这可能是有趣的。
进一步阅读
如果您想更深入地了解这个主题,本节将提供更多资源。
教程
- k 倍交叉验证的温和介绍
- 如何用 Keras 开发 Python 深度学习神经网络的堆叠集成
- 如何用 Python 从零开始实现堆叠泛化(堆叠)
- 如何在 Keras 创建深度学习模型的装袋集成
- 深度学习神经网络的集成学习方法
书
- 应用预测建模,2013。
文章
- 交叉验证(统计),维基百科。
- 一起学习,维基百科。
蜜蜂
- sklearn . dataset . make _ blobs API。
- sklearn.model_selection。KFold API 。
- sklearn . neighborsclassifier API。
- 硬化. tree .决策树分类器 API 。
- sklearn . metrics . accuracy _ score API。
- sklearn.linear_model。物流配送应用编程接口。
- sklearn . model _ selection . train _ test _ split API。
摘要
在本教程中,您发现了机器学习中的异常预测。
具体来说,您了解到:
- 超差预测是对未用于训练模型的数据进行的一种超差预测。
- 在对看不见的数据进行预测时,超差预测最常用于估计模型的表现。
- 叠外预测可以用来构建一个集合模型,称为叠化概化或叠化集合。
你有什么问题吗? 在下面的评论中提问,我会尽力回答。
如何用 Python 开发随机森林集成
最后更新于 2021 年 4 月 27 日
随机森林是一种集成机器学习算法。
鉴于其在广泛的分类和回归预测建模问题上的良好或优异的表现,它可能是最受欢迎和广泛使用的机器学习算法。
它也很容易使用,因为它只有很少的关键超参数和合理的试探法来配置这些超参数。
在本教程中,您将发现如何开发用于分类和回归的随机森林集合。
完成本教程后,您将知道:
- 随机森林集成是决策树的集成,是装袋的自然延伸。
- 如何用 Sklearn 使用随机森林集成进行分类和回归?
- 如何探索随机森林模型超参数对模型表现的影响?
用我的新书Python 集成学习算法启动你的项目,包括分步教程和所有示例的 Python 源代码文件。
我们开始吧。
- 更新 2020 年 8 月:增加了常见问题部分。
如何用 Python 开发随机森林集成 图片由希拉·桑德提供,保留部分权利。
教程概述
本教程分为四个部分;它们是:
- 随机森林算法
- 随机森林科学工具包-学习应用编程接口
- 随机森林分类
- 回归的随机森林
- 随机森林超参数
- 探索样本数量
- 探索功能数量
- 探索树的数量
- 探索树的深度
- 常见问题
随机森林算法
随机森林是决策树算法的集合。
它是决策树自举聚合(bagging) 的扩展,可用于分类和回归问题。
在装袋过程中,会创建许多决策树,其中每个树都是从训练数据集的不同引导样本创建的。一个自举样本是训练数据集的一个样本,其中一个样本可能在样本中出现不止一次,称为替换采样。
Bagging 是一种有效的集成算法,因为每个决策树都适合于稍微不同的训练数据集,并且反过来具有稍微不同的表现。与普通的决策树模型不同,例如分类和回归树 (CART),集成中使用的树是未标记的,这使得它们对训练数据集略微过度。这是可取的,因为它有助于使每棵树更加不同,并且具有较少的相关预测或预测误差。
来自这些树的预测在所有决策树中被平均,导致比模型中的任何单个树更好的表现。
集合中的每个模型随后被用于生成新样本的预测,并且这些 m 个预测被平均以给出森林的预测
—第 199 页,应用预测建模,2013 年。
回归问题的预测是集合中所有树的预测平均值。对分类问题的预测是对集合中所有树的类别标签的多数投票。
- 回归:预测是整个决策树的平均预测。
- 分类:预测是跨决策树预测的多数票类标签。
和装袋一样,森林中的每棵树都对新样本的分类投一票,整个集合中每个类的投票比例就是预测的概率向量。
—第 387 页,应用预测建模,2013 年。
随机森林包括从训练数据集中的自举样本构建大量决策树,如 bagging。
与装袋不同,随机森林还包括在构建树的每个分割点选择输入特征(列或变量)的子集。通常,构建决策树包括评估数据中每个输入变量的值,以便选择分割点。通过将特征简化为可以在每个分割点考虑的随机子集,它迫使集合中的每个决策树更加不同。
随机森林通过对树木去相关的小调整,提供了对袋装树木的改进。[……]但是当构建这些决策树时,每次考虑树中的分裂时,从 p 个预测器的完整集合中选择 m 个预测器的随机样本作为分裂候选。
—第 320 页,R中应用的统计学习介绍,2014。
结果是,由集成中的每棵树做出的预测,进而预测误差,或多或少是不同的或相关的。当对来自这些相关性较低的树的预测进行平均以做出预测时,它通常比袋装决策树产生更好的表现。
也许为随机森林调整的最重要的超参数是在每个分割点要考虑的随机特征的数量。
随机森林的调整参数是随机选择的预测因子 k 的数量,在每次分裂时从中选择,通常称为 mtry。在回归背景下,Breiman (2001)建议将 mtry 设置为预测因子数量的三分之一。
—第 199 页,应用预测建模,2013 年。
回归的一个好的启发式方法是将这个超参数设置为输入特征数的 1/3。
- num _ features _ for _ split = total _ input _ features/3
对于分类问题,Breiman (2001)建议将 mtry 设置为预测数的平方根。
—第 387 页,应用预测建模,2013 年。
一个很好的分类启发式方法是将这个超参数设置为输入特征数的平方根。
- num _ features _ for _ split = sqrt(total _ input _ feature)
另一个需要调整的重要超参数是决策树的深度。更深的树通常对训练数据更过度,但相关性也更低,这反过来可以提高集成的表现。深度从 1 到 10 级可能是有效的。
最后,可以设置集成中决策树的数量。通常,这种情况会增加,直到看不到进一步的改善。
随机森林科学工具包-学习应用编程接口
随机森林集成可以从零开始实现,尽管这对初学者来说很有挑战性。
Sklearn Python 机器学习库为机器学习提供了一个随机森林的实现。
它有现代版本的图书馆。
首先,通过运行以下脚本来确认您使用的是现代版本的库:
# check Sklearn version
import sklearn
print(sklearn.__version__)
运行脚本将打印您的 Sklearn 版本。
您的版本应该相同或更高。如果没有,您必须升级 Sklearn 库的版本。
0.22.1
这两个模型以相同的方式运行,并采用相同的参数来影响决策树的创建。
随机性用于模型的构建。这意味着算法每次在相同的数据上运行时,都会产生稍微不同的模型。
当使用具有随机学习算法的机器学习算法时,通过在多次运行或重复交叉验证中平均它们的表现来评估它们是一个很好的实践。当拟合最终模型时,可能需要增加树的数量,直到模型的方差在重复评估中减小,或者拟合多个最终模型并对它们的预测进行平均。
让我们看看如何为分类和回归任务开发一个随机森林集成。
随机森林分类
在本节中,我们将研究使用随机森林解决分类问题。
首先,我们可以使用 make_classification()函数创建一个包含 1000 个示例和 20 个输入特征的合成二进制分类问题。
下面列出了完整的示例。
# test classification dataset
from sklearn.datasets import make_classification
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=3)
# summarize the dataset
print(X.shape, y.shape)
运行该示例将创建数据集并总结输入和输出组件的形状。
(1000, 20) (1000,)
接下来,我们可以在这个数据集上评估一个随机森林算法。
我们将使用重复分层 k 折叠交叉验证来评估模型,重复 3 次,折叠 10 次。我们将报告所有重复和折叠的模型准确率的平均值和标准偏差。
# evaluate random forest algorithm for classification
from numpy import mean
from numpy import std
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.ensemble import RandomForestClassifier
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=3)
# define the model
model = RandomForestClassifier()
# evaluate the model
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
n_scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')
# report performance
print('Accuracy: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))
运行该示例会报告模型的均值和标准差准确率。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
在这种情况下,我们可以看到带有默认超参数的随机森林集成达到了大约 90.5%的分类准确率。
Accuracy: 0.905 (0.025)
我们也可以使用随机森林模型作为最终模型,并对分类进行预测。
首先对所有可用数据进行随机森林集合拟合,然后调用 predict() 函数对新数据进行预测。
下面的示例在我们的二进制类别数据集上演示了这一点。
# make predictions using random forest for classification
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=3)
# define the model
model = RandomForestClassifier()
# fit the model on the whole dataset
model.fit(X, y)
# make a single prediction
row = [[-8.52381793,5.24451077,-12.14967704,-2.92949242,0.99314133,0.67326595,-0.38657932,1.27955683,-0.60712621,3.20807316,0.60504151,-1.38706415,8.92444588,-7.43027595,-2.33653219,1.10358169,0.21547782,1.05057966,0.6975331,0.26076035]]
yhat = model.predict(row)
print('Predicted Class: %d' % yhat[0])
运行该示例使随机森林集成模型适合整个数据集,然后用于对新的数据行进行预测,就像我们在应用程序中使用该模型时可能做的那样。
Predicted Class: 0
现在我们已经熟悉了使用随机森林进行分类,让我们看看回归的 API。
回归的随机森林
在本节中,我们将研究使用随机森林解决回归问题。
首先,我们可以使用make _ revolution()函数创建一个包含 1000 个示例和 20 个输入特征的合成回归问题。
下面列出了完整的示例。
# test regression dataset
from sklearn.datasets import make_regression
# define dataset
X, y = make_regression(n_samples=1000, n_features=20, n_informative=15, noise=0.1, random_state=2)
# summarize the dataset
print(X.shape, y.shape)
运行该示例将创建数据集并总结输入和输出组件的形状。
(1000, 20) (1000,)
接下来,我们可以在这个数据集上评估一个随机森林算法。
正如我们在上一节中所做的,我们将使用重复的 k-fold 交叉验证来评估模型,重复 3 次,重复 10 次。我们将报告所有重复和折叠模型的平均绝对误差(MAE)。Sklearn 库使 MAE 为负,因此它被最大化而不是最小化。这意味着负 MAE 越大越好,完美模型的 MAE 为 0。
下面列出了完整的示例。
# evaluate random forest ensemble for regression
from numpy import mean
from numpy import std
from sklearn.datasets import make_regression
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedKFold
from sklearn.ensemble import RandomForestRegressor
# define dataset
X, y = make_regression(n_samples=1000, n_features=20, n_informative=15, noise=0.1, random_state=2)
# define the model
model = RandomForestRegressor()
# evaluate the model
cv = RepeatedKFold(n_splits=10, n_repeats=3, random_state=1)
n_scores = cross_val_score(model, X, y, scoring='neg_mean_absolute_error', cv=cv, n_jobs=-1, error_score='raise')
# report performance
print('MAE: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))
运行该示例会报告模型的均值和标准差 MAE。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
在这种情况下,我们可以看到具有默认超参数的随机森林集合达到了大约 90 的 MAE。
MAE: -90.149 (7.924)
我们也可以使用随机森林模型作为最终模型,并对回归进行预测。
首先对所有可用数据进行随机森林集合拟合,然后调用 predict() 函数对新数据进行预测。
下面的例子在我们的回归数据集上演示了这一点。
# random forest for making predictions for regression
from sklearn.datasets import make_regression
from sklearn.ensemble import RandomForestRegressor
# define dataset
X, y = make_regression(n_samples=1000, n_features=20, n_informative=15, noise=0.1, random_state=2)
# define the model
model = RandomForestRegressor()
# fit the model on the whole dataset
model.fit(X, y)
# make a single prediction
row = [[-0.89483109,-1.0670149,-0.25448694,-0.53850126,0.21082105,1.37435592,0.71203659,0.73093031,-1.25878104,-2.01656886,0.51906798,0.62767387,0.96250155,1.31410617,-1.25527295,-0.85079036,0.24129757,-0.17571721,-1.11454339,0.36268268]]
yhat = model.predict(row)
print('Prediction: %d' % yhat[0])
运行该示例使随机森林集成模型适合整个数据集,然后用于对新的数据行进行预测,就像我们在应用程序中使用该模型时可能做的那样。
Prediction: -173
现在我们已经熟悉了使用 Sklearn API 来评估和使用随机森林集合,让我们来看看如何配置模型。
随机森林超参数
在本节中,我们将仔细研究一些您应该考虑为随机森林集合进行调整的超参数,以及它们对模型表现的影响。
探索样本数量
集成中的每个决策树都适合从训练数据集中提取的自举样本。
如果您愿意,可以通过将“ bootstrap ”参数设置为 False 来关闭。在这种情况下,整个训练数据集将用于训练每个决策树。不建议这样。
“ max_samples ”参数可以设置为 0 到 1 之间的浮点数,以控制训练数据集大小的百分比,从而使引导样本用于训练每个决策树。
例如,如果训练数据集有 100 行,则 max_samples 参数可以设置为 0.5,并且每个决策树将适合具有(100 * 0.5)或 50 行数据的引导样本。
较小的样本量会使树更加不同,而较大的样本量会使树更加相似。将 max_samples 设置为“ None ”将使样本大小与训练数据集的大小相同,这是默认设置。
下面的示例演示了 10%到 100%的不同引导样本大小对随机森林算法的影响。
# explore random forest bootstrap sample size on performance
from numpy import mean
from numpy import std
from numpy import arange
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.ensemble import RandomForestClassifier
from matplotlib import pyplot
# get the dataset
def get_dataset():
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=3)
return X, y
# get a list of models to evaluate
def get_models():
models = dict()
# explore ratios from 10% to 100% in 10% increments
for i in arange(0.1, 1.1, 0.1):
key = '%.1f' % i
# set max_samples=None to use 100%
if i == 1.0:
i = None
models[key] = RandomForestClassifier(max_samples=i)
return models
# evaluate a given model using cross-validation
def evaluate_model(model, X, y):
# define the evaluation procedure
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
# evaluate the model and collect the results
scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1)
return scores
# define dataset
X, y = get_dataset()
# get the models to evaluate
models = get_models()
# evaluate the models and store results
results, names = list(), list()
for name, model in models.items():
# evaluate the model
scores = evaluate_model(model, X, y)
# store the results
results.append(scores)
names.append(name)
# summarize the performance along the way
print('>%s %.3f (%.3f)' % (name, mean(scores), std(scores)))
# plot model performance for comparison
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()
运行示例首先报告每个数据集大小的平均准确率。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
在这种情况下,结果表明使用与训练数据集大小相等的引导样本大小可以在该数据集上获得最佳结果。
这是默认设置,在大多数情况下应该使用。
>10 0.856 (0.031)
>20 0.873 (0.029)
>30 0.881 (0.021)
>40 0.891 (0.033)
>50 0.893 (0.025)
>60 0.897 (0.030)
>70 0.902 (0.024)
>80 0.903 (0.024)
>90 0.900 (0.026)
>100 0.903 (0.027)
为每个自举样本大小的准确度分数分布创建一个方框和须图。
在这种情况下,我们可以看到一个普遍的趋势,即样本越大,模型的表现越好。
您可能希望扩展此示例,看看如果引导样本大小大于或甚至远大于训练数据集,会发生什么情况(例如,您可以将一个整数值设置为样本数,而不是训练数据集大小的浮动百分比)。
随机森林自举样本量与分类准确率的箱线图
探索功能数量
为每个分割点随机采样的要素数量可能是为随机森林配置的最重要的要素。
它通过 max_features 参数设置,默认为输入特征数的平方根。在这种情况下,对于我们的测试数据集,这将是 sqrt(20) 或大约四个特征。
以下示例探讨了在每个分割点随机选择的特征数量对模型准确率的影响。我们将尝试从 1 到 7 的值,并期望一个小的值,大约 4,在启发式的基础上表现良好。
# explore random forest number of features effect on performance
from numpy import mean
from numpy import std
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.ensemble import RandomForestClassifier
from matplotlib import pyplot
# get the dataset
def get_dataset():
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=3)
return X, y
# get a list of models to evaluate
def get_models():
models = dict()
# explore number of features from 1 to 7
for i in range(1,8):
models[str(i)] = RandomForestClassifier(max_features=i)
return models
# evaluate a given model using cross-validation
def evaluate_model(model, X, y):
# define the evaluation procedure
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
# evaluate the model and collect the results
scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1)
return scores
# define dataset
X, y = get_dataset()
# get the models to evaluate
models = get_models()
# evaluate the models and store results
results, names = list(), list()
for name, model in models.items():
# evaluate the model
scores = evaluate_model(model, X, y)
# store the results
results.append(scores)
names.append(name)
# summarize the performance along the way
print('>%s %.3f (%.3f)' % (name, mean(scores), std(scores)))
# plot model performance for comparison
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()
运行示例首先报告每个特征集大小的平均准确率。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
在这种情况下,结果表明介于 3 和 5 之间的值是合适的,这证实了在这个数据集上 4 是合理的默认值。如果分类准确度的标准偏差小于三或四,则五的值可能更好。
>1 0.897 (0.023)
>2 0.900 (0.028)
>3 0.903 (0.027)
>4 0.903 (0.022)
>5 0.903 (0.019)
>6 0.898 (0.025)
>7 0.900 (0.024)
为每个要素集大小的准确率分数分布创建了一个方框和触须图。
我们可以看到表现上升并达到峰值的趋势,其值在 3 到 5 之间,当考虑更大的特征集大小时,表现会再次下降。
随机森林特征集大小与分类准确率的箱线图
探索树的数量
树的数量是为随机林配置的另一个关键超参数。
通常,树的数量会增加,直到模型表现稳定下来。直觉可能暗示更多的树会导致过拟合,尽管事实并非如此。给定学习算法的随机性质,bagging 和随机森林算法似乎在某种程度上都不会过拟合训练数据集。
树的数量可以通过“n _ estimates”参数设置,默认为 100。
下面的示例探讨了值在 10 到 1000 之间的树的数量的影响。
# explore random forest number of trees effect on performance
from numpy import mean
from numpy import std
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.ensemble import RandomForestClassifier
from matplotlib import pyplot
# get the dataset
def get_dataset():
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=3)
return X, y
# get a list of models to evaluate
def get_models():
models = dict()
# define number of trees to consider
n_trees = [10, 50, 100, 500, 1000]
for n in n_trees:
models[str(n)] = RandomForestClassifier(n_estimators=n)
return models
# evaluate a given model using cross-validation
def evaluate_model(model, X, y):
# define the evaluation procedure
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
# evaluate the model and collect the results
scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1)
return scores
# define dataset
X, y = get_dataset()
# get the models to evaluate
models = get_models()
# evaluate the models and store results
results, names = list(), list()
for name, model in models.items():
# evaluate the model
scores = evaluate_model(model, X, y)
# store the results
results.append(scores)
names.append(name)
# summarize the performance along the way
print('>%s %.3f (%.3f)' % (name, mean(scores), std(scores)))
# plot model performance for comparison
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()
运行该示例首先报告每个配置的树数的平均准确率。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
在这种情况下,我们可以看到大约 100 棵树后,表现会上升并保持不变。平均准确度分数在 100、500 和 1000 棵树之间波动,这可能是统计噪声。
>10 0.870 (0.036)
>50 0.900 (0.028)
>100 0.910 (0.024)
>500 0.904 (0.024)
>1000 0.906 (0.023)
为每个配置数量的树的准确度分数的分布创建一个方框和须图。
随机森林集合大小与分类准确率的箱线图
探索树的深度
最后一个有趣的超参数是集成中使用的决策树的最大深度。
默认情况下,树被构建到任意深度,并且不被修剪。这是一个明智的默认,尽管我们也可以探索不同固定深度的拟合树。
最大树深度可以通过最大深度参数指定,默认设置为无(无最大深度)。
下面的例子探讨了随机森林最大树深对模型表现的影响。
# explore random forest tree depth effect on performance
from numpy import mean
from numpy import std
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.ensemble import RandomForestClassifier
from matplotlib import pyplot
# get the dataset
def get_dataset():
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=3)
return X, y
# get a list of models to evaluate
def get_models():
models = dict()
# consider tree depths from 1 to 7 and None=full
depths = [i for i in range(1,8)] + [None]
for n in depths:
models[str(n)] = RandomForestClassifier(max_depth=n)
return models
# evaluate a given model using cross-validation
def evaluate_model(model, X, y):
# define the evaluation procedure
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
# evaluate the model and collect the results
scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1)
return scores
# define dataset
X, y = get_dataset()
# get the models to evaluate
models = get_models()
# evaluate the models and store results
results, names = list(), list()
for name, model in models.items():
# evaluate the model
scores = evaluate_model(model, X, y)
# store the results
results.append(scores)
names.append(name)
# summarize the performance along the way
print('>%s %.3f (%.3f)' % (name, mean(scores), std(scores)))
# plot model performance for comparison
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()
运行示例首先报告每个配置的最大树深度的平均准确率。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
在这种情况下,我们可以看到更大的深度会带来更好的模型表现,默认的无最大深度会在这个数据集上获得最佳表现。
>1 0.771 (0.040)
>2 0.807 (0.037)
>3 0.834 (0.034)
>4 0.857 (0.030)
>5 0.872 (0.025)
>6 0.887 (0.024)
>7 0.890 (0.025)
>None 0.903 (0.027)
为每个配置的最大树深的准确率分数分布创建一个方框和须图。
在这种情况下,我们可以看到表现随着树深度的增加而提高的趋势,支持无最大深度的默认值。
随机森林最大树深与分类准确率的箱线图
常见问题
在这一节中,我们将仔细研究 radom forest 集成过程中的一些常见症结。
问:集成应该用什么算法?
随机森林被设计成决策树算法的集合。
问:应该用多少个文工团成员?
应该增加树的数量,直到数据集的表现没有进一步提高。
作为起点,我们建议至少使用 1000 棵树。如果交叉验证表现配置文件在 1,000 棵树上仍在改进,则合并更多的树,直到表现达到平衡。
—第 200 页,应用预测建模,2013 年。
问:文工团不会因为树木太多而过度吗?
不。一般来说,随机森林群落不太可能过度繁殖。
另一种说法是随机森林“不能过度收集”数据。毫无疑问,增加[树木数量]不会导致随机森林序列过度砍伐…
—第 596 页,统计学习的要素,2016。
问:自举样本应该有多大?
让引导样本与原始数据集大小一样大是一种好的做法。
这是原始数据集的 100%大小或相等的行数。
问:每个分割点应该选择多少特征?
最佳实践是测试一组不同的值,并发现最适合数据集的值。
作为一种启发,您可以使用:
- 分类:特征数量的平方根。
- 回归:特征数量的三分之一。
问:有哪些问题很适合随机森林?
众所周知,随机森林在广泛的分类和回归问题上效果很好,甚至是最好的。试试看吧。
作者对随机森林的成功提出了宏大的主张:“最准确”、“最可解释”等等。根据我们的经验,随机森林做得非常好,只需要很少的调整。
—第 590 页,统计学习的要素,2016。
进一步阅读
如果您想更深入地了解这个主题,本节将提供更多资源。
教程
报纸
- 随机森林,2001。
书
蜜蜂
文章
摘要
在本教程中,您发现了如何开发用于分类和回归的随机森林集合。
具体来说,您了解到:
- 随机森林集成是决策树的集成,是装袋的自然延伸。
- 如何用 Sklearn 使用随机森林集成进行分类和回归?
- 如何探索随机森林模型超参数对模型表现的影响?
你有什么问题吗? 在下面的评论中提问,我会尽力回答。
如何用 XGBoost 开发随机森林集成
最后更新于 2021 年 4 月 27 日
XGBoost 库提供了梯度提升的有效实现,可以配置为训练随机森林集合。
随机森林是比梯度提升更简单的算法。XGBoost 库允许以一种重新调整用途和利用库中实现的计算效率来训练随机森林模型的方式来训练模型。
在本教程中,您将发现如何使用 XGBoost 库开发随机森林集成。
完成本教程后,您将知道:
- XGBoost 提供了梯度提升的有效实现,可以配置为训练随机森林集成。
- 如何使用 XGBoost API 训练和评估用于分类和回归的随机森林集成模型。
- 如何调整 XGBoost 随机森林集合模型的超参数。
用我的新书Python 集成学习算法启动你的项目,包括分步教程和所有示例的 Python 源代码文件。
我们开始吧。
如何用 XGBoost 开发随机森林集成 摄影:简·莫西曼,版权所有。
教程概述
本教程分为五个部分;它们是:
- 带扩展的随机森林
- 随机森林的扩展应用编程接口
- 为分类选择随机森林
- 用于回归的随机森林
- 随机森林超参数
带扩展的随机森林
XGBoost 是一个开源库,提供了梯度提升集成算法的高效实现,简称为 Extreme Gradient Boosting 或 XGBoost。
因此,XGBoost 指的是项目、库和算法本身。
梯度提升是分类和回归预测建模项目的首选算法,因为它通常会获得最佳表现。梯度提升的问题是训练一个模型通常非常慢,并且这个问题被大数据集所加剧。
XGBoost 通过引入大量技术来解决梯度提升的速度问题,这些技术可以显著加速模型的训练,并且通常会带来更好的模型整体表现。
您可以在本教程中了解更多关于 XGBoost 的信息:
除了支持梯度提升,核心的 XGBoost 算法还可以配置为支持其他类型的树集成算法,如随机森林。
随机森林是决策树算法的集合。
每个决策树都适合训练数据集的一个自举样本。这是训练数据集的一个示例,其中给定的示例(行)可以被选择多次,称为带替换的采样。
重要的是,考虑了树中每个分割点的输入变量(列)的随机子集。这确保了添加到集合中的每棵树都是有技巧的,但随机方式不同。在每个分割点考虑的特征数量通常是一个小子集。例如,在分类问题上,常见的启发式方法是选择等于特征总数平方根的特征数,例如,如果数据集有 20 个输入变量,则选择 4 个。
您可以在教程中了解更多关于随机森林集成算法的信息:
使用 XGBoost 库训练随机森林集成的主要好处是速度。预计它的使用速度将明显快于其他实现,例如本机 Sklearn 实现。
现在我们知道了 XGBoost 提供了对随机森林集成的支持,让我们看看具体的 API。
随机森林的扩展应用编程接口
第一步是安装 XGBoost 库。
我建议使用 pip 包管理器,从命令行使用以下命令:
sudo pip install xgboost
安装后,我们可以加载库,并在 Python 脚本中打印版本,以确认它安装正确。
# check xgboost version
import xgboost
# display version
print(xgboost.__version__)
运行脚本将加载 XGBoost 库并打印库版本号。
您的版本号应该相同或更高。
1.0.2
XGBoost 库提供了两个包装类,允许该库提供的随机森林实现与 Sklearn 机器学习库一起使用。
它们分别是用于分类和回归的 XGBRFClassifier 和xgbrfreversor类。
...
# define the model
model = XGBRFClassifier()
集成中使用的树的数量可以通过“n _ estimator”参数来设置,通常,这是增加的,直到模型没有观察到表现的进一步提高。通常使用成百上千棵树。
...
# define the model
model = XGBRFClassifier(n_estimators=100)
XGBoost 不支持为每个决策树绘制引导样本。这是图书馆的一个局限。
相反,可以通过“子样本”参数将训练数据集的子样本指定为 0.0 到 1.0 之间的百分比(训练数据集中的 100%行)。建议使用 0.8 或 0.9 的值,以确保数据集足够大,可以训练出熟练的模型,但又足够不同,可以在集成中引入一些多样性。
...
# define the model
model = XGBRFClassifier(n_estimators=100, subsample=0.9)
训练模型时在每个分割点使用的特征数量可以通过“ colsample_bynode ”参数指定,并取数据集中 0.0 到 1.0 的列数百分比(训练数据集中输入行的 100%)。
如果我们的训练数据集中有 20 个输入变量,并且分类问题的启发式方法是特征数量的平方根,那么这可以设置为 sqrt(20) / 20,或者大约 4 / 20 或 0.2。
...
# define the model
model = XGBRFClassifier(n_estimators=100, subsample=0.9, colsample_bynode=0.2)
您可以在这里了解更多关于如何为随机森林集成配置 XGBoost 库的信息:
既然我们已经熟悉了如何使用 XGBoost API 来定义随机森林集合,那么让我们来看看一些工作示例。
为分类选择随机森林
在本节中,我们将着眼于为分类问题开发一个 XGBoost 随机森林集成。
首先,我们可以使用 make_classification()函数创建一个包含 1000 个示例和 20 个输入特征的合成二进制分类问题。
下面列出了完整的示例。
# test classification dataset
from sklearn.datasets import make_classification
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=7)
# summarize the dataset
print(X.shape, y.shape)
运行该示例将创建数据集并总结输入和输出组件的形状。
(1000, 20) (1000,)
接下来,我们可以在这个数据集上评估一个 XGBoost 随机森林算法。
我们将使用重复分层 k 折叠交叉验证来评估模型,重复 3 次,折叠 10 次。我们将报告所有重复和折叠的模型准确率的平均值和标准偏差。
# evaluate xgboost random forest algorithm for classification
from numpy import mean
from numpy import std
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from xgboost import XGBRFClassifier
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=7)
# define the model
model = XGBRFClassifier(n_estimators=100, subsample=0.9, colsample_bynode=0.2)
# define the model evaluation procedure
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
# evaluate the model and collect the scores
n_scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1)
# report performance
print('Mean Accuracy: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))
运行该示例会报告模型的均值和标准差准确率。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
在这种情况下,我们可以看到 XGBoost 随机森林集成实现了大约 89.1%的分类准确率。
Mean Accuracy: 0.891 (0.036)
我们也可以使用 XGBoost 随机森林模型作为最终模型,进行分类预测。
首先,XGBoost 随机森林集合适合所有可用数据,然后可以调用 predict() 函数对新数据进行预测。
下面的示例在我们的二进制类别数据集上演示了这一点。
# make predictions using xgboost random forest for classification
from numpy import asarray
from sklearn.datasets import make_classification
from xgboost import XGBRFClassifier
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=7)
# define the model
model = XGBRFClassifier(n_estimators=100, subsample=0.9, colsample_bynode=0.2)
# fit the model on the whole dataset
model.fit(X, y)
# define a row of data
row = [0.2929949,-4.21223056,-1.288332,-2.17849815,-0.64527665,2.58097719,0.28422388,-7.1827928,-1.91211104,2.73729512,0.81395695,3.96973717,-2.66939799,3.34692332,4.19791821,0.99990998,-0.30201875,-4.43170633,-2.82646737,0.44916808]
row = asarray([row])
# make a prediction
yhat = model.predict(row)
# summarize the prediction
print('Predicted Class: %d' % yhat[0])
运行该示例使 XGBoost 随机森林集成模型适用于整个数据集,然后用于对新的数据行进行预测,就像我们在应用程序中使用该模型时可能做的那样。
Predicted Class: 1
现在我们已经熟悉了使用随机森林进行分类,让我们看看回归的 API。
用于回归的随机森林
在本节中,我们将着眼于为回归问题开发一个 XGBoost 随机森林集成。
首先,我们可以使用make _ revolution()函数创建一个包含 1000 个示例和 20 个输入特征的合成回归问题。
下面列出了完整的示例。
# test regression dataset
from sklearn.datasets import make_regression
# define dataset
X, y = make_regression(n_samples=1000, n_features=20, n_informative=15, noise=0.1, random_state=7)
# summarize the dataset
print(X.shape, y.shape)
运行该示例将创建数据集并总结输入和输出组件的形状。
(1000, 20) (1000,)
接下来,我们可以在这个数据集上评估一个 XGBoost 随机森林集成。
正如我们在上一节中所做的,我们将使用重复的 k-fold 交叉验证来评估模型,重复 3 次,重复 10 次。
我们将报告所有重复和折叠模型的平均绝对误差(MAE)。Sklearn 库使 MAE 为负,因此它被最大化而不是最小化。这意味着负 MAE 越大越好,完美模型的 MAE 为 0。
下面列出了完整的示例。
# evaluate xgboost random forest ensemble for regression
from numpy import mean
from numpy import std
from sklearn.datasets import make_regression
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedKFold
from xgboost import XGBRFRegressor
# define dataset
X, y = make_regression(n_samples=1000, n_features=20, n_informative=15, noise=0.1, random_state=7)
# define the model
model = XGBRFRegressor(n_estimators=100, subsample=0.9, colsample_bynode=0.2)
# define the model evaluation procedure
cv = RepeatedKFold(n_splits=10, n_repeats=3, random_state=1)
# evaluate the model and collect the scores
n_scores = cross_val_score(model, X, y, scoring='neg_mean_absolute_error', cv=cv, n_jobs=-1)
# report performance
print('MAE: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))
运行该示例会报告模型的均值和标准差 MAE。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
在这种情况下,我们可以看到具有默认超参数的随机森林集合达到了大约 108 的 MAE。
MAE: -108.290 (5.647)
我们还可以使用 XGBoost 随机森林集合作为最终模型,并对回归进行预测。
首先,随机森林集合适用于所有可用数据,然后可以调用 predict()函数对新数据进行预测。
下面的例子在我们的回归数据集上演示了这一点。
# gradient xgboost random forest for making predictions for regression
from numpy import asarray
from sklearn.datasets import make_regression
from xgboost import XGBRFRegressor
# define dataset
X, y = make_regression(n_samples=1000, n_features=20, n_informative=15, noise=0.1, random_state=7)
# define the model
model = XGBRFRegressor(n_estimators=100, subsample=0.9, colsample_bynode=0.2)
# fit the model on the whole dataset
model.fit(X, y)
# define a single row of data
row = [0.20543991,-0.97049844,-0.81403429,-0.23842689,-0.60704084,-0.48541492,0.53113006,2.01834338,-0.90745243,-1.85859731,-1.02334791,-0.6877744,0.60984819,-0.70630121,-1.29161497,1.32385441,1.42150747,1.26567231,2.56569098,-0.11154792]
row = asarray([row])
# make a prediction
yhat = model.predict(row)
# summarize the prediction
print('Prediction: %d' % yhat[0])
运行该示例使 XGBoost 随机森林集成模型适用于整个数据集,然后用于对新的数据行进行预测,就像我们在应用程序中使用该模型时可能做的那样。
Prediction: 17
既然我们已经熟悉了如何开发和评估 XGBoost 随机森林集成,那么让我们来看看如何配置模型。
随机森林超参数
在本节中,我们将仔细研究一些您应该考虑为随机森林集合进行调整的超参数,以及它们对模型表现的影响。
探索树的数量
树的数量是为 XGBoost 随机林配置的另一个关键超参数。
通常,树的数量会增加,直到模型表现稳定下来。直觉可能暗示更多的树会导致过拟合,尽管事实并非如此。给定学习算法的随机性质,bagging 和随机森林算法似乎在某种程度上都不会过拟合训练数据集。
树的数量可以通过“n _ estimates”参数设置,默认为 100。
下面的示例探讨了值在 10 到 1000 之间的树的数量的影响。
# explore xgboost random forest number of trees effect on performance
from numpy import mean
from numpy import std
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from xgboost import XGBRFClassifier
from matplotlib import pyplot
# get the dataset
def get_dataset():
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=7)
return X, y
# get a list of models to evaluate
def get_models():
models = dict()
# define the number of trees to consider
n_trees = [10, 50, 100, 500, 1000, 5000]
for v in n_trees:
models[str(v)] = XGBRFClassifier(n_estimators=v, subsample=0.9, colsample_bynode=0.2)
return models
# evaluate a give model using cross-validation
def evaluate_model(model, X, y):
# define the model evaluation procedure
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
# evaluate the model
scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1)
return scores
# define dataset
X, y = get_dataset()
# get the models to evaluate
models = get_models()
# evaluate the models and store results
results, names = list(), list()
for name, model in models.items():
# evaluate the model and collect the results
scores = evaluate_model(model, X, y)
# store the results
results.append(scores)
names.append(name)
# summarize performance along the way
print('>%s %.3f (%.3f)' % (name, mean(scores), std(scores)))
# plot model performance for comparison
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()
运行该示例首先报告每个配置的树数的平均准确率。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
在这种情况下,我们可以看到大约 500 棵树后,表现会上升并保持不变。平均准确度分数在 500、1000 和 5000 棵树之间波动,这可能是统计噪声。
>10 0.868 (0.030)
>50 0.887 (0.034)
>100 0.891 (0.036)
>500 0.893 (0.033)
>1000 0.895 (0.035)
>5000 0.894 (0.036)
为每个配置数量的树的准确度分数的分布创建一个方框和须图。
XGBoost 随机森林集合大小与分类准确率的箱线图
探索功能数量
为每个分割点随机采样的要素数量可能是为随机森林配置的最重要的要素。
它是通过“ colsample_bynode ”参数设置的,该参数从 0 到 1 取输入特征数量的百分比。
以下示例探讨了在每个分割点随机选择的特征数量对模型准确率的影响。我们将尝试从 0.0 到 1.0 的值,增量为 0.1,尽管我们预计低于 0.2 或 0.3 的值会产生良好或最佳的表现,因为这相当于输入特征数量的平方根,这是一种常见的启发式方法。
# explore xgboost random forest number of features effect on performance
from numpy import mean
from numpy import std
from numpy import arange
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from xgboost import XGBRFClassifier
from matplotlib import pyplot
# get the dataset
def get_dataset():
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=7)
return X, y
# get a list of models to evaluate
def get_models():
models = dict()
for v in arange(0.1, 1.1, 0.1):
key = '%.1f' % v
models[key] = XGBRFClassifier(n_estimators=100, subsample=0.9, colsample_bynode=v)
return models
# evaluate a give model using cross-validation
def evaluate_model(model, X, y):
# define the model evaluation procedure
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
# evaluate the model
scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1)
return scores
# define dataset
X, y = get_dataset()
# get the models to evaluate
models = get_models()
# evaluate the models and store results
results, names = list(), list()
for name, model in models.items():
# evaluate the model and collect the results
scores = evaluate_model(model, X, y)
# store the results
results.append(scores)
names.append(name)
# summarize performance along the way
print('>%s %.3f (%.3f)' % (name, mean(scores), std(scores)))
# plot model performance for comparison
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()
运行示例首先报告每个特征集大小的平均准确率。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
在这种情况下,随着集成成员使用更多的输入特征,我们可以看到平均模型表现下降的总体趋势。
结果表明,在这种情况下,推荐值 0.2 将是一个不错的选择。
>0.1 0.889 (0.032)
>0.2 0.891 (0.036)
>0.3 0.887 (0.032)
>0.4 0.886 (0.030)
>0.5 0.878 (0.033)
>0.6 0.874 (0.031)
>0.7 0.869 (0.027)
>0.8 0.867 (0.027)
>0.9 0.856 (0.023)
>1.0 0.846 (0.027)
为每个要素集大小的准确率分数分布创建了一个方框和触须图。
我们可以看到表现随着决策树所考虑的特征数量而下降的趋势。
XGBoost 随机森林特征集大小与分类准确率的方框图
进一步阅读
如果您想更深入地了解这个主题,本节将提供更多资源。
教程
- 应用机器学习 XGBoost 的温和介绍
- 如何用 Python 开发随机森林集成
- 使用 Sklearn、XGBoost、LightGBM 和 CatBoost 进行梯度提升
- 如何用 scikit 开发你的第一个 Python xboost 模型-学习
蜜蜂
摘要
在本教程中,您发现了如何使用 XGBoost 库开发随机森林集成。
具体来说,您了解到:
- XGBoost 提供了梯度提升的有效实现,可以配置为训练随机森林集成。
- 如何使用 XGBoost API 训练和评估用于分类和回归的随机森林集成模型。
- 如何调整 XGBoost 随机森林集合模型的超参数。
你有什么问题吗? 在下面的评论中提问,我会尽力回答。
如何用 Python 开发随机子空间集成
最后更新于 2021 年 4 月 27 日
随机子空间集成是一种机器学习算法,它结合了在训练数据集中不同列子集上训练的多个决策树的预测。
随机改变用于训练集成的每个贡献成员的列具有将多样性引入集成的效果,并且反过来,可以使用单个决策树提升表现。
它与决策树的其他集成相关,例如使用训练数据集中不同行样本创建树的自举聚合(bagging),以及结合 bagging 和随机子空间集成思想的随机森林。
尽管决策树经常被使用,但是一般的随机子空间方法可以用于任何机器学习模型,其表现随着输入特征的选择而有意义地变化。
在本教程中,您将发现如何开发用于分类和回归的随机子空间集成。
完成本教程后,您将知道:
- 随机子空间集成是由决策树生成的,决策树适合训练数据集中不同的特征样本(列)。
- 如何用 Sklearn 使用随机子空间集成进行分类和回归?
- 如何探索随机子空间模型超参数对模型表现的影响?
用我的新书Python 集成学习算法启动你的项目,包括分步教程和所有示例的 Python 源代码文件。
我们开始吧。
如何用 Python 开发随机子空间集成 图片由马塞尔·阿明提供,版权所有。
教程概述
本教程分为三个部分;它们是:
- 随机子空间集成
- 基于装袋的随机子空间集成
- 分类的随机子空间集成
- 回归的随机子空间集成
- 随机子空间集成超参数
- 探索树的数量
- 探索功能数量
- 探索替代算法
随机子空间集成
预测建模问题由一个或多个输入变量和一个目标变量组成。
变量是数据中的一列,通常也称为特征。我们可以将所有输入要素一起视为定义了一个 n 维向量空间,其中 n 是输入要素的数量,每个示例(数据的输入行)是要素空间中的一个点。
这是机器学习中常见的概念化,随着输入特征空间变大,空间中点之间的距离增加,一般称为维数灾难。
因此,输入特征的子集可以被认为是输入特征空间或子空间的子集。
选择特征是定义输入特征空间的子空间的一种方式。例如,特征选择是指通过选择要保留的特征子集或要删除的特征子集来减少输入特征空间的维数的尝试,通常基于它们与目标变量的关系。
或者,我们可以选择输入特征的随机子集来定义随机子空间。这可以用作集成学习算法的基础,其中模型可以适合每个特征的随机子空间。这被称为随机子空间集成或随机子空间方法。
训练数据通常由一组特征描述。不同的特征子集,或称为子空间,提供不同的数据视图。因此,从不同子空间训练的个体学习器通常是不同的。
—第 116 页,集合方法,2012。
这是由田锦浩在 1998 年的论文《构建决策森林的随机子空间方法》中提出的,其中决策树适合于每个随机子空间。
更一般地说,这是一种用于集成学习的多样性技术,属于一类改变每个模型的训练数据集以试图降低集成中模型预测之间的相关性的方法。
过程很简单,只需为集合中的每个模型选择输入特征(列)的随机子集,并在整个训练数据集中的模型上拟合模型。它可以通过额外的更改进行扩充,例如使用自举或训练数据集中的随机行样本。
该分类器由通过伪随机选择特征向量的分量子集而系统地构建的多个树组成,即在随机选择的子空间中构建的树。
——构建决策森林的随机子空间方法,1998。
因此,随机子空间集成与自举聚集(bagging)相关,该自举聚集通过用替换(例如自举采样方法)在训练数据集的不同随机样本上训练每个模型(通常是决策树)来引入多样性。随机森林集成也可以被认为是装袋和随机子集集成方法的混合。
使用不同特征子集的算法通常被称为随机子空间方法…
—第 21 页,集成机器学习,2012。
随机子空间方法可以用于任何机器学习算法,尽管它非常适合对输入特征的大变化敏感的模型,例如决策树和 k 近邻。
它适用于具有大量输入要素的数据集,因为它可以带来良好的表现和效率。如果数据集包含许多不相关的输入特征,使用特征选择作为数据准备技术可能会更好,因为子空间中不相关特征的普遍存在可能会损害集成的表现。
对于具有大量冗余特征的数据,在子空间中训练学习器不仅有效,而且高效。
—第 116 页,集合方法,2012。
现在我们已经熟悉了随机子空间集成,让我们来探索如何实现这种方法。
基于装袋的随机子空间集成
我们可以在 Sklearn 中使用 bagging 实现随机子空间集成。
我们可以将 bagging 配置为随机子空间集成,方法是将“ bootstrap ”参数设置为“ False ”以关闭训练数据集行的采样,并通过“ max_features ”参数将最大特征数设置为给定值。
装袋的默认模型是决策树,但它可以更改为我们喜欢的任何模型。
我们可以演示使用 bagging 来实现带有决策树的随机子空间集成,用于分类和回归。
分类的随机子空间集成
在这一节中,我们将考虑使用 bagging 为分类问题开发一个随机子空间集成。
首先,我们可以使用 make_classification()函数创建一个包含 1000 个示例和 20 个输入特征的合成二进制分类问题。
下面列出了完整的示例。
# test classification dataset
from sklearn.datasets import make_classification
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=5)
# summarize the dataset
print(X.shape, y.shape)
运行该示例将创建数据集并总结输入和输出组件的形状。
(1000, 20) (1000,)
接下来,我们可以将 bagging 模型配置为该数据集上决策树的随机子空间集成。
每一个模型都适合于一个随机的子空间,这个子空间由 10 个任意选择的输入特征组成。
...
# define the random subspace ensemble model
model = BaggingClassifier(bootstrap=False, max_features=10)
我们将使用重复的分层 k 折叠交叉验证来评估模型,重复 3 次,折叠 10 次。我们将报告所有重复和折叠的模型准确率的平均值和标准偏差。
# evaluate random subspace ensemble via bagging for classification
from numpy import mean
from numpy import std
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.ensemble import BaggingClassifier
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=5)
# define the random subspace ensemble model
model = BaggingClassifier(bootstrap=False, max_features=10)
# define the evaluation method
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
# evaluate the model on the dataset
n_scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1)
# report performance
print('Mean Accuracy: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))
运行该示例会报告模型的均值和标准差准确率。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
在这种情况下,我们可以看到具有默认超参数的随机子空间集成在这个测试数据集上实现了大约 85.4%的分类准确率。
Mean Accuracy: 0.854 (0.039)
我们还可以使用随机子空间集成模型作为最终模型,并对分类进行预测。
首先,对所有可用数据进行集合拟合,然后调用 predict() 函数对新数据进行预测。
下面的示例在我们的二进制类别数据集上演示了这一点。
# make predictions using random subspace ensemble via bagging for classification
from sklearn.datasets import make_classification
from sklearn.ensemble import BaggingClassifier
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=5)
# define the model
model = BaggingClassifier(bootstrap=False, max_features=10)
# fit the model on the whole dataset
model.fit(X, y)
# make a single prediction
row = [[-4.7705504,-1.88685058,-0.96057964,2.53850317,-6.5843005,3.45711663,-7.46225013,2.01338213,-0.45086384,-1.89314931,-2.90675203,-0.21214568,-0.9623956,3.93862591,0.06276375,0.33964269,4.0835676,1.31423977,-2.17983117,3.1047287]]
yhat = model.predict(row)
print('Predicted Class: %d' % yhat[0])
运行该示例使随机子空间集成模型适合整个数据集,然后用于对新的数据行进行预测,就像我们在应用程序中使用该模型时可能做的那样。
Predicted Class: 1
现在我们已经熟悉了使用 bagging 进行分类,让我们看看回归的 API。
回归的随机子空间集成
在这一节中,我们将研究使用 bagging 解决回归问题。
首先,我们可以使用make _ revolution()函数创建一个包含 1000 个示例和 20 个输入特征的合成回归问题。
下面列出了完整的示例。
# test regression dataset
from sklearn.datasets import make_regression
# define dataset
X, y = make_regression(n_samples=1000, n_features=20, n_informative=15, noise=0.1, random_state=5)
# summarize the dataset
print(X.shape, y.shape)
运行该示例将创建数据集并总结输入和输出组件的形状。
(1000, 20) (1000,)
接下来,我们可以通过对该数据集进行装袋来评估随机子空间集成。
和前面一样,我们必须配置 bagging 来使用训练数据集的所有行,并指定要随机选择的输入要素的数量。
...
# define the model
model = BaggingRegressor(bootstrap=False, max_features=10)
正如我们在上一节中所做的,我们将使用重复的 k-fold 交叉验证来评估模型,重复 3 次,重复 10 次。我们将报告所有重复和折叠模型的平均绝对误差(MAE)。Sklearn 库使 MAE 为负,因此它被最大化而不是最小化。这意味着负 MAE 越大越好,完美模型的 MAE 为 0。
下面列出了完整的示例。
# evaluate random subspace ensemble via bagging for regression
from numpy import mean
from numpy import std
from sklearn.datasets import make_regression
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedKFold
from sklearn.ensemble import BaggingRegressor
# define dataset
X, y = make_regression(n_samples=1000, n_features=20, n_informative=15, noise=0.1, random_state=5)
# define the model
model = BaggingRegressor(bootstrap=False, max_features=10)
# define the evaluation procedure
cv = RepeatedKFold(n_splits=10, n_repeats=3, random_state=1)
# evaluate the model
n_scores = cross_val_score(model, X, y, scoring='neg_mean_absolute_error', cv=cv, n_jobs=-1, error_score='raise')
# report performance
print('MAE: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))
运行该示例会报告模型的均值和标准差准确率。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
在这种情况下,我们可以看到具有默认超参数的 bagging 集成实现了大约 114 的 MAE。
MAE: -114.630 (10.920)
我们也可以使用随机子空间集成模型作为最终模型,并对回归进行预测。
首先,集合适合所有可用数据,然后可以调用 predict()函数对新数据进行预测。
下面的例子在我们的回归数据集上演示了这一点。
# random subspace ensemble via bagging for making predictions for regression
from sklearn.datasets import make_regression
from sklearn.ensemble import BaggingRegressor
# define dataset
X, y = make_regression(n_samples=1000, n_features=20, n_informative=15, noise=0.1, random_state=5)
# define the model
model = BaggingRegressor(bootstrap=False, max_features=10)
# fit the model on the whole dataset
model.fit(X, y)
# make a single prediction
row = [[0.88950817,-0.93540416,0.08392824,0.26438806,-0.52828711,-1.21102238,-0.4499934,1.47392391,-0.19737726,-0.22252503,0.02307668,0.26953276,0.03572757,-0.51606983,-0.39937452,1.8121736,-0.00775917,-0.02514283,-0.76089365,1.58692212]]
yhat = model.predict(row)
print('Prediction: %d' % yhat[0])
运行该示例使随机子空间集成模型适合整个数据集,然后用于对新的数据行进行预测,就像我们在应用程序中使用该模型时可能做的那样。
Prediction: -157
现在我们已经熟悉了使用 Sklearn API 来评估和使用随机子空间集成,让我们来看看如何配置模型。
随机子空间集成超参数
在本节中,我们将仔细研究一些您应该考虑为随机子空间集成进行调整的超参数,以及它们对模型表现的影响。
探索树的数量
随机子空间方法的一个重要超参数是集成中使用的决策树的数量。更多的树将稳定模型的方差,抵消每个树选择的引入多样性的特征数量的影响。
树的数量可以通过“n _ estimates”参数设置,默认为 10。
下面的示例探讨了值在 10 到 5,000 之间的树的数量的影响。
# explore random subspace ensemble number of trees effect on performance
from numpy import mean
from numpy import std
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.ensemble import BaggingClassifier
from matplotlib import pyplot
# get the dataset
def get_dataset():
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=5)
return X, y
# get a list of models to evaluate
def get_models():
models = dict()
n_trees = [10, 50, 100, 500, 1000, 5000]
for n in n_trees:
models[str(n)] = BaggingClassifier(n_estimators=n, bootstrap=False, max_features=10)
return models
# evaluate a given model using cross-validation
def evaluate_model(model):
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1)
return scores
# define dataset
X, y = get_dataset()
# get the models to evaluate
models = get_models()
# evaluate the models and store results
results, names = list(), list()
for name, model in models.items():
scores = evaluate_model(model)
results.append(scores)
names.append(name)
print('>%s %.3f (%.3f)' % (name, mean(scores), std(scores)))
# plot model performance for comparison
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()
运行该示例首先报告每个配置数量的决策树的平均准确性。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
在这种情况下,我们可以看到,随着集成成员的数量增加到 5000 人,这种表现似乎在继续改善。
>10 0.853 (0.030)
>50 0.885 (0.038)
>100 0.891 (0.034)
>500 0.894 (0.036)
>1000 0.894 (0.034)
>5000 0.896 (0.033)
为每个配置数量的树的准确度分数的分布创建一个方框和须图。
随着集成中使用的决策树数量的增加,我们可以看到进一步改进的总体趋势。
随机子空间集合大小与分类准确率的箱线图
探索功能数量
为每个随机子空间选择的特征数量控制着整体的多样性。
更少的特征意味着更多的多样性,而更多的特征意味着更少的多样性。更多的多样性可能需要更多的树来减少模型预测的方差。
我们可以通过设置“ max_features ”参数来改变随机特征的数量,从而改变集合的多样性。
下面的示例使用集成中固定数量的树将值从 1 更改为 20。
# explore random subspace ensemble number of features effect on performance
from numpy import mean
from numpy import std
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.ensemble import BaggingClassifier
from matplotlib import pyplot
# get the dataset
def get_dataset():
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=5)
return X, y
# get a list of models to evaluate
def get_models():
models = dict()
for n in range(1,21):
models[str(n)] = BaggingClassifier(n_estimators=100, bootstrap=False, max_features=n)
return models
# evaluate a given model using cross-validation
def evaluate_model(model):
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1)
return scores
# define dataset
X, y = get_dataset()
# get the models to evaluate
models = get_models()
# evaluate the models and store results
results, names = list(), list()
for name, model in models.items():
scores = evaluate_model(model)
results.append(scores)
names.append(name)
print('>%s %.3f (%.3f)' % (name, mean(scores), std(scores)))
# plot model performance for comparison
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()
运行示例首先报告每个特征数量的平均准确率。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
在这种情况下,我们可以看到,当使用 100 棵决策树时,在随机子空间中使用 8 到 11 个特征可能适合这个数据集。这可能建议首先将树的数量增加到一个较大的值,然后调整在每个子集中选择的特征的数量。
>1 0.607 (0.036)
>2 0.771 (0.042)
>3 0.837 (0.036)
>4 0.858 (0.037)
>5 0.869 (0.034)
>6 0.883 (0.033)
>7 0.887 (0.038)
>8 0.894 (0.035)
>9 0.893 (0.035)
>10 0.885 (0.038)
>11 0.892 (0.034)
>12 0.883 (0.036)
>13 0.881 (0.044)
>14 0.875 (0.038)
>15 0.869 (0.041)
>16 0.861 (0.044)
>17 0.851 (0.041)
>18 0.831 (0.046)
>19 0.815 (0.046)
>20 0.801 (0.049)
为每个随机子集特征的准确率分数分布创建一个方框和须图。
我们可以看到一个普遍的趋势,即准确率增加到一个点,并且在 11 个特征之后表现稳步下降。
随机子空间集成特征与分类准确率的箱线图
探索替代算法
决策树是随机子空间集成中最常用的算法。
这是因为它们易于配置,并且在大多数问题上运行良好。
其他算法可以用来构造随机子空间,并且必须被配置为具有适度高的方差。一个例子是 k 近邻算法,其中 k 值可以设置为低值。
集合中使用的算法是通过“ base_estimator ”参数指定的,并且必须设置为要使用的算法和算法配置的实例。
下面的例子演示了使用一个kneighgborcsclassifier作为通过 bagging 类在随机子空间集成中使用的基本算法。这里,算法与默认超参数一起使用,其中 k 设置为 5。
...
# define the model
model = BaggingClassifier(base_estimator=KNeighborsClassifier(), bootstrap=False, max_features=10)
下面列出了完整的示例。
# evaluate random subspace ensemble with knn algorithm for classification
from numpy import mean
from numpy import std
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import BaggingClassifier
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=5)
# define the model
model = BaggingClassifier(base_estimator=KNeighborsClassifier(), bootstrap=False, max_features=10)
# define the evaluation procedure
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
# evaluate the model
n_scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')
# report performance
print('Accuracy: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))
运行该示例会报告模型的均值和标准差准确率。
注:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。
在这种情况下,我们可以看到具有 KNN 和默认超参数的随机子空间集成在这个测试数据集上实现了大约 90%的分类准确率。
Accuracy: 0.901 (0.032)
进一步阅读
如果您想更深入地了解这个主题,本节将提供更多资源。
报纸
- 构建决策森林的随机子空间方法,1998。
书
- 使用集成方法的模式分类,2010。
- 集成方法,2012。
- 集成机器学习,2012。
蜜蜂
文章
摘要
在本教程中,您发现了如何开发用于分类和回归的随机子空间集成。
具体来说,您了解到:
- 随机子空间集成是由决策树生成的,决策树适合训练数据集中不同的特征样本(列)。
- 如何用 Sklearn 使用随机子空间集成进行分类和回归?
- 如何探索随机子空间模型超参数对模型表现的影响?
你有什么问题吗? 在下面的评论中提问,我会尽力回答。