python训练day14 shap图绘制

SHAP 原理

目标:

理解复杂机器学习模型(尤其是“黑箱”模型,如随机森林、梯度提升树、神经网络等)

为什么会对特定输入做出特定预测。 SHAP 提供了一种统一的方法来解释模型的输出。

核心思想:

合作博弈论中的 Shapley 值

SHAP (SHapley Additive exPlanations) 的核心基于博弈论中的 Shapley 值概念。

想象一个合作游戏:

1. 玩家 (Players)::模型的特征 (Features) 就是玩家。

2. 游戏 (Game):目标是预测某个样本的输出值。

3. 合作 (Coalition):不同的特征子集可以“合作”起来进行预测。

4. 奖励/价值 (Payout/Value):某个特征子集进行预测得到的值。

5. 目标:如何公平地将最终预测结果(相对于平均预测结果的“收益”)分配给每个参与的特征(玩家)?

Shapley 值的计算思路(概念上):

为了计算一个特定特征(比如“特征 A”)对某个预测的贡献(它的 Shapley 值),SHAP 会考虑:

1. 所有可能的特征组合(子集/联盟):从没有特征开始,到包含所有特征。

2. 特征 A 的边际贡献:对于**每一个特征组合,比较“包含特征 A 的组合的预测值”与“不包含特征 A 但包含其他相同特征的组合的预测值”之间的差异。这个差异就是特征 A 在这个特定组合下的“边际贡献”。

3. 加权平均:Shapley 值是该特征在所有可能**的特征组合中边际贡献的加权平均值。权重确保了分配的公平性。

SHAP 的关键特性 (加性解释 - Additive Explanations):

SHAP 的一个重要特性是加性 (Additive)。这意味着:

基准值 (Base Value / Expected Value):这是模型在整个训练(或背景)数据集上的平均预测输出。可以理解为没有任何特征信息时的“默认”预测。

SHAP 值之和:对于任何一个样本的预测,所有特征的 SHAP 值加起来,再加上基准值,就精确地等于该样本的模型预测值。

模型预测值(样本 X) = 基准值 + SHAP值(特征1) + SHAP值(特征2) + ... + SHAP值(特征N)

为什么会生成 `shap_values` 数组?

根据上述原理,SHAP 需要为每个样本的每个特征计算一个贡献值(SHAP 值):

1. 解释单个预测:SHAP 的核心是解释单个预测结果。

2. 特征贡献:对于这个预测,我们需要知道**每个特征**是把它往“高”推了,还是往“低”推了(相对于基准值),以及推了多少。

3. 数值化:这个“推力”的大小和方向就是该特征对该样本预测的SHAP 值。

因此:

对于回归问题:

模型只有一个输出。

对 `n_samples` 个样本中的每一个,计算 `n_features` 个特征各自的 SHAP 值。

这就自然形成了形状为 `(n_samples, n_features)` 的数组。 `shap_values[i, j]` 代表第 `i` 个样本的第 `j` 个特征对该样本预测值的贡献。

对于分类问题:

模型通常为每个类别输出一个分数或概率。

SHAP 需要解释模型是如何得到每个类别的分数的。

因此,对 `n_samples` 个样本中的每一个,分别为每个类别计算 `n_features` 个特征的 SHAP 值。

最常见的组织方式是返回一个列表,列表长度等于类别数。列表的第 `k` 个元素是一个 `(n_samples, n_features)` 的数组,表示所有样本的所有特征对预测类别 `k`的贡献。

`shap_values[k][i, j]` 代表第 `i` 个样本的第 `j` 个特征对该样本预测类别 `k`的贡献。

总结:

SHAP 通过计算每个特征对单个预测(相对于平均预测)的边际贡献(Shapley 值),提供了一种将模型预测分解到每个特征上的方法。这种分解对于每个样本和每个特征(以及分类问题中的每个类别)都需要进行,因此生成了我们看到的 `shap_values` 数组结构。

import shap
import matplotlib.pyplot as plt

# 初始化 SHAP 解释器
explainer = shap.TreeExplainer(rf_model)

# 计算 SHAP 值(基于测试集),这个shap_values是一个numpy数组,表示每个特征对每个样本的贡献值
shap_values = explainer.shap_values(X_test) # 这个计算耗时


#数学维度
shap_values # 每一行代表一个样本,每一列代表一个特征,值表示该特征对该样本的预测结果的影响程度。正值表示该特征对预测结果有正向影响,负值表示负向影响。

shap_values.shape # 第一维是样本数,第二维是特征数,第三维是类别数

print("shap_values shape:", shap_values.shape)
print("shap_values[0] shape:", shap_values[0].shape)
print("shap_values[:, :, 0] shape:", shap_values[:, :, 0].shape)
print("X_test shape:", X_test.shape)

# --- 1. SHAP 特征重要性条形图 (Summary Plot - Bar) ---
print("--- 1. SHAP 特征重要性条形图 ---")
shap.summary_plot(shap_values[:, :, 0], X_test, plot_type="bar",show=False)  #  这里的show=False表示不直接显示图形,这样可以继续用plt来修改元素,不然就直接输出了
plt.title("SHAP Feature Importance (Bar Plot)")
plt.show()


# --- 2. SHAP 特征重要性蜂巢图 (Summary Plot - Violin) ---
print("--- 2. SHAP 特征重要性蜂巢图 ---")
shap.summary_plot(shap_values[:, :, 0], X_test,plot_type="violin",show=False,max_display=10) # 这里的show=False表示不直接显示图形,这样可以继续用plt来修改元素,不然就直接输出了
plt.title("SHAP Feature Importance (Violin Plot)")
plt.show()
# 注意下上面几个参数,plot_type可以是bar和violin,max_display表示显示前多少个特征,默认是20个

base_value :标量值,代表模型的基线预测值。
shap_values :一维数组,长度需要和特征数量一致,代表每个特征对预测结果的贡献。
features :一维数组或 Pandas 的 Series ,长度和 shap_values 一致,代表输入样本的特征值shap_values :二维数组,形状为 (样本数, 特征数) ,代表每个样本的每个特征的 SHAP 值。
features :二维数组或 Pandas 的 DataFrame ,形状为 (样本数, 特征数) ,代表输入的特征矩阵。
shap.dependence_plot

ind :字符串或整数,代表要绘制的特征的名称或索引。
shap_values :二维数组,形状为 (样本数, 特征数) 。
features :二维数组或 Pandas 的 DataFrame ,形状为 (样本数, 特征数

import shap
import xgboost
import pandas as pd
 
 
X, y = shap.datasets.adult()
model = xgboost.XGBClassifier(eval_metric='mlogloss').fit(X, y)
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X)
 
# 汇总图
shap.summary_plot(shap_values, X)
 
# 力引导图
shap.force_plot(explainer.expected_value, shap_values[0,:], X.iloc[0,:])
 
# 依赖图
shap.dependence_plot("Age", shap_values, X)
 
# 决策图
shap.decision_plot(explainer.expected_value, shap_values[0], X.columns)
 
 
#分类
import shap
import xgboost
import pandas as pd
 
# 数据集
data = pd.read_csv('data.csv')
X = data.iloc[:, 1:]
y = data.iloc[:, 0]
 
# 训练分类模型
model = xgboost.XGBClassifier(eval_metric='mlogloss').fit(X, y)
 
# 创建解释器并计算 SHAP 值
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X)
 
# 绘制汇总图
shap.summary_plot(shap_values, X)
 
#回归
import shap
import xgboost
import pandas as pd
 
# 加载数据集
data = pd.read_csv('data.csv')
X = data.iloc[:, 1:]
y = data.iloc[:, 0]
 
# 训练回归模型
model = xgboost.XGBRegressor().fit(X, y)
 
# 创建解释器并计算 SHAP 值
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X)
 
# 绘制汇总图
shap.summary_plot(shap_values, X)
 

https://blog.csdn.net/qq_68017428/article/details/148290680

@浙大疏锦行

你可能感兴趣的:(python训练,python,开发语言,人工智能)