一、選題背景
心血管疾病(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()