decision

目录

  • 1  SHAP 决策图

    • 1.1 加载数据集并训练模型

    • 1.2 计算 SHAP 值

  • 2 基本决策图功能

  • 3 决策图何时有用?

    • 3.1 清晰展示大量特征效果

    • 3.2  可视化多输出预测

    • 3.3 展示交互的累积效应

    • 3.4 探索一系列特征值的特征效果

    • 3.5 识别异常值

    • 3.6 识别典型的预测路径

    • 3.7 比较和对比多个模型的预测

  • 4  SHAP 交互值

  • 5  在图表之间保持顺序和比例

  • 6 选择显示的特征

  • 7  更改 SHAP 基值

SHAP 决策图

SHAP 决策图展示了复杂模型如何得出它们的预测(即模型如何做出决策)。本笔记本通过简单的示例说明了决策图的功能和用例。如需更详细的叙述,点击这里

加载数据集并训练模型

在大多数示例中,我们使用在 UCI Adult Income 数据集上训练的 LightGBM 模型。目标:预测个人年收入是否超过 $50K。

[1]:
import pickle
import warnings
from pprint import pprint

import lightgbm as lgb
import matplotlib.pyplot as plt
import numpy as np
from sklearn.model_selection import StratifiedKFold, train_test_split

import shap

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

# create a train/test split
random_state = 7
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=random_state
)
d_train = lgb.Dataset(X_train, label=y_train)
d_test = lgb.Dataset(X_test, label=y_test)

params = {
    "max_bin": 512,
    "learning_rate": 0.05,
    "boosting_type": "gbdt",
    "objective": "binary",
    "metric": "binary_logloss",
    "num_leaves": 10,
    "verbose": -1,
    "min_data": 100,
    "boost_from_average": True,
    "random_state": random_state,
}

model = lgb.train(
    params,
    d_train,
    10000,
    valid_sets=[d_test],
    early_stopping_rounds=50,
    verbose_eval=1000,
)
Training until validation scores don't improve for 50 rounds.
Early stopping, best iteration is:
[683]   valid_0's binary_logloss: 0.277144

计算 SHAP 值

计算前20个测试观测值的SHAP值和SHAP交互值。

[2]:
explainer = shap.TreeExplainer(model)
expected_value = explainer.expected_value
if isinstance(expected_value, list):
    expected_value = expected_value[1]
print(f"Explainer expected value: {expected_value}")

select = range(20)
features = X_test.iloc[select]
features_display = X_display.loc[features.index]

with warnings.catch_warnings():
    warnings.simplefilter("ignore")
    shap_values = explainer.shap_values(features)[1]
    shap_interaction_values = explainer.shap_interaction_values(features)
if isinstance(shap_interaction_values, list):
    shap_interaction_values = shap_interaction_values[1]
Explainer expected value: -2.4296968952292404

基本决策图特征

参考下面的20个测试观测值的决策图。注意:这个图本身并不具有信息量;我们仅用它来阐释主要概念。 * x轴表示模型的输出。在这种情况下,单位是log odds。 * 图在x轴上以``explainer.expected_value``为中心。所有SHAP值相对于模型的期望值,类似于线性模型的效应相对于截距。 * y轴列出了模型的特征。默认情况下,特征按重要性降序排列。重要性是根据图中绘制的观测值计算的。这通常与整个数据集的重要性排序不同。 除了特征重要性排序外,决策图还支持层次聚类特征排序和用户定义的特征排序。 * 每个观测值的预测由一条彩色线表示。在图的顶部,每条线在其对应观测值的预测值处击中x轴。该值决定了线在光谱上的颜色。 * 从图的底部到顶部,每个特征的SHAP值被添加到模型的基值中。这显示了每个特征如何对整体预测做出贡献。 * 在图的底部,观测值在``explainer.expected_value``处汇聚。

[3]:
shap.decision_plot(expected_value, shap_values, features_display)
../../../_images/example_notebooks_api_examples_plots_decision_plot_8_0.png

与力图类似,决策图支持 link='logit' 将对数几率转换为概率。

[4]:
shap.decision_plot(expected_value, shap_values, features_display, link="logit")
../../../_images/example_notebooks_api_examples_plots_decision_plot_10_0.png

可以使用虚线样式突出显示观察结果。在这里,我们突出显示了一个被错误分类的观察结果。

[5]:
# Our naive cutoff point is zero log odds (probability 0.5).
y_pred = (shap_values.sum(1) + expected_value) > 0
misclassified = y_pred != y_test[select]
shap.decision_plot(
    expected_value, shap_values, features_display, link="logit", highlight=misclassified
)
../../../_images/example_notebooks_api_examples_plots_decision_plot_12_0.png

让我们通过单独绘制它来检查被错误分类的观察结果。当单独绘制一个观察结果时,其相应的特征值会被显示出来。注意线条的形状已经改变。为什么?特征顺序在y轴上根据这个单独观察的特征重要性发生了变化。章节“在多个图之间保持顺序和比例”展示了如何为多个图使用相同的特征顺序。

[6]:
shap.decision_plot(
    expected_value,
    shap_values[misclassified],
    features_display[misclassified],
    link="logit",
    highlight=0,
)
../../../_images/example_notebooks_api_examples_plots_decision_plot_14_0.png

下面显示了错误分类观察的力图。在这种情况下,决策图和力图都能有效地展示模型是如何做出决策的。

[7]:
shap.force_plot(
    expected_value,
    shap_values[misclassified],
    features_display[misclassified],
    link="logit",
    matplotlib=True,
)
../../../_images/example_notebooks_api_examples_plots_decision_plot_16_0.png

决策图何时有用?

决策图有几种使用场景。我们在这里展示几个案例。1. 清晰展示大量特征效果。2. 可视化多输出预测。3. 展示交互作用的累积效果。4. 探索特征值范围内的特征效果。5. 识别异常值。6. 识别典型的预测路径。7. 比较和对比多个模型的预测。

清晰展示大量功能效果

像力图一样,决策图显示了模型输出中涉及的重要特征。然而,当涉及大量重要特征时,决策图可能比力图更有帮助。为了演示,我们使用了一个基于 UCI Communities and Crime 数据集训练的模型。该模型使用了101个特征。下面的两个图描述了相同的预测。力图的水平格式使其无法清晰地显示所有重要特征。相比之下,决策图的垂直格式可以显示任意数量的特征的影响。

[8]:
# Load the prediction from disk to keep the example short.
with open("./data/crime.pickle", "rb") as fl:
    a, b, c = pickle.load(fl)
shap.force_plot(a, b, c, matplotlib=True)
../../../_images/example_notebooks_api_examples_plots_decision_plot_18_0.png
[9]:
shap.decision_plot(a, b, c, feature_display_range=slice(None, -31, -1))
../../../_images/example_notebooks_api_examples_plots_decision_plot_19_0.png

可视化多输出预测

决策图可以展示多输出模型如何得出预测结果。在这个例子中,我们使用了一个在 UCI 心脏病数据集 上训练的 Catboost 模型的 SHAP 值。有五个类别表示疾病的严重程度:类别 1 表示没有疾病;类别 5 表示疾病晚期。

为了保持示例简短,SHAP 值从磁盘加载。变量 heart_base_values 是每个类别的 SHAP 期望值列表。同样,变量 heart_shap_values 是 SHAP 矩阵列表;每个类别对应一个矩阵。这是 shap.TreeExplainer 返回的多输出格式。

[10]:
# Load all from disk to keep the example short.
with open("./data/heart.pickle", "rb") as fl:
    (
        heart_feature_names,
        heart_base_values,
        heart_shap_values,
        heart_predictions,
    ) = pickle.load(fl)
class_count = len(heart_base_values)

创建一个生成绘图图例标签的函数。提示:在图例标签中包含预测值,以帮助区分类别。

[11]:
def class_labels(row_index):
    return [
        f"Class {i + 1} ({heart_predictions[row_index, i].round(2):.2f})"
        for i in range(class_count)
    ]

使用 shap.multioutput_decision_plot 绘制观察 #2 的 SHAP 值。图表的默认基值是多输出基值的平均值。SHAP 值相应地进行了调整,以产生准确的预测。虚线(高亮)表示模型的预测类别。对于此观察,模型确信疾病存在,但无法轻易区分类别 3、4 和 5。

[12]:
row_index = 2
shap.multioutput_decision_plot(
    heart_base_values,
    heart_shap_values,
    row_index=row_index,
    feature_names=heart_feature_names,
    highlight=[np.argmax(heart_predictions[row_index])],
    legend_labels=class_labels(row_index),
    legend_location="lower right",
)
../../../_images/example_notebooks_api_examples_plots_decision_plot_25_0.png

对于观察 #3,模型自信地预测疾病不存在。

[13]:
row_index = 3
shap.multioutput_decision_plot(
    heart_base_values,
    heart_shap_values,
    row_index=row_index,
    feature_names=heart_feature_names,
    highlight=[np.argmax(heart_predictions[row_index])],
    legend_labels=class_labels(row_index),
    legend_location="lower right",
)
../../../_images/example_notebooks_api_examples_plots_decision_plot_27_0.png

显示交互的累积效应

决策图支持 SHAP 交互值:从基于树的模型中估计的一阶交互。虽然 SHAP 依赖图是可视化个体交互的最佳方式,但决策图可以显示一个或多个观测值的主要效应和交互的累积效应。

这里的决策图解释了使用主效应和交互效应的 UCI Adult Income 数据集中的单个预测。显示了20个最重要的特征。有关对交互效应支持的更多详细信息,请参阅“SHAP交互值”部分。

[14]:
shap.decision_plot(
    expected_value,
    shap_interaction_values[misclassified],
    features_display[misclassified],
    link="logit",
)
../../../_images/example_notebooks_api_examples_plots_decision_plot_29_0.png

探索一系列特征值的特征效应

决策图可以揭示预测如何随一组特征值的变化而变化。这种方法对于展示假设情景和揭示模型行为非常有用。在这个例子中,我们创建了仅在资本收益上有所不同的假设观察。

UCI 成人收入 数据集的以下参考观察开始。

[15]:
idx = 25
X_display.loc[idx]
[15]:
Age                                56
Workclass                   Local-gov
Education-Num                      13
Marital Status     Married-civ-spouse
Occupation               Tech-support
Relationship                  Husband
Race                            White
Sex                              Male
Capital Gain                        0
Capital Loss                        0
Hours per week                     40
Country                 United-States
Name: 25, dtype: object

使用参考观测的多个副本来创建一个合成数据集。将’资本收益’的值从$0-$10,000按$100的增量变化。检索相应的SHAP值。这种方法使我们能够评估和调试模型。分析师也可能发现这种方法在展示假设情景时很有用。请记住,本示例中显示的资本收益的影响是针对参考记录的,因此不能被普遍化。

[16]:
rg = range(0, 10100, 100)
R = X.iloc[np.repeat(idx, len(rg))].reset_index(drop=True)
R["Capital Gain"] = rg

with warnings.catch_warnings():
    warnings.simplefilter("ignore")
    hypothetical_shap_values = explainer.shap_values(R)[1]

hypothetical_predictions = expected_value + hypothetical_shap_values.sum(axis=1)
hypothetical_predictions = 1 / (1 + np.exp(-hypothetical_predictions))

这个依赖图展示了SHAP值在一个特征值范围内的变化。这个模型的SHAP值代表了对数几率的变化。这个图显示在$5,000附近有显著的SHAP值变化。它还显示在$0和大约$3,000处有一些显著的异常值。

[17]:
shap.dependence_plot(
    "Capital Gain", hypothetical_shap_values, R, interaction_index=None
)
../../../_images/example_notebooks_api_examples_plots_decision_plot_35_0.png

虽然依赖图很有帮助,但在上下文中很难辨别SHAP值的实际效果。为此,我们可以在概率尺度上绘制合成数据集的决策图。首先,我们绘制参考观测值以建立上下文。预测概率为0.76。资本收益为零,模型为此分配了一个小的负效应。特征已手动排序以匹配接下来的两个图。

[18]:
# The feature ordering was determined via 'hclust' on the synthetic data set. We specify the order here manually so
# the following two plots match up.
feature_idx = [8, 5, 0, 2, 4, 3, 7, 10, 6, 11, 9, 1]
shap.decision_plot(
    expected_value,
    hypothetical_shap_values[0],
    X_display.iloc[idx],
    feature_order=feature_idx,
    link="logit",
)
../../../_images/example_notebooks_api_examples_plots_decision_plot_37_0.png

现在,我们绘制合成数据。参考记录用虚线标记。特征通过层次聚类排序,以将相似的预测路径分组。我们看到,在实际应用中,资本收益的影响在很大程度上是两极分化的;只有少数预测值介于0.2和0.8之间。

[19]:
shap.decision_plot(
    expected_value,
    hypothetical_shap_values,
    R,
    link="logit",
    feature_order="hclust",
    highlight=0,
)
../../../_images/example_notebooks_api_examples_plots_decision_plot_39_0.png

进一步检查预测后,我们发现了一个大约在 $4,300 的阈值,但存在异常。资本收益为 $0, $3,000 和 $3,100 的预测异常高;资本收益为 $5,000 的预测异常低。这些异常在这里用图例标出,以帮助识别每个预测。$3,000 和 $3,100 的预测路径相同。

[20]:
def legend_labels(idx):
    return [rf"\${i * 100:,} ({hypothetical_predictions[i]:.2f})" for i in idx]


show_idx = [0, 30, 31, 50]
shap.decision_plot(
    expected_value,
    hypothetical_shap_values[show_idx],
    X,
    feature_order=feature_idx,
    link="logit",
    legend_labels=legend_labels(show_idx),
    legend_location="upper center",
)
../../../_images/example_notebooks_api_examples_plots_decision_plot_41_0.png

识别异常值

决策图可以帮助识别异常值。指定 feature_order='hclust' 以将具有相似预测路径的观察值分组。这通常使异常值更容易被发现。在绘制异常值时避免使用 link='logit',因为预测的幅度会被 sigmoid 函数扭曲。

下图显示了概率范围 [0.03, 0.1] 内的所有预测。(在此示例中排除了小于 0.03 的预测,因为它们代表大量观察结果。)有两个预测立即引人注目。’年龄’、’资本损失’ 和 ‘资本收益’ 的影响最为显著。

[21]:
y_pred = model.predict(X_test)  # Get predictions on the probability scale.
T = X_test[(y_pred >= 0.03) & (y_pred <= 0.1)]
with warnings.catch_warnings():
    warnings.simplefilter("ignore")
    sh = explainer.shap_values(T)[1]
r = shap.decision_plot(
    expected_value, sh, T, feature_order="hclust", return_objects=True
)
../../../_images/example_notebooks_api_examples_plots_decision_plot_43_0.png

根据SHAP值定位异常值,并根据其特征值绘制它们。异常值的绘制使用与原始图相同的特征顺序和比例。更多详情请参见“在图之间保留顺序和比例”。

[22]:
# Find the two observations with the most negative 'Age' SHAP values.
idx = np.argpartition(sh[:, T.columns.get_loc("Age")], 2)[0:2]

# Plot the observations individually with their corresponding feature values. The plots use the same feature order
# as the original plot.
for i in idx:
    shap.decision_plot(
        expected_value,
        sh[i],
        X_display.loc[T.index[i]],
        feature_order=r.feature_idx,
        xlim=r.xlim,
    )
../../../_images/example_notebooks_api_examples_plots_decision_plot_45_0.png
../../../_images/example_notebooks_api_examples_plots_decision_plot_45_1.png

识别典型的预测路径

决策图可以揭示模型的典型预测路径。在这里,我们绘制了概率区间 [0.98, 1.0] 内的所有预测,以查看高分预测的共同点。我们使用 'hclust' 特征排序来分组相似的预测路径。该图显示了两条不同的路径:一条由 ‘Capital Gain’ 主导,而另一条由 ‘Capital Loss’ 主导。’Relationship’、’Age’ 和 ‘Education-Num’ 的影响也很显著。

[23]:
y_pred = model.predict(X_test)  # Get predictions on the probability scale.
T = X_test[y_pred >= 0.98]
with warnings.catch_warnings():
    warnings.simplefilter("ignore")
    sh = explainer.shap_values(T)[1]
shap.decision_plot(expected_value, sh, T, feature_order="hclust", link="logit")
../../../_images/example_notebooks_api_examples_plots_decision_plot_47_0.png

比较和对比几个模型的预测

决策图对于比较不同模型的预测,或解释模型集合的预测非常有用。在这个例子中,我们绘制了在 UCI Adult Income 数据集上训练的五个 LightGBM 模型的预测结果。在这个例子中,我们创建了一个包含五个模型的集合,并使用 shap.multioutput_decision_plot 绘制了这些模型的预测结果。

使用5折交叉验证训练五个LightGBM模型的集成。

[26]:
model_count = 5
skf = StratifiedKFold(model_count, True, random_state=random_state)
models = []
for t, v in skf.split(X, y):
    m = lgb.LGBMClassifier(**params, n_estimators=1000)
    m.fit(
        X.iloc[t],
        y[t],
        eval_set=(X.iloc[v], y[v]),
        early_stopping_rounds=50,
        verbose=False,
    )
    score = m.best_score_["valid_0"]["binary_logloss"]
    print(f"Best score: {score}")
    models.append(m)
Best score: 0.28279460948508833
Best score: 0.2743920496745268
Best score: 0.2706647518976772
Best score: 0.2809048231217079
Best score: 0.2785044277595166

将模型的基础值和 SHAP 值组合成列表。这模拟了 shap 包对多输出模型的输出。

[27]:
def get_ensemble_shap_values(models, X):
    base_values = [None] * model_count
    shap_values = [None] * model_count
    predictions = [None] * model_count
    for i, m in enumerate(models):
        a = m.predict(
            X, pred_contrib=True
        )  # `pred_contrib=True` returns SHAP values for LightGBM
        base_values[i] = a[0, -1]  # The last column in the matrix is the base value.
        shap_values[i] = a[:, 0:-1]
        predictions[i] = 1 / (
            1 + np.exp(-a.sum(axis=1)[0])
        )  # Predictions as probabilities
    return base_values, shap_values, predictions

从集成模型中获取单个观测值的SHAP值。

[28]:
(
    ensemble_base_values,
    ensemble_shap_values,
    ensemble_predictions,
) = get_ensemble_shap_values(models, X.iloc[[27]])

绘制 SHAP 值。图例标识每个模型的预测。提示:在图例标签中包含预测值,以帮助区分模型。

如果概率 0.5 是我们这个二分类任务的截断值,我们可以看到这个观测值很难分类。然而,模型 2 确信该个体每年的收入低于 $50K。如果这是一个典型的观测值,那么可能值得研究为什么这个模型的预测会有所不同。

[29]:
# Create labels for legend
labels = [
    f"Model {i + 1} ({ensemble_predictions[i].round(2):.2f})"
    for i in range(model_count)
]

# Plot
shap.multioutput_decision_plot(
    ensemble_base_values,
    ensemble_shap_values,
    0,
    feature_names=X.columns.to_list(),
    link="logit",
    legend_labels=labels,
    legend_location="lower right",
)
../../../_images/example_notebooks_api_examples_plots_decision_plot_55_0.png

SHAP 交互值

决策图支持如这里所示的SHAP交互值。注意,线条并没有完全在图的底部收敛到 explainer.expected_value。这是因为包括交互和主要效应在内共有N(N + 1)/2 = 12(13)/2 = 78个特征,但决策图默认只显示20个最重要的特征。请参阅“选择要显示的特征”部分,了解如何显示更多特征。

[30]:
shap.decision_plot(expected_value, shap_interaction_values, features, link="logit")
../../../_images/example_notebooks_api_examples_plots_decision_plot_57_0.png

决策图将三维的 SHAP 交互结构转换为标准的二维 SHAP 矩阵。它还会生成相应的特征标签。通过设置 return_objects=True,可以从决策图中检索这些结构。在这个例子中,我们通过设置 show=False 来省略绘图。

[31]:
r = shap.decision_plot(
    expected_value,
    shap_interaction_values,
    features,
    link="logit",
    show=False,
    return_objects=True,
)
plt.close()
print(f"SHAP dimensions: {r.shap_values.shape}", "\n")
pprint(r.feature_names[:-11:-1])
SHAP dimensions: (20, 78)

['Age',
 'Relationship',
 'Capital Gain',
 'Hours per week',
 'Education-Num',
 'Occupation',
 'Marital Status',
 'Sex',
 'Age *\nOccupation',
 'Marital Status *\nRelationship']

在图表之间保持顺序和比例

通常,使用相同的特征顺序和x轴刻度创建几个决策图有助于直接比较。当 return_objects=True 时,决策图返回可用于后续绘图的绘图结构。

[32]:
# Create the first plot, returning the plot structures.
r = shap.decision_plot(
    expected_value, shap_values, features_display, return_objects=True
)
../../../_images/example_notebooks_api_examples_plots_decision_plot_62_0.png
[33]:
# Create another plot using the same feature order and x-axis extents.
idx = 9
shap.decision_plot(
    expected_value,
    shap_values[idx],
    features_display.iloc[idx],
    feature_order=r.feature_idx,
    xlim=r.xlim,
)
../../../_images/example_notebooks_api_examples_plots_decision_plot_63_0.png

选择要显示的特征

决策图中显示的特征由两个参数控制:feature_orderfeature_display_rangefeature_order 参数决定了特征在显示前的排序方式。feature_display_range 参数决定了哪些排序后的特征会被显示。它接受一个 slicerange 对象作为参数。feature_display_range 参数还控制特征是按升序还是降序绘制。

例如,如果 feature_order='importance'``(默认),决策图在显示前会按重要性*升序*排列特征。如果 ``feature_display_range=slice(-1, -21, -1)``(默认),图表会按降序显示最后(即最重要的)20个特征。对象 ``slice(-1, -21, -1) 被解释为“从最后一个特征开始,以-1为步长迭代到倒数第21个特征。”终点-21不包括在内。

feature_display_range 参数在应用 'hclust' 排序时尤为重要。在这种情况下,许多重要特征位于特征范围的开始部分。然而,决策图默认显示特征范围的末尾。

以下图表展示了使用 'hclust' 排序的78个SHAP交互特征中的前10个。注意:因为我们只显示前10个特征,观察结果不会在其最终预测值处击中x轴。 代码片段 feature_display_range=range(10, -1, -1) 表示我们从特征10开始,以-1为步长计数到特征-1。范围的终点不包括在内。因此,我们看到了特征10到0。

[34]:
shap.decision_plot(
    expected_value,
    shap_interaction_values,
    features,
    link="logit",
    feature_order="hclust",
    feature_display_range=range(10, -1, -1),
)
../../../_images/example_notebooks_api_examples_plots_decision_plot_65_0.png

我们可以通过指定一个升序范围来生成相同的图:range(0, 11, 1)

[35]:
shap.decision_plot(
    expected_value,
    shap_interaction_values,
    features,
    link="logit",
    feature_order="hclust",
    feature_display_range=range(0, 11, 1),
)
../../../_images/example_notebooks_api_examples_plots_decision_plot_67_0.png

在选择范围内的最后几个特征时,使用切片更为方便,因为切片支持负索引。例如,索引 -20 表示从末尾开始的第 20 个项目。以下图表显示了按降序 'hclust' 排列的最后 10 个特征。

[36]:
shap.decision_plot(
    expected_value,
    shap_interaction_values,
    features,
    link="logit",
    feature_order="hclust",
    feature_display_range=slice(None, -11, -1),
)
../../../_images/example_notebooks_api_examples_plots_decision_plot_69_0.png

我们可以通过多种方式显示所有可用的功能。最简单的方式是 feature_display_range=slice(None, None, -1)注意:如果你的数据集包含许多特征,这将生成非常大的图表。

[37]:
shap.decision_plot(
    expected_value,
    shap_interaction_values,
    features,
    link="logit",
    feature_order="hclust",
    feature_display_range=slice(None, None, -1),
)
../../../_images/example_notebooks_api_examples_plots_decision_plot_71_0.png

更改 SHAP 基值

SHAP 值都是相对于某个基准值的。默认情况下,基准值是 explainer.expected_value:训练数据的原始模型预测的均值。

[38]:
# The model's training mean
print(model.predict(X_train, raw_score=True).mean().round(4))

# The explainer expected value
print(expected_value.round(4))
-2.4297
-2.4297

要获得原始预测值,将 explainer.expected_value 加上每个观测值的 SHAP 值之和。

[39]:
# The model's raw prediction for the first observation.
print(model.predict(features.iloc[[0]].values, raw_score=True)[0].round(4))

# The corresponding sum of the mean + shap values
print((expected_value + shap_values[0].sum()).round(4))
-3.1866
-3.1866

因此,必须向决策图提供 explainer.expected_value 以生成正确的预测。

在决策图中,基值是每个预测在图底部的起始值。使用 explainer.expected_value 作为基值并不总是视觉上直观的。考虑一个逻辑分类问题。如果我们选择概率 0.4 作为我们的截止值,如果预测在截止点收敛而不是 explainer.expected_value,可能会更有意义。为此,决策图提供了 new_base_value 参数。它将 SHAP 基值移动到一个任意点,而不改变预测值。

在这个例子中,我们将概率 0.4 指定为新的基准值。因为我们的模型的 SHAP 值是以对数几率表示的,所以在传递给决策图之前,我们将概率转换为对数几率。link='logit' 参数将基准值和 SHAP 值转换为概率。

[40]:
p = 0.4  # Probability 0.4
new_base_value = np.log(p / (1 - p))  # the logit function
shap.decision_plot(
    expected_value,
    shap_values,
    features_display,
    link="logit",
    new_base_value=new_base_value,
)
../../../_images/example_notebooks_api_examples_plots_decision_plot_77_0.png

作为对比,这里展示了使用原始基准值的决策图。

[41]:
shap.decision_plot(expected_value, shap_values, features_display, link="logit")
../../../_images/example_notebooks_api_examples_plots_decision_plot_79_0.png