LightGBMTunerでTrial数(学習回数)は指定できるのと思って調べたらできなかった話。

# はじめに

データ分析コンペに参加すると確実に使うであろう「Oputuna」というパラメータチューニングのライブラリがあります。

技術書などを勉強する中で、私も動かしたことはありますが実際に1から書いたコードで`Oputuna`を試すことがありませんでした。しかし、最近になってしっかりとデータ分析の勉強を始め、現在[Nishika](https://www.nishika.com/)で中古マンション価格予測というコンペをしています。

テーブルデータの回帰タスクとなり、データセットの中にはカテゴリーデータが多くを占めています。
そこで、`LightGBM`のモデルを選択し、`LightGBMTuner`という`Oputuna`の拡張機能(ラッパー)を利用してチューニングを行うようにしました。

そこで、Trial数って何回？自分で設定できるの？と思ったので調べたことをまとめます。

# Trial数(学習回数)について

結論から言うと、LightGBMTunerでは学習回数を指定することはできません。
学習回数はすでに決まっているようです。
nub_boost_roundなどの条件で決まっていると思われます。私の場合は`64回`で終了します。
(詳しい方コメントで教えていただきたいです)

しかし、学習しすぎては過学習など起きてしまうのではないかと思う方もいるかと思います。
私も検証データと評価データの差が大きいために過学習を疑っていました。

そういうときに、使えるLightGBMTunerの引数をご紹介します。

それは`time_budget`を指定することです。学習時間の制限することが可能です。

`time_budget=10`と指定すると、10秒間学習を行います。しかし10秒経った際に学習途中であればそれが終わるまで学習を続けます。

試しに、ボストンの住宅価格のデータセットで試してみます。

# 動作検証

環境はGoogleColabratoryを想定しています。

```
# optunaインストール
!pip install optuna

# 必要なライブラリの用意
from sklearn.datasets import load_boston
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error as mae
import lightgbm
import optuna.integration.lightgbm as lgb
import time
 
# データセット読み込み
boston = load_boston()

# データフレーム作成
df = pd.DataFrame(boston.data, columns=boston.feature_names)
df['目的変数（住宅価格）'] = boston.target

#　学習データと検証データに分ける
df_train, df_val = train_test_split(df, test_size=0.2)

col = "目的変数（住宅価格）"
train_y = df_train[col]
train_x = df_train.drop(col, axis=1)

val_y = df_val[col]
val_x = df_val.drop(col, axis=1)

# LightGBMに入力できるデータ形式にする
trains = lgb.Dataset(train_x, train_y)
valids = lgb.Dataset(val_x, val_y)

# LightGBMの設定 (回帰でMAEを評価する)
opt_params = {
    "objective":"regression",
    "metric":"mae"
}

# 学習時間を図る
start = time.time()

# 学習
# 10秒で終了する
# 200epochごとにMAEを表示
# 1000epoch学習
opt=lgb.train(
    opt_params,
    trains,
    valid_sets = valids,
    verbose_eval=200,
    num_boost_round = 1000,
    early_stopping_rounds = 100,
    time_budget = 10
)

# 学習時間表示
end = time.time()
print('学習時間:', end-start)
```

結果は以下のようになります。

```
(省略)

Training until validation scores don't improve for 100 rounds.
num_leaves, val_score: 2.486855:  95%|#########5| 19/20 [00:07<00:00,  2.58it/s][I 2021-05-28 11:12:36,252] Trial 25 finished with value: 2.554504243795357 and parameters: {'num_leaves': 251}. Best is trial 10 with value: 2.4868550213003315.
[200]	valid_0's l1: 2.60909
Early stopping, best iteration is:
[266]	valid_0's l1: 2.5545
num_leaves, val_score: 2.486855:  95%|#########5| 19/20 [00:07<00:00,  2.61it/s]
  0%|          | 0/10 [00:00<?, ?it/s]
  0%|          | 0/3 [00:00<?, ?it/s]
  0%|          | 0/20 [00:00<?, ?it/s]
  0%|          | 0/5 [00:00<?, ?it/s]学習時間: 10.211193084716797

```

25回で時間になり終了になりました。
学習時間は10秒となっています。

# おわりに

Trial数について疑問に感じて調べましたが、すぐに答えに行きつかなかったのでまとめてみました。
細かい設定をしたい場合は拡張機能ではなく、Oputnaを使うほうがTrial数も制御できてよいか思います。

OptunaもLightGBMTunerもできること同じなのに何が違うのとも思っていたので、そういうところに違いがあるんだなと学ぶこともできました。

# 参考サイト
[Optuna の拡張機能 LightGBM Tuner によるハイパーパラメータ自動最適化](https://tech.preferred.jp/ja/blog/hyperparameter-tuning-with-optuna-integration-lightgbm-tuner/)
[scikit-learn ボストンの住宅価格データセットを使って「回帰分析」をやってみた](https://chusotsu-program.com/scikit-learn-boston/)