使用 SHAP 时如何解释 GBT 分类器的 base_value?

Posted

技术标签:

【中文标题】使用 SHAP 时如何解释 GBT 分类器的 base_value?【英文标题】:How to interpret base_value of GBT classifier when using SHAP? 【发布时间】:2021-12-19 09:56:07 【问题描述】:

我最近发现了this amazing library for ML interpretability。我决定使用来自 sklearn 的 toy dataset 构建一个简单的 xgboost 分类器并绘制一个 force_plot

为了理解图书馆所说的情节:

上面的解释显示了每个有助于推动 从基础值的模型输出(平均模型输出超过 我们传递的训练数据集)到模型输出。功能推动 预测较高的显示为红色,那些推低预测的 是蓝色的(这些力图在我们的 Nature BME 中引入 纸)。

所以在我看来,base_value 应该与 clf.predict(X_train).mean() 相同,等于 0.637。然而,在看情节时情况并非如此,这个数字实际上甚至不在 [0,1] 之内。我尝试在不同的基础(10,e,2)中进行日志,假设这将是某种单调变换......但仍然不是运气。我怎样才能得到这个 base_value?

!pip install shap

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.ensemble import GradientBoostingClassifier
import pandas as pd
import shap

X, y = load_breast_cancer(return_X_y=True)
X = pd.DataFrame(data=X)
y = pd.DataFrame(data=y)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

clf = GradientBoostingClassifier(random_state=0)
clf.fit(X_train, y_train)

print(clf.predict(X_train).mean())

# load JS visualization code to notebook
shap.initjs()

explainer = shap.TreeExplainer(clf)
shap_values = explainer.shap_values(X_train)

# visualize the first prediction's explanation (use matplotlib=True to avoid javascript)
shap.force_plot(explainer.expected_value, shap_values[0,:], X_train.iloc[0,:])

【问题讨论】:

【参考方案1】:

要在原始空间中获取base_value(当link="identity" 时),您需要展开类标签--> 到概率--> 到原始分数。注意,默认loss是"deviance",所以raw是inverse sigmoid:

# probabilites
y = clf.predict_proba(X_train)[:,1]
# raw scores, default link="identity"
y_raw = np.log(y/(1-y))
# expected raw score
print(np.mean(y_raw))
print(np.isclose(explainer.expected_value, np.mean(y_raw), 1e-12))
2.065861773054686
[ True]

原始空间中第 0 个数据点的相关图:

shap.force_plot(explainer.expected_value[0], shap_values[0,:], X_train.iloc[0,:], link="identity")

您是否希望切换到 sigmoid 概率空间 (link="logit"):

from scipy.special import expit, logit
# probabilites
y = clf.predict_proba(X_train)[:,1]
# exected raw base value
y_raw = logit(y).mean()
# expected probability, i.e. base value in probability spacy
print(expit(y_raw))
0.8875405774316522

概率空间中第 0 个数据点的相关图:

请注意,从 shap 的角度来看,base_value 的概率,如果没有可用数据,他们称之为基线概率,并不是一个理性的人会通过没有自变量来定义的(在这种情况下为0.6373626373626373


完整的可重现示例:

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.ensemble import GradientBoostingClassifier
import pandas as pd
import shap
print(shap.__version__)

X, y = load_breast_cancer(return_X_y=True)
X = pd.DataFrame(data=X)
y = pd.DataFrame(data=y)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

clf = GradientBoostingClassifier(random_state=0)
clf.fit(X_train, y_train.values.ravel())

# load JS visualization code to notebook
shap.initjs()

explainer = shap.TreeExplainer(clf, model_output="raw")
shap_values = explainer.shap_values(X_train)

from scipy.special import expit, logit
# probabilites
y = clf.predict_proba(X_train)[:,1]
# exected raw base value
y_raw = logit(y).mean()
# expected probability, i.e. base value in probability spacy
print("Expected raw score (before sigmoid):", y_raw)
print("Expected probability:", expit(y_raw))

# visualize the first prediction's explanation (use matplotlib=True to avoid Javascript)
shap.force_plot(explainer.expected_value[0], shap_values[0,:], X_train.iloc[0,:], link="logit")

输出:

0.36.0
Expected raw score (before sigmoid): 2.065861773054686
Expected probability: 0.8875405774316522

【讨论】:

太棒了!现在更有意义了。您能否在回复中添加指向偏差损失的链接?我想看看 xgboost 使用的实际公式以及为什么 sigmoid 是相反的。 @G.Macia 您继续推荐 xgboost,而您的问题是关于 scikit-learn 中的 GBT 分类器(我已经编辑了您的标题);请参阅docs 了解默认设置loss='deviance' 情节中应该是shap_values[0,:]还是shap_values[1,:] @desertnaut 我的理解01 是感兴趣数据点的行索引 你是对的,因为在这里你只保留了 y 中的 [:,1] 元素(即第 1 类的概率)。关于expected_value,它应该是模型在基础数据集中的平均预测(回归中直截了当,但这里可能没有那么多),而不是在没有可用数据时。尽管如此,我同意这不是大多数人会考虑的基线(顺便说一句,很好的答案,抱歉我不能投票两次)。

以上是关于使用 SHAP 时如何解释 GBT 分类器的 base_value?的主要内容,如果未能解决你的问题,请参考以下文章

如何告诉 shap 树解释器和 shap 值计算器哪些变量是分类的?

用于分类/多类分类的梯度提升树的弱学习器

ML之shap:基于FIFA 2018 Statistics(2018年俄罗斯世界杯足球赛)球队比赛之星分类预测数据集利用RF随机森林+计算SHAP值单样本力图/依赖关系贡献图可视化实现可解释性之攻略

R语言使用DALEX包的explain函数生成指定分类预测机器学习模型的解释器predict_parts函数基于shap方法分析对于指定的某一条样本(实例观察)每个变量对于预测结果的贡献大小

如何获得 Huggingface Transformer 模型预测 [零样本分类] 的 SHAP 值?

如何将 SHAP 与 sklearn 中的线性 SVC 模型一起使用 Pipeline?