はじめに
東京23区の賃料を予測する回帰モデルをXGboostで作成しています。
モデルを作成するときにパラメータのチューニングで苦戦して色々と調べたので、この記事にまとめます。
機械学習に関して特別知識があるわけではないため、間違いを含んでいるかもしれません。その際はコメント欄で指摘していただけると助かります。
チューニングの方法として有名なものでグリッドサーチやベイズの最適化という手法があるのですが、精度や即効性の観点から今回はOptunaというハイパラメータ最適化ツールを利用して最適化してみました。
Optunaはベイズ最適化アルゴリズムの一種を利用したハイパーパラメータチューニングのフレームワークです
チューニングすべきとされるハイパラメータ
そもそもどの値をチューニングすべきなのか?
XGboostのモデル作成においてチューニングすべきとされるハイパラメータの一覧です。
パラメータ | デフォルト | 内容 | よく取る値 |
---|---|---|---|
eta | 0.3 | 学習率を調整。小さくするとより頑健になる | 0.01~0.2 |
max_depth | 6 | 木の深さの最大値。過学習を制御する。 | 3,4,5, ... 10 |
min_child_weight | 1 | 子ノードにおいて観察されるデータの重み付けの合計値の最小の値 | |
subsample | 1 | 各木においてランダムに抽出される列の割合 | 0.5~1 |
colsample_bytree | 1 | 各レベル単位での、分割における列のsubsample比率 | 0.5~1 |
lambda | 1 | 重みに関するL2正則化項 | |
alpha | 0 | 重みに関するL1正則化項 |
Optunaでチューニングしてみる
今回は5つのパラメータn_estimators
、max_depth
、min_child_weight
、subsample
、colsample_bytree
をOptunaを用いてチューニングしていきます。
方針
-
最適化したいパラメータを選択。
この時の注意点としてはパラメータを増やすことによって処理に必要な時間が指数関数的に増える。そのため、できるだけ少ないパラメータを選択する。 -
最小化したい目的関数を定義
今回は回帰タスクなので、MSE(平均二乗誤差)を目的関数として最小化を行う。
Optunaは目的関数の最小化しかできないので、確率など最大化したいものは1-xや1/xなどを目的関数とする。 -
最適化の実行
-
結果を出力
最適化されたパラメータの値や、最小化された目的関数の値を確認することができる。
実際のコード
Optunaのインストール
$ pip install optuna
Optunaのインポート
import optuna
ハイパラメータの指定と目的関数の作成
具体的なパラメータの指定方法は新しい項目を設けて記している。
def opt(trial):
# パラメータの指定
n_estimators = trial.suggest_int('n_estimators', 0, 1000)
max_depth = trial.suggest_int('max_depth', 1, 20)
min_child_weight = trial.suggest_int('min_child_weight', 1, 20)
subsample = trial.suggest_discrete_uniform('subsample', 0.5, 0.9, 0.1)
colsample_bytree = trial.suggest_discrete_uniform('colsample_bytree', 0.5, 0.9, 0.1)
# XGBostのインスタンス生成
xgboost_tuna = XGBRegressor(
random_state=42,
n_estimators = n_estimators,
max_depth = max_depth,
min_child_weight = min_child_weight,
subsample = subsample,
colsample_bytree = colsample_bytree,
)
# 学習
xgboost_tuna.fit(X_train,y_train)
# 予測
tuna_pred_test = xgboost_tuna.predict(X_test)
# MSEを返す
return np.sqrt(mean_squared_error(y_test, tuna_pred_test))
最適化
最適化を実行する時に試行回数を指定できる。
# studyオブジェクトの作成
study = optuna.create_study()
# 最適化の実行
study.optimize(opt, n_trials=50)
結果の確認
# 最適パラメータの表示
print(study.best_params)
# 最小化された目的関数を表示
print(study.study.best_value)
最適化の続行
先ほど試行を50回行い、今回50回行うので合計で100回試行を行ったことになる。
study.optimize(objective, n_trials=50)
パラメータの指定方法
Optunaが対応しているデータ型は5つ。データ型によってパラメータの指定方法が異なるので1つずつみていく。
-
Categorical parameter:カテゴリー型パラメーター
optimizer = trial.suggest_categorical('optimizer', ['MomentumSGD', 'Adam'])
第一引数でパラメーターの名前、第二引数でリスト型で値を指定する。 -
Int parameter:整数値型パラメーター
num_layers = trial.suggest_int('num_layers', 1, 3)
第一引数でパラメーターの名前、第二・第三引数に指定した数値の間でパラメーターをチューニング。 -
Uniform parameter:浮動小数点型パラメーター
dropout_rate = trial.suggest_uniform('dropout_rate', 0.0, 1.0)
第一引数でパラメーターの名前、第二・第三引数に指定した数値の間でパラメーターをチューニング。 -
Loguniform parameter:対数型パラメーター
learning_rate = trial.suggest_loguniform('learning_rate', 1e-5, 1e-2)
第一引数でパラメーターの名前、第二・第三引数に指定した数値の間でパラメーターをチューニング。 -
Discrete-uniform parameter:離散値型パラメーター
drop_path_rate = trial.suggest_discrete_uniform('drop_path_rate', 0.0, 1.0, 0.1)
第一引数でパラメーターの名前、第二引数以降で値を指定する。