Optunaでパラメータチューニングしてみた【第一弾】
このサイトを参考にOptunaでパラメータチューニングを初めてやってみた。
参考サイトは別のCSVのデータで行っていますが、こちらの記事ではsklearnに入っているデータを利用してみた。
参考サイトですごいなと思ったのは他のサイトであるあるな感じでoptunaで普通に単純にパラメータを出すだけではなく、rmse値を最小化するようにパラメータをチューニングする以下の関数
def objective(trial): params = {'metric': {'rmse'}, 'max_depth' : trial.suggest_int('max_depth', 1, 10), 'subsumple' : trial.suggest_uniform('subsumple', 0.0, 1.0), 'subsample_freq' : trial.suggest_int('subsample_freq', 0, 1), 'leaning_rate' : trial.suggest_loguniform('leaning_rate', 1e-5, 1), 'feature_fraction' : trial.suggest_uniform('feature_fraction', 0.0, 1.0), 'lambda_l1' : trial.suggest_uniform('lambda_l1' , 0.0, 1.0), 'lambda_l2' : trial.suggest_uniform('lambda_l2' , 0.0, 1.0)} gbm = lgb.train(params, lgb_train, valid_sets=(lgb_train, lgb_eval), num_boost_round=10000, early_stopping_rounds=100, verbose_eval=50) predicted = gbm.predict(X_test) RMSE = np.sqrt(mean_squared_error(y_test, predicted)) pruning_callback = optuna.integration.LightGBMPruningCallback(trial, 'rmse') return RMSE
を作っていたのが非常に面白かったので利用してみました。
以下がコードの全貌です。
#データセット用のライブラリ from sklearn import datasets, model_selection #データ分析用のライブラリ import pandas as pd import numpy as np #データ可視化ライブラリ import matplotlib.pyplot as plt import seaborn as sns #LightGBMライブラリ import lightgbm as lgb #訓練データとモデル評価用データに分けるライブラリ from sklearn.model_selection import train_test_split #ハイパーパラメータチューニング自動化ライブラリ import optuna #関数処理で必要なライブラリ from sklearn.metrics import mean_squared_error from sklearn.metrics import r2_score #その他 from sklearn import metrics #データ準備 features, labels = datasets.load_boston(return_X_y = True) #データ分割 X_train,X_test,y_train,y_test = train_test_split(features, labels, test_size=0.2) #LightGBM用のデータセットに加工 lgb_train = lgb.Dataset(X_train, y_train) lgb_eval = lgb.Dataset(X_test, y_test) #optunaへ入れる情報をまとめた関数 def objective(trial): params = {'metric': {'rmse'}, 'max_depth' : trial.suggest_int('max_depth', 1, 10), 'subsumple' : trial.suggest_uniform('subsumple', 0.0, 1.0), 'subsample_freq' : trial.suggest_int('subsample_freq', 0, 1), 'leaning_rate' : trial.suggest_loguniform('leaning_rate', 1e-5, 1), 'feature_fraction' : trial.suggest_uniform('feature_fraction', 0.0, 1.0), 'lambda_l1' : trial.suggest_uniform('lambda_l1' , 0.0, 1.0), 'lambda_l2' : trial.suggest_uniform('lambda_l2' , 0.0, 1.0)} gbm = lgb.train(params, lgb_train, valid_sets=(lgb_train, lgb_eval), num_boost_round=1000, early_stopping_rounds=100, verbose_eval=300) predicted = gbm.predict(X_test) RMSE = np.sqrt(mean_squared_error(y_test, predicted)) pruning_callback = optuna.integration.LightGBMPruningCallback(trial, 'rmse') return RMSE #optunaの起動 study = optuna.create_study() study.optimize(objective, timeout = 60) print('Best trial:') trial = study.best_trial print('Value:{}'.format(trial.value)) print('Paramas:') for key, value in trial.params.items(): print(',"{}":{}'.format(key, value)) #予測値と正解値を描写する関数 def True_Pred_map(pred_df): RMSE = np.sqrt(mean_squared_error(pred_df['true'], pred_df['pred'])) R2 = r2_score(pred_df['true'], pred_df['pred']) plt.figure(figsize=(8,8)) ax = plt.subplot(111) ax.scatter('true', 'pred', data=pred_df) ax.set_xlabel('True Value', fontsize=15) ax.set_ylabel('Pred Value', fontsize=15) ax.set_xlim(pred_df.min().min()-0.1 , pred_df.max().max()+0.1) ax.set_ylim(pred_df.min().min()-0.1 , pred_df.max().max()+0.1) x = np.linspace(pred_df.min().min()-0.1, pred_df.max().max()+0.1, 2) y = x ax.plot(x,y,'r-') plt.text(0.1, 0.9, 'RMSE = {}'.format(str(round(RMSE, 5))), transform=ax.transAxes, fontsize=15) plt.text(0.1, 0.8, 'R^2 = {}'.format(str(round(R2, 5))), transform=ax.transAxes, fontsize=15) #Optunaで最適化されたパラメータ params = { "metric": {'rmse'} ,"max_depth":4 ,"subsumple":0.5654007940457206 ,"subsample_freq":0 ,"leaning_rate":0.00017894703178220227 ,"feature_fraction":0.5230674363641012 ,"lambda_l1":0.7312452385011556 ,"lambda_l2":0.021966875171314314 } #LightGBMのモデル構築 model = lgb.train( params ,lgb_train ,valid_sets=(lgb_train, lgb_eval) ,num_boost_round=10000 ,early_stopping_rounds=100 ,verbose_eval=300 ) #モデル評価用データで予測値出力 y_pred = model.predict(X_test) #可視化関数にぶち込めるように予測値と正答値をデータフレームに加工 pred_df = pd.concat([pd.Series(y_test), pd.Series(y_pred)], axis=1) pred_df.columns = ['true', 'pred'] #可視化関数を実行 True_Pred_map(pred_df) # 特徴量の重要度をプロット lgb.plot_importance(model)
何もしていないのに結構精度が良くてさすがLightGBMとOptunaですね。