python - 如何理解二元分类问题的 Shapley 值?
问题描述
我对 shapley python 包很陌生。我想知道我应该如何解释二进制分类问题的 shapley 值?这是我到目前为止所做的。首先,我使用 lightGBM 模型来拟合我的数据。就像是
import shap
import lightgbm as lgb
params = {'object':'binary,
...}
gbm = lgb.train(params, lgb_train, num_boost_round=300)
e = shap.TreeExplainer(gbm)
shap_values = e.shap_values(X)
shap.summary_plot(shap_values[0][:, interested_feature], X[interested_feature])
因为这是一个二分类问题。shap_values 包含两个部分。我假设一个用于 0 类,另一个用于 1 类。如果我想知道一个功能的贡献。我必须绘制两个如下图。
对于 0 级
但是我应该如何获得更好的可视化?结果无法帮助我理解“cold_days 是否增加了输出成为 1 类或成为 0 类的概率?”
使用相同的数据集,如果我使用 ANN,则输出是这样的。我认为 shapley 结果清楚地告诉我,“cold_days”将积极增加结果成为第 1 类的概率。
我感觉 LightGBM 输出有问题,但我不确定如何修复它。如何获得类似于 ANN 模型的更清晰的可视化?
#编辑
我怀疑我以某种方式错误地使用了 lightGBM 来得到奇怪的结果。这是原始代码
import lightgbm as lgb
import shap
lgb_train = lgb.Dataset(x_train, y_train, free_raw_data=False)
lgb_eval = lgb.Dataset(x_val, y_val, free_raw_data=False)
params = {
'boosting_type': 'gbdt',
'objective': 'binary',
'metric': 'binary_logloss',
'num_leaves': 70,
'learning_rate': 0.005,
'feature_fraction': 0.7,
'bagging_fraction': 0.7,
'bagging_freq': 10,
'verbose': 0,
'min_data_in_leaf': 30,
'max_bin': 128,
'max_depth': 12,
'early_stopping_round': 20,
'min_split_gain': 0.096,
'min_child_weight': 6,
}
gbm = lgb.train(params,
lgb_train,
num_boost_round=300,
valid_sets=lgb_eval,
)
e = shap.TreeExplainer(gbm)
shap_values = e.shap_values(X)
shap.summary_plot(shap_values[0][:, interested_feature], X[interested_feature])
解决方案
让我们LGBMClassifier
在乳腺癌数据集上运行:
from sklearn.datasets import load_breast_cancer
from lightgbm import LGBMClassifier
from shap import TreeExplainer, summary_plot
X, y = load_breast_cancer(return_X_y=True, as_frame=True)
model = LGBMClassifier().fit(X,y)
exp = TreeExplainer(model)
sv = exp.shap_values(X)
summary_plot(sv[1], X, max_display=3)
summary_plot(sv[0], X, max_display=3)
你将从这个练习中得到什么:
0 类和 1 类的 SHAP 值是对称的。为什么?因为如果一个特征对第 1 类有一定的贡献,它同时会减少相同数量的第 0 类的概率。所以一般来说,对于二元分类,看
sv[1]
可能就足够了。对第 1 类的贡献值较低
worst area
,反之亦然。这种关系不是严格线性的,尤其是对于 0 类,这需要用非线性模型(树、NN 等)对这种关系进行建模这同样适用于其他描绘的特征。
希望这可以帮助。
附言
我猜你的第二个情节来自一个预测单个类概率的模型,比如 1,但是如果不看你的整个代码就很难判断。
推荐阅读
- python-3.x - ImageDataBunch.from_df 位置索引器超出范围
- python - 如何解决此错误:InvalidSchema("No connection adapters were found for {!r}".format(url))?
- docker - 如何使用 react-scripts 3.4 和 babel-loader 8.1 使 yarn start 在 Docker 映像中工作?
- android - 在我的应用程序的 Google Play 上传版本上引发“CouldNotFindSpotifyApp”异常
- swift - FSCalendar 检查今天的日期
- c# - 装箱值类型十进制到可为空的对象?
- javascript - 如何在 Javascript 中创建自定义异步函数?
- react-native - 仅左右 React Native 阴影
- javascript - 赋值后访问类属性返回未定义
- django - 如何使表单域准确?