LightGBMの最適なパラメータを求める際にOptunaが便利です。指定した条件内で最も精度が良くなるパラメータを設定してくれます。
Optunaチューニング
データセット
import numpy as np
import pandas as pd
from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split
data = load_diabetes()
df = pd.DataFrame(data.data, columns = data.feature_names)
df["label"] = data.target
train, valid = train_test_split(df, test_size = 0.1)
load_diabetesで回帰予測をしましょう。
チューニングなしで学習
import lightgbm as lgbm
feat_cols = [c for c in df.columns if c != "label"]
train_X = train[feat_cols]
valid_X = valid[feat_cols]
train_y = train["label"]
valid_y = valid["label"]
train_ds = lgbm.Dataset(train_X, train_y)
valid_ds = lgbm.Dataset(valid_X, valid_y)
params = {"objective": "regression", "verbose": -1}
results = {}
model = lgbm.train(
params = params,
train_set = train_ds,
num_boost_round = 100,
valid_sets = [train_ds, valid_ds],
valid_names = ["train", "valid"],
callbacks = [lgbm.log_evaluation(10), lgbm.record_evaluation(results)]
)
デフォルトのパラメータで学習します。
import matplotlib.pyplot as plt
plt.figure(figsize = (12, 4))
plt.plot(results["train"]["l2"])
plt.plot(results["valid"]["l2"])
plt.show()
from sklearn.metrics import r2_score
r2_score(valid_y, model.predict(valid_X))
# 0.4662953855094151
R2スコアは0.466であまり良くないですね。
Optunaチューニング
# !pip install optuna
import optuna
def objective(trial):
params = {
"objective": "regression",
"verbose": -1,
"lambda_l1": trial.suggest_float("lambda_l1", 1e-8, 10.0, log = True),
"lambda_l2": trial.suggest_float("lambda_l2", 1e-8, 10.0, log = True),
"num_leaves": trial.suggest_int("num_leaves", 2, 256),
}
model = lgbm.train(
params = params,
train_set = train_ds,
num_boost_round = 100,
valid_sets = [train_ds, valid_ds],
valid_names = ["train", "valid"],
)
score = r2_score(valid_y, model.predict(valid_X))
return score
study = optuna.create_study(direction = 'maximize')
study.optimize(objective, n_trials = 100, timeout = 60 * 60)
print("Best trial:", study.best_trial.params)
# Best trial: {'lambda_l1': 0.5511594566765063, 'lambda_l2': 7.716533312476801, 'num_leaves': 3}
objective関数内で最大化したいスコアを出力するようにします。
trialが付与されているパラメータが最適化されます。整数値をとるものはsuggest_int、少数を含むものはsuggest_floatで指定しましょう。log=Trueなら対数スケールでサーチしてくれます。
optimizeでサーチを実行します。n_trialsがサーチ回数、timeoutは実行の制限時間です。上記の場合は、60×60=1時間内で最大100回までサーチしてくれます。
最適な値はbest_trial.paramsで取得可能です。
最適化したパラメータで学習
params = {"objective": "regression", "verbose": -1}
params.update(study.best_trial.params)
results = {}
model = lgbm.train(
params = params,
train_set = train_ds,
num_boost_round = 100,
valid_sets = [train_ds, valid_ds],
valid_names = ["train", "valid"],
callbacks = [lgbm.log_evaluation(10), lgbm.record_evaluation(results)]
)
plt.figure(figsize = (12, 4))
plt.plot(results["train"]["l2"])
plt.plot(results["valid"]["l2"])
plt.show()
r2_score(valid_y, model.predict(valid_X))
# 0.5462229337843646
LightGBMに渡すパラメータを更新して再度学習してみましょう。
R2スコアが0.54に上がっていますね。
まとめ
Optunaでパラメータをサーチする方法を紹介しました。
かんたんに精度が上がる手法なので、ぜひ使ってみたいですね。
コメント