AI・機械学習 python 技術関連

[SHAP][PermutationImportance]モデルの判別結果の解釈

更新日:

概要

モデルの判定結果の説明方法について解説します。

はじめに

クライアントビジネスにおいても、モデルの根拠を求められる場合が多いので、その手法をご紹介したいと思います。

どうしてもAIは、入力から出力までがブラックボックス化してしまいがちですが、
AIの判定根拠をホワイトボックスに近づける作業になります。

どのようにホワイトボックス化するかというと、表データと画像系でそれぞれやり方が異なります。

表データの場合、下記を使用してモデルの判定の要因となった説明変数の重要度から判定根拠を示すことが出来ます。

  • 回帰係数/Feature Importance
    • ロジスティック回帰やアンサンブル系で、各説明変数の重みを取り出す。
  • SHAP/LIME
    • 判別結果のスコアをもとにロジスティック回帰モデルを疑似的に作成し、回帰係数を取り出す
  • PeermutationImportance
    • 各説明変数を1つずつ除外し、全体の精度にどのくらい影響があったのかどうかを数値化する。

画像データの場合は、判定根拠が強い部分を強調し画像化することで、
判定根拠を説明することが出来ます。
手法としては、

  • Grad-cam
    • DeepLearningのモデルのみ利用可能。判定結果を逆伝搬しパラメータの変化が大きさで影響度をみる

があります。

実装

SHAP(表データ)

irisデータセットで学習したロジスティック回帰モデルもとに、
SHAPで判別結果の可視化をします。

まずは、モデル作成とSHAPの初期設定

import shap
import sklearn

X_train,X_test,Y_train,Y_test = train_test_split(*shap.datasets.iris(), test_size=0.2, random_state=0)
linear_lr = sklearn.linear_model.LogisticRegression()
linear_lr.fit(X_train, Y_train)
print_accuracy(linear_lr.predict)

# explain all the predictions in the test set
explainer = shap.KernelExplainer(linear_lr.predict_proba, X_train)
shap_values = explainer.shap_values(X_test
shap.initjs()

個別の結果確認
どの特徴量が判定結果に影響したのかを可視化します。

sample = 17 #explain 17th instance in the data set
 
labels_pd = labels.as_data_frame()
actual = labels_pd.iloc[sample].values[0]
prediction = predictions_pd.iloc[sample]['predict']
print("Prediction for ",sample,"th instance is ",prediction," whereas its actual value is ",actual)
 
shap.force_plot(explainer.expected_value[prediction], shap_values[prediction][sample,:], df.iloc[sample])


複数の結果確認

for idx in range(0, len(class_names)):
 print(class_names[idx])
 shap.force_plot(explainer.expected_value[idx], shap_values[idx], df, link="logit")


モデル全体の確認
分類クラス別にどの特徴量が効いているのかを可視化します。

shap.summary_plot(shap_values, features.as_data_frame(), plot_type="bar")


特徴量別にどのクラスに影響を与えたかを可視化します。

for i in range(0, len(class_names)):
 current_class = class_names[i]
 print("Feature importances for ",current_class)
 shap.summary_plot(shap_values[i], features.as_data_frame(), plot_type="bar")

SHAP(画像データ)

Kerasで実装した、画像判別モデルにたいして、モデルがどこに着目したかヒートマップで表示します。

from keras.applications.vgg16 import VGG16
from keras.applications.vgg16 import preprocess_input
import keras.backend as K
import numpy as np
import json
import shap

# load pre-trained model and choose two images to explain
model = VGG16(weights='imagenet', include_top=True)
X,y = shap.datasets.imagenet50()
to_explain = X[[39,41]]

# load the ImageNet class names
url = "https://s3.amazonaws.com/deep-learning-models/image-models/imagenet_class_index.json"
fname = shap.datasets.cache(url)
with open(fname) as f:
    class_names = json.load(f)

# explain how the input to the 7th layer of the model explains the top two classes
def map2layer(x, layer):
    feed_dict = dict(zip([model.layers[0].input], [preprocess_input(x.copy())]))
    return K.get_session().run(model.layers[layer].input, feed_dict)
e = shap.GradientExplainer(
    (model.layers[7].input, model.layers[-1].output),
    map2layer(X, 7),
    local_smoothing=0 # std dev of smoothing noise
)
shap_values,indexes = e.shap_values(map2layer(to_explain, 7), ranked_outputs=2)

# get the names for the classes
index_names = np.vectorize(lambda x: class_names[str(x)][1])(indexes)

# plot the explanations
shap.image_plot(shap_values, to_explain, index_names)

Permutation Importance

上で作成した、回帰モデルの結果を使用してPermutationImportanceを確認します。

import eli5
from eli5.sklearn import PermutationImportance

perm = PermutationImportance(linear_lr,random_state=2019)
perm.fit(X_test,y_test)
eli5.show_weights(perm,feature_names=iris.feature_names)
# show importance
eli5.show_weights(perm,feature_names=iris.feature_names)
# show dataframe
eli5.explain_weights_df(perm,feature_names=iris.feature_names)

おわりに

PermutationImportanceは、相関係数が高い特徴量のペアが存在によって、係数の結果に大きく影響するので前もって相関行列で確認する必要があります。

Grad-CAMは、実装がめんどくさいので、SHAPが手っ取り早いですね。

-AI・機械学習, python, 技術関連

Copyright© AIなんて気合いダッ! , 2020 All Rights Reserved Powered by AFFINGER5.