關於AUC

maxuewei2發表於2024-03-02

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