なぜn_estimatorsやepochsをパラメータサーチしてはいけないのか
ハイパーパラメータを探索するため、グリッドサーチやOptunaなどを利用することがあると思います。
しかし、「ハイパーパラメータ探索してみた」のようなQiita記事などでは間違って書かれていることも多いのですが、XGBoostやLightGBMの n_estimators
( num_boosting_rounds
)やKerasの epochs
をパラメータサーチの対象にしてはいけません。
いけません、というか、すごく無駄なことをしています。
なぜ、n_estimatorsやepochsを探索すると無駄なのか
理由はシンプルで、これらのパラメータは「大きい値で精度確認する過程で小さい値の結果も分かる」からです。
LightGBMのn_estimators
は構築する決定木の数を表しています。
例として、n_estimators=5
(こんな小さい値で学習することはないですが、簡単のため)で学習を行ったとします。学習の過程で、n_estimators=1
のスコアも、n_estimators=2
のスコアも確認することができます。
1, 2, ..., 5とn_estimators
を振って確認した場合、合計15個の木を構築する必要がありますが、正しくやれば5個の木で十分です。単純計算で3倍、探索を高速化することができるでしょう。
n_estimatorsは学習率によっては5000程度になることもざらにあります。500, 1000, 1500, ... , 5000と500刻みに探索した場合、合計で27500個の木を構築することになります。本当なら5000個で済むのに。しかも、500刻みで探索していた場合、最適な点を見逃す可能性もあります。
Kerasのepochs
に代表される、ニューラルネットワークのepoch数も同様です。
epochs=100
で学習した場合、その過程で1epochから100epochまでのすべての学習状態を取得することができます。
では、どうすればいいのか?
一般的なのはEarlyStoppingを使用することでしょう。
テストデータとは別にバリデーションデータを用意し、バリデーションで対しての精度がサチったら(一定epochのあいだ向上が見られなかったら)終わりにするという方法です。
LightGBMのscikit-learn interfaceを使っているなら、eval_set
とearly_stopping_rounds
を指定すれば動きます。n_estimators
は大きめに取っておくとよいでしょう。
import lightgbm as lgb params = { 'n_estimators': 10000 # 大きめにとっておく # 他のパラメータは省略 } model = lgb.LGBMClassifier(**params) model.fit(X_train, y_train, eval_set=[(X_valid, y_valid)], early_stopping_rounds=100)
scikit-learn interfaceを使っていないなら、lgb.train
関数にvalid_sets
、early_stopping_rounds
を設定すれば動きます。num_boost_round
はn_estimators
と同様、大きめに取っておきましょう。
import lightgbm as lgb train_set = lgb.Dataset(X_train, y_train) valid_set = lgb.Dataset(X_valid, y_valid) model = lgb.train(params, train_set, num_boost_round=10000, valid_sets=[valid_set], early_stopping_rounds=100)
KerasでEarlyStoppingを行うならkeras.callbacks.EarlyStopping
を使います。使う場合はkeras.callbacks.ModelCheckpoint
と組み合わせ、最も良いモデルを保存するようにしておくと良いでしょう。
from keras import callbacks # モデルの定義とcompileは予めしておく callbacks = [ callbacks.ModelCheckpoint('best_model.h5', save_best_only=True) callbacks.EarlyStopping(patience=5) # 5epoch改善が無ければ止める ] model.fit(X_train, y_train, epochs=1000, callbacks=callbacks, validation_data=[(X_valid, y_valid)]
PyTorchなど、他のフレームワークの場合もEarlyStoppingの仕組みは実装されています。
まとめ
学習の途中経過が全て確認可能な手法を使うとき、n_estimatorsやepochsのような「学習回数」のパラメータを調整するのは時間がもったいないです。
他にもやりがちな例で各種ライブラリのverbose
をチューニングしてしまう、というものがあります。verboseは学習中にどれくらいメッセージを吐き出すかというパラメータで、モデルの精度には一切影響を与えません。精度が変わらないので、もちろんチューニングする必要はありません。
機械学習モデルをチューニングする時はそれぞれのパラメータの意味を理解した上で行うようにしましょう。使っているアルゴリズムに対しての理解を深めることも助けになるでしょう。