こんにちは。今回は、機械学習モデルの変数重要度を計測する手法の一つである、Permutation Importanceについて調べてみたことをまとめておきたいと思います。
Contents
Permutation Importanceとは?
Permutationとは、日本語に訳すると「置換」「並び替え」になります。
つまり、Permutation Importanceは、ある特徴量の値を、データレコード間で完全にランダムにシャッフルして予測を行ったときに、どの程度予測精度が低下するかによって重要度を判断する方法になります。
もしその特徴量がモデルの予測精度向上に大きく寄与していたのであれば、シャッフルしてしまうことで大きく精度が下がる(=重要度が高かった)。一方で、精度向上に寄与しない変数であれば、シャッフルしても精度は変わらないだろう(=重要度が低かった)、という考え方です。
とても直感的ですね。絵にするとこんなイメージかと思います。
Permutation Importanceの登場
Permutationという考え方は、2001年にランダムフォレストが発表された際に登場しているようです。
https://link.springer.com/content/pdf/10.1023/A:1010933404324.pdf
この点はScikit-Learnの公式ドキュメントでも上の論文が引用される形で言及されています。
https://scikit-learn.org/stable/modules/permutation_importance.html
The permutation feature importance is defined to be the decrease in a model score when a single feature value is randomly shuffled
Scikit-Learnの公式ドキュメントより
Permutation Importanceの特徴
上記のような計測方法であることで、Permutation Importanceには以下の特徴があります。
機械学習モデルの種類に依存しない
Permutation Importance計測の過程では、モデルの種類を意識しません。単純にデータをシャッフルして、結果として出力される予測値がどう変化するかを計測するだけです。
なので、どんなモデルに対しても計測することができます。
他の信頼できる重要度算出手法と比べて計算コストが低い
Permutation Importanceの考え方を理解すると、「あれ?そもそもその特徴量をシャッフルなんかせず、特徴量自体を削って精度がどれだけおちるか計測した方が良いんじゃね?」とも思えます。
ただ、これを実現しようとすると、モデルの学習工程も特徴量の数だけ繰り返していく必要があって計算コストが高くなります。
Permutation Importanceでは、学習モデルはそのままに、検証データだけ*シャッフルして予測を繰り返すので、計算コスト低く重要度が算出できます。
Permutation Importanceの数学
Permutation Importanceは、数式だと以下のように表現されます。
ここで、各文字・変数は以下を表しています。
- i : 変数重要度
- j:特徴量
- s:もともとの予測スコア
- K:データレコード(Importance算出に利用する検証データまたは学習データ)の数
- k:k番目のデータレコード
- s k,j:特徴量jをシャッフルしたときのデータkの予測スコア
つまり、ある特徴量jの重要度iは、本来の予測スコアから、jをシャッフルした時の予測スコアをデータセット分算出して平均をとったもの、として表現されることになります。
参考:
決定木モデルにおけるGini Importance vs Permutation Importance
この点が、今回私がPermutation Importanceを使いたいと思った動機です。
決定木系のモデルの変数重要度には、Gini Importanceも有名かと思います。これは、Scikit-LearnのRandom Forestモデルの変数重要度測定の規定値となっています。
このGini ImportanceとPermutation Importanceはどう使い分ければよいのでしょうか?
まず、Gini Importanceには1つ問題点があります。変数のカーディナリティ(取りうる値の種類)の違いによって重要度のバイアスが発生し得ます。
これについては、こちらの記事に分かりやすく書かれていましたのでリンクを貼らせていただきます。
なので、予測精度よりも説明性・解釈することを重視するようなモデル構築においては、こうしたバイアスが含まれていると誤った解釈をしてしまう可能性があるため、Permutation Importanceに注目した方が良いように思えます。
この点について、Scikit-Learnの公式ドキュメントにも見解が記載されています。Permutation ImportanceはGini Importanceの制約を克服した手法、というように書かれているので、なんとなくPermutation Importance推しのようにも読み取れます。
Warning : Impurity-based feature importances can be misleading for high cardinality features (many unique values). See Permutation feature importance as an alternative below.
…..
Permutation feature importance overcomes limitations of the impurity-based feature importance: they do not have a bias toward high-cardinality features and can be computed on a left-out test set.
https://scikit-learn.org/stable/auto_examples/ensemble/plot_forest_importances.html#feature-importance-based-on-mean-decrease-in-impurity
じゃあなんでRandom Forestの規定値はGini Importanceなんでしょうね・・?
以下のブログの最後にもヒントとなりそうなことが書かれていましたが、上記バイアスの発生し得ない状況(=特徴量間のカーディナリティが均等)においては、最も計算コスト低く(=Permutation Importanceを計測するための追加の予測を行う必要がない)妥当な解釈を与えることができるため、なのかもしれませんね。
https://blog.methodsconsultants.com/posts/be-aware-of-bias-in-rf-variable-importance-metrics/
ただ、現実世界のデータを使ってモデルを作っていくとき、よっぽど特徴量加工を精密にやらない限りそんな状況ってそうそうありえるのかなぁという気もしたので、そこまで計算コストが問題にならないのであればPermutation Importanceで計測しておいたらいいんじゃないか、という気がしました。(どなたか知見のある方いらっしゃれば是非教えてくださいm(_ _)m)
なお、たまたま見つけた「The revival of the Gini importance?」という2018年の論文があるのですが、こちらを見ると、そもそもGini Importanceのバイアスを発生しなくするような研究も行われているようでした。今後また、このあたりの常識も変わってくるかもしれませんね。
https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6198850/
Permutation Importanceの実装
それでは、最後にPermutation Importanceを実際に実装してみたいと思います。
これ、Scikit-LearnのVersion 0.22からScikit-Learn上にメソッドが標準装備されています。便利!
以下の宣言で利用できるようになります。
from sklearn.inspection import permutation_importance
今回はボストンの住宅価格データセットを使って実験してみます。Importanceの実装が目的なので特徴量エンジニアリングの過程は端折ります。
## 今回の実験で利用しないメソッドもImportしたりしてますが、無視してください
from sklearn.datasets import load_boston
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import RandomForestRegressor
from sklearn.inspection import permutation_importance
from sklearn.model_selection import KFold, StratifiedKFold, GridSearchCV, train_test_split,cross_val_score
from sklearn.metrics import mean_squared_error, roc_auc_score, r2_score
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
sns.set()
## データセットのロード
#######################################################
boston = load_boston()
data_X = pd.DataFrame(boston.data, columns=boston.feature_names)
data_y = boston.target
data_X.head()
## ランダムフォレストで予測モデルの構築
#######################################################
from sklearn.ensemble import RandomForestRegressor
X_train, X_test, y_train, y_test = train_test_split(data_X, data_y, test_size=0.2, random_state=440)
clf = RandomForestRegressor(n_estimators=30,max_depth=9)
#print("Cross Val Score (MSE):"+str(cross_val_score(clf, data_X, data_y, cv=5, scoring='r').mean()))
clf = clf.fit(X_train, y_train)
pred = clf.predict(X_test)
print(mean_squared_error(y_test, pred))
## Gini Importanceの可視化
df_importance = pd.DataFrame(zip(X_train.columns, clf.feature_importances_),columns=["Features","Importance"])
df_importance = df_importance.sort_values("Importance",ascending=False)
plt.figure(figsize=(10,5))
sns.barplot(x="Importance", y="Features",data=df_importance,ci=None)
plt.title("Gini Importance")
plt.tight_layout()
まずは、標準で計測されるGini Importanceを可視化してみました。続けてPermutation Importanceです。
以下の構文で計算することができます。可視化に映る前に、戻り値のデータセットの中身をみてみます。
result = permutation_importance(clf, X_test, y_test, n_repeats=5, random_state=42)
result
各特徴量、n_repeatsで指定したfoldの分だけImportanceが計測されて値が入っています。なので、可視化する場合は、平均値などを取って可視化してやれば良さそうです。
それでは、最後に可視化してみます。
df_importance = pd.DataFrame(zip(X_train.columns, result["importances"].mean(axis=1)),columns=["Features","Importance"])
df_importance = df_importance.sort_values("Importance",ascending=False)
plt.figure(figsize=(10,5))
sns.barplot(x="Importance", y="Features",data=df_importance,ci=None)
plt.title("Permutation Importance")
plt.tight_layout()
すみません、ボストンのデータセットはあまり使ったことがなくて内容ちゃんと把握していないのでこの場で結果の比較考察は行いませんが、以上でPermutation Importanceを可視化することができました!
ご参考になりましたら幸いです!最後に、この記事に関するフィードバックがありましたら、以下の「いいね」ボタンや、コメントを残していただけると幸いです!今後の記事改善に役立てていきたいと思います。
モデルの解釈をもっと勉強するなら・・
最近読んだこちらの本が、今回解説したPermutation Importanceを含め、機械学習モデルのふるまいを解釈する方法を体系的にまとめてくれていて大変参考になりました!
おしまい
Permutation Importanceの計測に使用するデータは、上では検証データと書きましたが、実は学習(訓練)データを利用する方法もあります。
この点はScikit-Learnの公式ドキュメントにも説明があり、以下の点が言及されています。
参考:
https://scikit-learn.org/stable/modules/permutation_importance.html