AutoML(AutoGluon)とSHAP を組合せて使ってみた


  • 製造業出身のデータサイエンティストがお送りする記事
  • 今回はAutoML ライブラリー(AutoGluon)とSHAP を組合せてを使ってみました。

はじめに

過去に他のAutoML ライブラリーやツールについては、別の記事に纏めておりますので下記をご参照ください。

また、過去にSHAP やLIME の記事は、別の記事に纏めておりますので下記をご参照ください。

AutoGluon とSHAP を組合せて使ってみた

ライブラリーのインストールは下記です(Google Colab 使用前提)。

!pip install --upgrade pip
!pip install --upgrade setuptools
!pip install --upgrade "mxnet<2.0.0"
!pip install --pre autogluon
!pip install shap

今回もUCI Machine Learning Repositoryで公開されているボストン住宅の価格データを用いて実施します。

# ライブラリーのインポート
from autogluon.tabular import TabularDataset, TabularPredictor
import pandas as pd
import numpy as np

import seaborn as sns
import matplotlib.pyplot as plt

%matplotlib inline

# ボストンの住宅価格データ
from sklearn.datasets import load_boston

# 前処理
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split

import sklearn
import shap
import time

shap.initjs()

import warnings
warnings.filterwarnings('ignore')

# データセットの読込み
boston = load_boston()

# 説明変数の格納
df = pd.DataFrame(boston.data, columns=boston.feature_names)
# 目的変数の追加
df["MEDV"] = boston.target

# ランダムシード値
RANDOM_STATE = 10

# 学習データと評価データの割合
TEST_SIZE = 0.2

# 学習データと評価データを作成
x_train, x_test, y_train, y_test = train_test_split(
    df.iloc[:, 0 : df.shape[1] - 1],
    df.iloc[:, df.shape[1] - 1],
    test_size=TEST_SIZE,
    random_state=RANDOM_STATE,
)

# trainのデータセットの2割をモデル学習時のバリデーションデータとして利用する
x_train, x_valid, y_train, y_valid = train_test_split(
    x_train, y_train, test_size=TEST_SIZE, random_state=RANDOM_STATE
)

df_train = pd.concat([x_train, y_train], axis=1)
df_valid = pd.concat([x_valid, y_valid], axis=1)

今回は、オプション指定無しで実行してみます。

predictor = TabularPredictor(
    label='MEDV',
    problem_type='regression', 
    eval_metric='root_mean_squared_error',
)

predictor.fit(
            train_data=df_train,
            tuning_data=df_valid,
            time_limit=None,
)

y_pred = predictor.predict(x_test)

ここから、SHAP を使っていきます。
まず、AutoGluon のラッパークラスを作成して、SHAP パッケージ内で予測のために呼び出すことができるように設定します。

class AutogluonWrapper:
    def __init__(self, predictor, feature_names):
        self.ag_model = predictor
        self.feature_names = feature_names

    def predict(self, X):
        if isinstance(X, pd.Series):
            X = X.values.reshape(1,-1)
        if not isinstance(X, pd.DataFrame):
            X = pd.DataFrame(X, columns=self.feature_names)
        return self.ag_model.predict(X)

次に特徴量のベースライン参照値を定義します。

x_train_summary = shap.kmeans(x_train, 10)
print("Baseline feature-values: \n", x_train_summary)

特定のAutoGluon 予測を説明するカーネルSHAP 値を返すKernelExplainer を作成します。

ag_wrapper = AutogluonWrapper(predictor, boston.feature_names)
print_accuracy(ag_wrapper.predict)

explainer = shap.KernelExplainer(ag_wrapper.predict, x_train_summary)

NSHAP_SAMPLES = 100  
N_VAL = 30  

NSHAP_SAMPLES は、各SHAP 値を計算するために使用するサンプルの数であり、値が大きいほど遅くなります。
N_VAL は、予測結果を解釈する際に必要となるデータポイントの数であり、値が大きいほど遅くなります。

特定の行に対しての予測結果は下記のように確認します。

ROW_INDEX = 0  # index of an example datapoint
single_datapoint = x_train.iloc[[ROW_INDEX]]
single_prediction = ag_wrapper.predict(single_datapoint)

shap_values_single = explainer.shap_values(single_datapoint, nsamples=NSHAP_SAMPLES)
shap.force_plot(explainer.expected_value, shap_values_single, x_train.iloc[ROW_INDEX,:]) 

カーネルSHAP に関する表示は以下のように実施します。

shap_values = explainer.shap_values(x_valid.iloc[0:N_VAL,:], nsamples=NSHAP_SAMPLES)
shap.force_plot(explainer.expected_value, shap_values, x_valid.iloc[0:N_VAL,:])

次に、SHAP value とFeature value の関係性を確認します。

shap.summary_plot(shap_values, x_valid.iloc[0:N_VAL,:])

特徴量の値とShapley Value の散布図は下記のように描画できます。

shap.dependence_plot("LSTAT", shap_values, x_valid.iloc[0:N_VAL,:])

さいごに

最後まで読んで頂き、ありがとうございました。
一部、AutoGluon とSHAP の活用で上手く理解できていない部分もありますが、AutoML とSHAP を組合せることができるのは良いなと思いました。

訂正要望がありましたら、ご連絡頂けますと幸いです。