期刊配图:SHAP蜂巢图与柱状图多维组合解读特征对模型的影响

机器学习向量数据库大模型

picture.image

背景

picture.image

picture.image

本次尝试旨在复现Fig. 4的可视化思想,通过结合SHAP蜂巢图和柱状图,直观展示各特征对模型输出的影响及其平均重要性分布

代码实现

模型构建


          
import pandas as pd
          
import numpy as np
          
import matplotlib.pyplot as plt
          
plt.rcParams['font.family'] = 'Times New Roman'
          
plt.rcParams['axes.unicode_minus'] = False
          
from sklearn.model_selection import train_test_split
          
df = pd.read_excel('2024-12-30公众号Python机器学习AI.xlsx')
          
# 划分特征和目标变量
          
X = df.drop(['y'], axis=1)
          
y = df['y']
          
# 划分训练集和测试集
          
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, 
          
                                                    random_state=42, stratify=df['y'])
          
                                                    
          
from xgboost import XGBClassifier
          
from sklearn.model_selection import GridSearchCV, StratifiedKFold
          
from sklearn.metrics import accuracy_score
          

          
# 定义 XGBoost 二分类模型
          
model_xgb = XGBClassifier(use_label_encoder=False, eval_metric='logloss', random_state=8)
          

          
# 定义参数网格
          
param_grid = {
          
    'n_estimators': [50, 100, 200],
          
    'max_depth': [3, 5, 7],
          
    'learning_rate': [0.01, 0.1, 0.2],
          
    'subsample': [0.8, 1.0],
          
    'colsample_bytree': [0.8, 1.0]
          
}
          

          
# 定义 K 折交叉验证 (Stratified K-Fold)
          
kfold = StratifiedKFold(n_splits=5, shuffle=True, random_state=8)
          

          
# 使用网格搜索寻找最佳参数
          
grid_search = GridSearchCV(estimator=model_xgb, param_grid=param_grid, scoring='accuracy',
          
                           cv=kfold, verbose=1, n_jobs=-1)
          

          
# 拟合模型
          
grid_search.fit(X_train, y_train)
          
# 使用最优参数训练模型
          
xgboost = grid_search.best_estimator_
      

通过网格搜索和交叉验证优化XGBoost二分类模型的超参数,并使用最佳参数在训练集上训练模型,为后续使用SHAP分析特征重要性提供基础的模型构建

通过调用函数绘图


          
import shap
          
explainer = shap.TreeExplainer(xgboost)
          
shap_values = explainer.shap_values(X_test)
      

picture.image


          
plt.figure(figsize=(10, 5), dpi=1200)
          
shap.summary_plot(shap_values, X_test, plot_type="bar", show=False)
          
plt.title('SHAP_numpy Sorted Feature Importance')
          
plt.tight_layout()
          
plt.savefig("2.pdf", format='pdf',bbox_inches='tight')
          
plt.show()
      

picture.image

分两部分绘制并保存SHAP特征重要性的可视化图:

  • 第一部分使用summary_plot函数以"点图"的形式展示每个特征的SHAP值分布和平均重要性。每个点代表数据集中样本在对应特征上的SHAP值,x轴表示SHAP值大小,点沿特征行堆叠显示密度,颜色表示特征原始值的大小,全面体现特征对模型输出的贡献
  • 第二部分再次调用summary_plot函数,以"柱状图"的形式可视化特征的平均SHAP值绝对值,展示特征的重要性排序及对模型预测的总体贡献

这里都是通过调用SHAP的summary_plot函数进行绘制

自定义绘制


          
from matplotlib.colors import LinearSegmentedColormap
          
from matplotlib import gridspec
          
from scipy.spatial import KDTree
          

          
shap_values_df = pd.DataFrame(shap_values, columns=X_test.columns)
          
# 计算 mean(|SHAP value|) 并排序特征
          
mean_abs_shap_values = shap_values_df.abs().mean().sort_values(ascending=False)
          
sorted_features = mean_abs_shap_values.index
          

          
# 创建绘图数据
          
plot_data = []
          
for feature in sorted_features:
          
    for shap_val, feature_val in zip(
          
        shap_values_df[feature], X_test[feature]
          
    ):
          
        normalized_value = (feature_val - X_test[feature].min()) / (
          
            X_test[feature].max() - X_test[feature].min()
          
        )  # 动态标准化
          
        plot_data.append(
          
            {"Feature": feature, "SHAP Value": shap_val, "Normalized Value": normalized_value}
          
        )
          

          
plot_df = pd.DataFrame(plot_data)
          

          
# 创建深蓝-淡灰-深红渐变色
          
custom_cmap = LinearSegmentedColormap.from_list("custom", ["#3465A4", "#E6E6E6", "#CC3333"])
          

          
# 创建 KDTree 用于计算邻近点
          
all_points = plot_df["SHAP Value"].values.reshape(-1, 1)  # SHAP Value 作为坐标
          
tree = KDTree(all_points)
          

          
# 定义抖动范围和距离阈值
          
jitter_scale = 0.15  # 抖动强度
          
distance_threshold = 0.05  # 距离阈值,决定是否抖动
          

          
# 创建图形和网格布局
          
fig = plt.figure(figsize=(12, 8))  # 调整图形大小
          
gs = gridspec.GridSpec(2, 1, height_ratios=[0.05, 0.85])  # 上方0.05部分用于颜色条
          

          
# 创建主绘图区域
          
ax = plt.subplot(gs[1])
          

          
for i, feature in enumerate(sorted_features):
          
    # 筛选每个特征的数据
          
    subset = plot_df[plot_df["Feature"] == feature]
          
    shap_values = subset["SHAP Value"].values
          

          
    # 初始化抖动数组
          
    jitter = np.zeros(len(shap_values))
          

          
    # 遍历每个点,判断是否需要抖动
          
    for idx, shap_value in enumerate(shap_values):
          
        # 查询邻近点数量
          
        neighbors = tree.query_ball_point([shap_value], r=distance_threshold)
          
        if len(neighbors) > 1:  # 如果邻近点数量大于1,则参与抖动
          
            jitter[idx] = np.random.normal(loc=0, scale=jitter_scale)
          

          
    # 绘制散点
          
    ax.scatter(
          
        subset["SHAP Value"], 
          
        jitter + i,  # y 轴位置加上抖动
          
        c=subset["Normalized Value"],  # 使用标准化后的值进行颜色映射
          
        cmap=custom_cmap,  # 使用自定义配色
          
        s=15, 
          
        alpha=0.7,
          
    )
          

          
# 添加 SHAP Value = 0 的灰色虚线
          
ax.axvline(x=0, color="gray", linestyle="--", linewidth=1.5, alpha=0.5)
          

          

          
# 设置图形标签
          
ax.set_xlabel("SHAP Value (Impact on Model Output)", fontsize=14)  # 调整字体大小
          
ax.set_ylabel("Features", fontsize=14)
          
ax.set_yticks(range(len(sorted_features)))
          
ax.set_yticklabels(sorted_features, fontsize=12)
          
ax.invert_yaxis()  # 反转 y 轴,使最重要的特征在顶部
          

          
# 移除网格线
          
ax.grid(False)
          

          
# 创建颜色条区域
          
cax = plt.subplot(gs[0])  # 独立的颜色条轴
          
sm = plt.cm.ScalarMappable(cmap=custom_cmap)
          
sm.set_array([])  # 颜色条无固定刻度值
          
cbar = fig.colorbar(sm, cax=cax, orientation="horizontal")
          
cbar.outline.set_visible(False)  # 去掉颜色条的黑边
          
cbar.ax.tick_params(labelsize=10)  # 调整刻度字体大小
          
cbar.ax.xaxis.set_ticks([])  # 隐藏刻度
          
cbar.ax.set_title("Feature Value", fontsize=14, pad=10)  # 显示统一的标题
          
cbar.ax.text(-0.02, 0.5, "Low", ha="center", va="center", transform=cbar.ax.transAxes, fontsize=12)
          
cbar.ax.text(1.02, 0.5, "High", ha="center", va="center", transform=cbar.ax.transAxes, fontsize=12)
          

          
# 调整布局
          
plt.subplots_adjust(top=0.92)  # 为颜色条和标题腾出空间
          
plt.savefig("3.pdf", format='pdf', bbox_inches='tight', dpi=1200)
          
plt.show()
      

picture.image

手动实现一个自定义的SHAP蜂巢图,通过动态标准化特征值、抖动处理密集点、颜色渐变表示特征值大小,并绘制每个特征的SHAP值分布及其对模型输出的影响

与原始代码的主要区别在于:

  • 手动实现:这段代码不依赖SHAP库的summary_plot,而是手动构建了一个更灵活的自定义可视化,支持动态调整布局和配色
  • 抖动处理:通过KDTree和距离阈值对重叠点进行抖动,增强了图形的可读性
  • 颜色映射和自定义颜色条:使用自定义颜色渐变来表示特征值大小,图形和颜色条的设计更加直观和美观

关于抖动处理:原始绘图通过点沿特征行堆叠来显示密度,但由于其具体堆叠规则不明确,因此这里采用了抖动处理的方式。本质上,这种方法仍然是为了展示在同一个SHAP值(或小范围)下存在多个数据点的情况。如果不进行抖动或堆叠处理,这些数据点可能会完全折叠为一个点,导致信息丢失或图形不够直观,对于shap的解读是不存在影响的

picture.image

在前面绘制SHAP蜂巢图的基础上,增加右侧的柱状图,用于展示每个特征的平均绝对SHAP值(mean(|SHAP value|)),以更直观地表达特征的重要性排序,实现蜂巢图和柱状图的结合,提供了更丰富的特征贡献解读

picture.image

这个可视化在前面的基础上添加了一个特征分组规则,并在柱状图中通过颜色对特征分组进行了直观表示,这里为什么采用一个特征分组规则规则来进行可视化用一个案例来展示说明:

假设在研究一个预测患者患某种疾病(例如糖尿病)的模型。模型的特征可以分为两大类:患者的生理指标和生活习惯

特征和分组: Group 1(生理指标):X_1: 血糖水平、 X_2: 血压、 X_3: 胰岛素敏感性、 X_4: BMI, Group 2(生活习惯):X_5: 饮食习惯、 X_6: 每周运动时间、 X_7: 吸烟习惯、 X_8: 每天睡眠时间、 X_9: 压力水平

新规则的实际意义:在右侧柱状图中,生理指标(Group 1)用浅蓝色,生活习惯(Group 2)用深蓝色,这样可以清晰地区分疾病发生是否更受生理指标还是生活习惯的影响。例如,如果浅蓝色柱子较高,说明生理指标对模型预测贡献更大;如果深蓝色柱子较高,则生活习惯的影响更显著,通过分组颜色和SHAP蜂巢图直观展示生理指标和生活习惯对疾病预测的相对重要性。这里只是说明一个案例无任何实际意义,当然也可以根据不同研究背景进行更多分组设计,提取其它维度的信息,代码与数据集获取:如需获取本文的源代码和数据集,请添加作者微信联系

往期推荐

期刊配图:ALE(累积局部效应)模型解释方法解决部分依赖图PDP多重共线性问题

期刊配图:基于t-sne降维与模型预测概率的分类效果可视化

期刊配图:多种机器学习算法结合SHAP特征贡献在递归特征选择中的运用

置信区间+误差条:机器学习分类评价指标精美呈现

SCI图表:基于相关性和标准差的多模型评价——泰勒图解析

期刊文章配图:基于分组折线图的多机器学习模型表现评估对比

复现SCI文章 SHAP 依赖图可视化以增强机器学习模型的可解释性

SCI图表复现:优化SHAP特征贡献图展示更多模型细节

复现 Nature 图表——基于PCA的高维数据降维与可视化实践及其扩展

复现Nature图表——基于PCA降维与模型预测概率的分类效果可视化

SCI图表复现:特征相关性气泡热图展示

一图胜千言:回归预测模型训练集与测试集的进阶可视化

期刊文章配图:基于雷达图的多机器学习模型表现评估对比

期刊文章配图:斯皮尔曼相关系数热图反应非线性变量相关性

picture.image

如果你对类似于这样的文章感兴趣。

欢迎关注、点赞、转发~

个人观点,仅供参考

0
0
0
0
相关资源
火山引擎大规模机器学习平台架构设计与应用实践
围绕数据加速、模型分布式训练框架建设、大规模异构集群调度、模型开发过程标准化等AI工程化实践,全面分享如何以开发者的极致体验为核心,进行机器学习平台的设计与实现。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论