CUBE SUGAR CONTAINER

技術系のこと書きます。

Python: Optuna の LightGBMTuner で Stepwise Tuning を試す

先日の PyData.tokyo で発表されていた Optuna の LightGBMTuner だけど v0.18.0 でリリースされたらしい。 まだ Experimental (実験的) リリースでドキュメントも整備されていないけど、動くみたいなのでコードを眺めながら試してみた。

github.com

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) は短時間でベターな解を出してきているように感じる。

Kaggleで勝つデータ分析の技術

Kaggleで勝つデータ分析の技術

  • 作者: 門脇大輔,阪田隆司,保坂桂佑,平松雄司
  • 出版社/メーカー: 技術評論社
  • 発売日: 2019/10/09
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログを見る