# 1 前言
?? 基于機(jī)器學(xué)習(xí)與大數(shù)據(jù)的糖尿病預(yù)測
??學(xué)長這里給一個題目綜合評分(每項(xiàng)滿分5分)
- 難度系數(shù):3分
- 工作量:3分
- 創(chuàng)新點(diǎn):4分
選題指導(dǎo),項(xiàng)目分享:文章來源:http://www.zghlxwxcb.cn/news/detail-480096.html
https://gitee.com/yaa-dc/warehouse-1/blob/master/python/README.md文章來源地址http://www.zghlxwxcb.cn/news/detail-480096.html
1 課題背景
本項(xiàng)目的目的主要是對糖尿病進(jìn)行預(yù)測。主要依托某醫(yī)院體檢數(shù)據(jù)(處理后),首先進(jìn)行了數(shù)據(jù)的描述性統(tǒng)計(jì)。后續(xù)針對數(shù)據(jù)的特征進(jìn)行特征選擇(三種方法),選出與性別、年齡等預(yù)測相關(guān)度最高的幾個屬性值。此后選擇Logistic回歸、支持向量機(jī)和XGBoost三種機(jī)器學(xué)習(xí)模型,將選擇好的屬性值輸入對糖尿病風(fēng)險(xiǎn)預(yù)警模型進(jìn)行訓(xùn)練,并運(yùn)用F1-Score、AUC值等方法進(jìn)行預(yù)警模型的分析評價。最后進(jìn)行了模型的調(diào)參(GridSearch),選擇了最優(yōu)參數(shù)輸入模型,對比后發(fā)現(xiàn)模型性能得到了一定提升。
2 數(shù)據(jù)導(dǎo)入處理
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import scipy
import warnings
warnings.filterwarnings("ignore")
# 顯示所有列
pd.set_option('display.max_columns', None)
# 顯示所有行
pd.set_option('display.max_rows', None)
plt.rcParams['font.sans-serif'] = ['KaiTi']
plt.rcParams['axes.unicode_minus'] = False
xls1=pd.ExcelFile(r'/home/mw/input/6661075/dia.xls')
dataConcat1=pd.read_excel(xls1)
dataConcat1.head()
為了后續(xù)更好地將數(shù)據(jù)輸入機(jī)器學(xué)習(xí)模型,有必要將某些數(shù)據(jù)列進(jìn)行分桶
#%matplotlib notebook #交互式圖表
age=dataConcat1['年齡']
age_binary=pd.cut(age,[0,30,45,60,100],labels=[0,1,2,3],right=False)
dataConcat1['年齡_cut']=age_binary
dataConcat1['年齡_cut']=dataConcat1['年齡_cut'].astype("float")
pulse=dataConcat1['脈搏']
pulse_binary=pd.cut(pulse,[0,60,99,200],labels=[0,1,2],right=False)
#right:bool型參數(shù),默認(rèn)為True,表示是否包含區(qū)間右部。比如如果bins=[1,2,3],right=True,則區(qū)間為(1,2],(2,3];right=False,則區(qū)間為(1,2),(2,3)
dataConcat1['脈搏']=pulse_binary
dataConcat1['脈搏']=dataConcat1['脈搏'].astype("float")
pressure=dataConcat1['舒張壓']
pressure_binary=pd.cut(pressure,[0,60,89,200],labels=[0,1,2],right=False)
dataConcat1['舒張壓']=pressure_binary
dataConcat1['舒張壓']=dataConcat1['舒張壓'].astype("float")
dataConcat1.head()
3 數(shù)據(jù)可視化分析
fig=plt.figure(figsize=(12,30))
plt.subplots_adjust(wspace = 0.4,hspace = 0.4 ) #調(diào)整子圖內(nèi)部間距
a2=plt.subplot2grid((5,2),(0,0),colspan=2)
diabetes_0_1 = dataConcat1.體重檢查結(jié)果[dataConcat1.是否糖尿病 == 0].value_counts()
diabetes_1_1 = dataConcat1.體重檢查結(jié)果[dataConcat1.是否糖尿病 == 1].value_counts()
df1=pd.DataFrame({'糖尿病患者':diabetes_1_1,'正常人':diabetes_0_1})
weight_map={0:'較瘦',1:'正常',2:'偏重',3:'肥胖'}
df1.index = df1.index.map(weight_map)
a2.bar(['較瘦','正常','偏重','肥胖'],df1['糖尿病患者'])
a2.bar(['較瘦','正常','偏重','肥胖'],df1['正常人'])
plt.title(u"BMI不同的人患糖尿病情況")
plt.xlabel(u"體重檢查結(jié)果")
plt.ylabel(u"人數(shù)")
plt.legend((u'糖尿病', u'正常人'),loc='best')
a1=plt.subplot2grid((5,2),(1,0))
diabetes_0 = dataConcat1.性別[dataConcat1.是否糖尿病 == 0].value_counts()
diabetes_1 = dataConcat1.性別[dataConcat1.是否糖尿病 == 1].value_counts()
df=pd.DataFrame({'糖尿病患者':diabetes_1,'正常人':diabetes_0})
sex_map={1:'男',0:'女'}
df.index = df.index.map(sex_map)
a1.bar(['男','女'],df['糖尿病患者'])
a1.bar(['男','女'],df['正常人'],bottom=list(df.loc[:,'糖尿病患者']))
plt.title(u"男女患糖尿病情況")
plt.xlabel(u"性別")
plt.ylabel(u"人數(shù)")
plt.legend((u'糖尿病', u'正常人'),loc='best')
plt.subplot2grid((5,2),(1,1))
dataConcat1.年齡[dataConcat1.是否糖尿病 == 1].plot(kind='kde')
dataConcat1.年齡[dataConcat1.是否糖尿病 == 0].plot(kind='kde')
plt.xlabel(u"年齡")# plots an axis lable
plt.ylabel(u"密度")
plt.title(u"糖尿病和正常人年齡分布")
plt.legend((u'糖尿病', u'正常人'),loc='best')
plt.subplot2grid((5,2),(2,0))
dataConcat1.高密度脂蛋白膽固醇[dataConcat1.是否糖尿病 == 1].plot(kind='kde')
dataConcat1.高密度脂蛋白膽固醇[dataConcat1.是否糖尿病 == 0].plot(kind='kde')
plt.xlabel(u"高密度脂蛋白膽固醇")# plots an axis lable
plt.ylabel(u"密度")
plt.title(u"高密度脂蛋白膽固醇分布")
plt.legend((u'糖尿病', u'正常人'),loc='best')
plt.subplot2grid((5,2),(2,1))
dataConcat1.低密度脂蛋白膽固醇[dataConcat1.是否糖尿病 == 1].plot(kind='kde')
dataConcat1.低密度脂蛋白膽固醇[dataConcat1.是否糖尿病 == 0].plot(kind='kde')
plt.xlabel(u"低密度脂蛋白膽固醇")# plots an axis lable
plt.ylabel(u"密度")
plt.title(u"低密度脂蛋白膽固醇分布")
plt.legend((u'糖尿病', u'正常人'),loc='best')
plt.subplot2grid((5,2),(3,0))
dataConcat1.極低密度脂蛋白膽固醇[dataConcat1.是否糖尿病 == 1].plot(kind='kde')
dataConcat1.極低密度脂蛋白膽固醇[dataConcat1.是否糖尿病 == 0].plot(kind='kde')
plt.xlabel(u"極低密度脂蛋白膽固醇")# plots an axis lable
plt.ylabel(u"密度")
plt.title(u"極低密度脂蛋白膽固醇分布")
plt.legend((u'糖尿病', u'正常人'),loc='best')
plt.subplot2grid((5,2),(3,1))
dataConcat1.尿素氮[dataConcat1.是否糖尿病 == 1].plot(kind='kde')
dataConcat1.尿素氮[dataConcat1.是否糖尿病 == 0].plot(kind='kde')
plt.xlabel(u"尿素氮")# plots an axis lable
plt.ylabel(u"密度")
plt.title(u"尿素氮分布")
plt.legend((u'糖尿病', u'正常人'),loc='best')
plt.subplot2grid((5,2),(4,0))
dataConcat1.尿酸[dataConcat1.是否糖尿病 == 1].plot(kind='kde')
dataConcat1.尿酸[dataConcat1.是否糖尿病 == 0].plot(kind='kde')
plt.xlabel(u"尿酸")# plots an axis lable
plt.ylabel(u"密度")
plt.title(u"尿酸分布")
plt.legend((u'糖尿病', u'正常人'),loc='best')
plt.subplot2grid((5,2),(4,1))
dataConcat1.肌酐[dataConcat1.是否糖尿病 == 1].plot(kind='kde')
dataConcat1.肌酐[dataConcat1.是否糖尿病 == 0].plot(kind='kde')
plt.xlabel(u"肌酐")# plots an axis lable
plt.ylabel(u"密度")
plt.title(u"肌酐分布")
plt.legend((u'糖尿病', u'正常人'),loc='best')
從基本的描述性統(tǒng)計(jì)中,我們可以發(fā)現(xiàn)糖尿病人與正常人之間的的一些差異,比如體重指數(shù)較高,高密度脂蛋白膽固醇較低,尿素氮和尿酸較高等。
4 特征選擇
4.1 通過相關(guān)性進(jìn)行篩選
無論算法是回歸(預(yù)測數(shù)字)還是分類(預(yù)測類別),特征都必須與目標(biāo)相關(guān)。 如果一個特征沒有表現(xiàn)出相關(guān)性,它就是一個主要的消除目標(biāo)。 可以分別測試數(shù)值和分類特征的相關(guān)性。
#屬性熱力如果模型僅用于預(yù)測,則只要擬合程度好,可不處理多重共線性問題,存在多重共線性的模型用于預(yù)測時,往往不影響預(yù)測結(jié)果。圖
plt.figure(figsize=(10,8))
df_cor=dataConcat1.iloc[:,1:-1]
df_cor.corr()
data_cor=df_cor.corr()
mask = np.triu(np.ones_like(data_cor, dtype=np.bool))
# adjust mask and df
mask = mask[1:, :-1]
corr = data_cor.iloc[1:, :-1].copy()
# color map
cmap = sns.diverging_palette(0, 230, 90, 60, as_cmap=True)
sns.heatmap(corr,mask=mask, annot=True, fmt=".2f", cmap=cmap,linewidth=3,
vmin=-1, vmax=1, cbar_kws={"shrink": .8},square=True)
plt.title('屬性熱力圖')
plt.tight_layout()#調(diào)整布局防止顯示不全
4.2 多重共線性
當(dāng)任何兩個特征之間存在相關(guān)性時,就會出現(xiàn)多重共線性。 在機(jī)器學(xué)習(xí)中,期望每個特征都應(yīng)該獨(dú)立于其他特征,即它們之間沒有共線性。
4.1中的Heatmap 是檢查和尋找相關(guān)特征的最簡單方法。
此外方差膨脹因子 (VIF) 是衡量多重共線性的另一種方法。 它被測量為整體模型方差與每個獨(dú)立特征的方差的比率。計(jì)算公式如下:
其中,為自變量對其余自變量作回歸分析的負(fù)相關(guān)系數(shù)。
一個特征的高VIF表明它與一個或多個其他特征相關(guān)。 根據(jù)經(jīng)驗(yàn),VIF大于10,則代表變量有較嚴(yán)重的多重共線性。
注意:如果模型僅用于預(yù)測,則只要擬合程度好,可不處理多重共線性問題,存在多重共線性的模型用于預(yù)測時,往往不影響預(yù)測結(jié)果。
from statsmodels.stats.outliers_influence import variance_inflation_factor
feature_names = ['性別', '年齡_cut', '低密度脂蛋白膽固醇','高密度脂蛋白膽固醇',
'極低密度脂蛋白膽固醇','甘油三酯', '總膽固醇', '脈搏', '舒張壓','高血壓史','尿素氮','尿酸','肌酐','體重檢查結(jié)果']
X=dataConcat1[feature_names]
y=dataConcat1.是否糖尿病
# 計(jì)算 VIF
vif = pd.Series([variance_inflation_factor(X.values, i) for i in range(X.shape[1])], index=X.columns)
# 展示VIF結(jié)果
index = X.columns.tolist()
vif_df = pd.DataFrame(vif, index = index, columns = ['vif']).sort_values(by = 'vif', ascending=False)
vif_df
4.3 RFE(遞歸特征消除法)
使用RFE進(jìn)行特征選擇:RFE是常見的特征選擇方法,也叫遞歸特征消除。它的工作原理是遞歸刪除特征,并在剩余的特征上構(gòu)建模型。它使用模型準(zhǔn)確率來判斷哪些特征(或特征組合)對預(yù)測結(jié)果貢獻(xiàn)較大。
2000 年,Weston G.等人在對研究對癌癥進(jìn)行分類時,提出了SVM-RFE特征選擇算法并應(yīng)用到癌癥分類。作為一種經(jīng)典的包裹式特征選擇方法,SVM-RFE特征選擇算法也曾被廣泛用于醫(yī)學(xué)預(yù)測問題的特征選擇,并取得良好的選擇效果。SVM-RFE 算法使用SVM算法作為基模型,對數(shù)據(jù)集中的特征進(jìn)行排序,然后使用遞歸特征消除算法將排序靠后特征消除,以此實(shí)現(xiàn)特征選擇。SVM的介紹與推導(dǎo)在2.1.2節(jié)有所提及,下面對該算法的實(shí)現(xiàn)步驟進(jìn)行總結(jié)。其算法的實(shí)現(xiàn)步驟如下:
①輸入原始特征集Q =(Q1,Q2,…,Qm);
②初始化目標(biāo)特征集= q;
③根據(jù)Q對支持向量機(jī)進(jìn)行訓(xùn)練,得到所有特征的權(quán)重,將其進(jìn)行平方處理后并按照降序?qū)μ卣鬟M(jìn)行排名;
④不斷對步驟迭代,直到留下最后一個屬性特征,更新;
⑤若得到的目標(biāo)特征集Q*模型的擬合程度不再繼續(xù)增加,MSE不再繼續(xù)降低,則算法結(jié)束,所得的n個特征即為所選擇的n個特征,否則,轉(zhuǎn)③。
#遞歸特征消除法,返回特征選擇后的數(shù)據(jù)
#參數(shù)estimator為基模型
#參數(shù)n_features_to_select為選擇的特征個數(shù)
min_max_scaler1 = preprocessing.MinMaxScaler()
X_train_minmax1 = min_max_scaler1.fit_transform(dataConcat1[feature_names])#特征歸一化處理
svc = SVC(kernel="linear")
selector=RFE(estimator=svc, n_features_to_select=8)
Xt=selector.fit_transform(X_train_minmax1,dataConcat1.是否糖尿病)
print("N_features %s" % selector.n_features_) # 保留的特征數(shù)
print("Support is %s" % selector.support_) # 是否保留
print("Ranking %s" % selector.ranking_) # 重要程度排名
for i in zip(selector.ranking_,feature_names,selector.support_):
print(i)
4.4 正則化
正則化減少了過擬合。 如果你有太多的特征,正則化控制它們的效果,或者通過縮小特征系數(shù)(稱為 L2 正則化)或?qū)⒁恍┨卣飨禂?shù)設(shè)置為零(稱為 L1 正則化)。一些模型具有內(nèi)置的 L1/L2 正則化作為超參數(shù)來懲罰特征。 可以使用轉(zhuǎn)換器 SelectFromModel 消除這些功能。這里實(shí)現(xiàn)一個帶有懲罰 = ‘l1’ 的 LinearSVC 算法。 然后使用 SelectFromModel 刪除一些功能。
model = LinearSVC(penalty= 'l1', C = 0.1,dual=False)
model.fit(X,y)
# 特征選擇
# L1懲罰項(xiàng)的SVC作為基模型的特征選擇,也可以使用threshold(權(quán)值系數(shù)之差的閾值)控制選擇特征的個數(shù)
selector = SelectFromModel(estimator = model, prefit=True,max_features=8)
X_new = selector.transform(X)
feature_names = np.array(X.columns)
feature_names[selector.get_support()]#獲取選擇的變量
經(jīng)過特征篩選,最終決定篩選年齡_cut,高密度脂蛋白膽固醇,舒張壓,脈搏,尿素氮,體重檢查結(jié)果,性別,甘油三酯作為后續(xù)機(jī)器學(xué)習(xí)模型輸入。
5 機(jī)器學(xué)習(xí)模型建立與評價
5.1 評價方式的選擇
對于不同的預(yù)測問題,選擇一個好的評價標(biāo)準(zhǔn)將會大大提高模型對實(shí)際問題的適應(yīng)性,從而選出最合適的模型。一般來說,各種模型評價的方式都與混淆矩陣(confusion matrix)有很大的關(guān)系。混淆矩陣是對一個模型進(jìn)行評價與衡量的一個標(biāo)準(zhǔn)化的表格,具體形式如下表所示。以糖尿病預(yù)測為例,其中第一行的和為實(shí)際患糖尿病的總?cè)藬?shù),第二行的和為實(shí)際未患糖尿病的總?cè)藬?shù),第一列的和為經(jīng)過模型預(yù)測后預(yù)測標(biāo)簽為患糖尿病的總?cè)藬?shù),第二列的和為經(jīng)過模型預(yù)測后預(yù)測標(biāo)簽為未患糖尿病的總?cè)藬?shù)。
準(zhǔn)確率、精確率和召回率在各個預(yù)測場景下都是是評價一個模型預(yù)測效果的重要參考指標(biāo)。精確率是針對機(jī)器學(xué)習(xí)預(yù)測結(jié)果而言的,召回率是針對原來的樣本的標(biāo)簽來說的。對于糖尿病標(biāo)注這個預(yù)測問題來說,精確率(Precision)表示的是預(yù)測糖尿病為陽性的樣本中有多少是真正的陽性樣本,而召回率(Recall)則是表示標(biāo)簽糖尿病為陽性的樣本例有多少被預(yù)測為陽性。
精確率和召回率在某些情況下,尤其是在某些醫(yī)學(xué)場景下并不能對機(jī)器學(xué)習(xí)模型的預(yù)測能力和預(yù)測效率進(jìn)行全面的評價,有些情況下會造成模型評價的嚴(yán)重偏倚,不能很好衡量這個分類器的效果,從而造成對使用和評價模型人員的誤導(dǎo)。為了解決這個問題,一個比較常見且較為簡單的方法就是F-Measure,也就是通過計(jì)算F1-Score(F1值)來評價一個模型的預(yù)測效果。
roc曲線可以很容易地查出一個分類器在某個閾值時對樣本的識別能力。進(jìn)行ROC分析所需要的工具和準(zhǔn)備并不繁瑣,利用二維平面上的帶有兩個坐標(biāo)軸來繪制曲線便可進(jìn)行ROC分析。其中曲線坐標(biāo)軸的橫軸(x軸)為FPR(False Positive Rate,假正率),代表訓(xùn)練出的分類器預(yù)測的陰性樣本中實(shí)際的陰性樣本占所有實(shí)際陰性樣本的比重;豎軸(y軸)為TPR(True Positive Rate,真正率),即前述的召回率(Recall),代表訓(xùn)練出的分類器預(yù)測的陽性樣本中實(shí)際陽性樣本占所有實(shí)際陽性樣本的比重。
??
對于某個模型來說,模型在測試集的表現(xiàn)不同,便可以得到多對不同的TPR和FPR值,進(jìn)一步在圖中映射成一個在ROC曲線上的點(diǎn)。在圖中預(yù)測模型分類時所使用的閾值是在不斷變化和調(diào)整的,根據(jù)閾值的變化,便可以繪制一個經(jīng)過點(diǎn)(0, 0)和點(diǎn)(1, 1)的曲線,也就是這個模型的ROC曲線。AUC(Area Under Curve)是與ROC曲線息息相關(guān)的一個值,代表位于ROC曲線下方面積的總和占整個圖(一個正方形)總面積的比例。AUC值的大小存在一個范圍,一般是在0.5到1.0之間上下浮動。當(dāng)AUC=0.5時,代表這個模型的分類效果約等于隨機(jī)分類的效果,而模型的AUC值越大,代表這個模型的分類表現(xiàn)越好。部分指標(biāo)計(jì)算公式如下所示。
5.2 模型的建立與評價
select_features=[ '年齡_cut','高密度脂蛋白膽固醇','舒張壓','脈搏','尿素氮','體重檢查結(jié)果',"性別","甘油三酯"]
X1 = dataConcat1[select_features]#變量篩選后的特征
y1 = dataConcat1.是否糖尿病
train_X, val_X, train_y, val_y = train_test_split(X1, y1, random_state=1)
model_logistics = LogisticRegression()
model_logistics.fit(train_X,train_y)
y_pred = model_logistics.predict(val_X)
scores_logistics=[]
scores_logistics.append(precision_score(val_y, y_pred))
scores_logistics.append(recall_score(val_y, y_pred))
confusion_matrix_logistics=confusion_matrix(val_y,y_pred)
f1_score_logistics=f1_score(val_y, y_pred,labels=None, pos_label=1, average='binary', sample_weight=None)
precision_logistics = precision_score(val_y, y_pred, average='binary')# 精確率指模型預(yù)測為正的樣本中實(shí)際也為正的樣本占被預(yù)測為正的樣本的比例。
importance=pd.DataFrame({"columns":list(val_X.columns), "coef":list(model_logistics.coef_.T)})
predictions_log=model_logistics.predict_proba(val_X)#每一類的概率
FPR_log, recall_log, thresholds = roc_curve(val_y, predictions_log[:,1],pos_label=1)
area_log=auc(FPR_log,recall_log)
print('logistics模型結(jié)果:\n')
print(pd.DataFrame(columns=['預(yù)測值=1','預(yù)測值=0'],index=['真實(shí)值=1','真實(shí)值=0'],data=confusion_matrix_logistics))#混淆矩陣
print("f1值:"+str(f1_score_logistics))
print("準(zhǔn)確率和召回率為:"+str(scores_logistics))
print('模型系數(shù):\n'+str(importance))
#SVM模型建立
min_max_scaler = preprocessing.MinMaxScaler()#注意要?dú)w一化
X_train_minmax = min_max_scaler.fit_transform(train_X)
X_test_minmax=min_max_scaler.transform(val_X)
model_svm=SVC(probability=True)
model_svm.fit(X_train_minmax,train_y)
y_pred = model_svm.predict(X_test_minmax)
scores_svm=[]
scores_svm.append(precision_score(val_y, y_pred))
scores_svm.append(recall_score(val_y, y_pred))
confusion_matrix_svm=confusion_matrix(val_y,y_pred)
f1_score_svm=f1_score(val_y, y_pred,labels=None, pos_label=1, average='binary', sample_weight=None)
predictions_svm=model_svm.predict_proba(X_test_minmax)#每一類的概率
FPR_svm, recall_svm, thresholds = roc_curve(val_y,predictions_svm[:,1], pos_label=1)
area_svm = auc(FPR_svm,recall_svm)
print('svm模型結(jié)果:\n')
print(pd.DataFrame(columns=['預(yù)測值=1','預(yù)測值=0'],index=['真實(shí)值=1','真實(shí)值=0'],data=confusion_matrix_svm))#混淆矩陣
print("f1值:"+str(f1_score_svm))
print("準(zhǔn)確率和召回率為:"+str(scores_svm))
#xgboost模型建立
model_XGB = XGBClassifier()
eval_set = [(val_X, val_y)]
model_XGB.fit(train_X, train_y, early_stopping_rounds=500, eval_metric="logloss", eval_set=eval_set, verbose=False)
# verbose改為True就能可視化loss
y_pred = model_XGB.predict(val_X)
scores_XGB=[]
scores_XGB.append(precision_score(val_y, y_pred))
scores_XGB.append(recall_score(val_y, y_pred))
confusion_matrix_XGB=confusion_matrix(val_y,y_pred)
f1_score_XGB=f1_score(val_y, y_pred,labels=None, pos_label=0, average="binary", sample_weight=None)
predictions_xgb=model_XGB.predict_proba(val_X)#每一類的概率
FPR_xgb, recall_xgb, thresholds = roc_curve(val_y,predictions_xgb[:,1], pos_label=1)
area_xgb = auc(FPR_xgb,recall_xgb)
print('xgboost模型結(jié)果:\n')
print(pd.DataFrame(columns=['預(yù)測值=1','預(yù)測值=0'],index=['真實(shí)值=1','真實(shí)值=0'],data=confusion_matrix_XGB))#混淆矩陣
print("f1值:"+str(f1_score_XGB))
print("精確度和召回率:"+str(scores_XGB))
#ROC圖的繪制
plt.figure(figsize=(10,8))
plt.plot(FPR_xgb, recall_xgb, 'b', label='XGBoost_AUC = %0.3f' % area_xgb)
plt.plot(FPR_svm, recall_svm,label='SVM_AUC = %0.3f' % area_svm)
plt.plot(FPR_log, recall_log,label='Logistic_AUC = %0.3f' % area_log)
plt.legend(loc='lower right')
plt.plot([0,1],[0,1],'r--')
plt.xlim([0.0,1.0])
plt.ylim([0.0,1.0])
plt.ylabel('Recall')
plt.xlabel('FPR')
plt.title('ROC_before_GridSearchCV')
plt.show()
5.3 模型參數(shù)調(diào)優(yōu)
Logistic模型調(diào)優(yōu):
C:C為正則化系數(shù)λ的倒數(shù),必須為正數(shù),默認(rèn)為1。和SVM中的C一樣,值越小,代表正則化越強(qiáng)。
SVM模型調(diào)優(yōu):
C:懲罰系數(shù),即對誤差的寬容度。c越高,說明越不能容忍出現(xiàn)誤差,容易過擬合。C越小,容易欠擬合。C過大或過小,泛化能力變差
gamma: 選擇RBF函數(shù)作為kernel后,該函數(shù)自帶的一個參數(shù)。隱含地決定了數(shù)據(jù)映射到新的特征空間后的分布,gamma越大,支持向量越少,gamma值越小,支持向量越多。支持向量的個數(shù)影響訓(xùn)練與預(yù)測的速度。
XGBoost參數(shù)調(diào)優(yōu):
XGBoost的參數(shù)較多,這里對三個參數(shù)進(jìn)行了調(diào)整,共分為兩步調(diào)整。整體思路是先調(diào)整較為重要的一組參數(shù),然后將調(diào)到最優(yōu)的參數(shù)輸入模型后繼續(xù)調(diào)下一組參數(shù)。
parameters_Logr = {'C':[0.05,0.1,0.5,1]}
parameters_svm = {'C':[0.05,0.1,1,5,10,20,50,100],'gamma':[0.01,0.05,0.1,0.2,0.3]}
# 網(wǎng)格搜索
grid_search_log = GridSearchCV(model_logistics,parameters_Logr, cv=5,scoring='roc_auc')
grid_search_log.fit(train_X, train_y)
grid_search_svm = GridSearchCV(model_svm,parameters_svm, cv=5,scoring='roc_auc')
grid_search_svm.fit(X_train_minmax, train_y)
# 獲得參數(shù)的最優(yōu)值
print('Log:\n')
print(grid_search_log.best_params_,grid_search_log.best_score_)
print('\nSVM:\n')
print(grid_search_svm.best_params_,grid_search_svm.best_score_)
#XGBoost調(diào)參
#第一步:先調(diào)max_depth、min_child_weight
param_test1 = {
'max_depth':range(3,10,2),
'min_child_weight':range(1,6,2)
}
gsearch1 = GridSearchCV(estimator = XGBClassifier(),
param_grid = param_test1,scoring='roc_auc')
gsearch1.fit(train_X,train_y,early_stopping_rounds=500, eval_metric="logloss", eval_set=eval_set, verbose=False)
gsearch1.best_params_,gsearch1.best_score_
#第二步:調(diào)gamma
param_test2 = {
'gamma':[0.01,0.05,0.1,0.2,0.3,0.5,1]
}
gsearch2 = GridSearchCV(estimator = XGBClassifier(max_depth=3,min_child_weight=3),
param_grid = param_test2, scoring='roc_auc', cv=5)
gsearch2.fit(train_X,train_y,early_stopping_rounds=500, eval_metric="logloss", eval_set=eval_set, verbose=False)
gsearch2.best_params_, gsearch2.best_score_
5.4 將調(diào)參過后的模型重新進(jìn)行訓(xùn)練并與原模型比較
model_logistics_after = LogisticRegression(C=0.5)
model_logistics_after.fit(train_X,train_y)
y_pred_after = model_logistics_after.predict(val_X)
scores_logistics_after=[]
scores_logistics_after.append(precision_score(val_y, y_pred_after))
scores_logistics_after.append(recall_score(val_y, y_pred_after))
confusion_matrix_logistics_after=confusion_matrix(val_y,y_pred_after)
f1_score_logistics_after=f1_score(val_y, y_pred_after,labels=None, pos_label=1, average='binary', sample_weight=None)
precision_logistics_after = precision_score(val_y, y_pred_after, average='binary')# 精確率指模型預(yù)測為正的樣本中實(shí)際也為正的樣本占被預(yù)測為正的樣本的比例。
importance_after=pd.DataFrame({"columns":list(val_X.columns), "coef":list(model_logistics_after.coef_.T)})
predictions_log_after=model_logistics_after.predict_proba(val_X)#每一類的概率
FPR_log_after, recall_log_after, thresholds_after = roc_curve(val_y, predictions_log_after[:,1],pos_label=1)
area_log_after=auc(FPR_log_after,recall_log_after)
print('調(diào)參后logistics模型結(jié)果:\n')
print(pd.DataFrame(columns=['預(yù)測值=1','預(yù)測值=0'],index=['真實(shí)值=1','真實(shí)值=0'],data=confusion_matrix_logistics_after))#混淆矩陣
print("f1值:"+str(f1_score_logistics_after))
print("準(zhǔn)確率和召回率為:"+str(scores_logistics_after))
print('模型系數(shù):\n'+str(importance_after))
model_svm_after=SVC(C=100,gamma=0.1,probability=True)
model_svm_after.fit(X_train_minmax,train_y)
y_pred_after = model_svm_after.predict(X_test_minmax)
scores_svm_after=[]
scores_svm_after.append(precision_score(val_y, y_pred_after))
scores_svm_after.append(recall_score(val_y, y_pred_after))
confusion_matrix_svm_after=confusion_matrix(val_y,y_pred_after)
f1_score_svm_after=f1_score(val_y, y_pred_after,labels=None, pos_label=1, average='binary', sample_weight=None)
predictions_svm_after=model_svm.predict_proba(X_test_minmax)#每一類的概率
FPR_svm_after, recall_svm_after, thresholds_after = roc_curve(val_y,predictions_svm_after[:,1], pos_label=1)
area_svm_after = auc(FPR_svm_after,recall_svm_after)
print('調(diào)參后svm模型結(jié)果:\n')
print(pd.DataFrame(columns=['預(yù)測值=1','預(yù)測值=0'],index=['真實(shí)值=1','真實(shí)值=0'],data=confusion_matrix_svm_after))#混淆矩陣
print("f1值:"+str(f1_score_svm_after))
print("準(zhǔn)確率和召回率為:"+str(scores_svm_after))
model_XGB_after = XGBClassifier(max_depth= 3, min_child_weight= 3,gamma=0.5)
eval_set = [(val_X, val_y)]
model_XGB_after.fit(train_X, train_y, early_stopping_rounds=500, eval_metric="logloss", eval_set=eval_set, verbose=False)
# verbose改為True就能可視化loss
y_pred_after = model_XGB_after.predict(val_X)
scores_XGB_after=[]
scores_XGB_after.append(precision_score(val_y, y_pred_after))
scores_XGB_after.append(recall_score(val_y, y_pred_after))
confusion_matrix_XGB_after=confusion_matrix(val_y,y_pred_after)
f1_score_XGB_after=f1_score(val_y, y_pred_after,labels=None, pos_label=0, average="binary", sample_weight=None)
predictions_xgb_after=model_XGB_after.predict_proba(val_X)#每一類的概率
FPR_xgb_after, recall_xgb_after, thresholds_after = roc_curve(val_y,predictions_xgb_after[:,1], pos_label=1)
area_xgb_after = auc(FPR_xgb_after,recall_xgb_after)
print('調(diào)參后xgboost模型結(jié)果:\n')
print(pd.DataFrame(columns=['預(yù)測值=1','預(yù)測值=0'],index=['真實(shí)值=1','真實(shí)值=0'],data=confusion_matrix_XGB_after))#混淆矩陣
print("f1值:"+str(f1_score_XGB_after))
print("精確度和召回率:"+str(scores_XGB_after))
plt.figure(figsize=(10,8))
plt.plot(FPR_xgb_after, recall_xgb_after, 'b', label='XGBoost_AUC = %0.3f' % area_xgb_after)
plt.plot(FPR_svm_after, recall_svm_after,label='SVM_AUC = %0.3f' % area_svm_after)
plt.plot(FPR_log_after, recall_log_after,label='Logistic_AUC = %0.3f' % area_log_after)
plt.legend(loc='lower right')
plt.plot([0,1],[0,1],'r--')
plt.xlim([0.0,1.0])
plt.ylim([0.0,1.0])
plt.ylabel('Recall')
plt.xlabel('FPR')
plt.title('ROC_after_GridSearchCV')
plt.show()
如下表是原模型和調(diào)參后的模型的比較(不同隨機(jī)數(shù)種子可能結(jié)果有所出入):
從對比結(jié)果可以看出,調(diào)參后的模型性能總體略優(yōu)于調(diào)參前的模型。
6 總結(jié)
本項(xiàng)目以體檢數(shù)據(jù)集為樣本進(jìn)行了機(jī)器學(xué)習(xí)的預(yù)測,但是需要注意幾個問題:
體檢數(shù)據(jù)量太少,僅有1006條可分析數(shù)據(jù),這對于糖尿病預(yù)測來說是遠(yuǎn)遠(yuǎn)不足的,所分析的結(jié)果代表性不強(qiáng)。
這里的數(shù)據(jù)糖尿病和正常人基本相當(dāng),而真實(shí)的數(shù)據(jù)具有很強(qiáng)的不平衡性。也就是說,糖尿病患者要遠(yuǎn)少于正常人,這種不平衡的數(shù)據(jù)集給真實(shí)情況下糖尿病的預(yù)測帶來了很大困難,當(dāng)然可以通過上采樣、下采樣或者其他方法進(jìn)行不平衡數(shù)據(jù)集的預(yù)測。
缺少時序數(shù)據(jù)使得預(yù)測變得不準(zhǔn)確,時序數(shù)據(jù)更能夠體現(xiàn)一個人的身體狀態(tài)。
選題指導(dǎo),項(xiàng)目分享:
https://gitee.com/yaa-dc/warehouse-1/blob/master/python/README.md
到了這里,關(guān)于數(shù)據(jù)分析畢業(yè)設(shè)計(jì) 大數(shù)據(jù)糖尿病預(yù)測與可視化 - 機(jī)器學(xué)習(xí) python的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!