
はじめに
こんにちは、HACARUSデータサイエンティストの尾上です。
scikit-learn や TensorFlow、PyTorch などのライブラリを利用すれば、データから機械学習モデルを簡単に作ることができるようになりました。これによって、過去のデータに基づいて、新しいデータに対しても予測をすることが可能になりました。一方で、機械学習モデル自体が複雑になりブラックボックス化することで、「なぜそのような予測をしたのか」を人間が解釈可能な形で知ることが難しくなってきました。これは、医療などの適用領域によっては、大きな問題となってきます。
このような背景から、機械学習モデルの解釈性 (XAI) に注目が集まっており、LIME や SHAP などが有名な方法として知られています。他にも、機械学習モデルを解釈するための様々な手法が提案されており、こちらの山下さんの記事では、Partial Dependence Plot (PDP) と Individual Conditional Expectation (ICE) plot について紹介されています。ただし、PDPはモデルの特徴量が独立であるという仮定が必要で、特徴量が相互作用を持つ場合、誤った解釈をしてしまう恐れがあります。そこで、ICE plot によりインスタンスごとの予測値の推移を可視化していますが、インスタンス数が多いとき、可視化が複雑になり直感的な理解が難しくなります。
そこで、本記事では、「Interpretable Machine Learning」の5章でも紹介されている PDPの信頼性 を可視化する方法の一つである Derivative Individual Conditional Expectation (d-ICE) について実際のデータを使用して紹介します。
PDP, ICE, d-ICE について
まず、PDP と ICE plotの概要について簡単に以下にまとめます.
- ICE plot: 個々 のインスタンスの特定の説明変数のみを変化させた時の予測値の推移
- PDP: ICE plot の平均
PDPは、周辺分布に基づいて予測の変化を可視化していますが、予測モデルが相互作用を持つ場合、現実的に起こりそうもないインスタンスの予測に基づいて計算されてしまうため、PDPの信頼性が低くなるという問題点があります。
具体例として、前回の記事に従い、乳がんデータセットに対して学習したランダムフォレストの「腫瘍半径 – 良性腫瘍確率」の関係性について、PDP と ICE plot を可視化してみます。
# 乳がんデータセットの読み込み
dataset = load_breast_cancer()
df = pd.DataFrame(dataset.data, columns=dataset.feature_names)
# 使用する特徴量の選択
feature_names = df.columns[[7, 20, 21, 24, 27, 28]]
df = df[feature_names]
# データセットの正規化 (範囲: [0, 1])
mms = MinMaxScaler(feature_range=(0, 1), copy=True)
X = mms.fit_transform(df)
X = pd.DataFrame(X, index=df.index, columns=df.columns)
# 正解ラベルの取り出し
y = dataset.target
# ランダムフォレストで分類モデルを学習
rfc = RandomForestClassifier()
rfc.fit(X, y)
# PDP, ICE プロットを描画
feature_id = 1
grid_resolution = 200
pdp_ice_result = partial_dependence(
estimator=rfc, X=X, features=[feature_id], percentiles=(0, 1), grid_resolution=grid_resolution, method='brute', kind='both')
pdp = pdp_ice_result["average"][0] ices = pdp_ice_result["individual"][0] grid_value = pdp_ice_result["values"][0]
plt.title("PDP and ICE for " + feature_names[feature_id])
plt.plot(grid_value, pdp, 'r')
plt.plot(grid_value, ices.T, 'c', alpha = 0.05)
plt.ylabel('benign prob.')
plt.xlabel(feature_names[feature_id])
plt.grid(True, linestyle='dotted', lw=0.5)
PDP から、直感的に「腫瘍半径」が大きくなると良性腫瘍だと判定する確率が低くなる、つまり、悪性であると判定するモデルであることがわかります。一方で、ICE plot により、各インスタンスの特定の説明変数の値のみを変化させた時の予測値の推移も可視化されていますが、この中に PDP とは異なる傾向の変化をするものが見られます。この原因は相互作用による影響であると考えられます。
PDP は相互作用があるかどうかによって、その解釈を信頼すべきか判断しなければなりません。解決策としては、ICE plot から相互作用があるかを確認する必要があるのですが、インスタンス数が多い時に、どの程度相互作用が存在しているのかを直感的に理解することは難しいです。
そこで、モデルの注目している特徴量に相互作用を持つ特徴量が存在するか、あるいは、相互作用を持つ特徴量が存在すればどの部分でどの程度関係性があるのかを可視化する方法として、「Interpretable Machine Learning」の5章では、「ICEの変化の仕方の散らばり」 = 「d-ICEの分散」を計算する方法が紹介されています。ここで、d-ICE は ICE の変化の仕方(微分)を意味しています。 そして、特徴量間に強い相互作用がある時、架空のデータを作り出している ICE plot の変化の仕方はインスタンスごとに大きく異なるので、d-ICE のばらつきも大きくなります。
それでは実際に、d-ICE のばらつきを調べてみましょう。
dices = np.diff(ices, 1, axis=1)
std_dice = np.std(dices, axis=0)
plt.title("std of d-ICE for " + feature_names[feature_id])
plt.ylabel('std d-ICE')
plt.xlabel(feature_names[feature_id])
plt.plot(grid_value[1:], std_dice, 'c')
plt.grid(True, linestyle='dotted', lw=0.5)
上記の図から、このモデルは「良性腫瘍確率」に対して、「腫瘍半径」が 0.2 ~ 0.4 付近でその他の特徴量と相互作用があるということが一目でわかります。
次に、d-ICEの標準偏差を用いて、PDP のばらつきを可視化してみます。
sig = 2 # 約95%の区間
pdp_upper = pdp.copy()
pdp_lower = pdp.copy()
pdp_upper[1:] += sig * std_dice
pdp_lower[1:] -= sig * std_dice
plt.plot(grid_value, pdp, color='red', label='PDP')
plt.fill_between(grid_value, pdp_upper, pdp_lower, color='c', alpha=0.3, label='STD')
plt.grid(True, linestyle='dotted', lw=0.5)
plt.ylabel('benign prob.')
plt.xlabel(X.columns[feature_id])
plt.title("PDP with confidence")
この図では、PDPと、その値における相互作用による予測のばらつきを可視化しています。
これをみると、注目している特徴量が、その他の特徴量と、どの程度の相互作用を持つかわかります。
つまり、PDP のどの部分が信頼できるのかがわかります。
相互作用を持たない場合の d-ICE
上記で使用したランダムフォレストは、d-ICE によって、予測値が 0.5 付近の決定境界にあたる部分で強い相互作用を持つということがわかりました。
では、相互作用をもたないモデル (例: 線形モデル) に対して d-ICE を計算するとどうなるでしょうか。
上記と同じデータセットに対して、ロジスティック回帰モデルで学習を行い、PDP, ICE, d-ICE を可視化した様子を示します。
これをみると、PDP と d-ICE のばらつきを重ね合わせた結果から、相互作用はどこにもみられず (もちろん、ロジスティック回帰モデルは相互作用を持たない)、全ての部分で PDP が信頼できることを示しています。
まとめ
今回は、モデルの説明性・解釈性を可視化する一つの方法である PDP の信頼性を d-ICE を用いることで確かめました。このブログを執筆するにあたって,使用した Python コードは,Google Colab で公開しています。興味がある方は、こちらもぜひご覧ください。
モデルの性能が上がらない時や、モデルが何を根拠にして予測をしたかわからない時には、PDP と ICE plot に加えて、d-ICE のばらつきを可視化することで一つのヒントが得られるかもしれません。ぜひ、参考にしてみてください。