Bagging 是一种集成机器学习算法,它结合了多个决策树的预测结果。
它也很容易实现,因为它只有少数几个关键的超参数,并且为这些超参数的配置提供了合理的启发式方法。
Bagging 通常表现良好,并为整个决策树集成算法领域提供了基础,例如流行的随机森林和极端随机树集成算法,以及鲜为人知的粘贴集成(Pasting)、随机子空间(Random Subspaces)和随机补丁(Random Patches)集成算法。
在本教程中,您将学习如何开发用于分类和回归的 Bagging 集成算法。
完成本教程后,您将了解:
- Bagging 集成算法是一种由在数据集不同样本上训练的决策树创建的集成算法。
- 如何使用 scikit-learn 进行分类和回归的 Bagging 集成。
- 如何探索 Bagging 模型超参数对模型性能的影响。
通过我的新书《使用 Python 的集成学习算法》启动您的项目,其中包括逐步教程和所有示例的 Python 源代码文件。
让我们开始吧。
- 2020 年 8 月更新:增加了常见问题部分。

如何在 Python 中开发 Bagging 集成算法
图片来源:daveynin,保留部分权利。
教程概述
本教程分为五个部分;它们是:
- Bagging 集成算法
- Bagging Scikit-Learn API
- Bagging 用于分类
- Bagging 用于回归
- Bagging 超参数
- 探索树的数量
- 探索样本数量
- 探索替代算法
- Bagging 扩展
- 粘贴集成(Pasting Ensemble)
- 随机子空间集成(Random Subspaces Ensemble)
- 随机补丁集成(Random Patches Ensemble)
- 常见问题
Bagging 集成算法
Bootstrap Aggregation,简称 Bagging,是一种集成机器学习算法。
具体来说,它是一个决策树模型的集成,尽管 Bagging 技术也可以用于结合其他类型模型的预测。
顾名思义,bootstrap aggregation 基于“bootstrap”样本的概念。
“自助采样”是指从数据集中有放回地抽取样本。有放回地抽取意味着从数据集中抽取的样本会被放回,允许它在新的样本中再次被选中,甚至多次被选中。这意味着样本可能包含原始数据集中的重复示例。
自助采样技术用于从少量数据样本中估计总体统计量。这是通过抽取多个自助样本,在每个样本上计算统计量,并报告所有样本的平均统计量来实现的。
使用自助采样的一个例子是从小数据集中估计总体均值。从数据集中抽取多个自助样本,在每个样本上计算均值,然后将估计均值的均值报告为总体的估计值。
令人惊讶的是,与对原始数据集进行单一估计相比,自助法提供了一种稳健且准确的方法来估计统计量。
同样的方法也可以用于创建决策树模型集成。
这是通过从训练数据集中抽取多个自助样本,并在每个样本上拟合一个决策树来实现的。然后将决策树的预测结果结合起来,以提供比单一决策树更稳健和准确的预测(通常如此,但并非总是如此)。
Bagging 预测器是一种生成预测器多个版本并利用这些版本获得聚合预测器的方法。[…] 多个版本是通过对学习集进行自助抽样复制并将其用作新的学习集来形成的。
— Bagging 预测器, 1996。
对于回归问题,通过对所有决策树的预测进行平均来得出预测结果。对于分类问题,通过对所有决策树的预测结果进行多数投票来得出类别预测。
Bagging 决策树之所以有效,是因为每个决策树都在略微不同的训练数据集上进行拟合,这反过来又使得每个树都有细微的差异并做出略微不同的有技巧的预测。
从技术上讲,我们说这种方法是有效的,因为树之间的预测相关性较低,进而预测误差也较低。
决策树,特别是未剪枝的决策树,被用来稍微过度拟合训练数据并具有高方差。其他高方差机器学习算法也可以使用,例如低 k 值的 k-近邻算法,尽管决策树已被证明是最有效的。
如果扰动学习集会导致构建的预测器发生显著变化,那么 Bagging 可以提高准确性。
— Bagging 预测器, 1996。
Bagging 并非总是能带来改进。对于已经表现良好的低方差模型,Bagging 可能会导致模型性能下降。
实验和理论证据都表明,Bagging 可以使一个良好但不稳定的过程向最优性迈进一大步。另一方面,它可能会略微降低稳定过程的性能。
— Bagging 预测器, 1996。
想开始学习集成学习吗?
立即参加我为期7天的免费电子邮件速成课程(附示例代码)。
点击注册,同时获得该课程的免费PDF电子书版本。
Bagging Scikit-Learn API
Bagging 集成算法可以从头开始实现,尽管这对于初学者来说可能具有挑战性。
例如,请参阅教程
scikit-learn Python 机器学习库提供了机器学习 Bagging 集成算法的实现。
它在库的现代版本中可用。
首先,通过运行以下脚本确认您正在使用该库的现代版本
1 2 3 |
# 检查 scikit-learn 版本 import sklearn print(sklearn.__version__) |
运行脚本将打印您的 scikit-learn 版本。
您的版本应该相同或更高。如果不是,您必须升级您的 scikit-learn 库版本。
1 |
0.22.1 |
Bagging 通过 BaggingRegressor 和 BaggingClassifier 类提供。
这两个模型的操作方式相同,并接受影响决策树创建方式的相同参数。
模型构建中使用了随机性。这意味着每次在相同数据上运行算法时,它都会生成一个略有不同的模型。
当使用具有随机学习算法的机器学习算法时,通过对多次运行或重复交叉验证的性能取平均值来评估它们是一种很好的做法。在拟合最终模型时,可能需要增加树的数量,直到模型的方差在重复评估中减小,或者拟合多个最终模型并对其预测进行平均。
让我们看看如何为分类和回归开发 Bagging 集成算法。
Bagging 用于分类
在本节中,我们将探讨在分类问题中使用 Bagging。
首先,我们可以使用 make_classification() 函数 创建一个包含 1,000 个示例和 20 个输入特征的合成二元分类问题。
完整的示例如下所示。
1 2 3 4 5 6 |
# 测试分类数据集 from sklearn.datasets import make_classification # 定义数据集 X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=5) # 汇总数据集 print(X.shape, y.shape) |
运行示例会创建数据集并总结输入和输出组件的形状。
1 |
(1000, 20) (1000,) |
接下来,我们可以在此数据集上评估 Bagging 算法。
我们将使用重复分层 k 折交叉验证来评估模型,其中包含三次重复和 10 折。我们将报告模型在所有重复和折叠中的准确率的均值和标准差。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# 评估 Bagging 分类算法 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 # 定义数据集 X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=5) # 定义模型 model = BaggingClassifier() # 评估模型 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') # 报告表现 print('Accuracy: %.3f (%.3f)' % (mean(n_scores), std(n_scores))) |
运行示例报告了模型的平均准确度和标准差。
注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。请考虑运行示例几次并比较平均结果。
在这种情况下,我们可以看到具有默认超参数的 Bagging 集成在此测试数据集上实现了约 85% 的分类准确率。
1 |
准确率:0.856 (0.037) |
我们还可以将 Bagging 模型用作最终模型,并进行分类预测。
首先,Bagging 集成在所有可用数据上进行拟合,然后可以调用 predict() 函数对新数据进行预测。
以下示例在我们的二元分类数据集上演示了这一点。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# 使用 Bagging 进行分类预测 from sklearn.datasets import make_classification from sklearn.ensemble import BaggingClassifier # 定义数据集 X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=5) # 定义模型 model = BaggingClassifier() # 在整个数据集上拟合模型 model.fit(X, y) # 进行单次预测 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]) |
运行示例会拟合 Bagging 集成模型到整个数据集,然后用于对新数据行进行预测,就像我们在应用程序中使用模型时一样。
1 |
预测类别:1 |
现在我们熟悉了 Bagging 用于分类,接下来我们看看用于回归的 API。
Bagging 用于回归
在本节中,我们将探讨在回归问题中使用 Bagging。
首先,我们可以使用 make_regression() 函数 创建一个包含 1,000 个示例和 20 个输入特征的合成回归问题。
完整的示例如下所示。
1 2 3 4 5 6 |
# 测试回归数据集 from sklearn.datasets import make_regression # 定义数据集 X, y = make_regression(n_samples=1000, n_features=20, n_informative=15, noise=0.1, random_state=5) # 汇总数据集 print(X.shape, y.shape) |
运行示例会创建数据集并总结输入和输出组件的形状。
1 |
(1000, 20) (1000,) |
接下来,我们可以在此数据集上评估 Bagging 算法。
与上一节一样,我们将使用重复的 k 折交叉验证来评估模型,其中包含三次重复和 10 折。我们将报告模型在所有重复和折叠中的平均绝对误差 (MAE)。scikit-learn 库将 MAE 设为负值,以便将其最大化而不是最小化。这意味着负值越大越好,完美模型的 MAE 为 0。
完整的示例如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# 评估 Bagging 回归集成算法 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 # 定义数据集 X, y = make_regression(n_samples=1000, n_features=20, n_informative=15, noise=0.1, random_state=5) # 定义模型 model = BaggingRegressor() # 评估模型 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') # 报告表现 print('MAE: %.3f (%.3f)' % (mean(n_scores), std(n_scores))) |
运行示例报告了模型的平均准确度和标准差。
注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。请考虑运行示例几次并比较平均结果。
在这种情况下,我们可以看到具有默认超参数的 Bagging 集成实现了约 100 的 MAE。
1 |
平均绝对误差:-101.133 (9.757) |
我们还可以将 Bagging 模型用作最终模型并进行回归预测。
首先,Bagging 集成在所有可用数据上进行拟合,然后可以调用 predict() 函数对新数据进行预测。
以下示例在我们的回归数据集上演示了这一点。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# Bagging 集成算法进行回归预测 from sklearn.datasets import make_regression from sklearn.ensemble import BaggingRegressor # 定义数据集 X, y = make_regression(n_samples=1000, n_features=20, n_informative=15, noise=0.1, random_state=5) # 定义模型 model = BaggingRegressor() # 在整个数据集上拟合模型 model.fit(X, y) # 进行单次预测 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]) |
运行示例会拟合 Bagging 集成模型到整个数据集,然后用于对新数据行进行预测,就像我们在应用程序中使用模型时一样。
1 |
预测值:-134 |
既然我们已经熟悉了如何使用 scikit-learn API 来评估和使用 Bagging 集成算法,接下来让我们看看如何配置模型。
Bagging 超参数
在本节中,我们将更深入地探讨 Bagging 集成算法的一些超参数,您应该考虑对它们进行调优,以及它们对模型性能的影响。
探索树的数量
Bagging 算法的一个重要超参数是集成中使用的决策树数量。
通常,会增加树的数量,直到模型性能稳定。直觉可能认为更多的树会导致过拟合,但情况并非如此。Bagging 和相关的决策树集成算法(如随机森林)由于学习算法的随机性,似乎对训练数据集的过拟合具有一定的免疫力。
树的数量可以通过“n_estimators”参数设置,默认为 100。
下面的示例探讨了树的数量在 10 到 5,000 之间对性能的影响。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# 探索 Bagging 集成树数量对性能的影响 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 # 获取数据集 定义 获取_数据集(): X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=5) 返回 X, y # 获取要评估的模型列表 定义 获取_模型(): models = dict() # 定义要考虑的树的数量 n_trees = [10, 50, 100, 500, 500, 1000, 5000] for n in n_trees: models[str(n)] = BaggingClassifier(n_estimators=n) 返回 模型 # 使用交叉验证评估给定模型 def evaluate_model(model, X, y): # 定义评估过程 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) 返回 分数 # 定义数据集 X, y = get_dataset() # 获取要评估的模型 模型 = 获取_模型() # 评估模型并存储结果 results, names = list(), list() for name, model in models.items(): # 评估模型 scores = evaluate_model(model, X, y) # 存储结果 results.append(scores) names.append(name) # 沿途总结性能 print('>%s %.3f (%.3f)' % (name, mean(scores), std(scores))) # 绘制模型性能以供比较 pyplot.boxplot(results, labels=names, showmeans=True) pyplot.show() |
运行示例首先报告每个配置的决策树数量的平均准确率。
注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。请考虑运行示例几次并比较平均结果。
在这种情况下,我们可以看到该数据集上的性能提高到大约 100 棵树之后趋于稳定。
1 2 3 4 5 6 |
>10 0.855 (0.037) >50 0.876 (0.035) >100 0.882 (0.037) >500 0.885 (0.041) >1000 0.885 (0.037) >5000 0.885 (0.038) |
为每个配置的树数量创建了准确率分数的箱线图。
我们看到在超过大约 100 棵树之后,性能没有进一步改善的普遍趋势。

Bagging 集成规模与分类准确率的箱线图
探索样本数量
自助样本的大小也可以改变。
默认是创建一个与原始数据集大小相同的自助样本。使用较小的数据集可以增加生成的决策树的方差,并可能导致更好的整体性能。
用于拟合每个决策树的样本数量通过“max_samples”参数设置。
下面的示例探讨了不同大小的样本作为原始数据集的比例,从 10% 到 100%(默认)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# 探索 Bagging 集成样本数量对性能的影响 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 BaggingClassifier from matplotlib import pyplot # 获取数据集 定义 获取_数据集(): X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=5) 返回 X, y # 获取要评估的模型列表 定义 获取_模型(): models = dict() # 探索从 10% 到 100% 的比例,以 10% 为增量 for i in arange(0.1, 1.1, 0.1): key = '%.1f' % i models[key] = BaggingClassifier(max_samples=i) 返回 模型 # 使用交叉验证评估给定模型 def evaluate_model(model, X, y): # 定义评估过程 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) 返回 分数 # 定义数据集 X, y = get_dataset() # 获取要评估的模型 模型 = 获取_模型() # 评估模型并存储结果 results, names = list(), list() for name, model in models.items(): # 评估模型 scores = evaluate_model(model, X, y) # 存储结果 results.append(scores) names.append(name) # 沿途总结性能 print('>%s %.3f (%.3f)' % (name, mean(scores), std(scores))) # 绘制模型性能以供比较 pyplot.boxplot(results, labels=names, showmeans=True) pyplot.show() |
运行示例首先报告每个样本集大小的平均准确率。
注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。请考虑运行示例几次并比较平均结果。
在这种情况下,结果表明性能通常随样本大小的增加而提高,这突出表明默认值 100% 的训练数据集大小是合理的。
探索更小的样本量并相应增加树的数量,以减少单个模型的方差,也可能很有趣。
1 2 3 4 5 6 7 8 9 10 |
>0.1 0.810 (0.036) >0.2 0.836 (0.044) >0.3 0.844 (0.043) >0.4 0.843 (0.041) >0.5 0.852 (0.034) >0.6 0.855 (0.042) >0.7 0.858 (0.042) >0.8 0.861 (0.033) >0.9 0.866 (0.041) >1.0 0.864 (0.042) |
为每个样本大小创建了准确率分数的箱线图。
我们看到准确率随样本大小增加的普遍趋势。

Bagging 样本大小与分类准确率的箱线图
探索替代算法
决策树是 Bagging 集成中最常用的算法。
其原因在于,它们很容易配置成高方差,并且通常表现良好。
其他算法也可以与 Bagging 一起使用,并且必须配置为具有适度高方差。一个例子是 k-近邻算法,其中 k 值可以设置为较低的值。
集成中使用的算法通过“base_estimator”参数指定,并且必须设置为要使用的算法实例和算法配置。
下面的示例演示了使用 KNeighborsClassifier 作为 Bagging 集成中使用的基础算法。这里,该算法使用默认超参数,其中 k 设置为 5。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# 评估使用 KNN 算法进行分类的 Bagging 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 # 定义数据集 X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=5) # 定义模型 model = BaggingClassifier(base_estimator=KNeighborsClassifier()) # 评估模型 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') # 报告表现 print('Accuracy: %.3f (%.3f)' % (mean(n_scores), std(n_scores))) |
运行示例报告了模型的平均准确度和标准差。
注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。请考虑运行示例几次并比较平均结果。
在这种情况下,我们可以看到具有 KNN 和默认超参数的 Bagging 集成在此测试数据集上实现了约 88% 的分类准确率。
1 |
准确率:0.888 (0.036) |
我们可以测试不同的 k 值,以找到模型方差的正确平衡,从而实现 Bagging 集成的良好性能。
下面的示例测试了 k 值介于 1 到 20 之间的 Bagging KNN 模型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# 探索 Bagging 集成中 KNN 的 k 值对性能的影响 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 sklearn.neighbors import KNeighborsClassifier from matplotlib import pyplot # 获取数据集 定义 获取_数据集(): X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=5) 返回 X, y # 获取要评估的模型列表 定义 获取_模型(): models = dict() # 评估 k 值从 1 到 20 for i in range(1,21): # 定义基础模型 base = KNeighborsClassifier(n_neighbors=i) # 定义集成模型 models[str(i)] = BaggingClassifier(base_estimator=base) 返回 模型 # 使用交叉验证评估给定模型 def evaluate_model(model, X, y): # 定义评估过程 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) 返回 分数 # 定义数据集 X, y = get_dataset() # 获取要评估的模型 模型 = 获取_模型() # 评估模型并存储结果 results, names = list(), list() for name, model in models.items(): # 评估模型 scores = evaluate_model(model, X, y) # 存储结果 results.append(scores) names.append(name) # 沿途总结性能 print('>%s %.3f (%.3f)' % (name, mean(scores), std(scores))) # 绘制模型性能以供比较 pyplot.boxplot(results, labels=names, showmeans=True) pyplot.show() |
运行示例首先报告每个 k 值的平均准确率。
注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。请考虑运行示例几次并比较平均结果。
在这种情况下,结果表明,当在 Bagging 集成中使用时,小的 k 值(例如 2 到 4)会带来最佳的平均准确率。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
>1 0.884 (0.025) >2 0.890 (0.029) >3 0.886 (0.035) >4 0.887 (0.033) >5 0.878 (0.037) >6 0.879 (0.042) >7 0.877 (0.037) >8 0.877 (0.036) >9 0.871 (0.034) >10 0.877 (0.033) >11 0.876 (0.037) >12 0.877 (0.030) >13 0.874 (0.034) >14 0.871 (0.039) >15 0.875 (0.034) >16 0.877 (0.033) >17 0.872 (0.034) >18 0.873 (0.036) >19 0.876 (0.034) >20 0.876 (0.037) |
为每个 k 值的准确率分布创建了箱线图。
我们看到准确率一开始随样本大小增加的普遍趋势,然后随着集成中使用的单个 KNN 模型的方差随 k 值增大而增加,性能适度下降。

Bagging KNN 邻居数量与分类准确率的箱线图
Bagging 扩展
Bagging 算法有许多修改和扩展,旨在提高该方法的性能。
其中最著名的可能是随机森林算法。
还有一些不那么著名但仍然有效的 Bagging 扩展,可能值得研究。
本节演示了其中一些方法,例如粘贴集成(pasting ensemble)、随机子空间集成(random subspace ensemble)和随机补丁集成(random patches ensemble)。
我们不会在数据集上对这些扩展进行竞赛,而是提供如何使用每种技术的实际示例,您可以复制粘贴并在自己的数据集上尝试。
粘贴集成(Pasting Ensemble)
粘贴集成是 Bagging 的一个扩展,它涉及基于训练数据集的随机样本而不是自助样本来拟合集成成员。
该方法旨在在训练数据集不适合内存的情况下,使用比训练数据集更小的样本量。
该过程将数据分成小块,在每个小块上训练一个预测器,然后将这些预测器组合起来。其中一个版本可以扩展到 TB 级数据集。这些方法也适用于在线学习。
— Pasting Small Votes for Classification in Large Databases and On-Line, 1999。
下面的示例演示了粘贴集成,通过将“bootstrap”参数设置为“False”,并将通过“max_samples”在训练数据集中使用的样本数量设置为一个适度值,在本例中为训练数据集大小的 50%。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# 评估粘贴集成算法用于分类 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 # 定义数据集 X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=5) # 定义模型 model = BaggingClassifier(bootstrap=False, max_samples=0.5) # 评估模型 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') # 报告表现 print('Accuracy: %.3f (%.3f)' % (mean(n_scores), std(n_scores))) |
运行示例报告了模型的平均准确度和标准差。
注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。请考虑运行示例几次并比较平均结果。
在这种情况下,我们可以看到粘贴集成在此数据集上实现了约 84% 的分类准确率。
1 |
准确率:0.848 (0.039) |
随机子空间集成(Random Subspaces Ensemble)
随机子空间集成是 Bagging 的一个扩展,它涉及基于从训练数据集特征的随机子集中构建的数据集来拟合集成成员。
它类似于随机森林,只是数据样本是随机的而不是自助样本,并且特征子集是为整个决策树选择的,而不是在树的每个分裂点选择。
该分类器由多个树组成,这些树通过伪随机选择特征向量组件的子集系统地构建,也就是说,树在随机选择的子空间中构建。
— 随机子空间方法用于构建决策森林, 1998。
下面的示例演示了随机子空间集成,通过将“bootstrap”参数设置为“False”,并将通过“max_features”在训练数据集中使用的特征数量设置为一个适度值,在本例中为 10。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# 评估随机子空间集成算法用于分类 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 # 定义数据集 X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=5) # 定义模型 model = BaggingClassifier(bootstrap=False, max_features=10) # 评估模型 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') # 报告表现 print('Accuracy: %.3f (%.3f)' % (mean(n_scores), std(n_scores))) |
运行示例报告了模型的平均准确度和标准差。
注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。请考虑运行示例几次并比较平均结果。
在这种情况下,我们可以看到随机子空间集成在此数据集上实现了约 86% 的分类准确率。
1 |
准确率:0.862 (0.040) |
我们预计随机子空间中的特征数量将提供模型方差和模型技能的适当平衡。
下面的示例演示了在随机子空间集成中使用不同数量特征(从 1 到 20)的效果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# 探索随机子空间集成中特征数量对性能的影响 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 # 获取数据集 定义 获取_数据集(): X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=5) 返回 X, y # 获取要评估的模型列表 定义 获取_模型(): models = dict() for i in range(1, 21): models[str(i)] = BaggingClassifier(bootstrap=False, max_features=i) 返回 模型 # 使用交叉验证评估给定模型 def evaluate_model(model, X, y): 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, error_score='raise') 返回 分数 # 定义数据集 X, y = get_dataset() # 获取要评估的模型 模型 = 获取_模型() # 评估模型并存储结果 results, names = list(), list() for name, model in models.items(): scores = evaluate_model(model, X, y) results.append(scores) names.append(name) print('>%s %.3f (%.3f)' % (name, mean(scores), std(scores))) # 绘制模型性能以供比较 pyplot.boxplot(results, labels=names, showmeans=True) pyplot.show() |
运行示例首先报告每个特征数量的平均准确率。
在这种情况下,结果表明,在该数据集上,随机子空间集成使用大约一半的特征数量(例如 9 到 13 个)可能会获得最佳结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
>1 0.583 (0.047) >2 0.659 (0.048) >3 0.731 (0.038) >4 0.775 (0.045) >5 0.815 (0.044) >6 0.820 (0.040) >7 0.838 (0.034) >8 0.841 (0.035) >9 0.854 (0.036) >10 0.854 (0.041) >11 0.857 (0.034) >12 0.863 (0.035) >13 0.860 (0.043) >14 0.856 (0.038) >15 0.848 (0.043) >16 0.847 (0.042) >17 0.839 (0.046) >18 0.831 (0.044) >19 0.811 (0.043) >20 0.802 (0.048) |
为每个随机子空间大小的准确率分数分布创建了箱线图。
我们看到准确率随着特征数量的增加而普遍增加,直到大约 10 到 13 个特征时趋于平稳,然后性能在此之后呈现适度下降的趋势。

随机子空间集成特征数量与分类准确率的箱线图
随机补丁集成(Random Patches Ensemble)
随机补丁集成是 Bagging 的一个扩展,它涉及基于从训练数据集的行(样本)和列(特征)的随机子集中构建的数据集来拟合集成成员。
它不使用自助样本,可以被认为是一个结合了粘贴集成的随机样本和随机子空间集成的随机特征样本的集成。
我们研究了一个非常简单但有效的集成框架,该框架通过从整个数据集的实例和特征中抽取随机子集,从数据的随机补丁构建集成的每个单独模型。
— 随机补丁上的集成, 2012。
下面的示例演示了随机补丁集成,其中决策树由训练数据集的随机样本创建,限制为训练数据集大小的 50%,并具有 10 个随机特征子集。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# 评估随机补丁集成算法用于分类 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 # 定义数据集 X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=5) # 定义模型 model = BaggingClassifier(bootstrap=False, max_features=10, max_samples=0.5) # 评估模型 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') # 报告表现 print('Accuracy: %.3f (%.3f)' % (mean(n_scores), std(n_scores))) |
运行示例报告了模型的平均准确度和标准差。
注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。请考虑运行示例几次并比较平均结果。
在这种情况下,我们可以看到随机补丁集成在此数据集上实现了约 84% 的分类准确率。
1 |
准确率:0.845 (0.036) |
常见问题
在本节中,我们将更深入地探讨 Bagging 集成过程中您可能遇到的一些常见难点。
问:集成中应该使用什么算法?
该算法应具有适度方差,这意味着它适度依赖于特定的训练数据。
决策树是默认使用的模型,因为它在实践中效果很好。只要其他算法配置为具有适度方差,也可以使用。
所选择的算法应该适度稳定,不像决策桩那样不稳定,也不像剪枝决策树那样非常稳定,通常使用未剪枝的决策树。
…众所周知,Bagging 应该与不稳定的学习器一起使用,通常,学习器越不稳定,性能提升越大。
— 第 52 页,《集成方法》,2012。
问:应该使用多少个集成成员?
模型的性能将随着决策树数量的增加而收敛到某个点,然后保持不变。
… Bagging 的性能随着集成规模(即基础学习器数量)的增大而收敛…
— 第 52 页,《集成方法》,2012。
因此,请持续增加树的数量,直到模型性能在您的数据集上稳定下来。
问:集成树太多会不会过拟合?
不会。Bagging 集成(通常)不太可能过拟合。
问:自助样本应该有多大?
通常情况下,将自助样本大小设置为与原始数据集大小相同是很好的做法。
即 100% 的大小或与原始数据集行数相等。
问:哪些问题适合 Bagging?
通常,Bagging 适用于小型或中等大小数据集的问题。但这只是一个粗略的指导。
Bagging 最适合于训练数据集相对较小的问题。
— 第 12 页,《集成机器学习》,2012。
试试看吧。
进一步阅读
如果您想深入了解,本节提供了更多关于该主题的资源。
教程
论文
- Bagging 预测器, 1996.
- 在大型数据库和在线分类中粘贴小投票, 1999.
- 用于构建决策森林的随机子空间方法, 1998.
- 随机补丁上的集成, 2012.
API
文章
总结
在本教程中,您学习了如何开发用于分类和回归的 Bagging 集成算法。
具体来说,你学到了:
- Bagging 集成算法是一种由在数据集不同样本上训练的决策树创建的集成算法。
- 如何使用 scikit-learn 进行分类和回归的 Bagging 集成。
- 如何探索 Bagging 模型超参数对模型性能的影响。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
谢谢您的教程!!它们都很有价值:))
请问,我们不应该只在训练集上使用 fit 方法吗?为什么您在所有数据集(X,y)上使用它呢?
不客气。
是的,模型只在训练数据集上进行拟合。
为了澄清我的理解,您在“机器学习评估阶段”处理可用数据中的训练/测试集。但是,当考虑部署最佳算法(在前一“阶段”中找到)时,您会创建一个用所有可用数据训练的模型,并在事后评估新的/未见过的示例,对吗?
不太对。
我们使用类似交叉验证的方法来估计每个模型/管道的性能,然后选择一个。现在我们知道它在新数据上的平均表现如何。
然后我们用所有数据拟合这个模型并开始使用它。无需再次评估。
Breiman 在他的文章中提到了两种粘贴:Rvote 和 Ivote。
我假设您使用
bootstrap=False
和 'max_samples=0.5' 实现了 Ivote Pasting但我如何实现 Rvote Pasting 呢?
也许您可以根据自己的需要修改上面的示例。
嗨,Jason,
还可以使用 scores.mean() 和 scores.std() 来计算分数的平均值和标准差,而无需调用 numpy 的 mean 和 std 函数。
罗恩
是的,我通常会忘记这一点。感谢您的提醒!
谢谢您的教程。
我尝试对回归问题的样本数量进行超参数调优,但我遇到了这个错误:“支持的目标类型为:('binary', 'multiclass')。反而得到了 'continuous'。”
我不知道为什么,我正在使用 randomforestregressor 函数,当代码想要评估模型并从定义的字典中获取模型时,就会出现这个错误。
如果您能给我一些建议,我将不胜感激。
也许上述模型不支持回归。我预计就是这种情况。
嗨,为什么 n_informative=15 和 n_redundant=5 呢? 🙂
这些参数只是一个示例。您可能需要根据您的具体问题进行更改。
我们可以将随机森林作为 Bagging 分类器的参数吗?
是的,将“base_estimator=RandomForestClassifier()”添加到 BaggingClassier() 调用中即可实现。但这会非常慢,因为您现在需要拟合很多决策树。
您不需要对数据进行缩放来使用 KNN 吗?
是的,那样会更好,特别是当每个特征的量级不同时。