【DAY14】SHAP图介绍

参考帖子:SHAP 可视化解释机器学习模型简介_shap图-CSDN博客

今日作业偏思考类型,有一定难度(暂未完成,等第二遍回来学再二编)

  1. 参考上述文档补全剩余的几个图
  2. 尝试确定一下shap各个绘图函数对于每一个参数的尺寸要求,如shap.force_plot力图中的数据需要满足什么形状?
  3. 确定分类问题和回归问题的数据如何才能满足尺寸,分类采取信贷数据集,回归采取单车数据集。

目录

一编(小白学习)

SHAP是什么?

3个核心概念

1. 基线值(Base Value)

2. SHAP值(Shapley Value)

3. 模型预测值

跑一遍简单代码

1. 准备数据(超级简单版)

2. 计算SHAP值(自动生成“配料账单”)

3. 画图解读(看图说话)

3.1 单个样本分析(force_plot)

3.2 全局特征重要性(summary_plot)

3.2.1 SHAP 特征重要性蜂巢图 (Summary Plot - Beeswarm) 

3.2.2 SHAP 特征重要性条形图 (Summary Plot - Bar)

3.2.3 SHAP 特征重要性小提琴图 (Summary Plot - Violin)


一编(小白学习)

SHAP是什么?

目标:理解复杂机器学习模型(尤其是“黑箱”模型,如随机森林、梯度提升树、神经网络等)为什么会对特定输入做出特定预测。 SHAP 提供了一种统一的方法来解释模型的输出。

PS:黑箱模型就像一个封闭的黑箱子,你往里面输入数据,它会输出结果,但是你很难知道箱子内部是怎么把输入转换成输出的。

核心思想:合作博弈论中的 Shapley 值(量化每个特征对模型预测结果的正向或负向影响。)

比喻:SHAP就像一份“披萨账单”,告诉你每种配料(特征)对总价格(预测结果)的贡献。

  • 比如总价20元,芝士贡献+8元,辣椒贡献+2元,菠萝扣了-5元(因为有人讨厌菠萝)。

3个核心概念

1. 基线值(Base Value)

比喻:披萨的“基础价格”——不放任何配料的空白披萨价格。

  • 比如所有披萨的平均价格是15元,这就是基线值。

2. SHAP值(Shapley Value)

比喻:每种配料带来的价格变化

  • 芝士:+8元 → SHAP值=+8

  • 菠萝:-5元 → SHAP值=-5

3. 模型预测值

公式预测值 = 基线值 + 所有SHAP值的和

  • 例如:15(基线) +8(芝士) +2(辣椒) -5(菠萝) =20元

跑一遍简单代码

# 1. 安装库(就像安装手机APP)
# !pip install shap 
# 我在anaconda环境下安装的
# pip install shap -i https://pypi.tuna.tsinghua.edu.cn/simple

# 2. 导入库(就像打开APP)
import shap
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier  # 随便选一个模型

任务:预测一个人是否患糖尿病(0=健康,1=患病)

1. 准备数据(超级简单版)

# 假设有3个特征(年龄、血糖、BMI),4个样本
data = {
    '年龄': [25, 60, 45, 30],
    '血糖': [80, 160, 120, 90],
    'BMI': [22, 30, 28, 24]
}
X = pd.DataFrame(data)
y = np.array([0, 1, 1, 0])  # 标签:是否患病

# 训练一个模型(就像教小孩认图)
model = RandomForestClassifier()
model.fit(X, y)

2. 计算SHAP值(自动生成“配料账单”)

# 创建解释器(就像收银机)
explainer = shap.Explainer(model)

# 计算SHAP值(计算每个特征的贡献)
shap_values = explainer(X)

# 查看基线值(空白披萨价格)
print("基线值:", explainer.expected_value)  

输出为:
基线值: [0.5375 0.4625]

3. 画图解读(看图说话)

 检查一下

print(type(shap_values))

输出为:
<class 'numpy.ndarray'>
shap_values
# 每一行代表一个样本,每一列代表一个特征,值表示该特征对该样本的预测结果的影响程度。
# 正值表示该特征对预测结果有正向影响,负值表示负向影响。

输出为:
array([[[ 0.1475, -0.1475],
        [ 0.12  , -0.12  ],
        [ 0.155 , -0.155 ]],

       [[-0.1425,  0.1425],
        [-0.16  ,  0.16  ],
        [-0.195 ,  0.195 ]],

       [[-0.0925,  0.0925],
        [-0.08  ,  0.08  ],
        [-0.195 ,  0.195 ]],

       [[ 0.1475, -0.1475],
        [ 0.12  , -0.12  ],
        [ 0.155 , -0.155 ]]])
shap_values.shape # 第一维是样本数,第二维是特征数,第三维是类别数

输出为:
(4, 3, 2)
# 打印 shap_values 数组的整体形状
# shap_values 通常是通过 SHAP 解释器计算得到的用于表示特征对模型预测结果贡献的数组
# 这里输出的形状信息可以帮助我们了解数据的维度结构,例如对于分类问题可能涉及样本数、特征数和类别数等维度
print("shap_values shape:", shap_values.shape)

# 打印 shap_values 数组中第一个元素(索引为 0)的形状
# 在某些情况下,shap_values 可能是一个包含多个数组的列表或多维数组
# 这里查看第一个元素的形状可以进一步分析其内部结构,比如在分类问题中可能对应某个类别的特征贡献数组
print("shap_values[0] shape:", shap_values[0].shape)

# 打印 shap_values 数组中所有样本、所有特征在第一个类别(索引为 0)下的子数组形状
# 通过这种切片操作,我们可以聚焦于特定类别的特征贡献情况
# 输出的形状信息有助于我们理解在这个特定类别下,样本和特征的维度关系
print("shap_values[:, :, 0] shape:", shap_values[:, :, 0].shape)

输出为:
shap_values shape: (4, 3, 2)
shap_values[0] shape: (3, 2)
shap_values[:, :, 0] shape: (4, 3)

调整一下图(第一次忘记搞,输出的图中显示不出中文)

import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置中文字体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题
3.1 单个样本分析(force_plot)
错误代码!
# 分析第2个人为什么被预测为患病(索引=1)
shap.force_plot(
    base_value=explainer.expected_value[1],  # 注意分类问题要选类别索引
    shap_values=shap_values[1][1,:],         # [样本索引][类别, 特征]
    features=X.iloc[1,:],                    # 第2个人的特征值
    matplotlib=True                          # 用Matplotlib显示(适合小白)
)

以后要格外注意!这步卡的我想鼠!!

分类问题和回归问题输出的shap_values的形状不同:

- 分类问题:shap_values.shape =(n_samples, n_features, n_classes)

- 回归问题:shap_values.shape = (n_samples, n_features)

数据维度的要求将是未来学习神经网络最重要的东西之一。

# 确保 shap_values 是 (n_samples, n_features, n_classes) 形状
if isinstance(shap_values, list):
    shap_values = np.stack(shap_values, axis=-1)

# 分析第2个人为什么被预测为患病(索引=1),假设关注类别 1
sample_index = 1
class_index = 1

shap.force_plot(
    base_value=explainer.expected_value[class_index],
    shap_values=shap_values[sample_index, :, class_index],
    features=X.iloc[sample_index, :],
    matplotlib=True
)
plt.show()

解读该图

  • 基线值:图中未明确给出具体数值,仅标记 “base value”,是模型预测的起始参考值
  • 年龄 = 60.0 :对最终预测值有正向贡献,使预测值高于基线值,增加患病可能性
  • 血糖 = 160.0 :对最终预测值有正向贡献,使预测值高于基线值,增加患病可能性
  • BMI = 30.0 :对最终预测值有正向贡献,使预测值高于基线值,增加患病可能性
  • 最终预测值:f (x) = 0.96 ,高于常见二分类阈值 0.5(模型实际阈值需依建模设定),倾向于预测为患病

3.2 全局特征重要性(summary_plot)
3.2.1 SHAP 特征重要性蜂巢图 (Summary Plot - Beeswarm) 
# 确保 shap_values 是 (n_samples, n_features, n_classes) 形状
if isinstance(shap_values, list):
    shap_values = np.stack(shap_values, axis=-1)

# --- 1. SHAP 特征重要性蜂巢图 (Summary Plot - Beeswarm) ---
print("--- 1. SHAP 特征重要性蜂巢图 ---")
shap.summary_plot(shap_values[:, :, 0], features=X, feature_names=X.columns, show=False, max_display=10)
plt.title("SHAP Feature Importance (Beeswarm Plot)")
plt.show()

# 我第一次代码 打印出来的图一模一样
# shap.summary_plot(shap_values[:, :, 0], X)  # 只看类别1(患病)的贡献

--- 1. SHAP 特征重要性蜂巢图 (Summary Plot - Beeswarm) ---

  • 每个点代表一个样本的特征贡献

  • BMI的SHAP值分布最广 → 对预测影响最大

  • 红色表示特征值高(如血糖=160),蓝色表示低(血糖=80)

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

--- 2. SHAP 特征重要性条形图 ---

3.2.3 SHAP 特征重要性小提琴图 (Summary Plot - Violin)
# --- 3. SHAP 特征重要性小提琴图 (Summary Plot - Violin) ---
print("--- 3. SHAP 特征重要性小提琴图 ---")
shap.summary_plot(shap_values[:, :, 0],features=X, feature_names=X.columns, plot_type="violin",show=False,max_display=10) # 这里的show=False表示不直接显示图形,这样可以继续用plt来修改元素,不然就直接输出了
plt.title("SHAP Feature Importance (Violin Plot)")
plt.show()

--- 3. SHAP 特征重要性小提琴图 ---

内容来自@浙大疏锦行python打卡训练营

​​​​​​@浙大疏锦行

### MATLAB 中绘制 SHAP 蜂群的方法 SHAP (SHapley Additive exPlanations) 是一种用于解释机器学习模型预测结果的技术。虽然 SHAP 值通常与 Python 库 `shap` 结合使用,但在 MATLAB 中也可以通过自定义绘函数来实现类似的可视化效果。 以下是基于 SHAP 数据在 MATLAB 中绘制蜂群的核心方法: #### 1. 准备数据 为了绘制 SHAP 蜂群,需要准备两个主要的数据集: - **特征值矩阵**:表示输入样本的各个特征值。 - **SHAP 值矩阵**:对应于每个样本及其特征的重要性得分。 假设已经计算好了这些数据,则可以按照如下方式处理[^1]。 ```matlab % 示例数据 featureValues = rand(100, 5); % 特征值矩阵 (100个样本, 5个特征) shapValues = randn(100, 5); % SHAP值矩阵 (100个样本, 对应5个特征) % 计算特征均值作为参考点 meanFeatureValues = mean(featureValues); ``` #### 2. 创建蜂群布局 蜂群的关键在于合理分布点的位置以避免重叠并保持清晰可读性。可以通过调整角度和半径的方式模拟这种布局[^2]。 ```matlab function [xPos, yPos] = createSwarmPositions(values, jitterFactor) nPoints = length(values); angles = linspace(0, 2*pi, nPoints + 1); % 圆周上均匀分配的角度 radii = abs(values) * jitterFactor; % 半径大小取决于绝对值 xPos = cos(angles(1:nPoints)) .* radii; yPos = sin(angles(1:nPoints)) .* radii; end ``` 调用此函数生成每列特征对应的坐标位置。 #### 3. 可视化部分 利用上述辅助函数完成最终形渲染过程。 ```matlab figure; for i = 1:size(shapValues, 2) featureName = sprintf('Feature %d', i); % 获取当前特征的相关数据 currentShap = shapValues(:, i); currentValue = featureValues(:, i); % 使用createSwarmPositions创建散点所需坐标 [swarmX, swarmY] = createSwarmPositions(currentValue, 0.1); scatter(swarmX, swarmY, [], currentShap, 'filled'); hold on; % 添加平均线指示器 plot([min(swarmX), max(swarmX)], [meanFeatureValues(i), meanFeatureValues(i)], ... '-k', 'LineWidth', 1.5); end xlabel('Jittered Position'); ylabel('Feature Value or Mean Reference'); title('SHAP Swarm Plot in MATLAB'); colorbar; colormap jet; legend({'Feature Impact'}, 'Location','bestoutside'); grid minor; axis equal tight; hold off; ``` 以上代码片段展示了如何手动构建一个接近标准库功能的效果[^3]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值