📈

【3日目】LightGBMでシンプルな回帰をやる【2021アドベントカレンダー】

2021/12/03に公開

2021年1人アドベントカレンダー(機械学習)、3日目の記事になります。

https://qiita.com/advent-calendar/2021/solo_advent_calendar

テーマは lightGBM によるシンプルな回帰 になります。

lightGBM の便利さは以下記事をご参照ください。
https://upura.hatenablog.com/entry/2019/10/29/184617

扱うデータがゲームの販売本数なので回帰を扱います。

Colab のコードはこちら Open In Colab

SEED = 42

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(
                                                    df.dropna(subset=["Global_Sales"]).drop(["Global_Sales",  "NA_Sales", "PAL_Sales", "JP_Sales", "Other_Sales"], axis=1).select_dtypes(include="number"), 
                                                    df.dropna(subset=["Global_Sales"])["Global_Sales"],  
                                                    test_size=0.3,
                                                    shuffle=True, 
                                                    random_state=SEED
                                                    ) 

LGBMRegressor

scikit-learn のようにシンプルに モデルのインスタンスの宣言、fit、predict で扱えるのが LGBMRegressor です。

import lightgbm as lgb

学習

model = lgb.LGBMRegressor(
    random_state = SEED,
)

model.fit(
    X_train, 
    y_train,
    eval_set=[(X_test, y_test), (X_train, y_train)],
    verbose=-1 # 学習ログを省略
)

# 学習履歴の表示
lgb.plot_metric(model)

https://stackoverflow.com/questions/60132246/how-to-plot-the-learning-curves-in-lightgbm-and-python

推論(以降同じ)

model.predict(X_test)

lightGBM

データセットの定義等の設定が必要になりますが、より詳細な定義が可能なのがこちらです。

# データセットを登録
lgb_train = lgb.Dataset(X_train, y_train)
lgb_test = lgb.Dataset(X_test, y_test, reference=lgb_train)

パラメーター

params = {
          'task': 'train',              # タスクを訓練に設定
          'boosting_type': 'gbdt',      # GBDTを指定
          'objective': 'regression',    # 回帰を指定
          'metric': 'rmse',             # 回帰の評価関数
          'learning_rate': 0.1,         # 学習率
          }

学習

lgb_results = {}                                    # 学習の履歴を入れる入物

model = lgb.train(
                  params=params,                    # ハイパーパラメータをセット
                  train_set=lgb_train,              # 訓練データを訓練用にセット
                  valid_sets=[lgb_train, lgb_test], # 訓練データとテストデータをセット
                  valid_names=['Train', 'Test'],    # データセットの名前をそれぞれ設定
                  num_boost_round=100,              # 計算回数
                  early_stopping_rounds=50,         # アーリーストッピング設定
                  evals_result=lgb_results,             # 学習の履歴を保存
                  verbose_eval=-1                           # ログを最後の1つだけ表示
                  )  

学習履歴の表示

evals_result に辞書型データを設定することで、学習履歴(メトリクスによる評価結果の推移)を確認することができます。

loss_train = lgb_results['Train']['rmse']
loss_test = lgb_results['Test']['rmse']   
  
fig = plt.figure()
ax1 = fig.add_subplot(111)
  
ax1.set_xlabel('Iteration')
ax1.set_ylabel('logloss')
 
ax1.plot(loss_train, label='train loss')
ax1.plot(loss_test, label='test loss')
 
plt.legend()
plt.show()

オリジナルの評価関数(カスタムメトリクス)

引数を設定することで基本的な評価関数(rmse, auc等)を設定することは可能ですが、独自の評価関数を設定することも可能です。

https://lightgbm.readthedocs.io/en/latest/Parameters.html#metric-parameters

その場合は、パラメーターで "None" (文字列。予約語の None ではない点に注意。) を設定しましょう。

params = {
          'task': 'train',              # タスクを訓練に設定
          'boosting_type': 'gbdt',      # GBDTを指定
          'objective': 'regression',    # 回帰を指定
          'metric': "None",             # 回帰の評価関数に None を指定
          'learning_rate': 0.1,         # 学習率
          }

https://tawara.hatenablog.com/entry/2020/05/09/162633

オリジナルの評価関数の作成

なんでもいいのですが、今回は RMSPE を扱ってみます。
https://atmarkit.itmedia.co.jp/ait/articles/2106/23/news031.html

返り値の3番目の bool 値は、この評価関数は数値が大きい方が精度がよい(True)のか、小さい方が精度がよい(False)のか、という設定になります。

is_higher_betterbool
Is eval result higher better, e.g. AUC is is_higher_better.

RMSPE は誤差であり小さい方が精度がよくなりますので、False とします。

https://lightgbm.readthedocs.io/en/latest/pythonapi/lightgbm.train.html

def custom_metrics(y_pred, data):

    y_true = data.get_label() # lgb.Dataset() から 目的変数を取得

    score = np.mean( np.sqrt( (y_true - y_pred) / y_true) ** 2 ) # 評価結果を算定。平均処理を行う

    return 'custom_metrics', score, False
lgb_results = {}                                    # 学習の履歴を入れる入物

model = lgb.train(
                  params=params,                    # ハイパーパラメータをセット
                  train_set=lgb_train,              # 訓練データを訓練用にセット
                  valid_sets=[lgb_train, lgb_test], # 訓練データとテストデータをセット
                  valid_names=['Train', 'Test'],    # データセットの名前をそれぞれ設定
                  num_boost_round=100,              # 計算回数
                  early_stopping_rounds=50,         # アーリーストッピング設定
                  evals_result=lgb_results,         # 学習の履歴を保存
                  verbose_eval=-1,                  # ログを最後の1つだけ表示
                  feval=custom_metrics,
                  )  

https://hippocampus-garden.com/lgbm_custom/

https://blog.amedama.jp/entry/lightgbm-custom-metric

3日目は以上になります、最後までお読みいただきありがとうございました。

Discussion