我对shap
这个Python包非常新手。我想知道如何解释二元分类问题的Shapley值?这是我目前所做的。首先,我使用了一个lightGBM模型来拟合我的数据。类似于
import shapimport lightgbm as lgbparams = {'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模型的更清晰的可视化效果?
#Edit
我怀疑我以某种方式错误地使用了lightGBM而得到了奇怪的结果。这是原始代码
import lightgbm as lgbimport shaplgb_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_cancerfrom lightgbm import LGBMClassifierfrom shap import TreeExplainer, summary_plotX, 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]
就足够了。 -
worst area
的低值有助于类别1,反之亦然。这种关系并不是严格线性的,尤其是对于类别0,这需要用非线性模型(树、神经网络等)来建模这种关系。 -
同样的情况也适用于其他显示的特征。
PS
我猜你的第二个图表来自于一个预测单一类别概率的模型,比如1,但没有看到你完整的代码很难判断。