一、选题背景
心血管疾病(CVD)是全球所有人发病和死亡的主要原因,约占所有死亡事件的三分之一。根据《中国心血管健康与疾病报告2020》显示,我国心血管患病率处于持续上升态势,目前患病人数越3.3亿。近十年来,我国城乡居民心血管病死亡率也呈上升趋势。据估计,每年有超过400万人死于心血管病,占所有死亡的41.89%,且这个数据仍处于上升阶段。为了解更多有关机器学习的知识,本课题试着通过病人的检查结果来预测是否患有心血管疾病。
二、机器学习案例设计方案
1.数据集来源
来源于kaggle:https://www.kaggle.com/sulianova/cardiovascular-disease-dataset
2.机器学习模型简述
逻辑回归模型
随机森林
分类树模型
神经网络
学习链接:
机器学习算法(一):逻辑回归模型(Logistic Regression, LR)_意念回复的博客-CSDN博客_逻辑回归模型
随机森林算法及其实现(Random Forest)_AAA小肥杨的博客-CSDN博客_随机森林
随机森林random forest及python实现_rosefun96的博客-CSDN博客_随机森林python实现
决策树DecisionTreeClassifier详解_小猪课堂的博客-CSDN博客_tree.decisiontreeclassifier
3.涉及到的技术难点与解决思路
技术难点
(1)特征相关性的可视化没有头绪,不知道怎么绘图
(2)对于各个模型还不够熟悉,只能简单的调参
(3)不知道怎么对模型进行校正,通过网格搜索模块来选择最优参数
解决思路
多查阅相关的资料,丰富知识,需要更多的学习
三、机器学习的实现步骤
#导入库
import numpy as np import pandas as pd import seaborn as sns import matplotlib.pyplot as plt from sklearn.preprocessing import LabelEncoder,StandardScaler from sklearn.linear_model import LogisticRegression # 逻辑回归(分类)
from sklearn.model_selection import cross_val_score # 交叉验证得分
from sklearn import metrics # 模型评价
from sklearn.metrics import roc_curve,auc from sklearn.model_selection import GridSearchCV#网格搜索模块
from sklearn.ensemble import RandomForestClassifier#随机森林
from sklearn.tree import DecisionTreeClassifier#分类树
from sklearn.neural_network import MLPClassifier#神经网络
关于数据集12个特征的说明
导入数据
import numpy as np import pandas as pd data = pd.read_csv('F:\cardio_train.csv',sep=';') data.head()#查看数据集前5行
#缺失值检测
data.isnull().sum()
可见,不存在缺失值
data.info()

接着处理数据,删去无效信息id并且将年龄换算成以年为单位
#删去无效信息
data.drop(['id'],axis=1,inplace=True) data['age']=round(data['age']/365)#四舍五入保留整数 #转化为整型
data['age'].astype(int)
data.describe()
然后进行可视化分析
#特征相关性热力图
corr = data.corr() cmap = sns.diverging_palette(220, 10, as_cmap=True)
mask = np.zeros_like(corr, dtype=np.bool) mask[np.triu_indices_from(mask)] = True f, ax = plt.subplots(figsize=(11, 9))
sns.heatmap(corr, mask=mask, cmap=cmap, vmax=.3, center=0, annot =True, square=True, linewidths=.5, cbar_kws={"shrink": .5});
结果如图
import seaborn as sns import matplotlib.pyplot as plt plt.figure(figsize=(15,8)) data['age']=data['age'].astype(int) sns.countplot(x='age',hue='cardio',data=data)
从图中可以看出年龄大于55岁的人们更容易患心血管疾病,且随着人的年龄逐渐增大,患心血管疾病的概率也越高。
再进行绘图分析胆固醇、血糖、吸烟、喝酒、运动对是否患有心血管疾病的影响
先来转换数据方便绘图
data_long = pd.melt(data, id_vars=['cardio'], value_vars=['cholesterol','gluc', 'smoke', 'alco', 'active']) data_long
sns.catplot(kind='count',x='variable',hue='value',col= 'cardio',data=data_long);
f,ax=plt.subplots(2,2,figsize=(10,7)) sns.barplot(x='cholesterol',y="cardio",data=data,ax=ax[0][0]) sns.barplot(x='gluc', y="cardio", data=data,ax=ax[0][1]) sns.barplot(x='smoke',y="cardio",data=data,ax=ax[1][0]) sns.barplot(x='alco', y="cardio", data=data,ax=ax[1][1])
从图中可以看出那些胆固醇、血糖高于平均值的人们更容易患有心血管疾病,而吸烟、喝酒对于患心血管疾病影响并不大,多运动可以帮助我们降低患心血管疾病的风险。
因为没有说明性别所对应的数字,所以根据平均升高来判断
data.groupby('gender')['height'].mean()
所以gender=1为女性,gender=2为男性。
sns.countplot(x='gender',hue="cardio",data=data)
从图中可以看出,男性患心血管疾病的概率比女性略微多一些。
特征工程
因为不能根据单一的身高或者体重来衡量人体胖瘦程度以及是否健康的一个标准,所以根据身高和体重来增加bmi特征
#根据升高和体重增加bmi特征
data['BMI'] = data['weight']/((data['height']/100)**2)
数据预处理
labelencoder = LabelEncoder() for col in data.columns: data[col] = labelencoder.fit_transform(data[col]) data.head()
#分离特征和标签
X = data.drop(['cardio'],axis=1) y = data['cardio']
#数据标准化
scaler = StandardScaler() X = scaler.fit_transform(X) X
#划分数据集
from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=4)
1.逻辑回归模型
from sklearn.linear_model import LogisticRegression # 逻辑回归(分类)
from sklearn.model_selection import cross_val_score # 交叉验证得分
from sklearn import metrics # 模型评价
model_LR = LogisticRegression() model_LR.fit(X_train, y_train)
#预测结果
y_prob = model_LR.predict_proba(X_test)[:,1] y_prob
y_pred = model_LR.predict(X_test)#分类为0和1
y_pred
查看具体的预测结果
model_LR.score(X_test,y_pred)
逻辑回归模型下的混淆矩阵
confusion_matrix = metrics.confusion_matrix(y_test, y_pred) confusion_matrix
#auc值(越大越好)
auc_roc = metrics.roc_auc_score(y_test, y_pred)#测试值和预测值
auc_roc#0.7296461547890318
#真假阳性
false_positive_rate, true_positive_rate,thresholds = roc_curve(y_test, y_prob) roc_auc = auc(false_positive_rate,true_positive_rate) roc_auc
绘制roc曲线(逻辑回归模型)
plt.figure(figsize=(10,10)) plt.title("ROC") plt.plot(false_positive_rate, true_positive_rate, color="red", label="AUC = %0.2f"%roc_auc ) plt.legend(loc="lower right") plt.plot([0,1],[0,1],linestyle="--") plt.axis("tight") # 真阳性:预测类别为1的positive;预测正确True
plt.ylabel("True Positive Rate") # 假阳性:预测类别为1的positive;预测错误False
plt.xlabel("False Positive Rate")
采取网格搜索的方法选择最佳参数再进行建模
# 未优化的模型 LR_model= LogisticRegression(solver='liblinear')#默认的solver='lbfgs'只能处理L2正则化 # 待确定的参数solver='lbfgs' tuned_parameters = {"C":[0.001,0.01,0.1,1,10,100,1000], "penalty":['l1','l2'] # 选择不同的正则方式,防止过拟合 } # 网格搜索模块 from sklearn.model_selection import GridSearchCV # 加入网格搜索功能 LR = GridSearchCV(LR_model, tuned_parameters,cv=10) # 搜索之后再建模 LR.fit(X_train, y_train) # 确定参数 print(LR.best_params_)#最好参数
y_prob = LR.predict_proba(X_test)[:,1] y_pred = LR.predict(X_test) LR.score(X_test,y_pred)#1.0
confusion_matrix = metrics.confusion_matrix(y_test, y_pred)
auc_roc = metrics.roc_auc_score(y_test,y_pred) auc_roc#0.7297179216901372
2.随机森林
# 建模
model_RR = RandomForestClassifier() # 拟合
model_RR.fit(X_train, y_train)
y_prob = model_RR.predict_proba(X_test)[:,1] y_prob
y_pred = model_RR.predict(X_test) model_RR.score(X_test,y_pred)#1.0
#混淆矩阵
confusion_matrix = metrics.confusion_matrix(y_test, y_pred) confusion_matrix
绘制roc曲线(随机森林 100棵树)
false_positive_rate, true_positive_rate, thresholds = roc_curve(y_test, y_prob) roc_auc = auc(false_positive_rate, true_positive_rate) roc_auc plt.figure(figsize=(10,10)) plt.title('ROC') plt.plot(false_positive_rate,true_positive_rate, color='red',label = 'AUC = %0.2f' % roc_auc) plt.legend(loc = 'lower right') plt.plot([0, 1], [0, 1],linestyle='--') plt.axis('tight') plt.ylabel('True Positive Rate') plt.xlabel('False Positive Rate') plt.show()
改变参数,再次建模拟合
随机森林(200棵树)
model_RF = RandomForestClassifier(n_estimators=200,oob_score=True,verbose=2,n_jobs=4) #200棵树 开启袋外采样 打印状态 4个核心并行
model_RF.fit(X_train,y_train) #训练集拟合
y_prob = model_RF.predict_proba(X_test)[:,1] y_pred = model_RF.predict(X_test) confusion_matrix = metrics.confusion_matrix(y_test, y_pred)
confusion_matrix
绘制roc曲线(随机森林 200棵树)
false_positive_rate, true_positive_rate, thresholds = roc_curve(y_test, y_prob) roc_auc = auc(false_positive_rate, true_positive_rate) roc_auc#0.7679752923488443
plt.figure(figsize=(10,10)) plt.title('ROC') plt.plot(false_positive_rate,true_positive_rate, color='red',label = 'AUC = %0.2f' % roc_auc) plt.legend(loc = 'lower right') plt.plot([0, 1], [0, 1],linestyle='--') plt.axis('tight') plt.ylabel('True Positive Rate') plt.xlabel('False Positive Rate') plt.show()
3.分类树模型
# 建模
model_tree = DecisionTreeClassifier() model_tree.fit(X_train, y_train)
y_prob = model_tree.predict_proba(X_test)[:,1] y_pred = model_tree.predict(X_test) confusion_matrix = metrics.confusion_matrix(y_test, y_pred) confusion_matrix
绘制roc曲线(C分类树模型)
false_positive_rate, true_positive_rate, thresholds = roc_curve(y_test, y_prob) roc_auc = auc(false_positive_rate, true_positive_rate) roc_auc#0.6313029283446727
plt.figure(figsize=(10,10)) plt.title('ROC') plt.plot(false_positive_rate,true_positive_rate, color='red',label = 'AUC = %0.2f' % roc_auc) plt.legend(loc = 'lower right') plt.plot([0, 1], [0, 1],linestyle='--') plt.axis('tight') plt.ylabel('True Positive Rate') plt.xlabel('False Positive Rate') plt.show()
4.神经网络
mlp = MLPClassifier() mlp.fit(X_train,y_train) y_prob = mlp.predict_proba(X_test)[:,1] y_pred = mlp.predict(X_test) confusion_matrix = metrics.confusion_matrix(y_test, y_pred) confusion_matrix
绘制roc曲线(神经网络)
false_positive_rate, true_positive_rate, thresholds = roc_curve(y_test, y_prob) roc_auc = auc(false_positive_rate, true_positive_rate) roc_auc#0.7993770412571006
plt.figure(figsize=(10,10)) plt.title('ROC') plt.plot(false_positive_rate,true_positive_rate, color='red',label = 'AUC = %0.2f' % roc_auc) plt.legend(loc = 'lower right') plt.plot([0, 1], [0, 1],linestyle='--') plt.axis('tight') plt.ylabel('True Positive Rate') plt.xlabel('False Positive Rate') plt.show()
将所有模型的auc_roc集合起来
#逻辑回归模型
y_prob = model_LR.predict_proba(X_test)[:,1] y_pred = model_LR.predict(X_test) auc_roc = metrics.roc_auc_score(y_test, y_pred) auc_roc#0.7296461547890318
#逻辑回归模型(优化后)
y_prob = LR.predict_proba(X_test)[:,1] y_pred = LR.predict(X_test) auc_roc = metrics.roc_auc_score(y_test, y_pred) auc_roc#0.7297179216901372
#随机森林(100棵树)
y_prob = model_RR.predict_proba(X_test)[:,1] y_pred = model_RR.predict(X_test) auc_roc = metrics.roc_auc_score(y_test, y_pred) auc_roc#0.7117307770370652
#随机森林(200棵树)
y_prob = model_RF.predict_proba(X_test)[:,1] y_pred = model_RF.predict(X_test) auc_roc = metrics.roc_auc_score(y_test, y_pred) auc_roc#0.7120185181258415
#分类树模型
y_prob = model_tree.predict_proba(X_test)[:,1] y_pred = model_tree.predict(X_test) auc_roc = metrics.roc_auc_score(y_test, y_pred) auc_roc#0.6299927461653179
#神经网络
y_prob = mlp.predict_proba(X_test)[:,1] y_pred = mlp.predict(X_test) auc_roc = metrics.roc_auc_score(y_test, y_pred) auc_roc#0.7323137344827928
模型 | 逻辑回归模型 | 逻辑回归模型(优化后) | 随机森林(100棵树) | 随机森林(200棵树) | 分类树模型 | 神经网络 |
auc_roc | 0.7296461547890318 |
0.7297179216901372 |
0.7117307770370652 |
0.7120185181258415 |
0.6299927461653179 |
0.7323137344827928 |
根据表格对比得出神经网络的精度更高
四、总结
1.在选择模型的过程中选择了SVM模型,因为数据较大所以需要跑很长的时间,所以放弃了。在选择模型的时候要根据数据集和目的来选择模型,或者通过特征工程筛选适当的特征进行拟合。
2.在完成设计的过程中,学习了用热力图来分析特征的相关性以及绘制更加直观的热力图的参数,在建模拟合的过程中,学习了如何通过网格搜索选取最优参数,在调整模型参数的同时时也对模型的一些的参数的功能有了更多的了解。
改进:对于特征工程的学习还不充足需要更多的学习,在特征工程中并没有进行特征选择,需要在实践中进一步的学习。
完整代码
1 #导入 2 import numpy as np
3 import pandas as pd 4 import seaborn as sns 5 import matplotlib.pyplot as plt 6 from sklearn.preprocessing import LabelEncoder,StandardScaler 7 from sklearn.linear_model import LogisticRegression # 逻辑回归(分类) 8 from sklearn.model_selection import cross_val_score # 交叉验证得分 9 from sklearn import metrics # 模型评价 10 from sklearn.metrics import roc_curve,auc 11 from sklearn.model_selection import GridSearchCV# 网格搜索模块 12 from sklearn.ensemble import 13 from sklearn.tree import DecisionTreeClassifier# 分类树 14 from sklearn.neural_network import MLPClassifier# 神经网络 15 #导入数据 16 data = pd.read_csv('F:\cardio_train.csv',sep=';') 17 data.head()#查看数据集前5行 18 #缺失值检测 19 data.isnull().sum() 20 data.describe() 21 #开始处理数据 22 23 #删去无效信息 24 data.drop(['id'],axis=1,inplace=True) 25 data['age']=round(data['age']/365)#四舍五入保留整数 26 #转化为整型 27 data['age'].astype(int) 28 #相关性 29 data.corr() 30 #绘图分析数据集各年龄和心血管疾病的关系 31 plt.figure(figsize=(15,8)) 32 data['age']=data['age'].astype(int) 33 sns.countplot(x='age',hue='cardio',data=data) 34 #绘图分析胆固醇、血糖、吸烟、喝酒、运动与患心血管疾病的关系 35 data_long = pd.melt(data, id_vars=['cardio'], value_vars=['cholesterol','gluc', 'smoke', 'alco', 'active']) 36 f,ax=plt.subplots(2,2,figsize=(10,7)) 37 sns.barplot(x='cholesterol',y="cardio",data=data,ax=ax[0][0]) 38 sns.barplot(x='gluc', y="cardio", data=data,ax=ax[0][1]) 39 sns.barplot(x='smoke',y="cardio",data=data,ax=ax[1][0]) 40 sns.barplot(x='alco', y="cardio", data=data,ax=ax[1][1]) 41 sns.barplot(x='active', y="cardio", data=data) 42 data.groupby('gender')['height'].mean()#求数据集中gender=1和gender=2的平均身高来辨别男女性 43 #特征相关性热力图 44 corr = data.corr() 45 cmap = sns.diverging_palette(220, 10, as_cmap=True) 46 # Generate a mask for the upper triangle 47 mask = np.zeros_like(corr, dtype=np.bool) 48 mask[np.triu_indices_from(mask)] = True 49 f, ax = plt.subplots(figsize=(11, 9)) 50 # Draw the heatmap with the mask and correct aspect ratio 51 sns.heatmap(corr, 52 mask=mask, 53 cmap=cmap, 54 vmax=.3, 55 center=0, 56 annot =True, 57 square=True, 58 linewidths=.5, 59 cbar_kws={"shrink": .5});
60 #根据升高和体重增加bmi特征 61 data['BMI'] = data['weight']/((data['height']/100)**2) 62 #数据预处理 63 labelencoder = LabelEncoder() 64 for col in data.columns: 65 data[col] = labelencoder.fit_transform(data[col]) 66 data.head() 67 #分离特征和标签 68 X = data.drop(['cardio'],axis=1) 69 y = data['cardio'] 70 #数据标准化 71 scaler = StandardScaler() 72 X = scaler.fit_transform(X) 73 X 74 #划分数据集 75 from sklearn.model_selection import train_test_split 76 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=4) 77 #1.逻辑回归 78 #建模拟合 79 model_LR = LogisticRegression() 80 model_LR.fit(X_train, y_train) 81 #预测结果 82 y_prob = model_LR.predict_proba(X_test)[:,1] 83 y_prob 84 y_pred = model_LR.predict(X_test)#分类为0和1 85 y_pred 86 model_LR.score(X_test,y_pred)#查看具体预测效果 87 confusion_matrix = metrics.confusion_matrix(y_test, y_pred)#混淆矩阵 88 confusion_matrix 89 #auc值(越大越好) 90 auc_roc = metrics.roc_auc_score(y_test, y_pred)#测试值和预测值 91 auc_roc#效果一般 92 #真假阳性 93 false_positive_rate, true_positive_rate,thresholds = roc_curve(y_test, y_prob) 94 roc_auc = auc(false_positive_rate,true_positive_rate) 95 roc_auc 96 #绘制roc曲线(逻辑回归模型) 97 plt.figure(figsize=(10,10)) 98 plt.title("ROC") 99 plt.plot(false_positive_rate, 100 true_positive_rate, 101 color="red", 102 label="AUC = %0.2f"%roc_auc 103 ) 104 105 plt.legend(loc="lower right") 106 plt.plot([0,1],[0,1],linestyle="--") 107 plt.axis("tight") 108 # 真阳性:预测类别为1的positive;预测正确True 109 plt.ylabel("True Positive Rate") 110 # 假阳性:预测类别为1的positive;预测错误False 111 plt.xlabel("False Positive Rate") 112 #通过网格搜索选择最优参数 113 114 # 未优化的模型 115 LR_model= LogisticRegression(solver='liblinear')#默认的solver='lbfgs'只能处理L2正则化 116 # 待确定的参数solver='lbfgs' 117 tuned_parameters = {"C":[0.001,0.01,0.1,1,10,100,1000], 118 "penalty":['l1','l2'] # 选择不同的正则方式,防止过拟合 119 } 120 # 网格搜索模块 121 from sklearn.model_selection import GridSearchCV 122 # 加入网格搜索功能 123 LR = GridSearchCV(LR_model, tuned_parameters,cv=10) 124 # 搜索之后再建模 125 LR.fit(X_train, y_train) 126 127 # 确定参数 128 print(LR.best_params_)#最好参数 129 #优化后 130 y_prob = LR.predict_proba(X_test)[:,1] 131 y_pred = LR.predict(X_test) 132 LR.score(X_test,y_pred) 133 confusion_matrix = metrics.confusion_matrix(y_test, y_pred) 134 confusion_matrix 135 auc_roc = metrics.roc_auc_score(y_test,y_pred) 136 auc_roc 137 #随机森林模型 138 139 # 建模 140 model_RR = RandomForestClassifier() 141 # 拟合 142 model_RR.fit(X_train, y_train) 143 y_prob = model_RR.predict_proba(X_test)[:,1] 144 y_pred = model_RR.predict(X_test) 145 model_RR.score(X_test,y_pred) 146 confusion_matrix = metrics.confusion_matrix(y_test, y_pred) 147 confusion_matrix 148 #绘制roc曲线(随机森林) 149 false_positive_rate, true_positive_rate, thresholds = roc_curve(y_test, y_prob) 150 roc_auc = auc(false_positive_rate, true_positive_rate) 151 roc_auc 152 plt.figure(figsize=(10,10)) 153 plt.title('ROC') 154 plt.plot(false_positive_rate,true_positive_rate, color='red',label = 'AUC = %0.2f' % roc_auc) 155 plt.legend(loc = 'lower right') 156 plt.plot([0, 1], [0, 1],linestyle='--') 157 plt.axis('tight') 158 plt.ylabel('True Positive Rate') 159 plt.xlabel('False Positive Rate') 160 plt.show() 161 #随机森林模型 200颗树 162 model_RF = RandomForestClassifier(n_estimators=200,oob_score=True,verbose=2,n_jobs=4) #200棵树 开启袋外采样 打印状态 4个核心并行 163 model_RF.fit(X_train,y_train) #训练集拟合 164 y_prob = model_RF.predict_proba(X_test)[:,1] 165 y_pred = model_RF.predict(X_test) 166 confusion_matrix = metrics.confusion_matrix(y_test, y_pred) 167 confusion_matrix 168 #绘制roc曲线(随机森林 200颗树) 169 false_positive_rate, true_positive_rate, thresholds = roc_curve(y_test, y_prob) 170 roc_auc = auc(false_positive_rate, true_positive_rate) 171 roc_auc 172 plt.figure(figsize=(10,10)) 173 plt.title('ROC') 174 plt.plot(false_positive_rate,true_positive_rate, color='red',label = 'AUC = %0.2f' % roc_auc) 175 plt.legend(loc = 'lower right') 176 plt.plot([0, 1], [0, 1],linestyle='--') 177 plt.axis('tight') 178 plt.ylabel('True Positive Rate') 179 plt.xlabel('False Positive Rate') 180 plt.show() 181 #决策树 182 model_tree = DecisionTreeClassifier() 183 model_tree.fit(X_train, y_train) 184 y_prob = model_tree.predict_proba(X_test)[:,1] 185 y_pred = model_tree.predict(X_test) 186 confusion_matrix = metrics.confusion_matrix(y_test, y_pred) 187 confusion_matrix 188 #绘制roc曲线(分类树模型) 189 false_positive_rate, true_positive_rate, thresholds = roc_curve(y_test, y_prob) 190 roc_auc = auc(false_positive_rate, true_positive_rate) 191 roc_auc 192 plt.figure(figsize=(10,10)) 193 plt.title('ROC') 194 plt.plot(false_positive_rate,true_positive_rate, color='red',label = 'AUC = %0.2f' % roc_auc) 195 plt.legend(loc = 'lower right') 196 plt.plot([0, 1], [0, 1],linestyle='--') 197 plt.axis('tight') 198 plt.ylabel('True Positive Rate') 199 plt.xlabel('False Positive Rate') 200 plt.show() 201 #神经网络 202 mlp = MLPClassifier() 203 mlp.fit(X_train,y_train) 204 y_prob = mlp.predict_proba(X_test)[:,1] 205 y_pred = mlp.predict(X_test) 206 confusion_matrix = metrics.confusion_matrix(y_test, y_pred) 207 confusion_matrix 208 #绘制roc曲线(神经网络模型) 209 false_positive_rate, true_positive_rate, thresholds = roc_curve(y_test, y_prob) 210 roc_auc = auc(false_positive_rate, true_positive_rate) 211 roc_auc 212 plt.figure(figsize=(10,10)) 213 plt.title('ROC') 214 plt.plot(false_positive_rate,true_positive_rate, color='red',label = 'AUC = %0.2f' % roc_auc) 215 plt.legend(loc = 'lower right') 216 plt.plot([0, 1], [0, 1],linestyle='--') 217 plt.axis('tight') 218 plt.ylabel('True Positive Rate') 219 plt.xlabel('False Positive Rate') 220 plt.show()