NGBoostの使い方

Python

NGBoost

公式ドキュメント
https://stanfordmlgroup.github.io/ngboost/intro.html
論文
https://arxiv.org/abs/1910.03225

分類

分類では、irisのデータセットを使っています。
fit関数にバリデーション用のデータを渡すことができます。

学習と予測

from ngboost import NGBClassifier

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
from ngboost.distns import k_categorical

# データセットの呼び出し
load_data = load_iris()
X_train, X_val, y_train, y_val = train_test_split(load_data.data, load_data.target, test_size=0.2)

# 学習
ngb = NGBClassifier(
    Dist=k_categorical(3),#分類のカテゴリ数
    natural_gradient=True, # 自然勾配の使用の有無
    n_estimators=100,
    learning_rate=0.01,
).fit(X_train, y_train,X_val, y_val)

# ここではバリデーションデータとテストデータ同じものを使っています
X_test = X_val
y_test = y_val
# 予測
y_preds = ngb.predict(X_test)
y_dists = ngb.pred_dist(X_test)

学習曲線の表示

import matplotlib.pyplot as plt

plt.figure(figsize = (10,8))
plt.plot(ngb.evals_result["train"]["LOGSCORE"],  linewidth=3)
plt.plot(ngb.evals_result["val"]["LOGSCORE"], linewidth=3)
plt.title("iter vs loss")
plt.grid(True)
plt.xlabel("iter", fontsize=18)
plt.ylabel("loss", fontsize=18)
plt.tick_params(labelsize = 12)
plt.legend(("train", "val"), fontsize=18)

Feature Importance

import pandas as pd
import seaborn as sns

df_f = pd.DataFrame({ 
                        "columns" : load_data.feature_names,
                        "feature_importances_loc" : ngb.feature_importances_[0],
                        "feature_importances_std" : ngb.feature_importances_[1],})

# 平均に対するFeature Importance
df_loc = df_f.sort_values("feature_importances_loc", ascending=False)
plt.figure(figsize = (10,8))
plt.title('Feature importance(loc)')
sns.barplot(x = df_loc["feature_importances_loc"], y = df_loc["columns"])
plt.show()
# 標準偏差に対するFeature Importance
df_std = df_f.sort_values("feature_importances_std", ascending=False)
plt.figure(figsize = (10,8))
plt.title('Feature importance(std)')
sns.barplot(x = df_std["feature_importances_std"], y = df_std["columns"])
plt.show()

回帰

from ngboost import NGBRegressor

from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error

# サンプルデータロード
load_data = load_boston()
X_train, X_val, y_train, y_val = train_test_split(load_data.data, load_data.target, test_size=0.2, random_state=42)

ngb = NGBRegressor(
    n_estimators=100,
    learning_rate=0.01,
).fit(X_train, y_train,X_val, y_val)

# ここではバリデーションデータとテストデータ同じものを使っています
X_test = X_val
y_test = y_val
# 予測
y_preds = ngb.predict(X_test)
y_dists = ngb.pred_dist(X_test)

結果の表示

# test Mean Squared Error
test_MSE = mean_squared_error(y_preds, y_test)
print('Test MSE', test_MSE)

学習曲線の表示

Feature Importance

import pandas as pd
import seaborn as sns

df_f = pd.DataFrame({ 
                        "columns" : load_data.feature_names,
                        "feature_importances_loc" : ngb.feature_importances_[0],
                        "feature_importances_std" : ngb.feature_importances_[1]})

# 平均に対するFeature Importance
df_loc = df_f.sort_values("feature_importances_loc", ascending=False)
plt.figure(figsize = (10,8))
plt.title('Feature importance(loc)')
sns.barplot(x = df_loc["feature_importances_loc"], y = df_loc["columns"])
plt.show()
# 標準偏差に対するFeature Importance
df_std= df_f.sort_values("feature_importances_std", ascending=False)
plt.figure(figsize = (10,8))
plt.title('Feature importance(std)')
sns.barplot(x = df_std["feature_importances_std"], y = df_std["columns"])
plt.show()

グラフの表示

import numpy as np
from tqdm import tqdm_notebook as tqdm

offset = np.ptp(y_preds)*0.1
y_range = np.linspace(min(y_val)-offset, max(y_val)+offset, 200).reshape((-1, 1))
dist_values = y_dists.pdf(y_range).transpose()

plt.figure(figsize=(25, 120))
for idx in tqdm(np.arange(X_val.shape[0])):
    
    plt.subplot(35, 3, idx+1)
    plt.plot(y_range, dist_values[idx])
    
    plt.vlines(y_preds[idx], 0, max(dist_values[idx]), "r", label="ngb pred")
    plt.vlines(y_val[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()

個数の指定

すべての予測に対して表示させると重くなる可能性があるので、最初から10個だけ表示させるようにしています。

import numpy as np
from tqdm import tqdm_notebook as tqdm

# 個数を指定
num = 10

offset = np.ptp(y_preds)*0.1
y_range = np.linspace(min(y_val)-offset, max(y_val)+offset, 200).reshape((-1, 1))
dist_values = y_dists.pdf(y_range).transpose()

plt.figure(figsize=(25, 120))
for idx in range(0,num):
    
    plt.subplot(35, 3, idx+1)
    plt.plot(y_range, dist_values[idx])
    
    plt.vlines(y_preds[idx], 0, max(dist_values[idx]), "r", label="ngb pred")
    plt.vlines(y_val[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_regression_demo
Explore and run machine learning code with Kaggle Notebooks | Using data from No attached data sources
タイトルとURLをコピーしました