Stanford ML Groupは予測の不確かさを扱える新しい勾配ブースティング「NGBoost」を発表された。今回の記事はNGBoostを解説と実験したいです。
関連記事: 決定木分析、ランダムフォレスト、Xgboost、LightGBM
目次:
1. NGBoostとは
2. NGBoostの特徴
3. 実験・コード
__3.1 データ読み込み
__3.2 Xgboost、LightGBM、NGBoost
__3.3 モデル評価
__3.4 可視化
4. まとめ
1. NGBoostとは
勾配ブースティング(Gradient Boosting)は、いくつかの弱学習器(または基本学習器)が加法アンサンブルで結合されています。NGBoostアルゴリズムは、ブースティングを使用して条件付き確率分布のパラメーターを推定する、確率的予測のための教師あり学習方法です。
NGBoostの論文: NGBoost: Natural Gradient Boosting for Probabilistic Prediction
https://arxiv.org/abs/1910.03225
https://stanfordmlgroup.github.io/projects/ngboost/
アルゴリズムには3つの構成要素があります。
Base learner (f)
Parametric probability distribution (Pθ)
Proper scoring rule (S)
Base Learner
決定木などのアルゴリズム
Probability Distribution
出力する確率分布、正規分布、ラプラス分布などの分布設定
Scoring rule
MLE, CRPSなどのスコア関数
2. NGBoostの特徴
NGBoostの特徴は、確率分布のパラメーターを決定する問題として、自然勾配をキャストして勾配ブーストを実行することです。
通常の勾配は、マルチパラメーター確率分布(正規分布など)の学習には非常に不適切な場合があります。 自然な勾配を使用した学習ダイナミクスは、下記の確率回帰の例に見られるように、はるかに安定し、より良い適合をもたらす傾向があります。
3. 実験・コード
データセット:scikit-learnの load_boston
モデル:Xgboost、LightGBM、NGBoost
モデル評価: RMSE(Root Mean Square Error)(二乗平均平方根誤差)
環境:Google Colab (CPU)
環境設定:
ライブラリのインストール
!pip install ngboost
ライブラリのインポート
# ライブラリのインポート import pandas as pd import numpy as np from tqdm import tqdm from datetime import datetime # データロード from sklearn.datasets import load_boston from sklearn.model_selection import train_test_split # モデル from xgboost import XGBRegressor from lightgbm import LGBMRegressor from ngboost.ngboost import NGBoost from ngboost.learners import default_tree_learner from ngboost.scores import MLE from ngboost.distns import Normal, LogNormal # 検定 from sklearn.metrics import mean_squared_error from math import sqrt # 可視化 import matplotlib.pyplot as plt
3.1 データ読み込み
# サンプルデータの読み込み seed = 20 result = {} # サンプルデータロード loaded_data = load_boston() X_train, X_test, y_train, y_test = train_test_split(loaded_data.data, loaded_data.target, test_size=0.2, random_state=seed) print('X_train Shape:', X_train.shape) print('y_train Shape:', y_train.shape) print('X_test Shape:', X_test.shape) print('y_test Shape:', y_test.shape)
X_train Shape: (455, 30)
y_train Shape: (455,)
X_test Shape: (114, 30)
y_test Shape: (114,)
3.2 Xgboost、LightGBM、NGBoost
xgboost
# モデル作成 start_time = datetime.now() xgb_rg = XGBRegressor(objective='reg:squarederror') xgb_rg.fit(X_train, y_train) # 推論 y_pred_xgb = pd.DataFrame(xgb_rg.predict(X_test)) # 検証 result[('1_xgboost', 'RMSE')] = round(sqrt(mean_squared_error(y_test,y_pred_xgb)),4) result[('1_xgboost', 'Runtime')] = datetime.now() - start_time
lightGBM
# モデル作成 start_time = datetime.now() lgbm_rg = LGBMRegressor(eval_metric='rmse') lgbm_rg.fit(X_train, y_train) # 推論 y_pred_lgb = pd.DataFrame(lgbm_rg.predict(X_test)) # 検証 result[('2_lightGBM', 'RMSE')] = round(sqrt(mean_squared_error(y_test,y_pred_lgb)),4) result[('2_lightGBM', 'Runtime')] = datetime.now() - start_time
NGBoost
# モデル作成 start_time = datetime.now() ngb_rg = NGBoost(Base=default_tree_learner, Dist=Normal, natural_gradient=True, verbose=False) ngb_rg.fit(X_train, y_train, X_val=X_test, Y_val=y_test) # 推論 y_pred_ngb = pd.DataFrame(ngb_rg.predict(X_test)) y_dists = ngb_rg.pred_dist(X_test) # 検証 result[('3_NGBoost', 'RMSE')] = round(sqrt(mean_squared_error(y_test,y_pred_ngb)),4) result[('3_NGBoost', 'Runtime')] = datetime.now() - start_time
3.3 モデル評価
モデルのデフォルトのパラメータにしました。なのでどちらが性能がいいかはわかりませんが、NGBoostはよい結果になっています。
# モデル評価 result_df = pd.Series(result).unstack().reindex(columns=['RMSE', 'Runtime']) result_df
3.4 可視化
テストデータの分布とそれぞれのXgboost、LightGBM、NGBoostの予測値を可視化しました。テストデータが114件あるので、グラフは114個出力されます。モデルの予測結果は正規分布を利用しているので、平均を点推定していることがわかります。
# データ処理
offset = np.ptp(y_pred_ngb)*0.1 y_range = np.linspace(min(y_test)-offset, max(y_test)+offset, 200).reshape((-1, 1)) dist_values = y_dists.pdf(y_range).transpose() y_pred_xgb_p = y_pred_xgb.values.tolist() y_pred_lgb_p = y_pred_lgb.values.tolist() y_pred_ngb_p = y_pred_ngb.values.tolist() # グラフ作成 plt.figure(figsize=(15, 50)) for idx in tqdm(np.arange(X_test.shape[0])): plt.subplot(30, 5, idx+1) plt.plot(y_range, dist_values[idx]) plt.vlines(y_pred_ngb_p[idx], 0, max(dist_values[idx]), "r", label="ngb pred") plt.vlines(y_pred_xgb_p[idx], 0, max(dist_values[idx]), "yellow", label="xgb pred") plt.vlines(y_pred_lgb_p[idx], 0, max(dist_values[idx]), "purple", label="lgb pred") plt.vlines(y_test[idx], 0, max(dist_values[idx]), "pink", label="ground truth") plt.legend(loc="best") plt.title(f"idx: {idx}") plt.xlim(y_range[0], y_range[-1]) plt.tight_layout() plt.show()
まとめ
今回はNGBoostのアルゴリズムを解説しました。実験はbostonのデータセットとデフォルトのパラメータにして、xgboost、lightGBM、NGBoostを実験しました。モデルのチュニックしなくて、NGBoostは一番低いエラーになります。ただ、NGBoostの実行時間はxgboostとlightGBMより遅いをわかりました。