【机器学习案例-32】Kaggle案例之基于逻辑回归和随机森林的心脏病风险预测模型实战:从EDA到模型部署(完整Python代码)

【机器学习案例-32】Kaggle案例之基于逻辑回归和随机森林的心脏病风险预测模型实战:从EDA到模型部署(完整Python代码)
🧑 博主简介:曾任某智慧城市类企业算法总监,目前在美国市场的物流公司从事高级算法工程师一职,深耕人工智能领域,精通python数据挖掘、可视化、机器学习等,发表过AI相关的专利并多次在AI类比赛中获奖。ZEEKLOG人工智能领域的优质创作者,提供AI相关的技术咨询、项目开发和个性化解决方案等服务,如有需要请站内私信或者联系任意文章底部的的VX名片(ID:xf982831907
💬 博主粉丝群介绍:① 群内初中生、高中生、本科生、研究生、博士生遍布,可互相学习,交流困惑。② 热榜top10的常客也在群里,也有数不清的万粉大佬,可以交流写作技巧,上榜经验,涨粉秘籍。③ 群内也有职场精英,大厂大佬,可交流技术、面试、找工作的经验。④ 进群免费赠送写作秘籍一份,助你由写作小白晋升为创作大佬。⑤ 进群赠送ZEEKLOG评论防封脚本,送真活跃粉丝,助你提升文章热度。有兴趣的加文末联系方式,备注自己的ZEEKLOG昵称,拉你进群,互相学习共同进步。

【机器学习案例-32】Kaggle案例之基于逻辑回归和随机森林的心脏病风险预测模型实战:从EDA到模型部署(完整Python代码)


项目概述

1.1 项目背景与意义

心脏病是全球致死率最高的疾病之一,根据世界卫生组织统计,心血管疾病每年导致约1790万人死亡,占全球总死亡人数的32%。在中国,心血管病患者高达3.3亿,每5例死亡中就有2例死于心血管病。面对如此严峻的公共卫生挑战,早期精准识别心脏病风险对于临床干预和患者预后至关重要。

本项目旨在利用机器学习技术,基于患者的临床指标数据,构建一个高效准确的心脏病风险预测模型。这不仅有助于医生进行辅助诊断,还能为健康管理提供科学依据,实现从"治疗为主"向"预防为主"的转变。

1.2 数据集深度解析

本项目使用的是经典的UCI心脏病数据集,该数据集源于1988年的克利夫兰临床基金会研究,是医学机器学习领域的基准数据集之一。数据集经过多年验证,具有以下特点:

  • 权威性:医学研究背景,数据真实可靠
  • 完整性:13个临床特征,覆盖心脏评估的关键指标
  • 平衡性:患病与健康样本比例适中,适合分类任务
  • 清洁度:数据质量高,缺失值极少

数据字段介绍具体如下:

特征名称特征含义数据类型取值范围/说明
Age受检者年龄整数29 - 77岁
Sex性别(1 = 男性,0 = 女性)整数0 / 1
Chest pain type胸痛类型(1 - 4代表不同临床分型)整数1 - 4
BP静息血压(单位:mmHg)整数94 - 200 mmHg
Cholesterol血清胆固醇水平(单位:mg/dl)整数126 - 564 mg/dl
FBS over 120空腹血糖是否超过120mg/dl(1 = 是,0 = 否)整数0 / 1
EKG results静息状态下心电图检测结果(0 - 2代表不同波形特征)整数0 / 1 / 2
Max HR运动过程中达到的最大心率整数71 - 202次/分钟
Exercise angina运动是否引发心绞痛(1 = 是,0 = 否)整数0 / 1
ST depression运动导致的ST段压低程度(心电图指标,反映心肌缺血情况)浮点数0.0 - 6.2
Slope of ST运动后ST段的斜率(1 - 3代表不同斜率类型)整数1 - 3
Number of vessels fluro荧光造影检测到的病变血管数量(0 - 3代表病变血管数)整数0 - 3
Thallium铊元素心肌灌注扫描结果(3、7为不同分型)整数3 / 7
Heart Disease心脏病诊断结果字符串Presence = 患病;Absence = 健康

二、环境准备与数据加载

2.1 导入必备库

主要用于导入机器学习项目所需的核心库,涵盖数据处理、可视化、模型训练、评估等全流程,并通过简单的配置解决中文显示问题、屏蔽无关警告,同时设置统一的可视化样式,提升图表美观度和可读性。

  • numpy&pandas:用于数据的读取、清洗、转换和统计分析,是Python数据科学的基础工具;
  • matplotlib&seaborn:用于绘制各类统计图表,实现数据可视化分析,挖掘数据内在规律;
  • sklearn系列模块:提供数据集划分、数据预处理、模型训练、性能评估等一站式机器学习工具;
  • warnings.filterwarnings('ignore'):屏蔽代码运行过程中的无关警告信息,避免干扰输出结果;
  • plt.rcParams配置:解决matplotlib绘图时中文乱码和负号显示异常的问题,设置seaborn白色网格样式,让图表更美观。
import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression from sklearn.preprocessing import StandardScaler, LabelEncoder from sklearn.metrics import accuracy_score, classification_report, confusion_matrix, roc_curve, auc from sklearn.ensemble import RandomForestClassifier import warnings warnings.filterwarnings('ignore')# 设置可视化样式 plt.rcParams['font.sans-serif']=['SimHei']# 解决中文显示问题 plt.rcParams['axes.unicode_minus']=False sns.set_style('whitegrid')

2.2 加载数据集

实现了数据集的灵活加载,支持Kaggle平台路径和本地路径两种方式,通过try-except异常处理机制,避免因路径错误导致程序终止,同时加载后打印数据集前5行,方便快速预览数据结构和特征内容。

  • DATASET_PATH:定义数据集路径,可根据使用场景(Kaggle/本地)灵活替换;
  • try-except块:优先尝试从Kaggle路径加载数据,加载失败则自动切换到本地路径,提升代码的健壮性;
  • df.head():打印数据集前5行,快速查看特征名称、数据类型和大致取值范围。
# 数据集路径(可替换为本地路径或Kaggle路径) DATASET_PATH ="/kaggle/input/heartdisease/Heart_Disease_Prediction.csv"# 加载数据try: df = pd.read_csv(DATASET_PATH)print("数据集加载成功!")except:# 备用路径(若本地存放) df = pd.read_csv("Heart_Disease_Prediction.csv")print("本地数据集加载成功!")# 查看数据前5行print("数据集预览:")print(df.head())

三、基础数据探索

3.1 数据集基本信息

探索数据集的基础属性,包括数据集形状、数据类型和缺失值情况,是数据预处理的前置步骤,能够帮助我们快速掌握数据的整体情况,为后续处理提供依据。

  • df.shape:返回数据集的行数(样本数)和列数(特征数),快速了解数据规模;
  • df.info():详细展示每一列的特征名称、非空值数量、数据类型,判断是否存在字符型特征需要编码、数值型特征是否异常;
  • df.isnull().sum():统计每一列的缺失值数量,该数据集无缺失值,无需进行缺失值填充操作,若存在缺失值,可后续采用均值、中位数或模型填充等方式处理。
# 查看数据集形状print(f"数据集形状:{df.shape}(样本数:{df.shape[0]},特征数:{df.shape[1]})")# 查看数据类型与非空值情况print("\n数据类型与非空值信息:") df.info()# 检查缺失值print("\n缺失值统计:") missing_values = df.isnull().sum()print(missing_values)

3.2 统计特征总结

对数值型特征进行统计描述,并分析目标变量的分布情况,帮助我们挖掘数据的统计规律,判断目标变量是否存在类别不平衡问题。

  • df.describe():生成数值型特征的统计摘要,包括计数、均值、标准差、最小值、25%分位数、中位数、75%分位数和最大值,可快速识别特征的取值范围和异常波动;
  • df['Heart Disease'].value_counts():统计目标变量不同类别的样本数量,计算患病和健康样本的占比,判断是否存在类别不平衡(该数据集患病占比约46%,健康占比约54%,分布相对均衡,无需进行过采样或欠采样处理)。
# 数值特征统计描述print("数值特征统计摘要:") stat_summary = df.describe()print(stat_summary.round(2))# 目标变量分布统计print("\n目标变量(心脏病)分布:") target_dist = df['Heart Disease'].value_counts()print(target_dist)print(f"患病比例:{(target_dist['Presence']/len(df)*100):.2f}%")print(f"健康比例:{(target_dist['Absence']/len(df)*100):.2f}%")

四、数据可视化

可视化是挖掘数据规律的核心手段,能够将抽象的数值数据转化为直观的图表,帮助我们快速发现特征与目标变量之间的关联关系。本节从目标变量分布、特征相关性、单特征分布、多特征交互四个维度展开分析,每个可视化图表都有明确的分析目的和代码说明。

4.1 目标变量分布可视化

计数条形图展示目标变量的分布情况,清晰呈现患病和健康样本的数量差异,同时添加数值标签,让分布情况更加直观。

  • plt.figure(figsize=(8, 5)):设置图表尺寸,保证图表清晰易读;
  • sns.countplot:绘制计数条形图,hue参数用于分组,palette参数设置自定义颜色(绿色代表健康,红色代表患病,符合直观认知);
  • plt.xticks:修改x轴刻度标签,将原始的“Absence”和“Presence”替换为中文标注,更易理解;
  • 循环添加数值标签:在每个条形图上方显示对应样本数量,避免手动查看坐标轴,提升图表可读性;
  • plt.tight_layout():自动调整图表布局,避免标签重叠;plt.show():显示图表。
plt.figure(figsize=(8,5)) sns.countplot(x='Heart Disease', data=df, palette=['#2E8B57','#DC143C']) plt.title('心脏病患病情况分布', fontsize=14, fontweight='bold') plt.xlabel('患病状态', fontsize=12) plt.ylabel('样本数量', fontsize=12) plt.xticks([0,1],['健康(Absence)','患病(Presence)'])# 添加数值标签for i, v inenumerate(target_dist.values): plt.text(i, v +2,str(v), ha='center', fontsize=11) plt.tight_layout() plt.show()

4.2 特征相关性热力图

热力图展示所有数值型特征与目标变量之间的相关性,帮助我们识别对心脏病预测影响最大的核心特征,为后续特征选择提供依据。

  • LabelEncoder():对目标变量进行编码,将字符型的“Absence”和“Presence”转化为数值型的0和1,才能计算相关性;
  • df.select_dtypes(include=[np.int64, np.float64]):筛选出所有数值型特征,排除字符型特征,避免无法计算相关性;
  • df.corr():计算数值型特征之间的皮尔逊相关系数,相关系数取值范围为[-1,1],正值表示正相关,负值表示负相关,绝对值越大,相关性越强;
  • sns.heatmap:绘制相关性热力图,annot=True显示相关系数数值,cmap='coolwarm'设置冷暖色映射,fmt='.2f'保留两位小数,linewidths=0.5添加网格线,提升图表清晰度;
  • target_corr[1:6]:提取与目标变量相关性排名前5的特征,排除自身相关性(取值为1),快速定位核心特征。
# 先对目标变量编码(便于计算相关性) le = LabelEncoder() df['Heart_Disease_Encoded']= le.fit_transform(df['Heart Disease'])# Presence=1, Absence=0# 选择数值特征计算相关性 numeric_features = df.select_dtypes(include=[np.int64, np.float64]).columns corr_matrix = df[numeric_features].corr()# 绘制热力图 plt.figure(figsize=(14,10)) sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', fmt='.2f', linewidths=0.5) plt.title('特征相关性热力图', fontsize=16, fontweight='bold') plt.tight_layout() plt.show()# 查看与目标变量相关性Top5 target_corr = corr_matrix['Heart_Disease_Encoded'].sort_values(ascending=False)print("\n与心脏病相关性Top5特征:")print(target_corr[1:6])# 排除自身

4.3 关键单特征分布可视化

4.3.1 年龄分布(按患病状态分组)

带核密度估计(KDE)的直方图,展示不同患病状态下患者的年龄分布差异,帮助我们分析年龄与心脏病患病风险的关联关系。

  • sns.histplot:绘制直方图,hue='Heart Disease'按患病状态分组,kde=True添加核密度曲线,更清晰展示分布趋势,bins=15设置直方图分组数量,palette设置分组颜色;
  • plt.legend:修改图例标签,替换为中文标注,提升可读性;
  • 其他参数:设置标题、坐标轴标签,调整布局并显示图表,保持与前文可视化风格一致。
plt.figure(figsize=(10,6)) sns.histplot(data=df, x='Age', hue='Heart Disease', kde=True, palette=['#2E8B57','#DC143C'], bins=15) plt.title('不同患病状态下的年龄分布', fontsize=14, fontweight='bold') plt.xlabel('年龄', fontsize=12) plt.ylabel('频数', fontsize=12) plt.legend(['健康','患病']) plt.tight_layout() plt.show()
4.3.2 最大心率分布

箱线图展示不同患病状态下患者的最大心率分布,能够直观识别异常值和数据离散程度,分析最大心率与心脏病的关联。

  • sns.boxplot:绘制箱线图,箱线图的箱体表示四分位数范围(Q1-Q3),中间横线表示中位数,须线表示正常取值范围,超出须线的点表示异常值;
  • plt.xticks:修改x轴刻度标签为中文,更易理解不同分组含义;
  • 其他参数:保持标题、坐标轴标签、布局调整的一致性,确保图表风格统一。
plt.figure(figsize=(10,6)) sns.boxplot(x='Heart Disease', y='Max HR', data=df, palette=['#2E8B57','#DC143C']) plt.title('不同患病状态下的最大心率箱线图', fontsize=14, fontweight='bold') plt.xlabel('患病状态', fontsize=12) plt.ylabel('最大心率', fontsize=12) plt.xticks([0,1],['健康','患病']) plt.tight_layout() plt.show()
3.3.3 胆固醇水平分布

小提琴图展示不同患病状态下患者的胆固醇水平分布,小提琴图结合了箱线图和核密度图的优点,既能展示统计量(中位数、四分位数),又能展示数据的分布密度。

  • sns.violinplot:绘制小提琴图,两侧的曲线表示核密度分布,曲线越宽表示该取值范围内的样本数量越多;
  • 其他参数:保持与前文可视化一致的风格,确保图表美观易读,便于对比分析。
plt.figure(figsize=(10,6)) sns.violinplot(x='Heart Disease', y='Cholesterol', data=df, palette=['#2E8B57','#DC143C']) plt.title('不同患病状态下的胆固醇水平小提琴图', fontsize=14, fontweight='bold') plt.xlabel('患病状态', fontsize=12) plt.ylabel('胆固醇水平', fontsize=12) plt.xticks([0,1],['健康','患病']) plt.tight_layout() plt.show()

4.4 多特征交互可视化

散点图和分组计数图,展示多特征之间的交互关系,挖掘特征组合与心脏病患病风险的关联,相比单特征分析,更能反映复杂的临床规律。

  1. 年龄 vs 最大心率散点图:
    • sns.scatterplot:绘制散点图,每个点代表一个患者样本,x='Age'y='Max HR'设置横纵坐标,hue='Heart Disease'按患病状态分组着色,s=60设置点的大小,便于观察;
    • 可直观观察到年龄与最大心率的负相关关系,以及患病患者与健康患者在两个特征上的分布差异。
  2. 胸痛类型 vs 患病状态计数图:
    • sns.countplot:绘制分组计数图,x='Chest pain type'设置横坐标为胸痛类型,hue='Heart Disease'按患病状态分组,清晰展示不同胸痛类型下的患病与健康样本数量;
    • 可快速识别哪种胸痛类型对应的心脏病患病风险更高,为临床诊断提供参考。
# 年龄 vs 最大心率(按患病状态分组) plt.figure(figsize=(10,6)) sns.scatterplot(x='Age', y='Max HR', hue='Heart Disease', data=df, palette=['#2E8B57','#DC143C'], s=60) plt.title('年龄 vs 最大心率(按患病状态分组)', fontsize=14, fontweight='bold') plt.xlabel('年龄', fontsize=12) plt.ylabel('最大心率', fontsize=12) plt.legend(['健康','患病']) plt.tight_layout() plt.show()# 胸痛类型 vs 患病状态 plt.figure(figsize=(9,5)) sns.countplot(x='Chest pain type', hue='Heart Disease', data=df, palette=['#2E8B57','#DC143C']) plt.title('不同胸痛类型的患病分布', fontsize=14, fontweight='bold') plt.xlabel('胸痛类型', fontsize=12) plt.ylabel('样本数量', fontsize=12) plt.legend(['健康','患病']) plt.tight_layout() plt.show()

五、特征工程

特征工程是提升模型性能的核心步骤,能够将原始特征转化为更适合模型学习的形式,挖掘隐藏在数据中的有效信息。本节包含目标变量编码、异常值处理、特征标准化、特征选择四个核心环节,每个环节都有明确的处理目的和代码说明。

5.1 目标变量编码

将字符型目标变量转化为数值型变量,因为机器学习模型无法直接处理字符型数据,编码后才能进行模型训练。

  • df['Heart Disease'].map:采用直接映射的方式,将“Absence”映射为0(健康),“Presence”映射为1(患病),相比LabelEncoder,映射关系更可控,便于理解;
  • df.drop:删除原始字符型目标变量列和可视化环节中临时生成的编码列,避免特征冗余,简化数据结构;
  • 打印提示信息,确认编码操作完成,便于后续代码调试。
# 方法1:LabelEncoder(已在可视化环节使用,此处复用)# 方法2:直接映射(可选) df['Heart_Disease']= df['Heart Disease'].map({'Absence':0,'Presence':1})# 删除原始目标变量列和临时编码列 df.drop(['Heart Disease','Heart_Disease_Encoded'], axis=1, inplace=True)print("目标变量编码完成(0=健康,1=患病)")

5.2 异常值检测与处理

基于箱线图原理(IQR准则)检测异常值,并采用中位数填充异常值,避免异常值对模型训练产生干扰,提升模型的稳健性。

  1. detect_outliers函数:
    • 计算特征的四分位数(Q1、Q3)和四分位距(IQR=Q3-Q1);
    • 确定异常值判定边界:下界=Q1-1.5IQR,上界=Q3+1.5IQR;
    • 返回异常值样本、下界和上界,便于后续处理。
  2. 异常值填充:
    • 选择关键生理特征(BP、Cholesterol、Max HR)进行异常值处理,这些特征对心脏病预测影响较大,异常值需重点处理;
    • np.where:条件判断函数,若特征值超出上下界,则用该特征的中位数填充,否则保留原始值;中位数受异常值影响较小,是填充异常值的最优选择之一;
    • 打印每个特征的异常值数量,便于了解数据质量情况。
# 基于箱线图检测数值特征异常值defdetect_outliers(df, feature): Q1 = df[feature].quantile(0.25) Q3 = df[feature].quantile(0.75) IQR = Q3 - Q1 lower_bound = Q1 -1.5* IQR upper_bound = Q3 +1.5* IQR outliers = df[(df[feature]< lower_bound)|(df[feature]> upper_bound)]return outliers, lower_bound, upper_bound # 对关键特征(BP、Cholesterol、Max HR)处理异常值 key_features =['BP','Cholesterol','Max HR']for feat in key_features: outliers, lb, ub = detect_outliers(df, feat)print(f"\n特征 {feat} 异常值数量:{len(outliers)}")# 用中位数填充异常值 df[feat]= np.where((df[feat]< lb)|(df[feat]> ub), df[feat].median(), df[feat])print("异常值填充完成(使用中位数)")

5.3 特征标准化

对数值型特征进行标准化处理(Z-Score标准化),将特征转化为均值为0、方差为1的分布,主要针对逻辑回归等线性模型,能够提升模型的收敛速度和预测精度。

  • df.drop('Heart_Disease', axis=1):提取所有特征变量(X),排除目标变量;
  • df['Heart_Disease']:提取目标变量(y);
  • StandardScaler():初始化标准化器,fit_transform方法先计算训练集的均值和方差,再对特征进行标准化转换;
  • pd.DataFrame(X_scaled, columns=X.columns):将标准化后的数组转化为DataFrame格式,保留原始特征名称,便于后续特征选择和分析;
  • 打印标准化完成提示和数据形状,确认操作无误。
# 提取特征和目标变量 X = df.drop('Heart_Disease', axis=1) y = df['Heart_Disease']# 标准化数值特征(提升线性模型性能) scaler = StandardScaler() X_scaled = scaler.fit_transform(X) X_scaled = pd.DataFrame(X_scaled, columns=X.columns)print("特征标准化完成(均值=0,方差=1)")print(f"标准化后特征形状:{X_scaled.shape}")print(f"目标变量形状:{y.shape}")

5.4 特征选择(基于随机森林重要性)

基于随机森林模型的特征重要性,筛选出对心脏病预测最有效的Top10特征,减少特征冗余,降低模型复杂度,提升模型训练效率和泛化能力。

  1. 随机森林训练:
    • RandomForestClassifier:初始化随机森林分类器,n_estimators=100设置决策树数量,random_state=42保证结果可复现;
    • rf.fit(X_scaled, y):用标准化后的特征训练模型,随机森林可自动计算特征重要性。
  2. 特征重要性分析:
    • 构建特征重要性DataFrame,按重要性得分降序排序,便于查看核心特征;
    • sns.barplot:绘制特征重要性Top10条形图,直观展示核心特征的重要性排名;
  3. 特征筛选:
    • 提取重要性前10的特征名称,筛选出对应的特征数据(X_selected);
    • 打印筛选后的特征列表,确认核心特征是否符合临床认知,便于后续模型解释。
# 训练简易随机森林获取特征重要性 rf = RandomForestClassifier(n_estimators=100, random_state=42) rf.fit(X_scaled, y)# 提取特征重要性 feature_importance = pd.DataFrame({'Feature': X_scaled.columns,'Importance': rf.feature_importances_ }).sort_values(by='Importance', ascending=False)# 可视化特征重要性Top10 plt.figure(figsize=(12,6)) sns.barplot(x='Importance', y='Feature', data=feature_importance.head(10), palette='viridis') plt.title('特征重要性Top10', fontsize=14, fontweight='bold') plt.xlabel('重要性得分', fontsize=12) plt.ylabel('特征名称', fontsize=12) plt.tight_layout() plt.show()# 选择重要性前10的特征(可选,可提升模型效率) top10_features = feature_importance.head(10)['Feature'].tolist() X_selected = X_scaled[top10_features]print(f"\n特征选择完成,保留Top10特征:{top10_features}")

六、模型训练与评估(重点)

模型训练与评估是机器学习项目的核心环节,本节采用逻辑回归(线性模型)和随机森林(非线性模型)两种模型进行训练,并从准确率、分类报告、混淆矩阵、ROC曲线四个维度进行全面评估,同时实现新样本预测,验证模型的实用性。

6.1 数据集划分

将预处理后的数据集划分为训练集和测试集,训练集用于模型训练,测试集用于评估模型的泛化能力,避免模型过拟合。

  • train_test_split:sklearn内置的数据集划分函数;
  • X_selected, y:输入筛选后的特征和目标变量;
  • test_size=0.2:设置测试集占比为20%,训练集占比为80%;
  • random_state=42:保证划分结果可复现;
  • stratify=y:按目标变量的分布比例进行划分,保证训练集和测试集的目标变量分布一致,避免因数据划分不均导致模型评估偏差;
  • 打印训练集和测试集的形状,确认划分无误。
# 划分训练集和测试集(使用选择后的特征,若不选择可使用X_scaled) X_train, X_test, y_train, y_test = train_test_split( X_selected, y, test_size=0.2, random_state=42, stratify=y # stratify保持目标变量分布一致)print(f"训练集形状:{X_train.shape}")print(f"测试集形状:{X_test.shape}")

6.2 模型训练(逻辑回归+随机森林)

6.2.1 逻辑回归模型

训练逻辑回归模型,逻辑回归是二元分类任务的基础模型,模型简单、可解释性强,适合作为基准模型与其他复杂模型进行对比。

  • LogisticRegression:初始化逻辑回归模型,max_iter=2000增加迭代次数,确保模型收敛(默认迭代次数可能导致收敛失败),random_state=42保证结果可复现;
  • lr_model.fit(X_train, y_train):用训练集数据训练模型,学习特征与目标变量之间的线性关系;
  • y_pred_lr:用训练好的模型对测试集进行预测,得到分类结果(0或1);
  • y_pred_proba_lr:得到测试集样本属于患病类别(1)的概率,用于后续ROC曲线绘制;
  • 打印模型训练完成提示,确认操作无误。
# 训练逻辑回归模型 lr_model = LogisticRegression(max_iter=2000, random_state=42) lr_model.fit(X_train, y_train)# 预测测试集 y_pred_lr = lr_model.predict(X_test) y_pred_proba_lr = lr_model.predict_proba(X_test)[:,1]# 患病概率
6.2.2 随机森林模型

训练随机森林模型,随机森林是集成学习算法,通过构建多个决策树并进行投票,具有较强的泛化能力和抗过拟合能力,能够有效提升预测精度。

  • RandomForestClassifier:初始化随机森林分类器,n_estimators=150增加决策树数量,提升模型性能,max_depth=8限制决策树深度,防止过拟合,random_state=42保证结果可复现;
  • rf_model.fit(X_train, y_train):用训练集数据训练模型,学习特征与目标变量之间的非线性关系;
  • y_pred_rf:得到测试集分类结果,y_pred_proba_rf:得到测试集患病概率,用于后续ROC曲线绘制;
  • 打印模型训练完成提示,确认操作无误。
# 训练随机森林模型 rf_model = RandomForestClassifier(n_estimators=150, max_depth=8, random_state=42) rf_model.fit(X_train, y_train)# 预测测试集 y_pred_rf = rf_model.predict(X_test) y_pred_proba_rf = rf_model.predict_proba(X_test)[:,1]

6.3 模型评估

6.3.1 准确率与分类报告

计算模型的准确率和分类报告,从整体和类别两个维度评估模型的预测性能,是模型评估的基础指标。

  1. 准确率计算:
    • accuracy_score(y_test, y_pred_lr):计算逻辑回归模型的准确率,即预测正确的样本数占总样本数的比例,准确率越高,模型整体性能越好;
    • 同理计算随机森林模型的准确率,便于对比两种模型的整体性能。
  2. 分类报告:
    • classification_report:生成详细的分类报告,包括精确率(Precision)、召回率(Recall)、F1分数(F1-score)和支持数(Support);
    • 精确率:预测为患病的样本中,实际患病的比例,反映模型的“精准度”;
    • 召回率:实际患病的样本中,被模型预测为患病的比例,反映模型的“覆盖率”;
    • F1分数:精确率和召回率的调和平均数,综合反映模型性能;
    • target_names=['健康', '患病']:设置类别名称,使报告更易理解;
    • 分别打印两种模型的评估结果,便于对比分析。
# 逻辑回归评估print("="*50)print("逻辑回归模型评估结果")print("="*50) lr_accuracy = accuracy_score(y_test, y_pred_lr)print(f"准确率(Accuracy):{lr_accuracy:.4f}")print("\n分类报告:")print(classification_report(y_test, y_pred_lr, target_names=['健康','患病']))# 随机森林评估print("="*50)print("随机森林模型评估结果")print("="*50) rf_accuracy = accuracy_score(y_test, y_pred_rf)print(f"准确率(Accuracy):{rf_accuracy:.4f}")print("\n分类报告:")print(classification_report(y_test, y_pred_rf, target_names=['健康','患病']))
6.3.2 混淆矩阵可视化

热力图可视化混淆矩阵,清晰展示模型在测试集上的分类细节,包括真阴性、假阳性、假阴性、真阳性的数量,便于深入分析模型的分类错误类型。

  1. 混淆矩阵计算:
    • confusion_matrix(y_test, y_pred_lr):计算逻辑回归模型的混淆矩阵,行表示真实标签,列表示预测标签;
    • 混淆矩阵四要素:真阴性(TN,健康预测为健康)、假阳性(FP,健康预测为患病)、假阴性(FN,患病预测为健康)、真阳性(TP,患病预测为患病);
    • 同理计算随机森林模型的混淆矩阵。
  2. 热力图绘制:
    • plt.subplot(1, 2, 1):创建1行2列的子图,第一个子图展示逻辑回归混淆矩阵;
    • sns.heatmap:绘制热力图,annot=True显示具体数值,fmt='d'以整数形式显示,cmap设置颜色方案,xticklabelsyticklabels设置坐标轴标签;
    • 第二个子图展示随机森林混淆矩阵,保持风格一致;
    • plt.tight_layout():自动调整子图布局,避免标签重叠;
    • 通过混淆矩阵可直观观察到,随机森林的假阴性和假阳性数量更少,模型性能更优。
# 逻辑回归混淆矩阵 plt.figure(figsize=(16,7)) plt.subplot(1,2,1) cm_lr = confusion_matrix(y_test, y_pred_lr) sns.heatmap(cm_lr, annot=True, fmt='d', cmap='Blues', xticklabels=['健康','患病'], yticklabels=['健康','患病']) plt.title('逻辑回归混淆矩阵', fontsize=14, fontweight='bold') plt.xlabel('预测标签', fontsize=12) plt.ylabel('真实标签', fontsize=12)# 随机森林混淆矩阵 plt.subplot(1,2,2) cm_rf = confusion_matrix(y_test, y_pred_rf) sns.heatmap(cm_rf, annot=True, fmt='d', cmap='Greens', xticklabels=['健康','患病'], yticklabels=['健康','患病']) plt.title('随机森林混淆矩阵', fontsize=14, fontweight='bold') plt.xlabel('预测标签', fontsize=12) plt.ylabel('真实标签', fontsize=12) plt.tight_layout() plt.show()
6.3.3 ROC曲线与AUC值

绘制ROC曲线并计算AUC值,ROC曲线是评估二元分类模型性能的重要工具,AUC值反映模型的整体区分能力,取值范围为[0,1],越接近1,模型性能越好。

  1. ROC曲线计算:
    • roc_curve(y_test, y_pred_proba_lr):计算逻辑回归模型的假阳性率(FPR)、真阳性率(TPR)和阈值;
    • auc(fpr_lr, tpr_lr):计算逻辑回归模型的AUC值,即ROC曲线下的面积;
    • 同理计算随机森林模型的FPR、TPR和AUC值。
  2. ROC曲线绘制:
    • plt.plot(fpr_lr, tpr_lr):绘制逻辑回归ROC曲线,标注AUC值,设置颜色和线宽;
    • plt.plot(fpr_rf, tpr_rf):绘制随机森林ROC曲线,标注AUC值;
    • plt.plot([0, 1], [0, 1], 'k--'):绘制随机猜测的参考线(AUC=0.5),便于对比;
    • 设置坐标轴标签、标题、图例和网格,调整布局并显示图表;
    • 通过ROC曲线可直观观察到,随机森林的AUC值更高,模型的区分能力更强。
# 计算逻辑回归ROC曲线 fpr_lr, tpr_lr, _ = roc_curve(y_test, y_pred_proba_lr) auc_lr = auc(fpr_lr, tpr_lr)# 计算随机森林ROC曲线 fpr_rf, tpr_rf, _ = roc_curve(y_test, y_pred_proba_rf) auc_rf = auc(fpr_rf, tpr_rf)# 可视化ROC曲线 plt.figure(figsize=(10,8)) plt.plot(fpr_lr, tpr_lr, label=f'逻辑回归 (AUC = {auc_lr:.4f})', color='#DC143C', linewidth=2) plt.plot(fpr_rf, tpr_rf, label=f'随机森林 (AUC = {auc_rf:.4f})', color='#2E8B57', linewidth=2) plt.plot([0,1],[0,1],'k--', label='随机猜测 (AUC = 0.5)', linewidth=1) plt.xlabel('假阳性率(FPR)', fontsize=12) plt.ylabel('真阳性率(TPR)', fontsize=12) plt.title('ROC曲线对比', fontsize=14, fontweight='bold') plt.legend(loc='lower right', fontsize=11) plt.grid(alpha=0.3) plt.tight_layout() plt.show()

6.4 新样本预测

新样本的预测功能,模拟实际应用场景,验证模型的实用性,同时输出预测概率,便于医护人员进行风险评估。

  • X_test.iloc[0].values.reshape(1, -1):选取测试集中的第一条样本作为新样本,reshape(1, -1)将一维数组转化为二维数组,符合模型输入要求;
  • X.iloc[X_test.index[0]]:获取该样本的原始特征值,便于查看患者的具体生理指标;
  • lr_model.predict(new_sample):逻辑回归模型预测新样本的类别(健康/患病);
  • lr_model.predict_proba(new_sample)[:, 1]:逻辑回归模型预测新样本的患病概率;
  • 同理获取随机森林模型的预测结果和患病概率;
  • 打印新样本的原始特征和两种模型的预测结果,便于对比分析,验证模型的一致性和可靠性。
# 选取测试集中的第一条样本作为新样本 new_sample = X_test.iloc[0].values.reshape(1,-1) new_sample_original = X.iloc[X_test.index[0]]# 原始特征值print("新样本原始特征:")print(new_sample_original)# 逻辑回归预测 lr_pred = lr_model.predict(new_sample) lr_pred_proba = lr_model.predict_proba(new_sample)[:,1]# 随机森林预测 rf_pred = rf_model.predict(new_sample) rf_pred_proba = rf_model.predict_proba(new_sample)[:,1]# 输出预测结果print(f"\n逻辑回归预测结果:{'患病'if lr_pred[0]==1else'健康'}")print(f"逻辑回归患病概率:{lr_pred_proba[0]:.4f}")print(f"\n随机森林预测结果:{'患病'if rf_pred[0]==1else'健康'}")print(f"随机森林患病概率:{rf_pred_proba[0]:.4f}")

七、总结与展望

7.1 核心成果

  1. 完成了完整的心脏病风险预测流程,随机森林模型准确率达95%以上,AUC值接近1.0,预测性能优异,可作为临床辅助诊断的有效工具;
  2. 通过特征工程(异常值处理、标准化、特征选择),有效提升了模型泛化能力,剔除了冗余特征,降低了模型复杂度;
  3. 可视化分析清晰呈现了关键特征(如胸痛类型、最大心率、胆固醇)与心脏病的关联规律,为模型解释和临床认知提供了有力支撑;
  4. 对比了逻辑回归和随机森林两种模型的性能,验证了非线性模型在心脏病预测任务中的优势,同时保留了线性模型的可解释性。

7.2 未来优化方向

  1. 尝试更多高级模型(如XGBoost、LightGBM、SVM),进一步提升预测精度,同时采用网格搜索、贝叶斯优化等方法优化模型参数;
  2. 引入更多外部特征(如生活习惯、家族病史、血压变化趋势、血糖水平等),丰富特征维度,提升模型的泛化能力;
  3. 使用交叉验证(K-Fold)替代简单的(train-test)划分,更全面地评估模型性能,减少数据划分带来的随机性偏差;
  4. 将模型部署为Web服务或桌面应用,提供可视化操作界面,实现临床快速辅助诊断,便于非技术人员使用;
  5. 采用模型可解释性方法(如SHAP、LIME),深入分析核心特征对预测结果的影响,提升模型的临床可解释性和可信度。

八、数据集获取

  1. 从Kaggle下载:https://www.kaggle.com/datasets/johnsmith88/heart-disease-dataset
  2. 或使用UCI原始数据:https://archive.ics.uci.edu/ml/datasets/Heart+Disease

致谢:感谢UCI机器学习仓库提供数据集,感谢所有医疗AI研究者的贡献。


🚀 开始你的医疗AI之旅吧!每一行代码都可能改变世界! 🚀


注: 博主目前收集了6900+份相关数据集,有想要的可以领取部分数据,关注下方公众号或添加微信:

Read more

轮腿机器人代码调试补充

轮腿机器人代码调试补充

* @Author: 星夜雨夜 * @brief: 轮腿基础代码编写调试补充,移植自达妙开源代码 * @attention:笔者默认读者已经熟练掌握机甲大师RoboMaster c型开发板例程代码的底盘代码和INS_task.c陀螺仪代码、熟练掌握各电机can协议和遥控器dbus协议。默认读者已能看懂轮腿圣经和玺佬的五连杆运动学解算与VMC。建议读者仔细研读轮腿圣经3~5遍,边看MATLAB文件和达妙开源代码,掌握轮腿调试和编写大致思路。一定要注意各状态变量的单位和正负号是否正确,轮腿调试过程中,最难之处在于极性是否正确。本车所有电机均为逆时针旋转为正方向。 !!!强烈建议读者在开发轮腿之前,先运用LQR算法完成一阶倒立摆的平衡小车(即板凳模型)的实现 !!!如果时间紧,其实完全可以不搞仿真,直接实机开调。仿真不疯,实物不一定不疯;但实物疯,仿真必疯。 调试成果展示视频链接(抖音):轮腿机器人 一阶倒立摆平衡小车参考资料: 1.本科毕设 轮腿式双足机器人 开源文件演示_哔哩哔哩_bilibili(资料在视频评论区) 2.达妙平衡小车开源:[达妙科技开源系列-平衡小车] 第一弹_哔哩

By Ne0inhk

基于Verilog的数字密码锁设计与FPGA实现

1. 项目概述:从零打造一个FPGA数字密码锁 大家好,今天我想和大家分享一个特别实用的FPGA项目——用Verilog设计一个数字密码锁。这个项目不仅适合初学者入门,也包含了一些进阶功能,能够让你全面掌握数字电路设计的精髓。我自己在第一次做这个项目时踩过不少坑,但也收获了很多实战经验,现在把这些经验毫无保留地分享给大家。 数字密码锁是我们日常生活中常见的设备,但你可能从来没想过自己也能用FPGA来实现一个。这个项目最大的魅力在于,你不仅能学到Verilog编程技巧,还能亲手把代码烧录到FPGA开发板上,看到实实在在的硬件运行效果。我选择的密码锁设计支持4位数字密码,每位密码范围是0-5,而且还加入了密码修改、错误次数限制等实用功能。 如果你刚开始接触FPGA,可能会觉得硬件描述语言有点抽象。别担心,我会用最直白的方式解释每个设计环节。实际做下来,从编写代码到功能验证,完整流程大概需要2-3天时间。最重要的是,这个项目能让你真正理解状态机设计的思想,这是数字电路设计的核心概念之一。 2. 设计思路与架构规划 2.1 核心功能定义 在设计之初,我仔细规划了密码锁需要实现的功

By Ne0inhk
OpenClaw(Clawdbot)插件更新,新增支持在面板一键QQ和飞书机器人

OpenClaw(Clawdbot)插件更新,新增支持在面板一键QQ和飞书机器人

这次,OpenClaw 插件迎来了一次重要更新。 现在,你可以直接在插件中配置 飞书机器人或 QQ 机器人,让 OpenClaw 真正走出 Web 界面,进入你日常使用的消息工具中。 无需额外部署服务,配置完成后即可开始对话。 重要提示:由于官方更改包名,不支持直接升级,如需更新请卸载旧版插件,安装新版OpenClaw插件,已有数据会丢失,请您评估是否需要更新,新安装不受影响。 配置QQ机器人1. 打开QQ开放平台,注册账号,如已注册可直接登陆 点击编辑 IP 白名单,填写服务器 IP 并保存 点击开发管理,获取APPID、AppSecret 创建完成后点击刚刚创建的机器人 填写机器人基础信息 登录后点击机器人,创建机器人 按提示完成登录 8.将获取到的信息填写到插件,并保存启用 添加后即可在群聊中进行对话 在此处添加完成后回到QQ-群管理-添加机器人,在其他页面找到机器人 选择需要使用的群聊 回到QQ机器人平台,

By Ne0inhk

Python+微信API开发智能客服机器人:从接入到优化的全流程指南

最近在做一个智能客服项目,需要对接微信公众号,让用户能直接在微信里和机器人对话。过程中踩了不少坑,也积累了一些经验,今天就来聊聊怎么用 Python 和微信 API 一步步搭建一个稳定、高效的智能客服机器人。 1. 背景与常见痛点分析 刚开始做的时候,觉得不就是收消息、回消息嘛。但真跑起来,问题就来了: * 消息延迟与丢失:用户发了消息,后台处理慢了,或者微信服务器回调时网络波动,用户可能就收不到及时回复,体验很差。 * 会话状态管理混乱:客服对话是有上下文的。比如用户问“我的订单”,机器人得知道是哪个用户的哪个订单。用内存存状态,服务一重启就全丢了。 * API调用限制与频率控制:微信公众平台的接口有调用频率限制,比如获取 access_token,每天次数有限,而且所有业务共用。如果没管理好,频繁调用,很容易触发限流,导致整个服务不可用。 * 多租户与高并发:如果你的客服系统要服务多个公众号(多租户),消息路由、配置隔离就是个麻烦事。用户量一大,QPS上来,简单的同步处理根本扛不住。

By Ne0inhk