背景
这篇文章的灵感来源于一篇关于房颤危重病人住院死亡率预测模型的期刊文章,图A展示的是一个预测模型的界面,用于评估住院期间患有房颤的危重病人的死亡率,图B和图C是对图A所展示模型工具的辅助分析和评价——期刊文章配图:基于旭日图的数据解读与模型应用评价,不同于以往的预测工具顶刊APP部署复现——基于XGBoost模型的心脏病风险预测与解释:Streamlit应用程序开发,相较于这两篇文章本次创新之处在于集成 多模型选择 和 模型评价 功能,用户可以选择多种机器学习模型(通常情况下,应用部署只会选择性能最优的模型,但这并不意味着其他模型没有参考价值),并查看APP在其专家使用过后的评分,所有这些评价指标通过旭日图在应用界面中直观地展示
APP结果展示
在本应用中,为了与文献中的展示方式保持一致,采用了旭日图来展示模型在不同评价指标上的反馈效果。这些反馈来自部署后的医学专家使用体验,反映了模型在实际使用中的表现,包括准确性、可解释性和便捷性等多个维度
由于应用支持多模型选择,每个模型在性能、可解释性、计算效率等方面的表现有所差异,为进一步分析这些差异,未来可以加入SHAP力图来展示每个模型在单个样本上的特征贡献度,帮助用户更直观地了解模型如何得出预测,此外,还可以输出ROC曲线图等性能指标,从不同角度对模型的预测能力进行可视化比较
总体而言,多个模型的性能差异有助于用户针对特定场景选择合适的模型,旭日图的反馈只是专家使用后的一种宏观评价,结合其他模型可解释性和性能指标的可视化展示,将为用户提供更全面的模型性能评估参考,代码与数据集获取:如需获取本文完整的源代码和数据集,请添加作者微信联系
代码实现
数据读取处理
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_csv('2024-11-15公众号Python机器学习AI.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'])
从文件中读取数据,将特征与目标变量分离,并使用 train_test_split 函数按 8:2 比例将数据划分为训练集和测试集,确保数据划分时目标变量的类别分布保持一致(即分层抽样)
模型构建
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV
# 随机森林模型参数
params_rf = {
'n_jobs': -1, # 使用所有可用的CPU核心进行并行运算
'random_state': 42 # 随机种子,用于重现模型的结果
}
# 初始化随机森林分类模型
model_rf = RandomForestClassifier(**params_rf)
# 定义参数网格,用于网格搜索
param_grid_rf = {
'n_estimators': [100, 200, 300], # 树的数量
'max_depth': [4, 5, 6, 7], # 树的深度
'max_features': [0.6, 0.7], # 每棵树使用的特征比例
'min_samples_split': [2, 5], # 节点分裂所需的最小样本数
'min_samples_leaf': [1, 2] # 叶子节点的最小样本数
}
# 使用GridSearchCV进行网格搜索和k折交叉验证
grid_search_rf = GridSearchCV(
estimator=model_rf,
param_grid=param_grid_rf,
scoring='neg_log_loss', # 评价指标为负对数损失
cv=5, # 5折交叉验证
n_jobs=-1, # 并行计算
verbose=1 # 输出详细进度信息
)
# 训练模型
grid_search_rf.fit(X_train, y_train)
# 使用最优参数训练模型
RF = grid_search_rf.best_estimator_
import xgboost as xgb
# 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)
# 使用最优参数训练模型
XGBoost = grid_search.best_estimator_
from catboost import CatBoostClassifier
# 初始化CatBoost分类模型参数
params_cb = {
'verbose': 1, # 输出详细进度信息
'random_seed': 42 # 随机种子,用于重现模型的结果
}
# 初始化CatBoost分类模型
model_cb = CatBoostClassifier(**params_cb)
# 定义参数网格,用于网格搜索
param_grid_cb = {
'iterations': [100, 200, 300], # 迭代次数(类似于树的数量)
'depth': [4, 5, 6, 7], # 树的深度
'learning_rate': [0.01, 0.05, 0.1], # 学习率
'l2_leaf_reg': [1, 3, 5], # L2正则化系数,用于防止过拟合
}
# 使用GridSearchCV进行网格搜索和k折交叉验证
grid_search_cb = GridSearchCV(
estimator=model_cb,
param_grid=param_grid_cb,
scoring='neg_log_loss', # 评价指标为负对数损失
cv=5, # 5折交叉验证
n_jobs=-1, # 并行计算
verbose=1 # 输出详细进度信息
)
# 训练模型
grid_search_cb.fit(X_train, y_train)
# 使用最优参数训练模型
CatBoost = grid_search_cb.best_estimator_
使用网格搜索优化三个机器学习模型(随机森林、XGBoost 和 CatBoost)的超参数,以在心脏病预测任务中找到最佳配置,首先为每个模型定义参数网格和评价指标(负对数损失),然后通过 GridSearchCV 进行5折交叉验证,自动寻找在验证集上表现最好的超参数组合,训练完成后,提取出每个模型的最佳参数,并使用它们来生成最终优化的分类器,最终,生成经过调优的 RF、XGBoost 和 CatBoost 三个模型,可用于进一步的预测或评估
模型评价
混淆矩阵热力图
import seaborn as sns
from sklearn.metrics import confusion_matrix
models = {
'RandomForest': RF,
'XGBoost': XGBoost,
'CatBoost': CatBoost
}
fig, axes = plt.subplots(1, 3, figsize=(18, 6), dpi=1200)
fig.suptitle("Confusion Matrices of Different Models")
for i, (model_name, model) in enumerate(models.items()):
y_pred = model.predict(X_test)
cm = confusion_matrix(y_test, y_pred)
sns.heatmap(cm, annot=True, fmt="d", cmap="Blues", ax=axes[i], cbar=False)
axes[i].set_title(f"{model_name} Confusion Matrix")
axes[i].set_xlabel("Predicted Label")
axes[i].set_ylabel("True Label")
plt.tight_layout(rect=[0, 0.03, 1, 0.95])
plt.savefig("1.pdf", format='pdf', bbox_inches='tight')
plt.show()
ROC曲线
from sklearn.metrics import roc_curve, auc
plt.figure(figsize=(10, 8), dpi=1200)
plt.title("ROC Curves of Different Models")
for model_name, model in models.items():
y_prob = model.predict_proba(X_test)[:, 1]
fpr, tpr, _ = roc_curve(y_test, y_prob)
roc_auc = auc(fpr, tpr)
plt.plot(fpr, tpr, label=f"{model_name} (AUC = {roc_auc:.4f})")
plt.plot([0, 1], [0, 1], 'k--', label="Random Guess (AUC = 0.5)")
plt.xlabel("False Positive Rate")
plt.ylabel("True Positive Rate")
plt.legend(loc="lower right")
plt.savefig("2.pdf", format='pdf', bbox_inches='tight')
plt.show()
模型性能指标
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, log_loss, roc_auc_score
metrics = {
"Model": [],
"Accuracy": [],
"Precision": [],
"Recall": [],
"F1 Score": [],
"Log Loss": [],
"ROC AUC": []
}
for model_name, model in models.items():
y_pred = model.predict(X_test)
y_prob = model.predict_proba(X_test)[:, 1]
# Append model name and each metric
metrics["Model"].append(model_name)
metrics["Accuracy"].append(accuracy_score(y_test, y_pred))
metrics["Precision"].append(precision_score(y_test, y_pred))
metrics["Recall"].append(recall_score(y_test, y_pred))
metrics["F1 Score"].append(f1_score(y_test, y_pred))
metrics["Log Loss"].append(log_loss(y_test, y_prob))
metrics["ROC AUC"].append(roc_auc_score(y_test, y_prob))
metrics_df = pd.DataFrame(metrics)
metrics_df
从结果来看,三个模型(Random Forest、XGBoost、CatBoost)在心脏病预测任务中的性能非常接近。尽管 CatBoost 的 ROC AUC 分数略高,达到 0.9430,表明它在区分正负类上稍占优势,但总体差异并不显著,通常情况下,选择表现最优的模型(例如 CatBoost)进行模型解释(如使用 SHAP、PDP、ICE 等方法),并最终将该模型部署到应用中供用户使用。然而,由于各模型的性能差异很小,我们也可以将所有模型部署到应用中,让用户自行选择运行哪个模型,系统将返回相应的预测结果和模型评价指标。这样,用户可以对比不同模型的预测差异,从而更灵活地应用模型,获得更丰富的诊断参考信息
模型保存
import joblib
# 保存模型
joblib.dump(RF , 'RF.pkl')
joblib.dump(XGBoost , 'XGBoost.pkl')
joblib.dump(CatBoost , 'CatBoost.pkl')
使用 joblib 库将训练好的三个模型(随机森林、XGBoost 和 CatBoost)分别保存为 RF.pkl、XGBoost.pkl 和 CatBoost.pkl 文件,以便后续加载和使用
Streamlit部署APP
最后就是利用Streamlit进行APP部署,该项目文件夹包含心脏病预测应用的核心文件:RF.pkl、XGBoost.pkl 和 CatBoost.pkl 为训练好的模型文件;heart_disease_predictor.py 是主程序文件,实现了模型加载、预测和结果展示;Basic_Information.png 和 accuracy.png 提供了专家信息和模型评价的可视化图;requirements.txt 列出了依赖库,方便环境配置,代码与数据集获取:如需获取本文完整的源代码和数据集,请添加作者微信联系
往期推荐
复现SCI文章 SHAP 依赖图可视化以增强机器学习模型的可解释性
复现 Nature 图表——基于PCA的高维数据降维与可视化实践及其扩展
复现Nature图表——基于PCA降维与模型预测概率的分类效果可视化
SCI图表复现:如何直观展示机器学习模型预测结果的准确性和一致性
如果你对类似于这样的文章感兴趣。
欢迎关注、点赞、转发~
个人观点,仅供参考