Bootstrap

基于机器学习的心脏病风险评估预测系统

温馨提示:文末有 CSDN 平台官方提供的学长 QQ 名片 :) 

1. 项目简介

        心脏病是全球范围内导致死亡的主要原因之一。早期识别和预防心脏病对于减少发病率和死亡率至关重要。传统的风险评估方法通常依赖于医生的经验和简单的风险因子计算,这种方法存在一定的局限性。近年来,机器学习技术在医学领域取得了显著进展,能够从大量的医疗数据中自动学习和提取特征,从而实现高效、准确的风险预测。

        本项目利用pandas工具,计算特征与患心脏病的斯皮尔曼相关性,并利用 Matplotlib 绘制绘制相关性热力图,同时对各特征统计量进行可视化,对性别、年龄、血压、胆固醇、血糖、心率、心绞痛等特征进行统计分布的可视化,分析与患病的潜在相关性。利用scikit-learn、xgboost等工具包构建不同机器学习模型,对患心脏病的预测性能进行对比分析,测试集预测准确率达到92.2%。后端利用Flask框架搭建 web 服务接口,前端采用 Bootstrap 和 echarts 等框架,构建可视化交互平台,方便对心脏病的在线评估预测。

基于机器学习的心脏病风险评估预测系统

2. 心脏病数据集预处理

        该数据集包含用于预测心脏病的医学数据。这些数据包括各种属性,如年龄、性别、胸痛类型(cp)、静息血压(trestbps)、胆固醇(chol)、空腹血糖(fbs)、静息心电图结果(restecg)、达到的最大心率(丘脑)、运动性心绞痛(exang)和运动相对于休息引起的ST段压低(oldpeak)。

df = pd.read_csv("./heart-disease.csv")
## 列名汉化
df.rename(columns={
    "age":"年龄",
    "sex":"性别",
    "cp":"胸痛类型",
    "chol":"胆固醇",
    "fbs":"空腹血糖",
    "restecg":"静息心电图结果",
    "thalach":"达到的最大心率",
    "exang":"运动性心绞痛",
    "oldpeak":"ST段压低",
    "slope":"最高运动ST段的斜率",
    "trestbps": "静息血压",
    
    "ca":"萤光显色主要血管数目",
    "thal":"地中海贫血",
    
    "target":"患病"
},inplace=True)

df.sample(10)
df.info()

3. 数据探索式可视化分析

 3.1 类别标签数量分布

tmp = df["患病"].value_counts().to_frame().reset_index().rename(columns={"count":"数量"})

tmp["患病"] = tmp["患病"].map(lambda x:"心脏病" if x == 1 else "正常")
tmp["百分比"] = tmp["数量"].map(lambda x:round(x/tmp["数量"].sum()*100,2))

labels,values,percent = tmp["患病"].tolist(),tmp["数量"].tolist(),tmp["百分比"].tolist()

fig = plt.figure(figsize=(6,6))

wedges,texts=plt.pie(values,wedgeprops={"width": 0.4, 'edgecolor': '#000', 'linewidth': 2})
 
kw = dict(arrowprops=dict(arrowstyle="-"), zorder=0, va="center")
 
for i, p in enumerate(wedges):
    ang = (p.theta2 - p.theta1) / 1.8 + p.theta1
    
    y = np.sin(np.deg2rad(ang))
    x = np.cos(np.deg2rad(ang))
    horizontalalignment = {-1: "right", 1: "left"}[int(np.sign(x))]
 
    connectionstyle = "angle,angleA=0,angleB={}".format(ang)
    kw["arrowprops"].update({"connectionstyle": connectionstyle})

    plt.annotate(
        labels[i]+"\n"+str(percent[i])+"%",
        xy=(x, y),
        xytext=(1.35 * np.sign(x), 1.4 * y),
        horizontalalignment=horizontalalignment,
        fontsize=12,
        **kw
    )
plt.title("是否患有心脏病的样本数量分布占比", fontsize=18, pad=20)
plt.show()

3.2 特征与目标的相关性分析

        可以看出:与心脏病是否患病的相关性较高的特征有:胸痛类型、达到的最大心率、最高运动ST段的斜率等。

  • cp(胸痛类型):与目标值呈强正相关(0.43)。这表明某些类型的胸痛与心脏病的存在显著相关。
  • 丘脑(达到的最大心率):与目标值(0.42)呈正相关,表明心率较高的患者更有可能患心脏病。
  • exang(运动诱导型心绞痛):与目标值呈强负相关(-0.44),表明运动诱导性心绞痛在没有心脏病的患者中更常见。
  • oldpeak(ST段压低):与目标呈负相关(-0.43),表明ST段压低水平越高,患心脏病的可能性越低。
  • 斜率(峰值运动ST段斜率):也与目标值呈负相关(-0.34),表明ST段斜率可能是一个重要因素。
  • 性别:呈负相关(-0.28),表明在此数据集中,男性(编码为1)患心脏病的可能性较小。
  • ca(荧光镜检查着色的主要血管数量):与目标呈中度负相关(-0.41),这意味着与心脏病相关的着色血管较少。

3.3 直方图和密度图上的数据分布

3.4 性别与心脏病患病相关性分析

3.5 胸痛类型与心脏病相关性分析

type_count = df.groupby('胸痛类型')['患病'].value_counts().unstack()
chest_pain_type_dict = {
    0: '典型心绞痛', 1: '非典型性心绞痛', 2: '非心绞痛', 3: '无症状'
}
type_count.index = type_count.index.map(chest_pain_type_dict)

fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(20, 6))

sns.countplot(df, x="胸痛类型", ax=axes[0])
axes[0].tick_params(axis='x', rotation=0)
axes[0].set_ylabel('胸痛类型')
axes[0].set_title('不同胸痛类型的样本数量分布', fontsize=16)
axes[0].set_xticklabels(labels=chest_pain_type_dict.values(), fontsize=12)

type_count.plot(kind='bar' , stacked=True, ax=axes[1], fontsize=12)
axes[1].tick_params(axis='x', rotation=0)
axes[1].set_ylabel('客户类型')
axes[1].set_title('不同胸痛类型的满患病占比分布', fontsize=16)

plt.show()

3.6 心脏病的胆固醇与达到的最大心率的联合分布

3.7 ST段压特征与是否患心脏病的相关性分析

3.8 萤光显色主要血管数目与是否患心脏病的相关性分析

plt.figure(figsize=(20, 6))
plt.subplot(121)

xg_counts = pos_df['萤光显色主要血管数目'].value_counts().reset_index()
labels = xg_counts['萤光显色主要血管数目'].values.tolist()
sizes = xg_counts['count']
# colors = ['gold', 'yellowgreen', 'lightcoral']  # 扇区颜色
explode = (0.1, 0, 0, 0, 0)  # 将第一块扇区突出显示
# 创建饼状图
plt.pie(sizes, labels=labels, explode=explode,

......

# colors = ['gold', 'yellowgreen', 'lightcoral']  # 扇区颜色
explode = (0.1, 0, 0, 0, 0)  # 将第一块扇区突出显示
# 创建饼状图
plt.pie(sizes, labels=labels, explode=explode,
        autopct='%1.1f%%', shadow=True, startangle=140)
plt.axis('equal')
plt.title('未患有心脏病患者的萤光显色主要血管数目分布', fontsize=16)

# 显示图表
plt.show()

3.9 年龄-心率-患病的相关性分析

3.10 血压(trestbps)和心率(thalach)关系

3.11 大血管数量(ca)和血压(trestbps)、患病关系

plt.figure(figsize=(12, 6))
sns.swarmplot(y='静息血压',data=df, x='萤光显色主要血管数目',hue='患病', size=7)
plt.xlabel('大血管数量')
plt.ylabel('静息血压')
plt.title('大血管数量(ca)和血压(trestbps)、患病的联合分布散点图', fontsize=16)
plt.show()

4. 基于机器学习的心脏病风险预测算法建模

4.1 多模型预测性能对比初探

        利用 scikit-learn、xgboost等工具包,构建AdaBoostClassifier、GradientBoostingClassifier、LogisticRegression、SVC、XGBClassifier等模型,利用切分出的训练集、验证集进行模型的训练:

abc = AdaBoostClassifier()
gbc = GradientBoostingClassifier()
lgr = LogisticRegression()
svc = SVC()
xgb_clf = XGBClassifier()

models = [abc, gbc, lgr, svc, xgb_clf]

names = ["Ada Boost", "Gradient Boosting",
        "Logistic Regression", "Support Vector Machine", "XGBoost"]

def training(model):
    model.fit(X_train, y_train)
    pred = model.predict(X_test)
    score = accuracy_score(pred, y_test)
    report = classification_report(pred, y_test)
    cm = confusion_matrix(pred, y_test)
    
    return score*100, report, cm

         可以看出,默认参数下XGBoost模型的预测准确率达到82.14%,下面对xgboost模型进行参数优化,以提升性能。

4.2 Xgboost 模型优化与模型训练

df_columns = X_train.columns.values
print('===> feature count: {}'.format(len(df_columns)))

xgb_params = {
    'eta': 0.01,
    'colsample_bytree': 0.4,
    'max_depth': 10,
    # 'lambda': 2.0,
    'eval_metric': 'auc',
    'objective': 'binary:logistic',
    'nthread': -1,
    'silent': 1,
    'booster': 'gbtree'
}

dtrain = xgb.DMatrix(X_train, y_train, feature_names=df_columns)
dvalid = xgb.DMatrix(X_valid, y_valid, feature_names=df_columns)

watchlist = [(dtrain, 'train'), (dvalid, 'valid')]

model = xgb.train(dict(xgb_params),
                      dtrain,
                      evals=watchlist,
                      verbose_eval=10,
                      early_stopping_rounds=100,
                      num_boost_round=4000)

4.3 特征重要程度情况

         可以看出,胆固醇、达到的最大心率对于预测是否存在缺陷的重要程度最高.

4.4 模型性能评估

        (1)AUC评估

# predict train
predict_train = model.predict(dtrain)
train_auc = evaluate_score(predict_train, y_train)

# predict validate
predict_valid = model.predict(dvalid)
valid_auc = evaluate_score(predict_valid, y_valid)

# predict test
dtest = xgb.DMatrix(X_test, feature_names=df_columns)
predict_test = model.predict(dtest)
test_auc = evaluate_score(predict_test, y_test)

print('训练集 auc = {:.7f} , 验证集 auc = {:.7f} , 测试集 auc = {:.7f}\n'.format(train_auc, valid_auc, test_auc))
训练集 auc = 0.9975709 , 验证集 auc = 0.8781513 , 测试集 auc = 0.9222222

        (2)测试集预测 ROC 曲线

        (3)测试集预测结果混淆矩阵计算

5. 心脏病风险评估预测系统

5.1 系统首页

        系统首页提供简洁明了的界面设计,包括系统名称、主要功能简介以及使用指南等内容。用户可以通过主页快速了解系统的基本操作流程及注意事项。首页上还会展示一些示例数据和预测结果,让用户直观地感受到系统的实际效果。

  • Web应用框架:使用Flask构建Web应用程序。
  • 前端框架:使用Bootstrap构建响应式前端界面。

5.2 诊断特征相关性分析

5.3 患病影响因素分析

5.4 心脏病在线评估

6. 总结

        本项目利用pandas工具,计算特征与患心脏病的斯皮尔曼相关性,并利用 Matplotlib 绘制绘制相关性热力图,同时对各特征统计量进行可视化,对性别、年龄、血压、胆固醇、血糖、心率、心绞痛等特征进行统计分布的可视化,分析与患病的潜在相关性。利用scikit-learn、xgboost等工具包构建不同机器学习模型,对患心脏病的预测性能进行对比分析,测试集预测准确率达到92.2%。后端利用Flask框架搭建 web 服务接口,前端采用 Bootstrap 和 echarts 等框架,构建可视化交互平台,方便对心脏病的在线评估预测。

欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。技术交流、源码获取认准下方 CSDN 官方提供的学长 QQ 名片 :)

精彩专栏推荐订阅:

1. Python-数据挖掘实战案例

2. Python-深度学习实战案例

3. Python-管理系统实战案例

;