scikit-optimize の BayesSearchCV を用いたベイズ最適化によるハイパーパラメータ探索
ベイズ最適化でハイパーパラメータをチューニングする
ハイパーパラメータのチューニングではパラメータを様々に振りながら学習を繰り返し、一番パフォーマンスが良いところを探し出します。 学習時間はモデルやデータサイズなどによって異なりますが、効率よく探索するかしないかで良いパラメータを得るまでの時間が大きく変わります。 探索方法には様々あり、基本的なところではグリッドサーチ(全探索)、ランダムサーチ(ランダム探索)があります。
今回紹介するものは、ベイズ最適化の手法を用いて効率よく探索する枠組みです *1 。
BayesSearchCV
ここで紹介するのは CrossValidation で汎化精度を確かめながら、ハイパーパラメータを探索する scikit-optimize の BayesSearchCV です。
https://scikit-optimize.github.io/#skopt.BayesSearchCV
ハイパーパラメータの汎化精度は交差検証でわかります(*2)。 そのため、交差検証で汎化精度を見ながら最適なハイパーパラメータを探索します。
手順で言うと次のようになります。
- ハイパーパラメータをランダムにピックアップする.
- 交差検証で精度を見る
- ベイズ最適化で次に探索するハイパーパラメータを定める(→2 へ)
これを全部やってくれるのが BayesSearchCV で、以下がサンプルコードとなります。
サンプル実装
#!/usr/bin/env python # -*- coding: utf-8 -*- import sys import os import numpy as np import scipy as sp import pandas as pd from skopt import BayesSearchCV from skopt.space import Real, Categorical, Integer from sklearn.model_selection import train_test_split import xgboost as xgb # データセットを読み込み from sklearn.datasets import load_breast_cancer X, y = load_breast_cancer(return_X_y=True) X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.75, random_state=0) estimator = xgb.XGBClassifier( booster='gbtree', silent=True, objective='binary:logistic', base_score=0.5, eval_metric='auc', n_jobs=-1 ) # パラメータ探索範囲設定 # 探索範囲 min,max,distribution を space クラスでで指定(min, max,(distribution)) from skopt.space import Real, Categorical, Integer param_grid = { 'n_estimators': Integer(1, 4), 'learning_rate': Real(0.01, 0.5, 'log-uniform'), 'max_depth': Integer(0, 3) } # 参考 # https://www.kaggle.com/shaz13/santander-xgboost-bayesian-optimization/code # https://www.kaggle.com/nanomathias/bayesian-optimization-of-xgboost-lb-0-9769 # ''' GridSearchCV 系と比べた固有の API(一部) - search_spaces : パラメータ探索範囲設定 - optimizer_kwargs : 最適化パラメータ。探索戦略やガウス過程パラメータなど。- - fit_params : clf.fit(X, y) に設定するパラメータ。学習実行時のパラメータ指定. ''' clf = BayesSearchCV( estimator=estimator, search_spaces=param_grid, scoring='roc_auc', cv=3, n_jobs=-1, n_iter=10, verbose=1, refit=True ) def status_print(optim_result): ''' ベイズ最適化のイテレーションで呼ばれるコールバック ''' results = pd.DataFrame(clf.cv_results_) new_params = results.tail(1).params.values[0] new_score = results.tail(1).mean_test_score print('Model #%d/%d : ROC-AUC(newest/best) = %.4f / %.4f' % ( len(results), clf.n_iter, new_score, clf.best_score_ )) # BayesSearchCV は sklearn の他の交差検証サーチ系クラス(RandomSearchCVなど)と同じAPIを持っています clf.fit(X, y, callback=status_print) print(pd.DataFrame(clf.cv_results_)) # 検証データのパフォーマンス print(clf.score(X_test, y_test))
探索の結果は clf.cv_resuts_ フィールドに格納されていて、pd.DataFrame にすると以下のようなデータとなっています。 この中には以下のデータが入っています(一部分列挙)。
- param_* は探索パラメータ
- mean_test_score は交差検証スコアの平均
- split{n}_test_score は交差検証の各分割でのスコア(これらを平均したものが mean_test_score)
- std_test_score は交差検証スコアの偏差
mean_fit_time | mean_score_time | mean_test_score | split0_test_score | split1_test_score | split2_test_score | std_fit_time | std_score_time | std_test_score | param_colsample_bylevel | param_colsample_bytree | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0.005673011 | 0.00219202 | 0.832636822 | 0.827494378 | 8.28E-01 | 0.842857143 | 0.000176986 | 0.00030934 | 0.007207978 | 0.432490483 | 0.101987568 |
1 | 0.005337397 | 0.002478361 | 0.5 | 0.5 | 0.5 | 0.5 | 0.000566812 | 0.000611297 | 0 | 0.45403928 | 0.928587396 |
2 | 0.005687555 | 0.002456427 | 0.5 | 5.00E-01 | 0.5 | 0.5 | 0.000361052 | 6.48E-05 | 0 | 0.471067626 | 0.880029631 |
3 | 0.005241315 | 0.00255092 | 0.5 | 5.00E-01 | 0.5 | 0.5 | 0.000284118 | 0.000263844 | 0 | 0.24114647 | 0.786112636 |
4 | 0.006174246 | 0.002198935 | 0.834788739 | 7.56E-01 | 0.832465381 | 0.915966387 | 0.000542449 | 0.000200357 | 0.065150251 | 0.699309626 | 0.752064985 |
5 | 0.007870754 | 0.002580643 | 0.5 | 0.5 | 0.5 | 0.5 | 0.000749173 | 0.000241813 | 0 | 0.932821363 | 0.339574308 |
6 | 0.004701535 | 0.00221777 | 0.5 | 0.5 | 0.5 | 0.5 | 0.000507002 | 0.000167713 | 0 | 0.818819988 | 0.79140138 |
7 | 0.004785299 | 0.002165318 | 0.5 | 0.5 | 5.00E-01 | 0.5 | 0.000287597 | 0.000235932 | 0 | 0.999741524 | 0.381359767 |
8 | 0.005346219 | 0.002468665 | 0.5 | 5.00E-01 | 0.5 | 0.5 | 0.000562654 | 0.000213206 | 0 | 0.55477075 | 0.31067584 |
9 | 0.005452951 | 0.00238506 | 0.5 | 5.00E-01 | 0.5 | 0.5 | 0.000326225 | 0.000221597 | 0 | 0.586112963 | 0.589381284 |
ベイズ最適化探索で得られた最適な結果は次のフィールドに格納されます。
- best_estimator_ : 最適なモデル
- best_params_ : 最適なハイパーパラメータ
- best_index : cv_results の最適なパラメータのインデックス
- best_score : 最適なモデルのスコア
まとめ
scikit-optimize の BayesSearchCV を用いて、ベイズ最適化によるハイパーパラメータ探索を試してみましたが、scikit-learn の RandomSearchCV や GridSearchCV と同じ使い方で、簡単にベイズ最適化を使えることがわかりました。
探索戦略のパラメータなどについては今後調べてみようと思います。