RandomForest 多类的 SHAP TreeExplainer:什么是 shap_values[i]?

问题描述 投票:0回答:2

我正在尝试绘制 SHAP 这是我的代码

rnd_clf
是一个
RandomForestClassifier
:

import shap 
explainer = shap.TreeExplainer(rnd_clf) 
shap_values = explainer.shap_values(X) 
shap.summary_plot(shap_values[1], X) 

我理解

shap_values[0]
是负数,
shap_values[1]
是正数。

但是对于多类 RandomForestClassifier 呢?我有

rnd_clf
分类之一:

['Gusto'、'Kestrel 200 SCI 老式公路自行车'、'Vilano 铝合金公路自行车 21 速 Shimano'、'Fixie']。

如何确定

shap_values[i]
的哪个索引对应于我的输出的哪个类别?

python scikit-learn random-forest shap
2个回答
9
投票

如何确定 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)

{0: 'Fixie',
 1: 'Gusto',
 2: 'Kestrel 200 SCI Older Road Bike',
 3: 'Vilano Aluminum Road Bike 21 Speed Shimano'}

因此,例如对于这种特殊情况,

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)

(750, 100)

此时我们的训练数据集包含 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)

(10, 750, 100)

10:班级数量。所有 SHAP 值都组织成 10 个数组,每个类 1 个数组。
750:数据点的数量。我们有每个数据点的本地 SHAP 值。
100:特征数量。我们的每个功能都有 SHAP 价值。

例如,对于

Class 3
,您将拥有:

print(shap_values[3].shape)

(750, 100)

750:每个数据点的 SHAP 值
100:每个功能的 SHAP 价值贡献

最后,您可以运行健全性检查,以确保模型的真实预测与

shap
的预测相同。

为此,我们将 (1) 交换

shap_values
的前 2 个维度,(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
)

True

然后您可以继续进行

summary_plot
,这将显示基于每个类别的 SHAP 值的功能排名。对于第 3 类,这将是:

summary_plot(shap_values[3],X_train)

解释如下:

  • 对于第 3 类,基于 SHAP 贡献最有影响力的特征是 44、64、17

  • 对于特征 64 和 17,较低的值往往会导致较高的 SHAP 值(因此类标签的概率较高)

  • 功能 92、6、53 在显示的 20 个功能中影响最小


0
投票

根据 this GitHub issues

shap_values
列表的顺序对应于模型的
.classes_
属性。最后你可以绘制类似的东西:

shap.summary_plot(shap_values, X_test.toarray(), feature_names=model.get_feature_names_out(), class_names=model.classes_)

请注意,如果您使用管道,则

model
可以是两个不同的模型,可通过
pipeline.named_steps
字典访问。比如说,在 NLP 中,您有一个用于
feature_names
i.e. 单词/n-gram)的分词器步骤和用于分类的 ML 模型 (
class_names
)。

© www.soinside.com 2019 - 2024. All rights reserved.