机器学习 - Bootstrap 聚合(Bagging)

Bagging

诸如决策树等方法容易在训练集上过度拟合,这可能导致对新数据的错误预测。

Bootstrap 聚合(bagging)是一种集成方法,旨在解决分类或回归问题中的过度拟合问题。Bagging 旨在提高机器学习算法的准确性和性能。它通过从原始数据集中随机抽取(有放回地)子集,并对每个子集拟合一个分类器(用于分类)或回归器(用于回归)来实现这一点。然后通过多数投票(用于分类)或平均(用于回归)来聚合每个子集的预测,从而提高预测准确性。

评估基本分类器

为了了解 bagging 如何改进模型性能,我们首先必须评估基本分类器在数据集上的表现。如果您不知道什么是决策树,请在继续之前回顾决策树课程,因为 bagging 是该概念的一个延续。

我们将尝试识别 sklearn 的葡萄酒数据集中发现的不同类别的葡萄酒。

让我们首先导入必要的模块。

from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.tree import DecisionTreeClassifier

接下来,我们需要加载数据并将其存储到 X(输入特征)和 y(目标)中。参数 as_frame 设置为 True,以便在加载数据时不会丢失特征名称。(如果 sklearn 版本低于 0.23,则必须跳过 as_frame 参数,因为它不受支持)

data = datasets.load_wine(as_frame = True)

X = data.data
y = data.target

为了正确评估模型在未见数据上的表现,我们需要将 X 和 y 分割为训练集和测试集。有关数据分割的信息,请参阅“训练/测试”课程。

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.25, random_state = 22)

准备好数据后,我们现在可以实例化一个基本分类器并将其拟合到训练数据上。

dtree = DecisionTreeClassifier(random_state = 22)
dtree.fit(X_train,y_train)

结果:

DecisionTreeClassifier(random_state=22)

我们现在可以预测未见测试集中葡萄酒的类别并评估模型性能。

y_pred = dtree.predict(X_test)

print("训练数据准确性:",accuracy_score(y_true = y_train, y_pred = dtree.predict(X_train)))
print("测试数据准确性:",accuracy_score(y_true = y_test, y_pred = y_pred))

结果:

Train data accuracy: 1.0
Test data accuracy: 0.8222222222222222

实例

导入必要的数据并评估基本分类器性能。

from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.tree import DecisionTreeClassifier

data = datasets.load_wine(as_frame = True)

X = data.data
y = data.target

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.25, random_state = 22)

dtree = DecisionTreeClassifier(random_state = 22)
dtree.fit(X_train,y_train)

y_pred = dtree.predict(X_test)

print("训练数据准确性:",accuracy_score(y_true = y_train, y_pred = dtree.predict(X_train)))
print("测试数据准确性:",accuracy_score(y_true = y_test, y_pred = y_pred))

亲自试一试

使用当前参数,基本分类器在数据集上的表现相当不错,测试数据集上的准确率达到 82%(如果您没有设置 random_state 参数,则可能会出现不同的结果)。

既然我们有了测试数据集的基线准确性,我们就可以看到 Bagging 分类器如何优于单个决策树分类器。

创建 Bagging 分类器

对于 bagging,我们需要设置参数 n_estimators,这是我们的模型将要聚合的基本分类器的数量。

对于这个样本数据集,估计器的数量相对较低,通常探索的范围要大得多。超参数调整通常使用网格搜索进行,但现在我们将使用估计器数量的选定集合值。

我们首先从导入必要的模型开始。

from sklearn.ensemble import BaggingClassifier

现在让我们创建一个表示要在每个集成中使用的估计器数量的值范围。

estimator_range = [2,4,6,8,10,12,14,16]

为了查看 Bagging 分类器在不同 n_estimators 值下的表现,我们需要一种方法来迭代值范围并存储每个集成的结果。为此,我们将创建一个 for 循环,将模型和分数分别存储在单独的列表中,以便稍后可视化。

注意:BaggingClassifier 中基本分类器的默认参数是 DicisionTreeClassifier,因此我们在实例化 bagging 模型时不需要设置它。

models = []
scores = []

for n_estimators in estimator_range:

    # 创建 bagging 分类器
    clf = BaggingClassifier(n_estimators = n_estimators, random_state = 22)

    # 拟合模型
    clf.fit(X_train, y_train)

    # 将模型和分数追加到各自的列表中
    models.append(clf)
    scores.append(accuracy_score(y_true = y_test, y_pred = clf.predict(X_test)))

模型和分数存储完毕后,我们现在可以可视化模型性能的改进。

import matplotlib.pyplot as plt

# 生成估计器数量与得分的图
plt.figure(figsize=(9,6))
plt.plot(estimator_range, scores)

# 调整标签和字体大小(以便可见)
plt.xlabel("n_estimators", fontsize = 18)
plt.ylabel("score", fontsize = 18)
plt.tick_params(labelsize = 16)

# 可视化图表
plt.show()

实例

导入必要的数据并评估 BaggingClassifier 性能。

import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.ensemble import BaggingClassifier

data = datasets.load_wine(as_frame = True)

X = data.data
y = data.target

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.25, random_state = 22)

estimator_range = [2,4,6,8,10,12,14,16]

models = []
scores = []

for n_estimators in estimator_range:

    # 创建 bagging 分类器
    clf = BaggingClassifier(n_estimators = n_estimators, random_state = 22)

    # 拟合模型
    clf.fit(X_train, y_train)

    # 将模型和分数追加到各自的列表中
    models.append(clf)
    scores.append(accuracy_score(y_true = y_test, y_pred = clf.predict(X_test)))

# 生成估计器数量与得分的图
plt.figure(figsize=(9,6))
plt.plot(estimator_range, scores)

# 调整标签和字体大小(以便可见)
plt.xlabel("n_estimators", fontsize = 18)
plt.ylabel("score", fontsize = 18)
plt.tick_params(labelsize = 16)

# 可视化图表
plt.show()

亲自试一试

结果:

结果解释

通过迭代估计器数量的不同值,我们可以看到模型性能从 82.2% 提高到 95.5%。在 14 个估计器之后,准确性开始下降,再次提醒,如果您设置了不同的 random_state,您看到的值将会有所不同。这就是为什么使用交叉验证来确保稳定结果的最佳做法。

在这种情况下,我们看到在识别葡萄酒类型方面,准确性提高了 13.3%。

另一种评估形式

由于引导程序选择观测值的随机子集来创建分类器,因此在选择过程中会留下一些“袋外”观测值。然后可以使用这些“袋外”观测值来评估模型,类似于测试集。请注意,袋外估计可能会高估二元分类问题的误差,并且仅应作为其他指标的补充。

在上一个练习中,我们看到 12 个估计器产生了最高的准确性,因此我们将使用它来创建模型。这次设置参数 oob_scoretrue,以使用袋外得分评估模型。

实例

使用袋外指标创建模型。

from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.ensemble import BaggingClassifier

data = datasets.load_wine(as_frame = True)

X = data.data
y = data.target

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.25, random_state = 22)

oob_model = BaggingClassifier(n_estimators = 12, oob_score = True,random_state = 22)

oob_model.fit(X_train, y_train)

print(oob_model.oob_score_)

亲自试一试

由于 OOB 和测试集中使用的样本不同,并且数据集相对较小,因此在准确性方面存在差异。OOB 和测试集的准确率完全相同的情况很少见,OOB 应再次用作估算错误的快速方法,但它不是唯一的评估指标。

从 Bagging 分类器中生成决策树

正如在决策树课程中所看到的,我们可以绘制出模型创建的决策树图形。我们还可以看到聚合分类器中使用的各个决策树。这有助于我们更直观地了解 bagging 模型如何得出其预测。

注意:这只适用于较小的数据集,其中的树相对较浅且较窄,因此易于可视化。

我们需要从 sklearn.tree 导入 plot_tree 函数。可以通过更改要可视化的估计器来绘制不同的树形图。

实例

从 Bagging 分类器中生成决策树:

from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.ensemble import BaggingClassifier
from sklearn.tree import plot_tree

X = data.data
y = data.target

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.25, random_state = 22)

clf = BaggingClassifier(n_estimators = 12, oob_score = True,random_state = 22)

clf.fit(X_train, y_train)

plt.figure(figsize=(30, 20))

plot_tree(clf.estimators_[0], feature_names = X.columns)

亲自试一试

结果:

在这里,我们只能看到用于对最终预测进行投票的第一个决策树。同样,通过更改分类器的索引,您可以看到已聚合的每个树。