どこにでもいる30代SEの学習ブログ

主にプログラミング関連の学習内容。読んだ本の感想や株式投資についても書いてます。

【機械学習】xgboostでグリッドサーチ(GridSearchCV)

f:id:predora005:20200921203514p:plain
<xgboostでグリッドサーチ(GridSearchCV)>*1

※ 2020/04/09にQrunchで書いた記事を移行しました。

scikit-learnのGridSearchCVを利用して、グリッドサーチを行いました。 xgboostにはscikit-learnのWrapperが用意されているため、scikit-learnを使ったことがある人であれば、違和感なく使うことが出来ます。

使い方

データの読み込み等を除いたソースは以下の通りです。

import xgboost as xgb
from sklearn.model_selection import StratifiedKFold, GridSearchCV

# サーチするパラメータをセット
params = {'eta': [0.01, 0.1, 1.0], 'gamma': [0, 0.1], 
                  'n_estimators': [10, 100], 'max_depth':[2, 4], 
                  'min_child_weigh': [1, 2], 'nthread': [2] }

# クラス分類用のモデルを作成
model = xgb.XGBClassifier()

# StratifiedKFoldでグリッドサーチ
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=1)
clf = GridSearchCV(estimator=model, param_grid=params, 
                    cv=skf, scoring="accuracy", n_jobs=1, verbose=3)
clf.fit(train_x, train_y)

GridSearchCV()がグリッドサーチのオブジェクトを作成している部分でclf.fit()で実行します。 各パラメータ(引数)の意味は次の通りです。

パラメータ(引数) 内容
estimator モデル
param_griddict サーチするパラメータ
cv クロスバリデーションの分割方法(※1)
scoring 評価指標("accuracy", "neg_mean_squared_error"等) (※2)
n_jobs 並行して実行するジョブの数。
verbose 冗長性(サーチ中のメッセージ表示の種類) (※3)

cv (※1)

設定できるパラメータは次の通りです。 - None: 自動で5 foldのクロスバリデーションになる - 整数値:指定した分割数のKFoldになる(分類の場合はStratified KFold) - CV splitter (KFoldオブジェクト等) - インデックスのリスト

scoring (※2)

公式に一覧が載っています。

3.3. Metrics and scoring: quantifying the quality of predictions — scikit-learn 0.22.2 documentation

verbose (※3)

公式に正確な情報はありませんが、 3はテスト毎にパラメータ・スコア・経過時間を表示、 2はテスト毎にパラメータ・経過時間を表示、 1はサーチの開始と終了、 0は表示しない。

ソースコード

データはscikit-learnのdatasetより、load_breast_cancerを使用しました。

[1] データ読み込みと分割

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split

# 乳がんの診断結果データ
cancer = load_breast_cancer()
cancer_data = pd.DataFrame(cancer.data, columns=cancer.feature_names)
cancer_target = pd.Series(cancer.target)

# 80%を学習用、20%をテスト用に使用する。
train_x, test_x, train_y, test_y = \
        train_test_split(cancer_data, cancer_target, test_size=0.2, shuffle=True)

[2] グリッドサーチ

import xgboost as xgb
from sklearn.model_selection import StratifiedKFold, GridSearchCV

# サーチするパラメータをセット
params = {'eta': [0.01, 0.1, 1.0], 'gamma': [0, 0.1], 
                  'n_estimators': [10, 100], 'max_depth':[2, 4], 
                  'min_child_weigh': [1, 2], 'nthread': [2] }

# クラス分類用のモデルを作成
model = xgb.XGBClassifier()

# StratifiedKFoldでグリッドサーチ
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=1)
clf = GridSearchCV(estimator=model, param_grid=params, 
                    cv=skf, scoring="accuracy", n_jobs=1, verbose=3)
clf.fit(train_x, train_y)

[3] グリッドサーチの結果を表示

import pandas as pd

# 各パラメータのスコア・標準偏差をDataFrame化
means = clf.cv_results_['mean_test_score']
stds = clf.cv_results_['std_test_score']
params = clf.cv_results_['params']
df = pd.DataFrame(data=zip(means, stds, params), columns=['mean', 'std', 'params'])

# スコアの降順に並び替え
df = df.sort_values('std', ascending=True)
df = df.sort_values('mean', ascending=False)

# スコア・標準偏差・パラメータを表示
for index, row in df.iterrows():
    print("score: %.3f +/-%.4f, params: %r" % 
          (row['mean'], row['std']*2, row['params']))
# score: 0.963 +/-0.0431, params: {'eta': 1.0, 'gamma': 0, 'max_depth': 4, 'min_child_weigh': 1, 'n_estimators': 100, 'nthread': 2}
# score: 0.963 +/-0.0431, params: {'eta': 1.0, 'gamma': 0, 'max_depth': 4, 'min_child_weigh': 2, 'n_estimators': 100, 'nthread': 2}
# score: 0.960 +/-0.0531, params: {'eta': 0.1, 'gamma': 0, 'max_depth': 4, 'min_child_weigh': 2, 'n_estimators': 100, 'nthread': 2}
# score: 0.960 +/-0.0531, params: {'eta': 0.1, 'gamma': 0, 'max_depth': 4, 'min_child_weigh': 1, 'n_estimators': 100, 'nthread': 2}
# score: 0.956 +/-0.0501, params: {'eta': 0.1, 'gamma': 0.1, 'max_depth': 4, 'min_child_weigh': 2, 'n_estimators': 100, 'nthread': 2}
# 〜〜〜 (以下省略) 〜〜〜

[4] 最良のパラメータを取得

print("Best score: %.4f" % (clf.best_score_))
print(clf.best_params_)
# Best score: 0.9626
# {'eta': 1.0, 'gamma': 0, 'max_depth': 4, 'min_child_weigh': 1, 'n_estimators': 100, 'nthread': 2}

model = clf.best_estimator_
pred = model.predict(test_x)
score = accuracy_score(test_y, pred)
print('score:{0:.4f}'.format(score))
# Score:0.9561

参考資料

sklearn.model_selection.GridSearchCV — scikit-learn 0.22.2 documentation

*1:Darwin LaganzonによるPixabayからの画像