機器學習第二週:如何評價模型的好壞
一、目標
數據拆分:訓練數據集&測試數據集
評價分類結果:精準度、混淆矩陣、精準率、召回率、F1 Score、ROC曲線等
評價迴歸結果:MSE、RMSE、MAE、R Squared
二、學習資料參考
-
《機器學習的敲門磚:kNN算法(中)》(https://mp.weixin.qq.com/s/vvCM0vWH5kmRfrRWxqXT8Q)全文,學習數據拆分,劃分訓練數據集&測試數據集的方法。分類準確度。
-
閱讀《評價分類結果(上):混淆矩陣、精準率、召回率》(https://mp.weixin.qq.com/s/Fi13jaEkM5EGjmS7Mm_Bjw)
-
《評價分類結果(下):F1 Score、ROC、AUC》**,全面瞭解評價分類結果
-
閱讀《模型之母:線性迴歸的評價指標》(https://mp.weixin.qq.com/s/BEmMdQd2y1hMu9wT8QYCPg),學習評價迴歸結果:MSE、RMSE、MAE、R Squared
注:本文是上面這四篇文章的筆記,均來自與公衆號 數據科學家聯盟組織的學習小組,木東居士和餅乾等分享的文章。
三、學習開始
-
數據拆分:
KNN算法中:對數據集進行劃分,包括訓練集和測試集,在劃分過程中儘可能隨機選擇,訓練集數據要足夠多,可以採用隨機後採集0.8比例的數據作爲訓練集,剩餘0.2作爲測試數據集的數據進行。
方法命名:https://mp.weixin.qq.com/s/vvCM0vWH5kmRfrRWxqXT8Q l來源: 數據科學家聯盟 作者:Japson
def train_test_split(X, y, test_ratio = 0.2 , seed = None): if seed: np.random.seed(seed) shuffle_index = np.random.permutation(len(X)) test_size = int(len(X) * test_ratio) test_index = shuffle_index[:test_size] train_index = shuffle_index[test_size:] X_train = X[train_index] X_test = X[test_index] y_train = y[train_index] y_test = y[test_index] return X_train , X_test, y_train ,y_test
參考下面鏈接:sklearn在代碼中引入model_selection.train_test_split,可以隨機分割訓練集和測試集(隨機數種子)。如果該方法不加random_state可能會造成確定模型和初始參數後,每運行一次都可能得到不同的準確率。
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=0)
https://blog.csdn.net/Tony_Stark_Wang/article/details/80407923
-
分類準確度accuracy
在劃分出測試數據集後,根據訓練數據集訓練出的模型,需要進行對模型驗證,評價 其好壞。
accuracy_score 計算分類準確率,返回被正確分類的樣本比例(默認)或者數量
在多標籤分類問題中,該函數返回子集的準確率,對於一個給定的多標籤樣本,如果預測得到的標籤集合與該樣本真正的標籤集嚴格吻合,則subset accuracy = 1.0 否則是0.0。但有些場合使用精度(查準率)和召回率(查全率)等更好些。
def accuracy_score(y_true, y_predict): """計算y_true和y_predict之間的準確率""" assert y_true.shape[0] == y_predict.shape[0],"the size of y_true must be equal to the size of y_predict" return sum(y_true == y_predict) / len(y_true)
有時只關心對應的測試結果,可以使用score,進一步進行分裝
def score(self, X_test, y_test): """根據X_test進行預測, 給出預測的真值y_test,計算預測算法的準確度""" y_predict = self.predict(X_test) return accuracy_score(y_test, y_predict)
-
超參數
knn_clf = KNeighborsClassifier(n_neighbors=3)
這裏的數值,是傳遞一個默認的k值,但是這個參數該如何選擇。
超參數,在機器學習算法模型執行之前需要制定的參數。調參數理解調的就是超參數,如該處算法KNN中的k。
在對於KNN算法中,最容易想到的就是利用訓練數據,通過循環1…k,選擇其中得到的score最佳的一個結果對應的K
# 指定最佳值的分數,初始化爲0.0;設置最佳值k,初始值爲-1 best_score = 0.0 best_k = -1 for k in range(1, 11): # 暫且設定到1~11的範圍內 knn_clf = KNeighborsClassifier(n_neighbors=k) knn_clf.fit(X_train, y_train) score = knn_clf.score(X_test, y_test) if score > best_score: best_k = k best_score = score print("best_k = ", best_k) print("best_score = ", best_score)
-
超參數:權重
在KNN算法中,我們是利用對應的k個鄰近點,每個點的權重都是1,如果根據距離遠近增加判斷結果所起的作用,影響大的增加權重大點。可以使用f(x)=1/x,對每種分類點距離倒數求和,判斷數值那個最大,然後該點所屬對應分類。
感覺可以調整f(x)
在sklearn.neighbors的構造函數 KNeighborsClassifier中有一個參數:weights ,默認uniform 是不考慮距離,也可以寫distance來考慮距離權重(默認是歐拉距離,如果要是曼哈頓距離,則可以寫參數P?)
在找兩個超參數,公衆號介紹使用了雙重循環,在每種距離運算下尋求k,最終尋求出一個最佳的兩個參數
# 兩種方式進行比較 best_method = "" best_score = 0.0 best_k = -1 for method in ["uniform","distance"]: for k in range(1, 11): knn_clf = KNeighborsClassifier(n_neighbors=k, weights=method, p=2) knn_clf.fit(X_train, y_train) score = knn_clf.score(X_test, y_test) if score > best_score: best_k = k best_score = score best_method = method print("best_method = ", method) print("best_k = ", best_k) print("best_score = ", best_score) 輸出: best_method = distance best_k = 4 best_score = 0.9916666666666667
method循環uniform,distance ,每種循環裏面嵌套子循環,子循環再遍歷k,在尋找最佳的score過程中,通過遍歷比較最終獲得一個滿意的k ,method
-
當有多個參數需要找尋最優時,是不是需要自己寫多個循環去搜索最優參數
餅乾說,超參數過多,超參數之間互相依賴等都是在具體超參數搜索過程中遇到的問題。如何一次性把想要的“最好”的超參數組合出來,sklearn中專門封裝了一個參數網格搜索方法GridSearch。使用時需要首先定義一個參數param_search。他是一個數據,數組中的每個元素是一個字典,字典中是對應的一組網格搜索,每一組網格搜索是這一組網格搜索每個參數的取值範圍。鍵是參數名稱,值是鍵所對應的的參數列表。
param_search = [ { "weights":["uniform"], "n_neighbors":[i for i in range(1,11)] }, { "weights":["distance"], "n_neighbors":[i for i in range(1,11)], "p":[i for i in range(1,6)] } ]
knn_clf = KNeighborsClassifier() # 調用網格搜索方法 from sklearn.model_selection import GridSearchCV # 定義網格搜索的對象grid_search,其構造函數的第一個參數表示對哪一個分類器進行算法搜索, #第二個參數表示網格搜索相應的參數 grid_search = GridSearchCV(knn_clf, param_search)
%%time 在網格中尋找最佳參數組 grid_search.fit(X_train, y_train) 輸出:CPU times: user 2min 21s, sys: 628 ms, total: 2min 21s Wall time: 2min 23s GridSearchCV(cv=None, error_score='raise', estimator=KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski', metric_params=None, n_jobs=1, n_neighbors=5, p=2, weights='uniform'), fit_params=None, iid=True, n_jobs=1, param_grid=[{'weights': ['uniform'], 'n_neighbors': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}, {'weights': ['distance'], 'n_neighbors': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'p': [1, 2, 3, 4, 5]}], pre_dispatch='2*n_jobs', refit=True, return_train_score='warn', scoring=None, verbose=0)
# 返回的是網格搜索搜索到的最佳的分類器對應的參數 grid_search.best_estimator_ 輸出:KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski', metric_params=None, n_jobs=1, n_neighbors=3, p=3, weights='distance')
#best_score grid_search.best_score_ 輸出:0.9853862212943633 grid_search.beat_params_ 輸出:{'n_neighbors':3, 'p':3, 'weights':'distance'} knn_clf = grid_search.beat_estimator_ knn_clf.score(X_test, y_test) 輸出:0.9833333333328
-
評價分類結果:混淆矩陣、精準率、召回率
在機器學習中如何評價一個算法的好壞,在迴歸問題中可以使用MSE/RMSE/MAE/R方。在使用分類精準度上,可能存在陷阱的,這是需要更加全面的信息。
在對於極度偏斜skewed data的數據,在使用分類準確度是不能衡量的,還需要使用混淆矩陣confusion matrix 做分析。
預測值0 預測值1 真實值0 TN FP 真實值1 FN TP TN:真實值是0,與測試值也是0,預測negative,預測正確
FP:真實值是0,預測值是1,預測positive,但預測錯誤了
FN:真實值是1,預測值是0,預測是negative,但預測錯誤了
TP:真實值是1,預測值是1,預測是positive,預測正確了
混淆矩陣的信息更多謝,提供更多一些指示的指標。
精準率和召回率
預測值0 預測值1 真實值0 9978(TN) 12(FP) 真實值1 2(FN) 8(TP) 所謂的精準率是:分母爲所有預測爲1的個數,分子是其中預測對了的個數。即預測值爲1,且預測對了的比例。
現實情況中我們更關注“患病”、“有風險”,且在“有風險”中且判斷正確的概率。如在100次結果爲患病的預測中,平均有40次是預測對的。精準率是我們關注的那個事件,預測的有多準。
召回率:所有真實值爲1的數據中,預測對了的個數。每當有100個癌症患者,算法可以成功的預測出8個。是在我們關注的那個事件真實的發生情況下,我們成功預測的比例是多少。舉個例子在知道算法準確率的情況下,爲什麼需要精準率和召回率
預測值0 預測值1 真實值0 9978 12 真實值1 2 8 如果簡單粗暴認爲所有人都是健康的,那麼算法準確率是99.78%,這個數據應該是毫無意義。如果算精準率則是40%,召回率是80%。也就是說在預測有病的人中預測準的概率是40%,在實際有病的人中成功預測的有80%。這兩個指標在本次分類中才能看出比準確率要實用。
總之:
精準率:我們關注的那件事,預測的有多準。
召回率:我們關注的那個事件真實的發生情況下,我們成功預測的比例是。
-
評價分類結果(下):F1 Score、ROC、AUC
當精準率和召回率一個高一個低時該如何選擇取捨那?適場景而定
在實際業務場景中,有很多沒有明顯的選擇,該如何在精準率和召回率中平衡,可以使用一個新的指標:F1 SCORE
F1 SCORE: 是精準率和召回率的調和平均值:
調和平均值,當其中某一個值高、另一個值低時,得到的Fs1 score也低;只有而且都非常高,F1纔會高。import numpy as np def f1_score(precision, recall): try: return 2*precision*recall /(precision + recall) except: return 0.0
0.9 0.1 --》 0.18…
ROC曲線
分類閾值、TPR和FPR
分類閾值:設置判斷樣本爲正例的閾值threshold ?
如果某個邏輯迴歸模型預測得到一個分數,但是這個分數是不是歸到一個類中,它需要一個判斷的條件,或者說是一個閾值,大於它,或者是小於他。
sklearn中有一個方法:decision_function
decision_scores = log_reg.decision_function(X_test)
y_predict = np.array(decision_scores >=5, dtype = ‘int’)
TPR :預測爲1,且預測對了的數量,佔真實值爲1的數據百分比。(召回率)
FPR:預測值爲1,單預測錯了的數量
ROC曲線:receiver operation characteristic Cureve,描述TPR和FPR之間的關係。x座標軸是FPR,y座標軸是TPR
TPR是所有真實值爲1中被判斷爲1的比例;FPR是真實值爲0中被錯誤判斷爲1的概率。理想情況下TPR=1 ,FPR=0。閾值取得最小正例預測值與最大負例預測值之間的值即可。
根據ROC曲線,x座標軸是FPR,y座標軸是TPR,我們想要真實值1中預測的越準確越好,即TPR越高越好,FPR是負例中錯誤的預測 成正確,這個值應該越少越好。因此也就是在左上角,說明效果越好。
當TPR=1,FPR=0,稱爲完美分類。當兩個算法的ROC曲線中隨便一點的TPR都要比兩外一個算法好,此時可以任務好的那個算法是兩個算法中我們想要的。
當兩個算法有交叉,這時無法判斷那個分類器較好時,按照餅乾哥的文章中說的可以計算曲線顯得面積AUC,作爲性能度量。???如何計算,請看AUC
AUC,在ROC曲線中,曲線下面的面試稱爲area under curve 。這個面積是小於1的。
AUC可以看做是由多個梯形的面積的和。
AUC=1,完美分類器;(0.5,1)優於隨機猜測。需要選取一個合適的閾值。AUC=0.5模型沒有預測價值;AUC<0.5 比隨機預測還差。
sklearn.metrics roc_auc_score
roc_auc_score(y_test,decision_scores)
-
線性迴歸的評價指標:MSE、RMSE、MAE、R Squared
線性迴歸模型,在使用最小二乘法,使訓練集與預測值的差的平方和最小,求出截距和係數,之後使用測試集進行測試,以此來衡量算法的好壞。
均方誤差MSE:在最小二乘法的計算過程中均方和往往在項數越多時,結果越相差很大。因此需要將測試的數據集的個數進行抵消,因此:mean squared error
均方根誤差RMSE(解決量綱問題):root mean squarde error
平均絕對誤差MAE: mean absolute error
R Square
R Square <=1,它越大越好,因爲減數的分子這樣就越小,即預測值和真實值之差的平方和越小,錯誤率低。其最大值是1.
當爲0時,則是基準模型,什麼叫做基準模型???
四、總結
本文中分別介紹了:數據拆分,將數據拆分爲訓練數據集&測試數據集。同時對於分類KNN,介紹了結果的評價指標,他們分別是精準度、混淆矩陣、精準率、召回率、F1 Score、ROC曲線等,各類指標都有其應用的場景。最後介紹了線性迴歸算法的評價,可以用MSE、RMSE、MAE、R Squared,其中效果最好的是R Squared。