梯度提升的早期停止

Beginner

This tutorial is from open-source community. Access the source code

简介

梯度提升(Gradient boosting)是一种集成技术,其中多个弱学习器(回归树)以迭代方式组合在一起,形成一个强大的单一模型。梯度提升中的早期停止支持使我们能够找到最少的迭代次数,这足以构建一个能够很好地泛化到未见数据的模型。

虚拟机使用提示

虚拟机启动完成后,点击左上角切换到“笔记本”标签,以访问 Jupyter Notebook 进行练习。

有时,你可能需要等待几秒钟让 Jupyter Notebook 完成加载。由于 Jupyter Notebook 的限制,操作验证无法自动化。

如果你在学习过程中遇到问题,随时向 Labby 提问。课程结束后提供反馈,我们将立即为你解决问题。

加载所需的库和数据

首先,我们需要加载所需的库和数据。我们将使用 scikit-learn 库来实现梯度提升。

import time
import numpy as np
import matplotlib.pyplot as plt
from sklearn import ensemble
from sklearn import datasets
from sklearn.model_selection import train_test_split

data_list = [
    datasets.load_iris(return_X_y=True),
    datasets.make_classification(n_samples=800, random_state=0),
    datasets.make_hastie_10_2(n_samples=2000, random_state=0),
]
names = ["Iris Data", "Classification Data", "Hastie Data"]
n_estimators = 200

准备数据

接下来,我们将通过将数据拆分为训练集和测试集来准备数据。

for X, y in data_list:
    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=0.2, random_state=0
    )

不使用早期停止构建并训练模型

现在我们将构建并训练一个不使用早期停止的梯度提升模型。

gb = ensemble.GradientBoostingClassifier(n_estimators=n_estimators, random_state=0)
start = time.time()
gb.fit(X_train, y_train)
time_gb.append(time.time() - start)

使用早期停止构建并训练模型

现在我们将构建并训练一个使用早期停止的梯度提升模型。我们指定一个validation_fraction(验证分数),它表示从整个数据集中留出用于评估模型验证损失的部分。梯度提升模型使用训练集进行训练,并使用验证集进行评估。当添加回归树的每个额外阶段时,使用验证集对模型进行评分。这个过程会一直持续,直到模型在最后n_iter_no_change个阶段的分数至少没有提高tol。在此之后,模型被认为已经收敛,并且进一步添加阶段被“提前停止”。最终模型的阶段数可以在属性n_estimators中获得。

gbes = ensemble.GradientBoostingClassifier(
        n_estimators=n_estimators,
        validation_fraction=0.2,
        n_iter_no_change=5,
        tol=0.01,
        random_state=0,
    )
start = time.time()
gbes.fit(X_train, y_train)
time_gbes.append(time.time() - start)

比较有无早期停止时的分数

现在我们将比较这两个模型的分数。

score_gb.append(gb.score(X_test, y_test))
score_gbes.append(gbes.score(X_test, y_test))

比较有无早期停止时的拟合时间

现在我们将比较这两个模型的拟合时间。

plt.figure(figsize=(9, 5))

bar1 = plt.bar(
    index, time_gb, bar_width, label="Without early stopping", color="crimson"
)
bar2 = plt.bar(
    index + bar_width, time_gbes, bar_width, label="With early stopping", color="coral"
)

max_y = np.amax(np.maximum(time_gb, time_gbes))

plt.xticks(index + bar_width, names)
plt.yticks(np.linspace(0, 1.3 * max_y, 13))

autolabel(bar1, n_gb)
autolabel(bar2, n_gbes)

plt.ylim([0, 1.3 * max_y])
plt.legend(loc="best")
plt.grid(True)

plt.xlabel("Datasets")
plt.ylabel("Fit Time")

plt.show()

比较有无早期停止时的分数

我们现在将比较这两个模型的分数。

plt.figure(figsize=(9, 5))

bar1 = plt.bar(
    index, score_gb, bar_width, label="Without early stopping", color="crimson"
)
bar2 = plt.bar(
    index + bar_width, score_gbes, bar_width, label="With early stopping", color="coral"
)

plt.xticks(index + bar_width, names)
plt.yticks(np.arange(0, 1.3, 0.1))

autolabel(bar1, n_gb)
autolabel(bar2, n_gbes)

plt.ylim([0, 1.3])
plt.legend(loc="best")
plt.grid(True)

plt.xlabel("Datasets")
plt.ylabel("Test score")

plt.show()

总结

在这个实验中,我们学习了梯度提升中的早期停止,它使我们能够找到构建一个能很好地推广到未见数据的模型所需的最少迭代次数。我们比较了有早期停止和没有早期停止的梯度提升模型的性能,并且观察到早期停止可以显著减少训练时间、内存使用和预测延迟。