multi-class 的 SHAP 值解释
SHAP values interpretation for multi-class
我正在查看 Iris 数据集,我在其中为我的 X_test 数据集计算了 SHAP_values,我提供了每个数组的前五个作为示例:
[
array([[-0.02994951, -0.00631915, -0.11904487, -0.13368648],
[-0.00344951, 0.06718085, 0.24445513, 0.40281352],
[-0.02701866, -0.00925 , -0.084 , -0.16873134],
[-0.02994951, -0.00631915, -0.11904487, -0.13368648],
[-0.03526866, -0.001 , -0.11904487, -0.13368648]]),
array([[ 0.02296024, 0.0191085 , 0.27049242, 0.31693884],
[ 0.02209713, -0.0431662 , -0.12745271, -0.20947822],
[-0.0270254 , -0.0025275 , -0.10235476, -0.22609234],
[ 0.03241468, 0.04532274, 0.25367799, 0.29808459],
[ 0.04827892, -0.00105323, 0.13303134, 0.36174298]]),
array([[ 0.00698927, -0.01278935, -0.15144755, -0.18325236],
[-0.01864762, -0.02401465, -0.11700243, -0.1933353 ],
[ 0.05404406, 0.0117775 , 0.18635476, 0.39482368],
[-0.00246517, -0.03900359, -0.13463313, -0.16439811],
[-0.01301026, 0.00205323, -0.01398647, -0.2280565 ]])
]
我有以下预期值:
EV = [0.289 0.358 0.353]
例如,对于数组 0 中的第一行,我已将期望值添加到数组 0 中的行 0 的总和中,然后我可以查看给定样本的贡献加起来是 0 还是 1 .
sv_0_sum = sv_0.iloc[0, :] # -0.28900000000000003
print(sv_0_sum.sum() + explainer.expected_value[0])
在这种情况下结果为 0。我认为这是有道理的,但是使用二进制 classification,SHAP 值将导致 2 个数组,其中反映了值。举个例子,给定某个数据集中一个样本的任意值是:
shap_values[0] = [0.013, 0.423, 0.245, -0.0123]
和
shap_values[1] = [-0.013, -0.423, -0.245, 0.0123]
但是这个概念如何与 multi-class 一起使用?在为 Iris 提供的三个数组中,我没有得到这种反射,那么我如何理解 multi-class 情况下输出的 SHAP 值?
让我们尝试重现:
from lightgbm import LGBMClassifier
from shap.datasets import iris
from shap import Explainer, Explanation
from shap import waterfall_plot
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(*iris(), random_state=42)
model = LGBMClassifier().fit(X_train, y_train)
explainer = Explainer(model)
sv = np.array(explainer.shap_values(X_test)) # <-- SHAP values
ev = np.array(explainer.expected_value) # <-- base values
您在这里得到的是每个 class:
的基础值
ev
array([-3.5596808 , -1.08989253, -3.20879218])
您将在其上添加形状值。注意形状:
ev.shape, sv.shape
((3,), (3, 38, 4))
其中:
3
对应的数量是classes
38
到例数
4
是特征,您有兴趣为其查找 SHAP 值。
那么,您可能会对如何解释特定预测感兴趣:
idx = 0
model.predict(X_test.iloc[[idx]], raw_score=True)
array([[-8.10103813, 1.50946338, -3.6985032 ]])
如果将每个感兴趣数据点的 SHAP 值添加到基值,您将获得相同的预测值:
ev + sv[:, idx, :].sum(-1)
array([-8.10103813, 1.50946338, -3.6985032 ])
或视觉上:
waterfall_plot(Explanation(sv[0][idx], ev[idx], feature_names=X_train.columns))
其中 0
代表感兴趣的 class 预测。
PS
由于 LGBM classifier 内置的随机性,您很可能会得到略有不同的结果。
我正在查看 Iris 数据集,我在其中为我的 X_test 数据集计算了 SHAP_values,我提供了每个数组的前五个作为示例:
[
array([[-0.02994951, -0.00631915, -0.11904487, -0.13368648],
[-0.00344951, 0.06718085, 0.24445513, 0.40281352],
[-0.02701866, -0.00925 , -0.084 , -0.16873134],
[-0.02994951, -0.00631915, -0.11904487, -0.13368648],
[-0.03526866, -0.001 , -0.11904487, -0.13368648]]),
array([[ 0.02296024, 0.0191085 , 0.27049242, 0.31693884],
[ 0.02209713, -0.0431662 , -0.12745271, -0.20947822],
[-0.0270254 , -0.0025275 , -0.10235476, -0.22609234],
[ 0.03241468, 0.04532274, 0.25367799, 0.29808459],
[ 0.04827892, -0.00105323, 0.13303134, 0.36174298]]),
array([[ 0.00698927, -0.01278935, -0.15144755, -0.18325236],
[-0.01864762, -0.02401465, -0.11700243, -0.1933353 ],
[ 0.05404406, 0.0117775 , 0.18635476, 0.39482368],
[-0.00246517, -0.03900359, -0.13463313, -0.16439811],
[-0.01301026, 0.00205323, -0.01398647, -0.2280565 ]])
]
我有以下预期值:
EV = [0.289 0.358 0.353]
例如,对于数组 0 中的第一行,我已将期望值添加到数组 0 中的行 0 的总和中,然后我可以查看给定样本的贡献加起来是 0 还是 1 .
sv_0_sum = sv_0.iloc[0, :] # -0.28900000000000003
print(sv_0_sum.sum() + explainer.expected_value[0])
在这种情况下结果为 0。我认为这是有道理的,但是使用二进制 classification,SHAP 值将导致 2 个数组,其中反映了值。举个例子,给定某个数据集中一个样本的任意值是:
shap_values[0] = [0.013, 0.423, 0.245, -0.0123]
和
shap_values[1] = [-0.013, -0.423, -0.245, 0.0123]
但是这个概念如何与 multi-class 一起使用?在为 Iris 提供的三个数组中,我没有得到这种反射,那么我如何理解 multi-class 情况下输出的 SHAP 值?
让我们尝试重现:
from lightgbm import LGBMClassifier
from shap.datasets import iris
from shap import Explainer, Explanation
from shap import waterfall_plot
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(*iris(), random_state=42)
model = LGBMClassifier().fit(X_train, y_train)
explainer = Explainer(model)
sv = np.array(explainer.shap_values(X_test)) # <-- SHAP values
ev = np.array(explainer.expected_value) # <-- base values
您在这里得到的是每个 class:
的基础值ev
array([-3.5596808 , -1.08989253, -3.20879218])
您将在其上添加形状值。注意形状:
ev.shape, sv.shape
((3,), (3, 38, 4))
其中:
3
对应的数量是classes38
到例数4
是特征,您有兴趣为其查找 SHAP 值。
那么,您可能会对如何解释特定预测感兴趣:
idx = 0
model.predict(X_test.iloc[[idx]], raw_score=True)
array([[-8.10103813, 1.50946338, -3.6985032 ]])
如果将每个感兴趣数据点的 SHAP 值添加到基值,您将获得相同的预测值:
ev + sv[:, idx, :].sum(-1)
array([-8.10103813, 1.50946338, -3.6985032 ])
或视觉上:
waterfall_plot(Explanation(sv[0][idx], ev[idx], feature_names=X_train.columns))
其中 0
代表感兴趣的 class 预测。
PS
由于 LGBM classifier 内置的随机性,您很可能会得到略有不同的结果。