簡單聊聊模型的效能評估標準
機器學習入門系列(2)--如何構建一個完整的機器學習專案,第十篇!
該系列的前 9 篇文章:
- 機器學習入門系列(2)--如何構建一個完整的機器學習專案(一)
- 機器學習資料集的獲取和測試集的構建方法
- 特徵工程之資料預處理(上)
- 特徵工程之資料預處理(下)
- 特徵工程之特徵縮放&特徵編碼
- 特徵工程(完)
- 常用機器學習演算法彙總比較(上)
- 常用機器學習演算法彙總比較(中)
- 常用機器學習演算法彙總比較(完)
這個系列的文章也是要開始進入尾聲了,最後就主要是模型評估部分的內容了。
在機器學習領域中,對模型的評估非常重要,只有選擇和問題相匹配的評估方法,才能快速發現演算法模型或者訓練過程的問題,迭代地對模型進行優化。
模型評估主要分為離線評估和線上評估兩個階段。並且針對分類、迴歸、排序、序列預測等不同型別的機器學習問題,評估指標的選擇也有所不同。
模型評估這部分會介紹以下幾方面的內容:
- 效能度量
- 模型評估方法
- 泛化能力
- 過擬合、欠擬合
- 超引數調優
本文會首先介紹效能度量方面的內容,主要是分類問題和迴歸問題的效能指標,包括以下幾個方法的介紹:
- 準確率和錯誤率
- 精確率、召回率以及 F1
- ROC 曲線 和 AUC
- 代價矩陣
- 迴歸問題的效能度量
- 其他評價指標,如計算速度、魯棒性等
1. 效能度量
效能度量就是指對模型泛化能力衡量的評價標準。
1.1 準確率和錯誤率
分類問題中最常用的兩個效能度量標準--準確率和錯誤率。
準確率:指的是分類正確的樣本數量佔樣本總數的比例,定義如下:
錯誤率:指分類錯誤的樣本佔樣本總數的比例,定義如下:
錯誤率也是損失函式為 0-1 損失時的誤差。
這兩種評價標準是分類問題中最簡單也是最直觀的評價指標。但它們都存在一個問題,在類別不平衡的情況下,它們都無法有效評價模型的泛化能力。即如果此時有 99% 的負樣本,那麼模型預測所有樣本都是負樣本的時候,可以得到 99% 的準確率。
這種情況就是 在類別不平衡的時候,佔比大的類別往往成為影響準確率的最主要因素 !
這種時候,其中一種解決方法就是更換評價指標,比如採用更為有效的平均準確率( 每個類別的樣本準確率的算術平均 ),即:
其中 m 是類別的數量。
對於準確率和錯誤率,用 Python 程式碼實現如下圖所示:
def accuracy(y_true, y_pred): return sum(y == y_p for y, y_p in zip(y_true, y_pred)) / len(y_true) def error(y_true, y_pred): return sum(y != y_p for y, y_p in zip(y_true, y_pred)) / len(y_true) 複製程式碼
一個簡單的二分類測試樣例:
y_true = [1, 0, 1, 0, 1] y_pred = [0, 0, 1, 1, 0] acc = accuracy(y_true, y_pred) err = error(y_true, y_pred) print('accuracy=', acc) print('error=', err) 複製程式碼
輸出結果如下:
accuracy= 0.4 error= 0.6 複製程式碼
1.2 精確率、召回率、P-R 曲線和 F1
1.2.1 精確率和召回率
精確率,也被稱作查準率,是指 所有預測為正類的結果中,真正的正類的比例 。公式如下:
召回率,也被稱作查全率,是指所有正類中,被分類器找出來的比例。公式如下:
對於上述兩個公式的符號定義,是在二分類問題中,我們將關注的類別作為正類,其他類別作為負類別,因此,定義:
TP(True Positive) FP FN(False Negative) TN(True Negative)
更形象的說明,可以參考下表,也是 混淆矩陣 的定義:
預測:正類 | 預測:負類 | |
---|---|---|
實際:正類 | TP | FN |
實際:負類 | FP | TN |
精確率和召回率是一對矛盾的度量,通常精確率高時,召回率往往會比較低;而召回率高時,精確率則會比較低,原因如下:
- 精確率越高,代表預測為正類的比例更高,而要做到這點,通常就是 只選擇有把握的樣本 。最簡單的就是隻挑選最有把握的一個樣本,此時
FP=0
,P=1
,但FN
必然非常大(沒把握的都判定為負類),召回率就非常低了; - 召回率要高,就是需要找到所有正類出來,要做到這點,最簡單的就是 所有類別都判定為正類 ,那麼
FN=0
,但FP
也很大,所有精確率就很低了。
而且不同的問題,側重的評價指標也不同,比如:
- 對於推薦系統,側重的是精確率 。也就是希望推薦的結果都是使用者感興趣的結果,即使用者感興趣的資訊比例要高,因為通常給使用者展示的視窗有限,一般只能展示 5 個,或者 10 個,所以更要求推薦給使用者真正感興趣的資訊;
- 對於醫學診斷系統,側重的是召回率 。即希望不漏檢任何疾病患者,如果漏檢了,就可能耽擱患者治療,導致病情惡化。
精確率和召回率的程式碼簡單實現如下,這是基於二分類的情況
def precision(y_true, y_pred): true_positive = sum(y and y_p for y, y_p in zip(y_true, y_pred)) predicted_positive = sum(y_pred) return true_positive / predicted_positive def recall(y_true, y_pred): true_positive = sum(y and y_p for y, y_p in zip(y_true, y_pred)) real_positive = sum(y_true) return true_positive / real_positive 複製程式碼
簡單的測試樣例以及輸出如下
y_true = [1, 0, 1, 0, 1] y_pred = [0, 0, 1, 1, 0] precisions = precision(y_true, y_pred) recalls = recall(y_true, y_pred) print('precisions=', precisions) # 輸出為0.5 print('recalls=', recalls)# 輸出為 0.3333 複製程式碼
1.2.2 P-R 曲線和 F1
很多時候,我們都可以根據分類器的預測結果對樣本進行排序,越靠前的是分類器越有把握是正類的樣本,而最後面的自然就是分類器覺得最不可能是正類的樣本了。
一般來說,這個預測結果其實就是分類器對樣本判斷為某個類別的置信度,我們可以選擇不同的閾值來調整分類器對某個樣本的輸出結果,比如設定閾值是 0.9,那麼只有置信度是大於等於 0.9 的樣本才會最終判定為正類,其餘的都是負類。
我們設定不同的閾值,自然就會得到不同的正類數量和負類數量,依次計算不同情況的精確率和召回率,然後我們可以 以精確率為縱軸,召回率為橫軸,繪製一條“P-R曲線” ,如下圖所示:

當然,以上這個曲線是比較理想情況下的,未來繪圖方便和美觀,實際情況如下圖所示:

對於 P-R 曲線,有:
1. 曲線從左上角 (0,1)
到右下角 (1,0)
的走勢,正好反映了精確率和召回率是一對矛盾的度量 ,一個高另一個低的特點:
- 開始是精確率高 ,因為設定閾值很高,只有第一個樣本(分類器最有把握是正類)被預測為正類,其他都是負類,所以精確率高,幾乎是 1,而召回率幾乎是 0,僅僅找到 1 個正類。
- 右下角時候就是召回率很高,精確率很低 ,此時設定閾值就是 0,所以類別都被預測為正類,所有正類都被找到了,召回率很高,而精確率非常低,因為大量負類被預測為正類。
2. P-R
曲線可以非常直觀顯示出分類器在樣本總體上的精確率和召回率。所以可以對比兩個分類器在同個測試集上的 P-R
曲線來比較它們的分類能力:
- 如果分類器
B
的P-R
曲線被分類器A
的曲線完全包住,如下左圖所示,則可以說,A
的效能優於B
; - 如果是下面的右圖,兩者的曲線有交叉,則很難直接判斷兩個分類器的優劣,只能根據具體的精確率和召回率進行比較:
- 一個合理的依據是 比較
P-R
曲線下方的面積大小 ,它在一定程度上表徵了分類器在精確率和召回率上取得“雙高”的比例,但這個數值不容易計算; - 另一個比較就是 平衡點 (Break-Event Point, BEP),它是 精確率等於召回率時的取值 ,如下右圖所示,而且可以判定, 平衡點較遠的曲線更好 。
- 一個合理的依據是 比較

當然了,平衡點還是過於簡化,於是有了 F1 值 這個新的評價標準,它是 精確率和召回率的調和平均值 ,定義為:
F1 還有一個更一般的形式: ,能讓我們表達出對精確率和召回率的不同偏好,定義如下:
其中 度量了召回率對精確率的相對重要性,當 ,就是 F1;如果 ,召回率更加重要;如果 ,則是精確率更加重要。
1.2.3 巨集精確率/微精確率、巨集召回率/微召回率以及巨集 F1 / 微 F1
很多時候,我們會得到不止一個二分類的混淆矩陣,比如多次訓練/測試得到多個混淆矩陣,在多個數據集上進行訓練/測試來估計演算法的“全域性”效能,或者是執行多分類任務時對類別兩兩組合得到多個混淆矩陣。
總之,我們希望在 n 個二分類混淆矩陣上綜合考察精確率和召回率。這裡一般有兩種方法來進行考察:
1.第一種是直接在 各個混淆矩陣上分別計算出精確率和召回率 ,記為 ,接著 計算平均值 ,就得到巨集精確率(macro-P)、巨集召回率(macro-R)以及巨集 F1(macro-F1) , 定義如下:
2.第二種則是 對每個混淆矩陣的對應元素進行平均 , 得到 TP、FP、TN、FN 的平均值 ,再基於這些平均值就就得到微精確率(micro-P)、微召回率(micro-R)以及微 F1(micro-F1) , 定義如下:
1.3 ROC 與 AUC
1.3.1 ROC 曲線
ROC 曲線的 Receiver Operating Characteristic 曲線的簡稱,中文名是“受試者工作特徵”,起源於軍事領域,後廣泛應用於醫學領域。
它的橫座標是 假正例率(False Positive Rate, FPR) ,縱座標是 真正例率(True Positive Rate, TPR) ,兩者的定義分別如下:
TPR 表示 正類中被分類器預測為正類的概率 ,剛好就等於正類的召回率;
FPR 表示 負類中被分類器預測為正類的概率 ,它等於 1 減去負類的召回率,負類的召回率如下, 稱為真反例率(True Negative Rate, TNR) , 也被稱為特異性,表示負類被正確分類的比例。
跟 P-R 曲線的繪製一樣,ROC 曲線其實也是通過 不斷調整區分正負類結果的閾值 來繪製得到的,它的縱軸是 TPR,橫軸是 FPR,這裡借鑑《百面機器學習》上的示例來介紹,首先有下圖所示的表格,表格是一個二分類模型的輸出結果樣例,包含 20 個樣本,然後有對應的真實標籤,其中 p 表示是正類別,而 n 表示是負類別。然後模型輸出概率表示模型對判斷該樣本是正類的置信度。

最開始如果設定閾值是無窮大的時候,那麼模型會將所有樣本判斷為負類,TP 和 FP 都會是 0,也就是 TPR 和 FPR 必然也是 0,ROC 曲線的第一個座標就是 (0, 0)。接著,閾值設定為 0.9,此時樣本序號為 1 的樣本會被判斷為正樣本,並且它確實是正樣本,那麼 TP = 1,而正類樣本的個數是有 10 個,所有 TPR = 0.1;然後沒有預測錯誤的正類,即 FP = 0,FPR = 0,這個時候曲線的第二個座標就是 (0, 0.1)。
通過不斷調整閾值,就可以得到曲線的不同座標,最終得到下圖所示的 ROC 曲線。

第二種更直觀地繪製 ROC 曲線的方法,首先統計出正負樣本的數量,假設分別是 P 和 N,接著,將橫軸的刻度間隔設定為 1/N,縱軸的刻度間隔設定為 1/P。然後根據模型輸出的概率對樣本排序,並按順序遍歷樣本,從零點開始繪製 ROC 曲線, 每次遇到一個正樣本就沿縱軸方向繪製一個刻度間隔的曲線 , 遇到一個負樣本就沿橫軸繪製一個刻度間隔的曲線 ,直到遍歷完所有樣本,曲線最終停留在 (1,1) 這個點,此時就完成了 ROC 曲線的繪製了。
當然,更一般的 ROC 曲線是如下圖所示的,會更加的平滑,上圖是由於樣本數量有限才導致的。

對於 ROC 曲線,有以下幾點特性:
1.ROC 曲線通常都是從左下角 (0,0) 開始,到右上角 (1,1) 結束。
- 開始時候, 第一個樣本被預測為正類 ,其他都是預測為負類別;
- TPR 會很低,幾乎是 0,上述例子就是 0.1,此時大量正類沒有被分類器找出來;
- FPR 也很低,可能就是0,上述例子就是 0,這時候被預測為正類的樣本可能實際也是正類,所以幾乎沒有預測錯誤的正類樣本。
- 結束時候, 所有樣本都預測為正類 。
- TPR 幾乎就是 1,因為所有樣本都預測為正類,那肯定就找出所有的正類樣本了;
- FPR 也是幾乎為 1,因為所有負樣本都被錯誤判斷為正類。
2.ROC 曲線中:
- 對角線對應於隨機猜想模型 ,即概率為 0.5;
- 點
(0,1)
是理想模型 ,因為此時TPR=1
,FPR=0
,也就是正類都預測出來,並且沒有預測錯誤; - 通常, ROC 曲線越接近點
(0, 1)
越好。
3.同樣可以根據 ROC 曲線來判斷兩個分類器的效能:
- 如果 分類器
A
的ROC
曲線被分類器B
的曲線完全包住,可以說B
的效能好過A
,這對應於上一條說的 ROC 曲線越接近點(0, 1)
越好; - 如果兩個分類器的
ROC
曲線發生了交叉,則同樣很難直接判斷兩者的效能優劣,需要藉助ROC
曲線下面積大小來做判斷,而這個面積被稱為AUC:Area Under ROC Curve
。
簡單的程式碼實現如下:
def true_negative_rate(y_true, y_pred): true_negative = sum(1 - (yi or yi_hat) for yi, yi_hat in zip(y_true, y_pred)) actual_negative = len(y_true) - sum(y_true) return true_negative / actual_negative def roc(y, y_hat_prob): thresholds = sorted(set(y_hat_prob), reverse=True) ret = [[0, 0]] for threshold in thresholds: y_hat = [int(yi_hat_prob >= threshold) for yi_hat_prob in y_hat_prob] ret.append([recall(y, y_hat), 1 - true_negative_rate(y, y_hat)]) return ret 複製程式碼
簡單的測試例子如下:
y_true = [1, 0, 1, 0, 1] y_hat_prob = [0.9, 0.85, 0.8, 0.7, 0.6] roc_list = roc(y_true, y_hat_prob) print('roc_list:', roc_list) # 輸出結果是 roc_list: [[0, 0], [0.3333333333333333, 0.0], [0.3333333333333333, 0.5], [0.6666666666666666, 0.5], [0.6666666666666666, 1.0], [1.0, 1.0]] 複製程式碼
1.3.2ROC 和 P-R 曲線的對比
相同點
1. 兩者刻畫的都是閾值的選擇對分類度量指標的影響 。雖然每個分類器對每個樣本都會輸出一個概率,也就是置信度,但通常我們都會人為設定一個閾值來影響分類器最終判斷的結果,比如設定一個很高的閾值--0.95,或者比較低的閾值--0.3。
- 如果是偏向於精確率,則提高閾值 ,保證只把有把握的樣本判斷為正類,此時可以設定閾值為 0.9,或者更高;
- 如果偏向於召回率,那麼降低閾值 ,保證將更多的樣本判斷為正類,更容易找出所有真正的正樣本,此時設定閾值是 0.5,或者更低。
2.兩個曲線的每個點都是 對應某個閾值的選擇,該點是在該閾值下的 (精確率,召回率)
/ (TPR, FPR)
。然後沿著橫軸方向對應閾值的下降。
不同
相比較 P-R
曲線, ROC
曲線有一個特點,就是 正負樣本的分佈發生變化時,它的曲線形狀能夠基本保持不變 。如下圖所示:

分別比較了增加十倍的負樣本後, P-R
和 ROC
曲線的變化,可以看到 ROC
曲線的形狀基本不變,但 P-R
曲線發生了明顯的變化。
所以 ROC
曲線的這個特點 可以降低不同測試集帶來的干擾 , 更加客觀地評估模型本身的效能 ,因此它適用的場景更多,比如排序、推薦、廣告等領域。
這也是由於 現實場景中很多問題都會存在正負樣本數量不平衡 的情況,比如計算廣告領域經常涉及轉化率模型,正樣本的數量往往是負樣本數量的千分之一甚至萬分之一,這時候選擇 ROC
曲線更加考驗反映模型本身的好壞。
當然,如果希望看到模型在特定資料集上的表現, P-R
曲線會更直觀地反映其效能。所以還是需要具體問題具體分析。
1.3.3 AUC 曲線
AUC
是 ROC
曲線的面積,其物理意義是:從所有正樣本中隨機挑選一個樣本,模型將其預測為正樣本的概率是 ;從所有負樣本中隨機挑選一個樣本,模型將其預測為正樣本的概率是 。 的概率就是 AUC
。
AUC
曲線有以下幾個特點:
-
如果完全隨機地對樣本進行分類,那麼 的概率是 0.5,則
AUC=0.5
; -
AUC 在樣本不平衡的條件下依然適用。
如:在反欺詐場景下,假設正常使用者為正類(設佔比 99.9%),欺詐使用者為負類(設佔比 0.1%)。
如果使用準確率評估,則將所有使用者預測為正類即可獲得 99.9%的準確率。很明顯這並不是一個很好的預測結果,因為欺詐使用者全部未能找出。
如果使用
AUC
評估,則此時FPR=1,TPR=1
,對應的AUC=0.5
。因此AUC
成功的指出了這並不是一個很好的預測結果。 -
AUC
反應的是 模型對於樣本的排序能力 (根據樣本預測為正類的概率來排序)。如:AUC=0.8
表示:給定一個正樣本和一個負樣本,在80%
的情況下,模型對正樣本預測為正類的概率大於對負樣本預測為正類的概率。 -
AUC
對於均勻取樣不敏感 。如:上述反欺詐場景中,假設對正常使用者進行均勻的降取樣。任意給定一個負樣本 n,設模型對其預測為正類的概率為 Pn 。降取樣前後,由於是均勻取樣,因此預測為正類的概率大於 Pn 和小於 Pn 的真正樣本的比例沒有發生變化。因此AUC
保持不變。但是如果是非均勻的降取樣,則預測為正類的概率大於 Pn 和小於 Pn 的真正樣本的比例會發生變化,這也會導致
AUC
發生變化。 -
正負樣本之間的預測為正類概率之間的差距越大,則
AUC
越高 。因為這表明正負樣本之間排序的把握越大,區分度越高。如:在電商場景中,點選率模型的
AUC
要低於購買轉化模型的AUC
。因為點選行為的成本低於購買行為的成本,所以點選率模型中正負樣本的差別要小於購買轉化模型中正負樣本的差別。
AUC
的計算可以通過對 ROC
曲線下各部分的面積求和而得。假設 ROC
曲線是由座標為下列這些點按順序連線而成的:
那麼 AUC
可以這樣估算:
程式碼實現如下:
def get_auc(y, y_hat_prob): roc_val = iter(roc(y, y_hat_prob)) tpr_pre, fpr_pre = next(roc_val) auc = 0 for tpr, fpr in roc_val: auc += (tpr + tpr_pre) * (fpr - fpr_pre) / 2 tpr_pre = tpr fpr_pre = fpr return auc 複製程式碼
簡單的測試樣例如下:
y_true = [1, 0, 1, 0, 1] y_hat_prob = [0.9, 0.85, 0.8, 0.7, 0.6] auc_val = get_auc(y_true, y_hat_prob) print('auc_val:', auc_val) # 輸出是 0.5 複製程式碼
1.4 代價矩陣
前面介紹的效能指標都有一個隱式的前提,錯誤都是 均等代價 。但實際應用過程中,不同型別的錯誤所造成的後果是不同的。比如將健康人判斷為患者,與患者被判斷為健康人,代價肯定是不一樣的,前者可能就是需要再次進行檢查,而後者可能錯過治療的最佳時機。
因此,為了衡量不同型別所造成的不同損失,可以為錯誤賦予 非均等代價(unequal cost) 。
對於一個二類分類問題,可以設定一個 代價矩陣(cost matrix) ,其中 表示將第 i
類樣本預測為第 j
類樣本的代價,而預測正確的代價是 0 。如下表所示:
預測:第 0 類 | 預測:第 1 類 | |
---|---|---|
真實:第 0 類 | 0 | |
真實: 第 1 類 | 0 |
-
在非均等代價下,希望找到的不再是簡單地最小化錯誤率的模型,而是希望找到 最小化總體代價
total cost
的模型 。 -
在非均等代價下,
ROC
曲線不能直接反映出分類器的期望總體代價,此時需要使用代價曲線cost curve
- 代價曲線的橫軸是 正例概率代價 ,如下所示,其中 p 是正例(第 0 類)的概率
-
代價曲線的縱軸是歸一化代價,如下所示:
其中,假正例率
FPR
表示模型將負樣本預測為正類的概率,定義如下:假負例率
FNR
表示將正樣本預測為負類的概率,定義如下:代價曲線如下圖所示:
1.5 迴歸問題的效能度量
對於迴歸問題,常用的效能度量標準有:
1.均方誤差(Mean Square Error, MSE),定義如下:
2.均方根誤差(Root Mean Squared Error, RMSE),定義如下:
3.均方根對數誤差(Root Mean Squared Logarithmic Error, RMSLE),定義如下
4.平均絕對誤差(Mean Absolute Error, MAE),定義如下:
這四個標準中,比較常用的第一個和第二個,即 MSE
和 RMSE
,這兩個標準一般都可以很好反映迴歸模型預測值和真實值的偏離程度,但如果遇到 個別偏離程度非常大的離群點 時,即便數量很少,也會讓這兩個指標變得很差。
遇到這種情況,有三種解決思路:
- 將離群點作為噪聲點來處理,即資料預處理部分需要過濾掉這些噪聲點;
- 從模型效能入手,提高模型的預測能力,將這些離群點產生的機制建模到模型中,但這個方法會比較困難;
- 採用其他指標,比如第三個指標
RMSLE
,它關注的是預測誤差的比例,即便存在離群點,也可以降低這些離群點的影響;或者是MAPE
,平均絕對百分比誤差(Mean Absolute Percent Error),定義為:
RMSE
的簡單程式碼實現如下所示:
def rmse(predictions, targets): # 真實值和預測值的誤差 differences = predictions - targets differences_squared = differences ** 2 mean_of_differences_squared = differences_squared.mean() # 取平方根 rmse_val = np.sqrt(mean_of_differences_squared) return rmse_val 複製程式碼
1.6 其他評價指標
- 計算速度:模型訓練和預測需要的時間;
- 魯棒性:處理缺失值和異常值的能力;
- 可拓展性:處理大資料集的能力;
- 可解釋性:模型預測標準的可理解性,比如決策樹產生的規則就很容易理解,而神經網路被稱為黑盒子的原因就是它的大量引數並不好理解。
小結
本文主要是基於二分類問題來介紹分類問題方面的幾種效能評估,它們都是非常常用的評價指標,通常實際應用中也主要是採用這幾種作為評估模型效能的方法。
參考:
- 《機器學習》--周志華
- 《百面機器學習》
- 《hands-on-ml-with-sklearn-and-tf》
- 9. 模型評估
- 分類模型評估的方法及Python實現
歡迎關注我的微信公眾號--機器學習與計算機視覺,或者掃描下方的二維碼,大家一起交流,學習和進步!
