XGBoost:学習曲線と検証曲線
概要
学習曲線とは学習の進行過程を数量的にプロットしたもの。DeepLearning等の 勾配法を利用した機械学習アルゴリズムを利用する際に、ステップ数毎の評価をするために使われる。同様に、検証データに対しては検証曲線(validation curve)と言われる。そこで、XGBoostでクロスバリデーションデータに対するcross validation curveをプロットしてみたいと考えた。しかし、調べてみても記事があまりなかったので実装してみる。
環境
macOS Mojave 10.14.5
python 3.7.4
xgboost 0.90
データ、モデルの準備
モデルはデフォルトのパラメータを使う。xgboost v.0.90ではデフォルトでobjective='reg:linear'
になっているが、v.1.00では代わりにobjective='reg:squarederror'
になっている。そのため、そのままで実行するとwarningがうるさいのでobjective
のみパラメータをセットする。v.1.00以降の人は何もしなくていいだろう。データはボストンの価格予測を使う。
from sklearn import datasets from sklearn.model_selection import train_test_split, KFold data = datasets.load_boston() #split train, test x_train, x_test, y_train, y_test = train_test_split(data['data'], data['target'], test_size=0.2, random_state=0) #create model params = {'objective': 'reg:squarederror'} model = xgb.XGBRegressor() model.set_params(**params)
クロスバリデーション
sklearnのKFoldを使って5 fold cross validationを行う。学習の際にeval_set
を指定するとステップ毎の評価を.evals_result()
で取り出せるようになる。それらの値を平均する。
#cross validation kf = KFold(n_splits=5, shuffle=False, random_state=0) eval_metric = 'rmse' evals_li = [] for i_train, i_test in kf.split(x_train): x_cv_train = x_train[i_train] y_cv_train = y_train[i_train] x_cv_test = x_train[i_test] y_cv_test = y_train[i_test] eval_set = [(x_cv_test, y_cv_test)] model.fit(x_cv_train, y_cv_train, eval_set=eval_set, eval_metric=eval_metric, verbose=False) evals_result = model.evals_result() evals_li.append(evals_result) result = np.zeros(100) for i in range(5): result += evals_li[i]['validation_0'][eval_metric] ave_cv_evals = result/5
学習と予測
先ほどと同様にしてeval_set
を指定する。今度はクロスバリデーションをしないで全ての訓練データで学習し評価する。
eval_set = [(x_train, y_train), (x_test, y_test)] model.fit(x_train, y_train, eval_set=eval_set, eval_metric=my_cv_score, verbose=False) evals_result = model.evals_result() train_evals = evals_result['validation_0'][eval_metric] test_evals = evals_result['validation_1'][eval_metric]
プロット
learning curve, cross validation curveとついでにテストデータに対してもプロットしてみた。
import matplotlib.pyplot as plt plt.figure(figsize=(10, 6)) plt.subplot(111) x = range(len(train_evals)) plt.plot(x, train_evals, label='train') plt.plot(x, test_evals, label='test') plt.plot(x, ave_cv_evals, label='validation') plt.grid() plt.legend() plt.show()
評価関数の作成
上記コードではeval_metric='rmse'
としたが、評価指標はrmse以外にもrmsle, mae, loglossなどがある。詳しくは公式を参照。しかし、使いたい評価関数がないときもあるため、今回自作してみた。ピアソンの相関係数で評価してみる。
from scipy.stats import peasonr def my_cv_score(y_pred, d_matrix_data): y_data = d_matrix_data.get_label() r, p = pearsonr(y_pred, y_data) return 'my_score', r
あとは、eval_metric='my_score'
とし、model.fit()
のeval_metric
にmy_score
関数をしてしてあげればよい。
#cross validation eval_metric = 'my_score' evals_li = [] for i_train, i_test in kf.split(x_train): x_cv_train = x_train[i_train] y_cv_train = y_train[i_train] x_cv_test = x_train[i_test] y_cv_test = y_train[i_test] eval_set = [(x_cv_test, y_cv_test)] model.fit(x_cv_train, y_cv_train, eval_set=eval_set, eval_metric=my_score, verbose=False) evals_result = model.evals_result() evals_li.append(evals_result) result = np.zeros(100) for i in range(5): result += evals_li[i]['validation_0'][eval_metric] ave_cv_evals = result/5 #training eval_set = [(x_train, y_train), (x_test, y_test)] model.fit(x_train, y_train, eval_set=eval_set, eval_metric=my_score, verbose=False) evals_result = model.evals_result() train_evals = evals_result['validation_0'][eval_metric] test_evals = evals_result['validation_1'][eval_metric] #plot evals import matplotlib.pyplot as plt plt.figure(figsize=(10, 6)) plt.subplot(111) x = range(len(train_evals)) plt.plot(x, train_evals, label='train') plt.plot(x, test_evals, label='test') plt.plot(x, ave_cv_evals, label='validation') plt.grid() plt.legend() plt.show()