【问题标题】:Force_plot for multiclass probability explainer多类概率解释器的 Force_plot
【发布时间】:2021-04-22 10:17:37
【问题描述】:

我遇到了关于 Python SHAP 库的错误。 虽然根据对数几率创建力图没有问题,但我无法根据概率创建力图。 目标是使 base_values 和 shap_values 总和为预测概率。

这行得通:

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import xgboost as xgb
import sklearn
import shap

X, y = shap.datasets.iris()
X_display, y_display = shap.datasets.iris(display=True)

X_train, X_test, y_train, y_test = sklearn.model_selection.train_test_split(X, y, test_size = 0.2, random_state = 42)

#fit xgboost model
params = {
    'objective': "multi:softprob",
    'eval_metric': "mlogloss",
    'num_class': 3
}

xgb_fit = xgb.train(
   params = params
   , dtrain = xgb.DMatrix(data = X_train, label = y_train) 
)

#create shap values and perform tests
explainer = shap.TreeExplainer(xgb_fit)
shap_values = explainer.shap_values(X_train)

这不起作用:

explainer = shap.TreeExplainer(
    model = xgb_fit
    , data = X_train
    , feature_perturbation='interventional'
    , model_output = 'probability'
)

使用过的包:

matplotlib 3.4.1

numpy 1.20.2

熊猫 1.2.4

scikit-learn 0.24.1

0.39.0 年

xgboost 1.4.1

【问题讨论】:

标签: python shap xgbclassifier


【解决方案1】:

要查看多类分类的原始分数如何在概率空间中相加,请尝试KernelExplainer

from xgboost import XGBClassifier
from sklearn.model_selection import train_test_split
from shap import datasets, KernelExplainer, force_plot, initjs
from scipy.special import softmax, expit

initjs()

X, y = datasets.iris()
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)
clf = XGBClassifier(random_state=42, 
                    eval_metric="mlogloss", 
                    use_label_encoder=False)
clf.fit(X_train, y_train)
ke = KernelExplainer(clf.predict_proba, data=X_train)
shap_values = ke.shap_values(X_test)

force_plot(ke.expected_value[1], shap_values[1][0], feature_names=X.columns)

完整性检查:

  1. 预期结果(最多舍入误差):
clf.predict_proba(X_test[:1])
#array([[0.0031177 , 0.9867134 , 0.01016894]], dtype=float32)
  1. 基值:
clf.predict_proba(X_train).mean(0)
#array([0.3339472 , 0.34133017, 0.32472247], dtype=float32)

(或者如果你愿意np.unique(y_train, return_counts=True)[1]/len(y_train)

【讨论】:

  • 太棒了,这行得通!你也知道如何使用 xgb.train() 来完成这项工作吗?
  • 理想情况下,这应该按照您在问题And this does not work 中的标题方式工作(至少我个人会加入您的行列,希望以这种方式工作)。不幸的是,这不起作用,并且根据 github 问题判断它在过去几个月里一直没有起作用。所以我的快速回答是:我不知道,就force_plot 而言。不过,根据您的需要,您可以尝试修改原始分数并通过 softmax 函数将它们转换为概率。
  • 谢谢,那么我将根据您的示例构建自己的解决方法,并希望将来能够修复。也许与此同时,我会更深入地研究原始代码 (github.com/slundberg/shap/blob/master/shap/explainers/_tree.py) 以评估代码的哪一部分导致上述错误。另外一点,您的示例引发了以下警告:“不建议使用 np.ndarray 的子集(切片数据),因为它会生成额外的副本并增加内存消耗”。对于 iris 数据集,这没有问题,但不幸的是,对于我的数据,它是。
猜你喜欢
  • 2012-12-06
  • 2018-07-05
  • 2016-11-18
  • 2011-06-19
  • 1970-01-01
  • 2016-10-18
  • 2018-05-03
  • 2020-11-16
  • 2019-02-17
相关资源
最近更新 更多