当前位置: 首页 > 后端技术 > Python

机器学习可以预测心血管疾病吗?没错,我是用python写的

时间:2023-03-26 18:18:43 Python

CDADataAnalyst出品人:Mika数据:振达后期:Mika【攻略】教你用python写一个心血管疾病预测模型。全世界每年约有1700万人死于心血管疾病,主要表现为心肌梗塞和心力衰竭。当心脏不能泵出足够的血液来满足身体的需要时,就会发生心力衰竭,这通常是由糖尿病、高血压或其他心脏病引起的。在检测心血管疾病的早期症状时,机器学习可以派上用场。通过病人的电子病历,可以记录病人的症状、身体特征和临床实验室检测值,进行生物统计分析,可以发现医生无法察觉的模式和相关性。特别是通过机器学习,可以根据数据预测患者的生存率。今天我们将教大家如何用Python编写一个心血管疾病预测模型。研究背景和数据来源我们使用的数据集来自DavideChicco和GiuseppeJurman发表的一篇论文:《机器学习可以仅通过血肌酐和射血分数来预测心力衰竭患者的生存率》。他们收集了2015年4月至12月在巴基斯坦费萨拉巴德心脏病研究所和费萨拉巴德联合医院的299名心力衰竭患者的病历。患者包括105名女性和194名男性,年龄在40至95岁之间。所有299名患者均有左心室收缩功能障碍和心力衰竭病史。Davide和Giuseppe应用多个机器学习分类器来预测患者的存活率并根据最重要的风险因素对特征进行排序。还使用传统的生物测定测试进行了替代特征排名分析,并将这些结果与机器学习算法提供的结果进行了比较。他们分析比较了心力衰竭患者的一系列数据,最终发现血肌酐和射血分数这两项数据可以很好地预测心力衰竭患者的生存率。今天我们将教大家如何使用Python编写一个预测模型,用于基于13个领域的299例患者诊断记录来预测心力衰竭患者的生存率。下面是具体步骤和关键代码。01.数据理解数据取自kaggle平台共享的心血管疾病数据集。共有13个字段和299个患者诊断记录。具体领域大纲如下:02.数据读取及初步处理首先导入需要的包。数据整理importnumpyasnpimportpandasaspd可视觉化importmatplotlib.pyplotaspltimportseabornassnsimportplotlyaspyimportplotly.graph_objsasgoimportplotly.expressaspximportplotly.figure_factoryasff模型构建fromsklearn.linear_modelimportLogisticRegression.learnifierfromsklearnsklearn.ensemer导入渐变boostingclassifier,randomforestClassifierimportlightgbm前'./data/heart_failure.csv')df.head()03.探索性分析1.描述性分析df.describe().T从上面的描述性分析结果,简单总结如下:Death:平均死亡率为32%;年龄分布:平均年龄60岁,最小40岁,最大95岁是否有糖尿病:41.8%患有糖尿病是否有高血压:35.1%患有高血压是否吸烟:32.1%曾吸烟2.目标变量产生数据death_num=df['DEATH_EVENT'].value_counts()death_num=death_num.reset_index()饼图fig=px.pie(death_num,names='index',values='DEATH_EVENT')fig.update_layout(title_text='目标变量DEATH_EVENT的分布')py.offline.plot(fig,filename='./html/目标变量DEATH_EVENT的分布.html')一共299人,其中96人没有活过随访期,占总人口的32.1%3.贫血从图中可以看出,有贫血症状的患者死亡概率较高,为35.66%bar1=draw_categorical_graph(df['anaemia'],df['DEATH_EVENT'],title='Redbloodcells,hemoglobinreductionandsurvival')bar1.render('./html/Redbloodcellhemoglobinreductionandsurvival.html')4.年龄来自直方图,可以看出,心血管疾病患者的年龄分布差异较大,表现为年龄越大,存活比例越低,死亡比例越高。产生数据surv=df[df['DEATH_EVENT']==0]['age']not_surv=df[df['DEATH_EVENT']==1]['age']hist_data=[surv,not_surv]group_labels=['Survived','NotSurvived']histogramfig=ff.create_distplot(hist_data,group_labels,bin_size=0.5)fig.update_layout(title_text='Ageandsurvivalstatusrelationship')py.offline.plot(fig,filename='./html/Relationshipageandsurvivalstatus.html')5.年龄/性别从组别统计和图表可以看出,不同性别之间的生存状况没有显着差异。在死亡的病例中,男性的平均年龄相对较高。6.年龄/吸烟数据表明,总体而言,吸烟与生存之间没有显着相关性。但是当我们关注吸烟的人时,50岁以下的人存活的概率更高。7.磷酸肌酸激酶(CPK)从直方图可以看出,血液中CPK酶水平较高的人有更高的死亡概率。8.射血分数射血分数代表心脏的泵血功能。如果水平太高或太低,生存的可能性就会降低。9.血小板血液中的血小板(100~300)×10^9/L,高或低代表异常,存活概率低。10.血清肌酐水平血清肌酐是检测肾功能最常用的指标。较高的指数表示肾功能不全、肾功能衰竭和较高的死亡概率。11.血清钠水平图表显示,较高或较低的血清钠通常与风险相关。12.相关分析从数值属性的相关图中可以看出,变量之间不存在显着的共线关系。num_df=df[['age','creatinine_phosphokinase','ejection_fraction','platelets','serum_creatinine','serum_sodium']]plt.figure(figsize=(12,12))sns.heatmap(num_df.corr(),vmin=-1,cmap='coolwarm',linewidths=0.1,annot=True)plt.title('数值变量之间的皮尔逊相关系数',fontdict={'fontsize':15})plt.show()04,特征筛选我们使用统计方法进行特征筛选。当目标变量DEATH_EVENT为分类变量时,自变量为分类变量时,采用卡方鉴定,自变量为数值变量时,采用方差分析。除X和yX=df.drop('DEATH_EVENT',axis=1)y=df['DEATH_EVENT']fromfeature_selectionimportFeature_selectfs=Feature_select(num_method='anova',cate_method='kf')X_selected=fs.fit_transform(X,y)X_selected.head()202017:19:49INFOattrselectsuccess!Afterselectattr:['serum_creatinine','serum_sodium','ejection_fraction','age','time']05,首先数据建模划分训练集和测试集。划分训练集和测试集Features=X_selected.columnsX=df[Features]y=df["DEATH_EVENT"]X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.2,stratify=y,random_state=2020)归一化定标器=StandardScaler()scaler_Xtrain=scaler.fit_transform(X_train)scaler_Xtest=scaler.fit_transform(X_test)lr=LogisticRegression()lr.fit(scaler_Xtrain,y_train)test_pred=lr.predict(scaler_Xtest)F1-scoreprint("F1_scoreofLogisticRegressionis:",round(f1_score(y_true=y_test,y_pred=test_pred),2))我们使用决策树进行建模,设置特征选择标准为gini,树的深度为5。输出混淆矩阵图:在这种情况下,第1类是我们感兴趣的。DecisionTreeClassifierclf=DecisionTreeClassifier(criterion='gini',max_depth=5,random_state=1)clf.fit(X_train,y_train)test_pred=clf.predict(X_test)F1-scoreprint("DecisionTreeClassifier的F1_score是:",round(f1_score(y_true=y_test,y_pred=test_pred),2))绘图plt.figure(figsize=(10,7))plot_confusion_matrix(clf,X_test,y_test,cmap='Blues')plt.title("DecisionTreeClassifier-ConfusionMatrix",fontsize=15)plt.xticks(range(2),["HeartNotFailed","HeartFail"],fontsize=12)plt.yticks(range(2),["HeartNotFailed","HeartFail"],fontsize=12)plt.show()F1_scoreofDecisionTreeClassifieris:0.61使用网格搜索进行参数调优,优化标准为f1。parameters={'splitter':('best','random'),'criterion':("gini","entropy"),"max_depth":[*range(1,20)],}clf=DecisionTreeClassifier(random_state=1)GS=GridSearchCV(clf,param_grid=parameters,cv=10,scoring='f1',n_jobs=-1)GS.fit(X_train,y_train)print(GS.best_params_)print(GS.best_score_){'criterion':'entropy','max_depth':3,'splitter':'best'}0.7638956305132776使用最优化的模型重新评估测评结果:test_pred=GS.best_estimator_.predict(X_test)F1-scoresprint(DecisionTreeClassifier的是:",round(f1_score(y_true=y_test,y_pred=test_pred),2))绘图plt.figure(figsize=(10,7))plot_confusion_matrix(GS,X_test,y_test,cmap='Blues')plt.title("DecisionTreeClassifier-ConfusionMatrix",fontsize=15)plt.xticks(range(2),["HeartNotFailed","HeartFail"],fontsize=12)plt.yticks(range(2),["HeartNotFailed","HeartFail"],fontsize=12)plt.show()使用随机森林RandomForestClassifierrfc=RandomForestClassifier(n_estimators=1000,random_state=1)parameters={'max_depth':np.a范围(2,20,1)}GS=GridSearchCV(rfc,param_grid=parameters,cv=10,scoring='f1',n_jobs=-1)GS.fit(X_train,y_train)print(GS.best_params_)print(GS.best_score_)test_pred=GS.best_estimator_.predict(X_test)F1-scoreprint("RandomForestClassifier的F1_score是:",round(f1_score(y_true=y_test,y_pred=test_pred),2)){'max_depth':3}0.791157747481277RandomForestClassifier的F1_score是:0.53使用Boostinggbl=GradientBoostingClassifier(n_estimators=1000,random_state=1)parameters={'max_depth':np.arange(2,20,1)}GS=GridSearchCV(gbl,param_grid=parameters,cv=10,scoring='f1',n_jobs=-1)GS.fit(X_train,y_train)print(GS.best_params_)print(GS.best_score_)测试集test_pred=GS.best_estimator_.predict(X_test)F1-scoreprint("F1_scoreGradientBoostingClassifier的分数是:“,round(f1_score(y_true=y_test,y_pred=test_pred),2)){'max_depth':3}0.7288420428900305F1_scoreofGradientBoostingClassifier是:0.65使用LGBMClassifierlgb_clf=lightgbm.LGBMClassifier(boosting_type='gbdt',random_state=1)parameters={'max_depth':np.arange(2,20,1)}GS=GridSearchCV(lgb_clf,param_grid=parameters,cv=10,scoring='f1',n_jobs=-1)GS.fit(X_train,y_train)print(GS.best_params_)print(GS.best_score_)测试集test_pred=GS.best_estimator_.predict(X_test)F1-scoreprint("LGBMClassifier的F1_score是:",round(f1_score(y_true=y_test,y_pred=test_pred),2)){'max_depth':2}0.780378102289867F1_scoreofLGBMClassifieris:0.74以下是各模型在测试集上的性能对比:LogisticRegression:0.63DecisionTreeClassifier:0.73RandomForestClassifier:0.53GradientBoosting分类器:0.65LGBM分类器:0.74参考链接:机器学习可以仅从血清肌酐和射血分数预测心力衰竭患者的生存率https://bmcmedinformdecismak....