AUC是推薦系統常用的線下評價指標,其全稱是Area Under the Curve。這裡的Curve一般是指ROC(受試者操作曲線,Receiver operating characteristic),所以我們所說的AUC一般是指AUROC。
本文將沿分類閾值 -> 混淆矩陣 -> ROC -> AUC的路線梳理對AUC的理解。
分類閾值->混淆矩陣
在做二分類任務時,模型一般會對每個樣本輸出一個分值s(有時這個分值也表示樣本是正例的機率)。
在這個分值區間裡,設定一個閾值t,就可以把在閾值之上的預測為正例,閾值之下的預測為負例。
根據樣本的真實標籤和模型的預測標籤,可以分為四種情況,統計四種情況的樣本個數,就可以得到一個混淆矩陣(confusion matrix):
正樣本 | 負樣本 | |
---|---|---|
預測為正 | TP(真正例) | FP(假正例) |
預測為負 | FN(假負例) | TN(真負例) |
比如下圖,正樣本和負樣本在分值區間上是兩個正態分佈,閾值t可以把每個分佈切分成兩塊。
左右調整閾值t的大小,這四個值也會隨之變化。於是,每個閾值t都會得到一個混淆矩陣。
假如我們要比較N個模型,每個模型設定K個閾值,那麼就有N*K個混淆矩陣。用這麼多混淆矩陣來比較這些模型的效果顯然不現實。
混淆矩陣->TPR/FPR
所以接下來,根據混淆矩陣裡的四個值,定義兩個指標:
- True Positive Rate (TPR,真正例率) = \(\frac{TP}{TP+FN}\)
- False Positive Rate (FPR,假正例率) = \(\frac{FP}{TN+FP}\)
對於真正例率TPR,分子是得分>t裡面正樣本的數目,分母是總的正樣本數目。
對於假正例率FPR,分子是得分>t裡面負樣本的數目,分母是總的負樣本數目。
一個好的模型,肯定是TPR越大越好,FPR越小越好。
分類閾值->TPR/FPR->ROC
那麼當我們調整閾值t時,因為混淆矩陣裡四個值的變化,這兩個指標也就會隨之變化。
當t變小時,因為FN變小,TPR會變大;因為TN變小,FPR也會變大。反之,當t變大時,TPR和FPR都會變小。
那麼如果我們取各種不同的閾值t,並以TPR和FPR作為座標軸,畫出各個t值對應的點,就可以得到這麼一個圖:
這個圖有這麼幾個特點
- 因為好的模型肯定是TPR大而FPR小,所以這些點都在左上的部分
- 因為t變大時,TPR和FPR都會變小,所以這些點從右上角到左下角是單調向下的
- 當t很小時,TN和FN是0,那麼TPR和FPR都是1。當t很大時,TP和FP都是0,那麼TPR和FPR都是0。
所以這些點是從右上角的(1,1)到左下角的(0,0)。
連線這些點,可以得到一個上凸的曲線,就是ROC曲線。
隨機模型的ROC曲線
隨機的模型不區分正負樣本,所以在得分>t的樣本里,正負樣本的比例應該與總體正負樣本的比例相同。無論t是多少。
即\(\frac{TP}{FP}=\frac{P}{N}=\frac{TP+FN}{TN+FP}\)。因此\(\frac{TP}{TP+FN}=\frac{FP}{TN+FP}\),即TPR\(=\)FPR。
所以隨機模型的ROC曲線是一條連線(0,0)和(1,1)的直線。
我們也可以畫出正負例在隨機模型的分值區間上的分佈,比如下圖的兩種情況,正負例在分值區間上同樣均勻分佈,或者正負例在分值區間上有相同的正態分佈,TPR和FPR都會隨著t的變化始終相等。
ROC->AUC
有了ROC曲線,比較多個模型的效果,就是比較多條ROC曲線。
曲線越往左上凸,模型效果越好。
但二維的曲線比較起來也還是不方便。
所以接下來定義ROC曲線下的面積為AUROC(Area Under the ROC Curve),大部分時候簡寫為AUC。
好的模型更向左上凸,所以曲線下面積也就更大,AUC也就更大。
所以就可以透過比較N個模型的AUC的大小來方便地比較它們的分類效果。
另外,隨機模型的AUC是對角線下的面積,即0.5。所以任何合理的模型的AUC都應該大於0.5。
AUC的另一種解釋
AUC除了以上定義為ROC曲線下面積,還有另一種常用的解釋。
即可以解釋為,隨機選取一個正樣本和一個負樣本,模型給正樣本的分值高於負樣本分值的機率。
這個解釋與以上用ROC曲線下面積來做的定義之間的關係,見StackExchange。
AUC的計算
根據上面對AUC的解釋,可以實現一種最簡單的\(O(n^2)\)複雜度的計算方法(\(n\)是樣本數)。
即取所有的正樣本和負樣本組成的二元組,共P*N個。統計這些二元組中,模型給正樣本分值大於負樣本分值的二元組所佔的比例。
點選檢視程式碼
import numpy as np
y = np.array([1, 0, 0, 0, 1, 0, 1, 0, 0, 1 ])
pred = np.array([0.9, 0.4, 0.3, 0.9, 0.35, 0.6, 0.65, 0.32, 0.8, 0.7])
def auc():
pos = pred[y==1]
neg = pred[y==0]
correct = 0
for i in pos:
for j in neg:
if i > j:
correct += 1
elif i == j:
correct += 0.5
return correct / (len(pos) * len(neg))
print(auc())
from sklearn import metrics
fpr, tpr, thresholds = metrics.roc_curve(y, pred, pos_label=1)
print(metrics.auc(fpr, tpr))
對樣本先排序可以把複雜度降低到\(O(n\log(n))\),見談auc的計算。
AUC的適用與不適用
適用
- 僅關心相對序,不考慮分值大小時
- 與閾值無關時
- 要求對正負樣本比例不敏感時,如對負樣本下采樣
不適用
- 關心分值大小時
- 某類正樣本或負樣本更重要時,如email spam classification
參考
- https://stats.stackexchange.com/questions/132777/what-does-auc-stand-for-and-what-is-it/133435#133435
- https://developers.google.com/machine-learning/crash-course/classification/roc-and-auc
- https://www.dataschool.io/roc-curves-and-auc-explained/
- https://tracholar.github.io/machine-learning/2018/01/26/auc.html
- https://stats.stackexchange.com/questions/190216/why-is-roc-auc-equivalent-to-the-probability-that-two-randomly-selected-samples
- https://stats.stackexchange.com/questions/180638/how-to-derive-the-probabilistic-interpretation-of-the-auc
- https://ccrma.stanford.edu/workshops/mir2009/references/ROCintro.pdf
- https://zhuanlan.zhihu.com/p/411010918
- https://medium.com/@penggongting/understanding-roc-auc-pros-and-cons-why-is-bier-score-a-great-supplement-c7a0c976b679
- https://stats.stackexchange.com/questions/105501/understanding-roc-curve
- https://en.wikipedia.org/wiki/Receiver_operating_characteristic
- https://www.youtube.com/watch?v=4jRBRDbJemM
- https://medium.com/greyatom/lets-learn-about-auc-roc-curve-4a94b4d88152