✨ 欢迎关注Python机器学习AI ✨
本节介绍: 期刊配图:shap决策图展示不同预测概率阈值样本的决策走向 。数据采用模拟数据,作者根据个人对机器学习的理解进行代码实现与图表输出,细节并不保证与原文一定相同,仅供参考。 详细数据和代码、文献将在稍后上传至交流群,付费成员可在交流群中获取下载。需要的朋友可关注公众文末提供的购买方式。 购买前请咨询,避免不必要的问题。
✨ 论文原图 ✨
可视化图展示了与创伤后应激障碍(PTSD)风险预测相关的亲属的个体预测路径,分别针对低风险和高风险的亲属。横轴表示PTSD的预测概率,范围从0到1,纵轴列出了影响预测的特征。图中的每一条线代表一个亲属,其中蓝色线条表示PTSD风险非常低(预测概率小于0.15),红色线条表示PTSD风险非常高(预测概率大于0.80)。每条线从底部开始,随着每个特征的贡献(SHAP值)的累积,逐渐向上移动,反映了模型输出的变化。这些特征按其在预测PTSD风险中的重要性从上到下排列。特征的颜色用于指示其对PTSD风险的影响方向:蓝色表示对PTSD风险的负面影响,红色表示正面影响。对于连续变量(如年龄、住院时间等)的数值特征,图中通过切换点来表示其临界值,这些切换点会改变特征对模型预测的影响方向。蓝色和红色的矩形帮助可视化每个特征对最终预测风险的贡献。
✨ 仿图 ✨
仿图展示了在模拟数据集上预测为类别0(未患心脏病,预测概率大于0.85)和类别1(患心脏病,预测概率大于0.80)的样本的决策路径,通过每个样本的特征值逐步影响模型的预测概率,蓝色曲线代表低风险样本(未患心脏病)逐步降低其预测概率,而红色曲线代表高风险样本(患心脏病)逐步提高其预测概率,帮助理解各特征如何对最终分类结果产生影响。此外,文献中的特征左右展示实际上是对原始数据的一个总结,经过后期的可视化(如P图)处理,可以更加直观和便捷地呈现数据,而无需通过代码输出,后续的代码中也将展示如何对这些特征进行总结
✨ 代码实现 ✨
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
plt.rcParams['font.family'] = 'Times New Roman'
plt.rcParams['axes.unicode_minus'] = False
import warnings
warnings.filterwarnings("ignore")
df = pd.read_csv('Dataset.csv')
# 划分特征和目标变量
X = df.drop(['target'], axis=1)
y = df['target']
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2,
random_state=42, stratify=df['target'])
import xgboost as xgb
from sklearn.model_selection import GridSearchCV
# XGBoost模型参数
params_xgb = {
'learning_rate': 0.02, # 学习率,控制每一步的步长,用于防止过拟合。典型值范围:0.01 - 0.1
'booster': 'gbtree', # 提升方法,这里使用梯度提升树(Gradient Boosting Tree)
'objective': 'binary:logistic', # 损失函数,这里使用逻辑回归,用于二分类任务
'max_leaves': 127, # 每棵树的叶子节点数量,控制模型复杂度。较大值可以提高模型复杂度但可能导致过拟合
'verbosity': 1, # 控制 XGBoost 输出信息的详细程度,0表示无输出,1表示输出进度信息
'seed': 42, # 随机种子,用于重现模型的结果
'nthread': -1, # 并行运算的线程数量,-1表示使用所有可用的CPU核心
'colsample_bytree': 0.6, # 每棵树随机选择的特征比例,用于增加模型的泛化能力
'subsample': 0.7, # 每次迭代时随机选择的样本比例,用于增加模型的泛化能力
'eval_metric': 'logloss' # 评价指标,这里使用对数损失(logloss)
}
# 初始化XGBoost分类模型
model_xgb = xgb.XGBClassifier(**params_xgb)
# 定义参数网格,用于网格搜索
param_grid = {
'n_estimators': [100, 200, 300, 400, 500], # 树的数量
'max_depth': [3, 4, 5, 6, 7], # 树的深度
'learning_rate': [0.01, 0.02, 0.05, 0.1], # 学习率
}
# 使用GridSearchCV进行网格搜索和k折交叉验证
grid_search = GridSearchCV(
estimator=model_xgb,
param_grid=param_grid,
scoring='neg_log_loss', # 评价指标为负对数损失
cv=5, # 5折交叉验证
n_jobs=-1, # 并行计算
verbose=1 # 输出详细进度信息
)
# 训练模型
grid_search.fit(X_train, y_train)
# 使用最优参数训练模型
best_model = grid_search.best_estimator_
import shap
explainer = shap.TreeExplainer(best_model)
# 计算shap值为numpy.array数组
shap_values_numpy = explainer.shap_values(X_test)
# 计算shap值为Explanation格式
shap_values_Explanation = explainer(X_test)
使用XGBoost模型对心脏病数据集进行训练,通过网格搜索优化模型超参数,计算并解释测试集样本的SHAP值,用于分析各特征对预测结果的贡献,由于决策图本质上也是针对单个样本进行解释,因此在绘制决策图之前,可以先通过SHAP力图和SHAP瀑布图等单样本可视化方法,帮助全面理解SHAP在单样本上的解释效果
# 获取第一个样本的 SHAP 值(实际是测试集的第二个样本因为python默认从0开始计位)
shap_values_for_first_sample = shap_values_numpy[1] # 从 SHAP 值数组中选择第一个样本的 SHAP 值
# 获取测试数据的特征名称(列名)
feature_names = X_test.columns # 获取 X_test 数据集的列名,即特征名称
# 获取第一个样本的原始特征值(即 X_test 中第1行的所有特征值)
original_values = X_test.iloc[1] # 获取 X_test 中第 1 行的数据作为原始特征值
# 获取 SHAP 解释器的基准值(expected_value)
base_value = explainer.expected_value # 这是 SHAP 模型的期望值,通常是背景分布的平均值
plt.figure(figsize=(10, 5), dpi=1200) # 设置图形的大小为 10x5 英寸,分辨率为 1200 dpi
# 绘制 SHAP force plot
shap.force_plot(base_value, shap_values_for_first_sample, original_values,
feature_names=feature_names, matplotlib=True, show=False)
# 解释:此函数将会绘制一个 SHAP force plot,显示第一个样本的 SHAP 值、特征值及其对模型输出的影响。
plt.savefig("1.pdf", format='pdf', bbox_inches='tight') # 将图形保存为 PDF 文件,去除多余的边距
plt.tight_layout()
plt.show()
绘制SHAP力图来解释测试集中的单个样本的特征对XGBoost模型输出的影响
plt.figure(figsize=(10, 5), dpi=1200)
shap.plots.waterfall(shap_values_Explanation[1], show=False, max_display=13)
plt.savefig("2.pdf", format='pdf', bbox_inches='tight')
plt.tight_layout()
plt.show()
绘制SHAP瀑布图,展示了测试集中第二个样本的SHAP值及各特征对预测结果的贡献
# 绘制 SHAP 决策图
plt.figure(figsize=(10, 5), dpi=1200)
shap.decision_plot(base_value, shap_values_for_first_sample, feature_names, show=False, link='logit')
plt.savefig("4.pdf", format='pdf', bbox_inches='tight')
plt.tight_layout()
plt.show()
绘制SHAP决策图,展示第一个样本的SHAP值如何影响模型预测
可以发现,SHAP力图、SHAP瀑布图和SHAP决策图都是通过传入样本的SHAP值、基准值等进行单样本解释,但由于可视化形式的限制,SHAP力图和SHAP瀑布图只能展示单个样本的解释,而SHAP决策图则能够在解释单样本决策路径的同时展示多个样本的预测过程
现在,针对测试集,提取类别0(未患心脏病)预测概率大于0.85和类别1(患心脏病)预测概率大于0.80的样本,并展示类似文献中的多个样本的单样本解释决策图,用于分析心脏病预测结果
这张图的蓝色曲线代表类别0(未患心脏病)预测概率大于0.85的样本,红色曲线代表类别1(患心脏病)预测概率大于0.80的样本,图中展示了各特征对模型输出的影响;为了与文献一致,可以通过双y轴的特征名显示可以代表不同预测概率类别的样本趋势,所以需要对这些样本对应的真实值进行统计分析
X\_test.iloc[class\_0\_above\_0\_85.index]
从测试集X_test中获取类别0(未患心脏病)且预测概率大于0.85的所有样本数据,参考文献中的数据通常是二分类数据,即0或1,这样的分类更容易得出明确的结论。然而,对于当前的数据集,不能仅仅通过0和1进行简单总结。例如针对类别0的预测时,thal 特征全部为0,而 cp 特征则包含了1、2、3、4等多个类别,接下来,将针对这两个特征,在类别1的表现上进行分析
X\_test.iloc[class\_1\_above\_0\_80.index]
从测试集 X_test 中获取类别1(患心脏病)且预测概率大于0.80的所有样本数据,其中 thal 特征大多数为2,但也有两个样本属于类别0;而 cp 特征大多数为4,只有一个样本为1
因此,针对当前数据集进行双y轴赋予特征名称是可行的,但对于特征的具体值,可以不必逐一列出。对于类别性数据,可以展示最多类别的占比;而对于连续性数据,可以展示其均值,这样可以更清晰地呈现数据的整体趋势和特征影响
# 获取连续性数据和类别性数据的列名
continuous_columns = ['age', 'trestbps', 'chol', 'thalach', 'oldpeak']
categorical_columns = [col for col in X_test.columns if col not in continuous_columns]
# 从class_0_above_0_85和class_1_above_0_80中提取样本数据
class_0_samples = X_test.iloc[class_0_above_0_85.index]
class_1_samples = X_test.iloc[class_1_above_0_80.index]
# 计算连续性数据的均值
continuous_data_mean_class_0 = class_0_samples[continuous_columns].mean()
continuous_data_mean_class_1 = class_1_samples[continuous_columns].mean()
# 计算类别性数据最多类别的占比及其对应的类别值
categorical_data_mode_class_0 = class_0_samples[categorical_columns].mode().iloc[0]
categorical_data_mode_class_1 = class_1_samples[categorical_columns].mode().iloc[0]
# 计算类别性数据最多类别的占比
categorical_data_mode_percentage_class_0 = class_0_samples[categorical_columns].apply(
lambda col: col.value_counts(normalize=True).max()).values
categorical_data_mode_percentage_class_1 = class_1_samples[categorical_columns].apply(
lambda col: col.value_counts(normalize=True).max()).values
# 打印结果
print("Continuous Data Mean (Class 0):\n", continuous_data_mean_class_0)
print("\nContinuous Data Mean (Class 1):\n", continuous_data_mean_class_1)
print("\nCategorical Mode (Class 0):\n", categorical_data_mode_class_0)
print("\nCategorical Mode (Class 1):\n", categorical_data_mode_class_1)
print("\nCategorical Mode Percentage (Class 0):\n", categorical_data_mode_percentage_class_0)
print("\nCategorical Mode Percentage (Class 1):\n", categorical_data_mode_percentage_class_1)
从测试集 X_test 中提取类别0(未患心脏病)和类别1(患心脏病)预测概率大于0.85和0.80的样本,计算并打印连续性数据的均值以及类别性数据中最多类别的占比及其对应的类别值,最后通过整理到决策图的双y轴图上即可
✨ 该文章案例 ✨
在上传至交流群的文件中,像往期文章一样,将对案例进行逐步分析,确保读者能够达到最佳的学习效果。内容都经过详细解读,帮助读者深入理解模型的实现过程和数据分析步骤,从而最大化学习成果。
同时,结合提供的免费AI聚合网站进行学习,能够让读者在理论与实践之间实现融会贯通,更加全面地掌握核心概念。
✨ 购买介绍 ✨
本节介绍到此结束,有需要学习数据分析和Python机器学习相关的朋友欢迎到淘宝店铺:Python机器学习AI,或添加作者微信deep_ML联系,购买作者的公众号合集。截至目前为止,合集已包含200多篇文章,购买合集的同时,还将提供免费稳定的AI大模型使用,包括但不限于ChatGPT、Deepseek、Claude等。
更新的内容包含数据、代码、注释和参考资料。 作者仅分享案例项目,不提供额外的答疑服务。项目中将提供详细的代码注释和丰富的解读,帮助您理解每个步骤 。 购买前请咨询,避免不必要的问题。
✨ 群友反馈 ✨
✨ 淘宝店铺 ✨
请大家打开淘宝扫描上方的二维码,进入店铺,获取更多Python机器学习和AI相关的内容,或者添加作者微信deep_ML联系 避免淘宝客服漏掉信息 ,希望能为您的学习之路提供帮助!
往期推荐
Frontiers in Oncology:利用生存机器学习RSF模型预测患者预后模拟实现
期刊配图:通过SHAP组图解读模型探索不同类型特征和分组对模型的影响
机器学习在临床数据分析中的应用:从数据预处理到Web应用实现的完整流程教学
Psychiatry Research基于SHAP可解释性的机器学习模型构建与评估:混淆矩阵、ROC曲线、DCA与校准曲线分析
nature communications:基于Light GBM与随机森林结合的多模型特征选择方法
如果你对类似于这样的文章感兴趣。
欢迎关注、点赞、转发~
个人观点,仅供参考