LightGBM Tunerを用いたハイパーパラメーターのチューニング

## はじめに
前回、kaggleをやった時のデータを用いて、optunaのハイパーパラメータのチューニングを試してみたいと思います。
データに関しては[前回記事](https://qiita.com/askl4267/items/53f1f2e1808bd60f36af)に記載してあります。

[optuna](https://preferred.jp/ja/projects/optuna/)はPreferred Networksが開発したもので、ハイパーパラメーターを自動でチューニングしてくれるものです。
特に、LightGBMのチューニングに関しては、グリッドサーチの掛け算的な探索に対して、足し算的に探索をしてくれます。
どういう事かと言うと、例えば、n_estimators=[50, 100, 150]、mad_depth=[10, 15, 20]で
最適なパラメータを探索するとします。
グリッドサーチなら３×３で９回の試行を繰り返します。それに対し、optunaのLightGBM tunerでは３＋３の６回の試行を繰り返します。
試行回数が少ない代わりに、optunaは、精度に重要と考えられるパラメーターから優先して調整を行います。そうすることにより、より少ない回数で最適なパラメーターを探索してくれます。
より詳細なことに関しては、[[Optuna の拡張機能 LightGBM Tuner によるハイパーパラメータ自動最適化]](https://tech.preferred.jp/ja/blog/hyperparameter-tuning-with-optuna-integration-lightgbm-tuner/)を参照してください。LightGBM Tinerの優位性について色々実験した結果が書いてあります。

では、早速やっていきたいと思います。


## lightgbm tunerによるハイパーパラメーターのチューニング

LightGBM Tunerを使う場合、普通にlightgbmをimportするのではなく、optunaを通してimportします。

```python3
# import lightbgm as lab (こっちの代わりに下のやり方でimportします)
from optuna.integration import lightgbm as lgb


# optuna.__version__  1.3.0
```
この方法で普通に学習させると自動でチューニングをしてくれます。


```python3
ts = time.time()

dtrain = lgb.Dataset(x_train, label=y_train)
eval_data = lgb.Dataset(x_val, label=y_val)

param = {
        'objective': 'regression',
        'metric': 'rmse',
        'verbosity': -1,
        'boosting_type': 'gbdt',
    }

best = lgb.train(param, 
                 dtrain,
                 valid_sets=eval_data,
                 early_stopping_rounds=100)

time.time() - ts

# time: 2945.9576

"""
###実際にチューニングしてくれているパラメータ###

param = {
        'lambda_l1': trial.suggest_loguniform('lambda_l1', 1e-8, 10.0),
        'lambda_l2': trial.suggest_loguniform('lambda_l2', 1e-8, 10.0),
        'num_leaves': trial.suggest_int('num_leaves', 2, 256),
        'feature_fraction': trial.suggest_uniform('feature_fraction', 0.4, 1.0),
        'bagging_fraction': trial.suggest_uniform('bagging_fraction', 0.4, 1.0),
        'bagging_freq': trial.suggest_int('bagging_freq', 1, 7),
        'min_child_samples': trial.suggest_int('min_child_samples', 5, 100),
    }
"""
```
ちなみにtrialのデフォルト値は1000となっています。
なんで、early_stopping_roundsを100に設定しています。

実行時間は約50分かかりました。結構時間かかりましたが、普段あまりチューニングしない
パラメータまで細かく探索してくれるなら、１時間ぐらい費やしてもいいのかなって個人的には思っています。

チューニング後のパラメーターは以下のようになりました。

```python3
best.params
best.best_iteration
best.best_score

"""
     {'objective': 'regression',
      'metric': 'rmse',
      'verbosity': -1,
      'boosting_type': 'gbdt',
      'lambda_l1': 0.0005523588106120283,
      'lambda_l2': 6.72929973145413e-07,
      'num_leaves': 6,
      'feature_fraction': 0.8,
      'bagging_fraction': 1.0,
      'bagging_freq': 0,
      'min_child_samples': 20}

      best.best_iteration: 555

      best.best_score(rmse): 0.93714
"""
```
このパラメータを使ったモデルで予測したところ、kaggleのスコアで0.94293が出ました。
前回の時よりも少し伸びました。

これ以上は、チューニングでもあまり変化はしないと思うので、他でfeature engineeringしていかないといけないですね。

難しい、、、

## 終わりに
今回は、LightGBM Tunerを使ったハイパーパラメーターのチューニングを行いました。

他のチューニング手法との精度の比較はしていないのですが、上記に貼ったリンクには、
共通ベンチマークを使って他のチューニング手法と比較もしており、その結果、LightGBM Tunerが最も優れていると言う結果がでています。まだ、できたばっかりの手法ですので、改善の余地はあるそうなのですが、色々試行錯誤しながらチューニングするよりも、だいぶ楽な気がします。
また、グリッドサーチのように大雑把な値でチューニングするのでは無く、細かくチューニングしてくれるので、kaggleで、後少しだけスコアを伸ばしたいと言うときにオススメです。