Jae*_*Lee 6 python random-forest scikit-learn shap
我正在尝试绘制 SHAP 这是我的代码rnd_clf
是RandomForestClassifier
:
import shap
explainer = shap.TreeExplainer(rnd_clf)
shap_values = explainer.shap_values(X)
shap.summary_plot(shap_values[1], X)
Run Code Online (Sandbox Code Playgroud)
我理解这shap_values[0]
是消极的也是shap_values[1]
积极的。
但是对于多类 RandomForestClassifier 呢?我有rnd_clf
以下分类之一:
[“Gusto”、“Kestrel 200 SCI 老式公路自行车”、“Vilano 铝合金公路自行车 21 速 Shimano”、“Fixie”]。
如何确定哪个索引shap_values[i]
对应于输出的哪个类别?
Ser*_*nov 10
如何确定 shap_values[i] 的哪个索引对应于输出的哪个类别?
shap_values[i]
是第 i 类的 SHAP 值。什么是第 i 个类更多的是您使用的编码模式的问题:LabelEncoder
、pd.factorize
等。
您可以尝试以下方法作为线索:
from sklearn.preprocessing import LabelEncoder
labels = [
"Gusto",
"Kestrel 200 SCI Older Road Bike",
"Vilano Aluminum Road Bike 21 Speed Shimano",
"Fixie",
]
le = LabelEncoder()
y = le.fit_transform(labels)
encoding_scheme = dict(zip(y, labels))
pprint(encoding_scheme)
Run Code Online (Sandbox Code Playgroud)
{0: 'Fixie',
1: 'Gusto',
2: 'Kestrel 200 SCI Older Road Bike',
3: 'Vilano Aluminum Road Bike 21 Speed Shimano'}
Run Code Online (Sandbox Code Playgroud)
所以,例如shap_values[3]
对于这个特殊情况是'Vilano Aluminum Road Bike 21 Speed Shimano'
为了进一步了解如何解释 SHAP 值,让我们准备一个包含 100 个特征和 10 个类别的多类分类合成数据集:
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from shap import TreeExplainer
from shap import summary_plot
X, y = make_classification(1000, 100, n_informative=8, n_classes=10)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)
print(X_train.shape)
Run Code Online (Sandbox Code Playgroud)
(750, 100)
Run Code Online (Sandbox Code Playgroud)
此时,我们的训练数据集包含 750 行、100 个特征和 10 个类别。
让我们训练RandomForestClassifier
它并将其提供给TreeExplainer
:
clf = RandomForestClassifier(n_estimators=100, max_depth=3)
clf.fit(X_train, y_train)
explainer = TreeExplainer(clf)
shap_values = np.array(explainer.shap_values(X_train))
print(shap_values.shape)
Run Code Online (Sandbox Code Playgroud)
(10, 750, 100)
Run Code Online (Sandbox Code Playgroud)
10:班级数量。所有 SHAP 值都组织成 10 个数组,每个类 1 个数组。
750:数据点的数量。每个数据点都有本地 SHAP 值。
100:特征数量。我们的每项功能都有 SHAP 价值。
例如,Class 3
您将拥有:
print(shap_values[3].shape)
Run Code Online (Sandbox Code Playgroud)
(750, 100)
Run Code Online (Sandbox Code Playgroud)
750:每个数据点的 SHAP 值
100:每个特征的 SHAP 值贡献
最后,您可以运行健全性检查,以确保模型的实际预测与 的预测相同shap
。
为此,我们将 (1) 交换 的前 2 个维度shap_values
,(2) 对所有特征的每个类的 SHAP 值求和,(3) 将 SHAP 值添加到基值:
shap_values_ = shap_values.transpose((1,0,2))
np.allclose(
clf.predict_proba(X_train),
shap_values_.sum(2) + explainer.expected_value
)
Run Code Online (Sandbox Code Playgroud)
True
Run Code Online (Sandbox Code Playgroud)
然后,您可以继续summary_plot
显示基于每个类别的 SHA 值的功能排名。对于第 3 类,这将是:
summary_plot(shap_values[3],X_train)
Run Code Online (Sandbox Code Playgroud)
其解释如下:
对于第 3 类,基于 SHAP 贡献的最有影响力的特征是 44、64、17
对于特征 64 和 17,较低的值往往会导致较高的 SHA 值(因此类标签的概率较高)
在显示的 20 个特征中,第 92、6、53 个特征影响最小