梯度提升正则化

Beginner

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

简介

在本实验中,你将学习如何使用 scikit-learn 为梯度提升实现不同的正则化策略。正则化是一种有助于防止过拟合的技术,过拟合是机器学习模型中常见的问题。本实验我们将使用二项偏差损失函数和 make_hastie_10_2 数据集。

虚拟机使用小贴士

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

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

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

导入库

让我们先导入必要的库。

import numpy as np
import matplotlib.pyplot as plt

from sklearn import ensemble
from sklearn import datasets
from sklearn.metrics import log_loss
from sklearn.model_selection import train_test_split

加载并分割数据

我们将使用 make_hastie_10_2 数据集,并将其分割为训练集和测试集。

X, y = datasets.make_hastie_10_2(n_samples=4000, random_state=1)

## map labels from {-1, 1} to {0, 1}
labels, y = np.unique(y, return_inverse=True)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.8, random_state=0)

定义参数

我们将为梯度提升分类器定义参数。我们将使用以下参数:

  • n_estimators:要执行的提升阶段数
  • max_leaf_nodes:每棵树中最大的叶节点数
  • max_depth:树的最大深度
  • random_state:用于一致性的随机种子
  • min_samples_split:拆分内部节点所需的最小样本数
original_params = {
    "n_estimators": 400,
    "max_leaf_nodes": 4,
    "max_depth": None,
    "random_state": 2,
    "min_samples_split": 5,
}

实施正则化策略

我们现在将实施不同的正则化策略并比较它们的性能。

无收缩

我们将从无收缩开始,这意味着学习率将设置为 1。

params = dict(original_params)
params.update({"learning_rate": 1.0, "subsample": 1.0})

clf = ensemble.GradientBoostingClassifier(**params)
clf.fit(X_train, y_train)
学习率 = 0.2

接下来,我们将学习率设置为 0.2,子采样设置为 1。

params = dict(original_params)
params.update({"learning_rate": 0.2, "subsample": 1.0})

clf = ensemble.GradientBoostingClassifier(**params)
clf.fit(X_train, y_train)
子采样 = 0.5

我们现在将子采样设置为 0.5,学习率设置为 1。

params = dict(original_params)
params.update({"learning_rate": 1.0, "subsample": 0.5})

clf = ensemble.GradientBoostingClassifier(**params)
clf.fit(X_train, y_train)
学习率 = 0.2 且 子采样 = 0.5

接下来,我们将学习率设置为 0.2,子采样设置为 0.5。

params = dict(original_params)
params.update({"learning_rate": 0.2, "subsample": 0.5})

clf = ensemble.GradientBoostingClassifier(**params)
clf.fit(X_train, y_train)
学习率 = 0.2 且 最大特征数 = 2

最后,我们将学习率设置为 0.2,并且每棵树仅使用 2 个特征。

params = dict(original_params)
params.update({"learning_rate": 0.2, "max_features": 2})

clf = ensemble.GradientBoostingClassifier(**params)
clf.fit(X_train, y_train)

绘制测试集偏差

我们现在将为每种正则化策略绘制测试集偏差。

plt.figure()

for label, color, setting in [
    ("无收缩", "橙色", {"learning_rate": 1.0, "subsample": 1.0}),
    ("learning_rate=0.2", "青绿色", {"learning_rate": 0.2, "subsample": 1.0}),
    ("subsample=0.5", "蓝色", {"learning_rate": 1.0, "subsample": 0.5}),
    (
        "learning_rate=0.2, subsample=0.5",
        "灰色",
        {"learning_rate": 0.2, "subsample": 0.5}
    ),
    (
        "learning_rate=0.2, max_features=2",
        "品红色",
        {"learning_rate": 0.2, "max_features": 2}
    )
]:
    params = dict(original_params)
    params.update(setting)

    clf = ensemble.GradientBoostingClassifier(**params)
    clf.fit(X_train, y_train)

    ## 计算测试集偏差
    test_deviance = np.zeros((params["n_estimators"],), dtype=np.float64)

    for i, y_proba in enumerate(clf.staged_predict_proba(X_test)):
        test_deviance[i] = 2 * log_loss(y_test, y_proba[:, 1])

    plt.plot(
        (np.arange(test_deviance.shape[0]) + 1)[::5],
        test_deviance[::5],
        "-",
        color=color,
        label=label
    )

plt.legend(loc="upper right")
plt.xlabel("提升迭代次数")
plt.ylabel("测试集偏差")

plt.show()

总结

在本实验中,我们学习了如何使用 scikit-learn 为梯度提升实现不同的正则化策略。我们使用了二项偏差损失函数和 make_hastie_10_2 数据集。我们实现了不同的正则化策略,如无收缩、学习率 = 0.2、子采样 = 0.5 以及最大特征数 = 2。最后,我们为每种正则化策略绘制了测试集偏差,以比较它们的性能。