先日の PyData.tokyo で発表されていた Optuna の LightGBMTuner だけど v0.18.0 でリリースされたらしい。 まだ Experimental (実験的) リリースでドキュメントも整備されていないけど、動くみたいなのでコードを眺めながら試してみた。
LightGBMTuner を使うことで、ユーザは LightGBM のハイパーパラメータを意識することなくチューニングできる。 チューニングには Stepwise Tuning という、特定のハイパーパラメータを一つずつ最適化していく手法が使われている。 これは、過去のコンペで実績のある手法らしい。 詳細については以下を参照のこと。
www.slideshare.net
使った環境は次の通り。
$ sw_vers ProductName: Mac OS X ProductVersion: 10.14.6 BuildVersion: 18G1012 $ python -V Python 3.7.5
もくじ
下準備
使うパッケージをインストールしておく。 なお、LightGBMTuner を動かす上で最低限必要なのは先頭から二つの Optuna と LightGBM だけ。
$ pip install optuna lightgbm seaborn scikit-learn sklearn-pandas category_encoders
使ってみる
今回は seaborn から読み込める Diamonds データセットを使って回帰のタスクを使う。 これは、それなりに行数のあるデータを使いたかったため。
以下が LightGBMTuner を使ってハイパーパラメータを最適化するサンプルコード。
基本的な使い方としては optuna.integration.lightgbm_tuner.train()
を lightgbm.train()
の代わりに用いる。
これだけで透過的に、ハイパーパラメータが最適化された上で学習済みの Booster オブジェクトが返ってくる。
なお、今のところ lightgbm.cv()
相当の機能は実装されていないので、自分でデータを Holdout するなり CV する必要がある。
サンプルコードでは、比較用のためにデフォルトのパラメータで学習されたモデルのメトリック (MSE) も出力している。
#!/usr/bin/env python # -*- coding: utf-8 -*- import numpy as np import category_encoders as ce import seaborn as sns import lightgbm as lgb from optuna.integration import lightgbm_tuner from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error from sklearn_pandas import DataFrameMapper def main(): # データセットを読み込む df = sns.load_dataset('diamonds') # ラベルエンコードする mapper = DataFrameMapper([ ('cut', ce.OrdinalEncoder()), ('color', ce.OrdinalEncoder()), ('clarity', ce.OrdinalEncoder()), ], default=None, df_out=True) df = mapper.fit_transform(df) # 説明変数と目的変数に分ける X, y = df.drop('price', axis=1), df.price # Holt-out 検証用にデータを分割する X_train, X_test, y_train, y_test = train_test_split(X, y, shuffle=True, random_state=42) # 学習用データと検証用データに分割する X_tr, X_val, y_tr, y_val = train_test_split(X_train, y_train, shuffle=True, random_state=42) # LightGBM のデータセット表現にする lgb_train = lgb.Dataset(X_tr, y_tr) lgb_valid = lgb.Dataset(X_val, y_val, reference=lgb_train) # 学習用基本パラメータ lgb_params = { 'objective': 'regression', 'metric': 'rmse', } # Optuna でハイパーパラメータを Stepwise Optimization する tuned_booster = lightgbm_tuner.train(lgb_params, lgb_train, valid_sets=lgb_valid, num_boost_round=1000, early_stopping_rounds=100, verbose_eval=10, ) # 比較用にデフォルトのパラメータを使ったモデルも用意する default_booster = lgb.train(lgb_params, lgb_train, valid_sets=lgb_valid, num_boost_round=1000, early_stopping_rounds=100, verbose_eval=10, ) # Optuna で最適化したモデルの Holt-out データに対するスコア y_pred_tuned = tuned_booster.predict(X_test) tuned_metric = mean_squared_error(y_test, y_pred_tuned) print('tuned model metric: ', tuned_metric) # デフォルトの Holt-out データに対するスコア y_pred_default = default_booster.predict(X_test) default_metric = mean_squared_error(y_test, y_pred_default) print('default model metric: ', default_metric) if __name__ == '__main__': main()
上記を保存して実行してみよう。 time コマンドで実行時間も計測してみる。
$ time python lgbtune.py ...(snip)... tuned model metric: 309501.36031006125 default model metric: 314903.9460911957 python lgbtune.py 324.61s user 6.12s system 298% cpu 1:50.82 total
ちゃんとチューニングしたモデルの方がデフォルトのパラメータより結果が良くなっている。 かつ、全体の実行時間も約 5 分で完了している。
これまでの経験から、ハイパーパラメータのチューニングはデフォルトのパラメータに勝つだけでも探索空間が広いとそれなりの時間を要する印象があった。 それを考えると LightGBMTuner (LightGBM + Stepwise Tuning) は短時間でベターな解を出してきているように感じる。
- 作者: 門脇大輔,阪田隆司,保坂桂佑,平松雄司
- 出版社/メーカー: 技術評論社
- 発売日: 2019/10/09
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
スマートPythonプログラミング: Pythonのより良い書き方を学ぶ
- 作者: もみじあめ
- 発売日: 2016/03/12
- メディア: Kindle版
- この商品を含むブログ (1件) を見る