✨ 欢迎关注Python机器学习AI ✨
本节介绍: 五大模型堆叠31种组合情况最优模型SHAP解释 ,数据采用模拟数据无任何现实意义 ,作者根据个人对机器学习的理解进行代码实现与图表输出,仅供参考。 完整 数据和代码将在稍后上传至交流群,成员可在交流群中获取下载。需要的朋友可关注公众文末提供的获取方式。点赞、推荐、转发参与文末免费赠书并提供高效的AI工具~!
✨ 论文信息 ✨
文献图中 A、B、C 三部分(图 5)分别用SHAP方法从不同角度解释模型预测结果的整体特征影响
A图:Bar plot这里直接绘制的所谓SHAP Value,可能是直接对SHAP值想加进行绘制,但是一般而言展示各特征对模型输出的平均影响力是通过SHAP值的绝对值平均进行绘制SHAP条形图,体现全局重要性排序,对于这种做法是不推荐的为什么——每个特征的SHAP值的绝对值平均代表它对模型输出的影响力,无论这个影响是正向还是负向,它反映的是这个特征有多大程度参与决策,而不是方向(推动还是抑制),如果不取绝对值,绘制柱状图可能会存在正负值互相抵消:模型虽然频繁用这个特征,但因正负方向交替,平均值接近0,特征重要性图就会低估真实影响,甚至把重要特征排在末尾
B 图:Beeswarm plot展示每个特征所有样本的SHAP值分布,同时用颜色编码特征取值(高低),揭示正负方向和非线性关系,一般进行展示不过多描述
C 图:dependence plot每张小图展示某一特征的取值和对应SHAP值的关系,便于观察边际效应和趋势,如非线性关系或阈值效应,对其会进行详细的讲解,可以理解为是把 B图的每个特征进行了可视化展示,更方便解读,关系更明朗
图6中的 A 和 B 图的作用展示两个个体(一个高风险,一个低风险)样本中,各特征对模型预测结果的具体贡献(SHAP 值),从而解释模型为何判定其预测概率分别为0.89和0.06,类似于SHAP力图或SHAP瀑布图的简化版,仅展示各个特征对单个样本预测值的正负贡献,但缺失“基准值”信息,关于这篇文献其它复现可参考历史文章——期刊复现:单变量特征降维与共线性分析结合RFE集成排名进行特征筛选下的组合拳流程、期刊复现:SVM、RF、BDT、DT、Logit五大模型堆叠31种组合情况优化与最优模型选择可视化
✨ 代码实现 ✨
plt.figure()
shap.summary_plot(shap_values, X_test, feature_names=X_test.columns, plot_type="dot", show=False)
plt.savefig("shap_1.pdf", format='pdf', bbox_inches='tight', dpi=1200)
plt.show()
SHAP中最常用的全局解释图之一,指定使用“点图”形式,每一行为一个特征,颜色表示特征值大小,横轴为SHAP值,也就是文献中的图B,关于模型部分在前期文章——期刊复现:SVM、RF、BDT、DT、Logit五大模型堆叠31种组合情况优化与最优模型选择可视化已经实现
plt.figure(figsize=(10, 5))
shap.summary_plot(shap_values, X_test, plot_type="bar", show=False)
plt.tight_layout()
plt.savefig("shap_2.pdf", format='pdf', bbox_inches='tight', dpi=1200)
plt.show()
绘制并保存SHAP值的柱状图,展示各特征对模型输出的平均影响力大小,适合用作模型解释中全局变量重要性展示,类似于文献中的图A,但是优劣已经阐述
import statsmodels.api as sm
# 获取新的特征列表
features = shap_values_df[['NtproBNP', 'AtrialFibrillationType', 'LeftAtrialDiam',
'SystolicBP', 'BMI', 'Hb', 'Sex', 'Statin', 'Dabigatran']].columns.tolist()
# 设置画布和子图结构(3行3列)
fig, axes = plt.subplots(3, 3, figsize=(10, 10))
axes = axes.flatten()
# 循环绘制每个特征的散点图
for i in range(len(axes)):
if i < len(features): # 如果还有特征未绘制
feature = features[i]
if feature in X_test.columns and feature in shap_values_df.columns:
ax = axes[i]
# 绘制散点图
ax.scatter(X_test[feature], shap_values_df[feature], s=10, color="#6A9ACE")
ax.axhline(y=0, color='red', linestyle='-.', linewidth=1) # 添加横线
# 添加标签
ax.set_xlabel(feature, fontsize=10)
ax.set_ylabel(f'SHAP value for\n{feature}', fontsize=10)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
else:
# 如果特征不存在,隐藏对应的子图
axes[i].axis('off')
else:
# 如果超过了特征数量,关闭剩余的子图
axes[i].axis('off')
plt.savefig("shap_3.pdf", format='pdf', bbox_inches='tight', dpi=1200)
plt.tight_layout()
plt.show()
绘制排名前9个指定特征在测试集上的SHAP值散点图(SHAP依赖图),用于展示各特征值与其对应SHAP值之间的关系,每个子图表示一个特征;横轴是该特征的取值,纵轴是其对应的 SHAP 值;用于揭示该特征的变化如何影响模型输出(正向或负向);红色虚线代表 SHAP 值为 0 的分界线;适合用来判断特征对模型输出的方向性与非线性关系,也就是文献中的图C
# 获取类别0的概率值
probs_class_0 = best.predict_proba(X_test)[:, 0]
indices_class_0_less_than_05 = np.where(probs_class_0 > 0.5)[0]
# 打印结果:显示对应的索引和类别0的概率
for index in indices_class_0_less_than_05:
print(f"样本索引: {index}, 类别0的预测概率: {probs_class_0[index]}")
筛选并打印出模型在测试集中预测为“类别0”的概率大于0.5的样本索引及其对应的概率值
样本索引: 0, 类别0的预测概率: 0.9388499601208223
样本索引: 1, 类别0的预测概率: 0.8060601835150523
样本索引: 2, 类别0的预测概率: 0.7610764030791878
样本索引: 4, 类别0的预测概率: 0.7185807460445682
样本索引: 5, 类别0的预测概率: 0.9215438770987564
样本索引: 6, 类别0的预测概率: 0.938271347506392
样本索引: 10, 类别0的预测概率: 0.8070484781411937
样本索引: 11, 类别0的预测概率: 0.9207555128867952
样本索引: 13, 类别0的预测概率: 0.5291430573436557
样本索引: 15, 类别0的预测概率: 0.5009361470857114
样本索引: 16, 类别0的预测概率: 0.6993764068912958
......
# 获取类别1的概率值
probs_class_1 = best.predict_proba(X_test)[:, 1]
indices_class_1_greater_than_05 = np.where(probs_class_1 > 0.5)[0]
# 打印结果:显示对应的索引和类别1的概率
for index in indices_class_1_greater_than_05:
print(f"样本索引: {index}, 类别1的预测概率: {probs_class_1[index]}")
筛选并打印出模型在测试集中预测为“类别1”的概率大于0.5的样本索引及其对应的预测概率
样本索引: 3, 类别1的预测概率: 0.6848041551200924
样本索引: 7, 类别1的预测概率: 0.8714038047551133
样本索引: 8, 类别1的预测概率: 0.690165625436705
样本索引: 9, 类别1的预测概率: 0.7601004741556072
样本索引: 12, 类别1的预测概率: 0.8239004938636667
样本索引: 14, 类别1的预测概率: 0.590161417193851
样本索引: 25, 类别1的预测概率: 0.6604734267170023
样本索引: 29, 类别1的预测概率: 0.5804566457039086
......
根据预测概率输出结果,最终选取索引为0的样本:属于低风险样本(预测偏向类别0);索引为9的样本:属于高风险样本(预测偏向类别1);这两个样本代表模型在低风险和高风险预测下的典型情况,使用SHAP方法为这两个样本分别绘制 单样本解释图
# 指定的特征顺序
selected_features = ['NtproBNP', 'AtrialFibrillationType', 'LeftAtrialDiam',
'SystolicBP', 'BMI', 'Hb', 'Sex', 'Statin', 'Dabigatran']
# 获取 SHAP 值(第一个样本)
shap_values_selected = shap_values_df.loc[0, selected_features]
# 计算剩余特征 SHAP 总和
other_features = shap_values_df.drop(columns=selected_features).iloc[0, :]
other_sum = other_features.sum()
# 构造一个有固定顺序的 Series(不进行排序)
ordered_features = selected_features + ['Other Features (Sum)']
shap_values_ordered = pd.Series(
list(shap_values_selected) + [other_sum],
index=ordered_features
)
# 设置画布
plt.figure(figsize=(12, 8))
# 颜色映射(coolwarm),按 SHAP 值归一化
cmap = plt.cm.get_cmap("coolwarm")
norm = plt.Normalize(vmin=shap_values_ordered.min(), vmax=shap_values_ordered.max())
colors = [cmap(norm(v)) for v in shap_values_ordered]
# 绘图(不排序,直接使用指定顺序)
ax = plt.barh(y=shap_values_ordered.index, width=shap_values_ordered.values,
color=colors, height=0.8)
# 反转 Y 轴:让 NtproBNP 在最上面
plt.gca().invert_yaxis()
# 添加数值标签(保留两位小数)
for i, v in enumerate(shap_values_ordered.values):
plt.text(v + 0.001, i, f"{v:.2f}", va='center',
fontsize=18, fontweight='bold', color='black')
# 设置标题(左对齐)
plt.title("Prob.=0.06", fontsize=23, fontweight='bold', loc='left')
# 坐标轴标签
plt.xlabel("SHAP Value", fontsize=18, fontweight='bold')
plt.xticks(fontsize=18, fontweight='bold')
plt.yticks(fontsize=18, fontweight='bold')
# 去除右边和顶部边框
ax = plt.gca()
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
plt.savefig("shap_4.pdf", format='pdf', bbox_inches='tight',dpi=1200)
plt.tight_layout()
plt.show()
为索引为0的单个样本绘制单样本SHAP值条形图,显示指定特征和“其他特征总和”对模型预测的贡献大小(从上到下按设定顺序排列),并在图中标注每个SHAP值的具体数值,文献中图6形式
shap_values_selected = shap_values_df.loc[9, selected_features]
other_features = shap_values_df.drop(columns=selected_features).iloc[9, :]
other_sum = other_features.sum()
ordered_features = selected_features + ['Other Features (Sum)']
shap_values_ordered = pd.Series(
list(shap_values_selected) + [other_sum],
index=ordered_features
)
plt.figure(figsize=(12, 8))
cmap = plt.cm.get_cmap("coolwarm")
norm = plt.Normalize(vmin=shap_values_ordered.min(), vmax=shap_values_ordered.max())
colors = [cmap(norm(v)) for v in shap_values_ordered]
ax = plt.barh(y=shap_values_ordered.index, width=shap_values_ordered.values,
color=colors, height=0.8)
plt.gca().invert_yaxis()
for i, v in enumerate(shap_values_ordered.values):
plt.text(v + 0.001, i, f"{v:.2f}", va='center',
fontsize=18, fontweight='bold', color='black')
plt.title("Prob.=0.76", fontsize=23, fontweight='bold', loc='left')
plt.xlabel("SHAP Value", fontsize=18, fontweight='bold')
plt.xticks(fontsize=18, fontweight='bold')
plt.yticks(fontsize=18, fontweight='bold')
ax = plt.gca()
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
plt.savefig("shap_5.pdf", format='pdf', bbox_inches='tight',dpi=1200)
plt.tight_layout()
plt.show()
为测试集索引为9的单个样本绘制SHAP值条形图,展示指定特征及“其他特征总和”对模型预测为类别1(高风险,概率 0.76)的影响程度与方向
当然,公众号中还有更多机器学习期刊实战技巧,您可以通过历史文章进行检索和阅读,关注公众号,点击“发信息”>“历史文章”即可搜索公众号所有文章信息
✨ 该文章案例 ✨
在上传至交流群的文件中,像往期文章一样,将对案例进行逐步分析,确保读者能够达到最佳的学习效果。内容都经过详细解读,帮助读者深入理解模型的实现过程和数据分析步骤,从而最大化学习成果。
同时,结合提供的免费AI聚合网站进行学习,能够让读者在理论与实践之间实现融会贯通,更加全面地掌握核心概念。
✨ 书籍推荐 ✨
无论你是零编程基础的科研新手,还是想提升机器学习技能的医学科研工作者,这本书都能带你从入门到进阶,掌握Python数据分析+医学AI应用的全流程技能
✨ 介绍 ✨
本节介绍到此结束,有需要学习数据分析和Python机器学习相关的朋友欢迎到淘宝店铺:Python机器学习AI,下方提供淘宝店铺二维码获取作者的公众号合集。截至目前为止,合集已包含近300多篇文章,购买合集的同时,还将提供免费稳定的AI大模型使用。
更新的内容包含数据、代码、注释和参考资料。 作者仅分享案例项目,不提供额外的答疑服务。项目中将提供详细的代码注释和丰富的解读,帮助您理解每个步骤 。 获取 前请咨询,避免不必要的问题。
✨ 群友反馈 ✨
✨ 淘宝店铺 ✨
请大家打开淘宝扫描上方的二维码,进入店铺,获取更多Python机器学习和AI相关的内容 ,希望能为您的学习之路提供帮助!
✨ AI工具推荐 ✨
✨ 赠书活动 ✨
支持知识分享,畅享学习乐趣!特别感谢清华大学出版社 对本次赠书活动的鼎力支持!即日起,只需点赞、推荐、转发 此文章,作者将从后台随机抽取一位幸运儿,免费包邮赠送清华出版社提供的《JMeter核心技术、性能测试与性能分析》这本精彩书籍📚!
💡 赶快参与,一键三连,说不定你就是那位幸运读者哦!
往期推荐
期刊复现:连续数据与分类数据共存的SHAP可视化散点图与箱形图组合形式
期刊复现:多分类任务如何拆分为二分类任务并进行堆叠预测提高模型预测性能
期刊配图:SHAP值分析模型可解释性在柱状图与蜂窝图中的进阶组合展示
期刊配图:通过堆叠Mean|SHAP|展示不同区间对模型贡献度的可视化分析
期刊复现:利用UMAP降维算法可视化深度学习随着训练次数的增加模型区分能力的变化
期刊配图:PCA、t-SNE与UMAP三种降维方法简化高维数据的展示应用对比
Science期刊复现:分类、回归与Shap分析多角度揭示同一数据集变量对目标的影响
多模型SHAP+PDP解读Stacking集成模型:从基学习器到元学习器的可解释性与模型调参实现
如果你对类似于这样的文章感兴趣。
欢迎关注、点赞、转发~
个人观点,仅供参考