勾配ブースティングの正則化

Beginner

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

はじめに

この実験では、scikit-learn を使って勾配ブースティングに対してさまざまな正則化戦略を実装する方法を学びます。正則化は、機械学習モデルにおいて一般的な問題である過学習を防ぐための手法です。この実験では、二項偏差損失関数と make_hastie_10_2 データセットを使用します。

VM のヒント

VM の起動が完了したら、左上隅をクリックして ノートブック タブに切り替え、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 [
    ("No shrinkage", "orange", {"learning_rate": 1.0, "subsample": 1.0}),
    ("learning_rate=0.2", "turquoise", {"learning_rate": 0.2, "subsample": 1.0}),
    ("subsample=0.5", "blue", {"learning_rate": 1.0, "subsample": 0.5}),
    (
        "learning_rate=0.2, subsample=0.5",
        "gray",
        {"learning_rate": 0.2, "subsample": 0.5},
    ),
    (
        "learning_rate=0.2, max_features=2",
        "magenta",
        {"learning_rate": 0.2, "max_features": 2},
    ),
]:
    params = dict(original_params)
    params.update(setting)

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

    ## compute test set deviance
    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("Boosting Iterations")
plt.ylabel("Test Set Deviance")

plt.show()

まとめ

この実験では、scikit-learn を使って勾配ブースティングに対するさまざまな正則化戦略をどのように実装するか学びました。二項分布の乖離損失関数と make_hastie_10_2 データセットを使用しました。シュリンクレッジなし、学習率 = 0.2、サブサンプリング = 0.5、最大特徴数 = 2 など、さまざまな正則化戦略を実装しました。最後に、各正則化戦略に対するテストセットの乖離度をプロットして、それらの性能を比較しました。