AUC值計算與實現(xiàn)

AUC(Area under curve)是機(jī)器學(xué)習(xí)常用的二分類評測手段,直接含義是ROC曲線下的面積。
ROC曲線理解起來更加的復(fù)雜且計算工程更加麻煩,因此從計算概率的角度理解AUC
也可以理解為:隨機(jī)抽出一對樣本(一個正樣本,一個負(fù)樣本),然后用訓(xùn)練得到的分類器來對這兩個樣本進(jìn)行預(yù)測,預(yù)測得到正樣本的概率大于負(fù)樣本概率的概率。

那如何實現(xiàn)這樣的計算呢?
我們從字面上的意思開始理解
一對樣本,根據(jù)模型預(yù)測的結(jié)果,預(yù)測得到正樣本的概率大于負(fù)樣本概率的概率。
因此計算方法即為如下:

在有M個正樣本,N個負(fù)樣本的數(shù)據(jù)集里。
一共有 MxN 對樣本(一對樣本即,一個正樣本與一個負(fù)樣本)。
統(tǒng)計這 MxN 對樣本里,正樣本的預(yù)測概率大于負(fù)樣本的預(yù)測概率的個數(shù)。

image.png

舉個例子:

class label pre
A 0 0.1
B 0 0.4
C 1 0.3
D 1 0.8

假設(shè)有4條樣本。2個正樣本,2個負(fù)樣本,那么MxN=4。
即總共有4個樣本對。分別是:
(C,A), (C,B), (D,A), (D,B)

在(C,B)樣本對中,正樣本C預(yù)測的概率小于負(fù)樣本B預(yù)測的概率(也就是C的得分比B低),記為0
在(D,B)樣本對中,正樣本D預(yù)測的概率大于負(fù)樣本B預(yù)測的概率(也就是D的得分比B高),記為1
所以最后的AUC結(jié)果即為:
(C,A), (C,B), (D,A), (D,B) =1+0+1+1
總樣本對為MxN=4
所以結(jié)果為:

image.png

如果遇見得分一樣的呢?

class label pre
A 0 0.1
B 0 0.4
C 1 0.4
D 1 0.8

同樣本是4個樣本對,對于樣本對(C,B)其I值為0.5。


image.png
from sklearn.metrics import roc_auc_score
def calcAUC(labels, probs):
    N = 0
    P = 0
    neg_prob = []
    pos_prob = []
    for _,i in enumerate(labels):
        if (i == 1):
            P += 1
            pos_prob.append(probs[_])
        else:
            N += 1
            neg_prob.append(probs[_])
    number = 0
    for pos in pos_prob:
        for neg in neg_prob:
            if (pos > neg):
                number += 1
            elif (pos == neg):
                number += 0.5
    return number / (N * P)

y = np.array([1,0,0,0,1,0,1,0,])
pred = np.array([0.9, 0.8, 0.3, 0.1,0.4,0.9,0.66,0.7])
print('auc=',calcAUC(y,pred))
print('roc_auc=',roc_auc_score(y,pred))
auc= 0.5666666666666667
roc_auc= 0.5666666666666667

上面的計算方法用了2個循環(huán),時間復(fù)雜度高,因此我們對其進(jìn)行如下優(yōu)化。

首先按照預(yù)測的概率從小到高排列:

class label pre
A 0 0.1
C 1 0.3
B 0 0.4
D 1 0.8

顯然比C小的就是A
比D小的就是A,B
C的位置是2 D的位置是4
2+4 =A+C+A+B+C+D -----------(1)
而我們的目標(biāo)是:
1+2=A+A+B -----------(2)
因此需要將(1)式減去 C+C+D
顯然就是將正樣本進(jìn)行排列然后用等差數(shù)列求和公式即:


image.png

所以最后的求解公式為:


image.png

如果出現(xiàn)預(yù)測相同的情況

class label pre rangk
A 0 0.1 1
B 1 0.5 2
C 1 0.5 3
D 0 0.5 4
E 0 0.5 5
F 1 0.8 6
G 1 0.9 7

那就是正負(fù)樣本平分位置即可


image.png

用python實現(xiàn):

import numpy as np
from sklearn.metrics import roc_curve
from sklearn.metrics import auc


def auc_calculate(labels,preds,n_bins=100):
    postive_len = sum(labels)   #正樣本數(shù)量(因為正樣本都是1)
    negative_len = len(labels) - postive_len #負(fù)樣本數(shù)量
    total_case = postive_len * negative_len #正負(fù)樣本對
    pos_histogram = [0 for _ in range(n_bins)] 
    neg_histogram = [0 for _ in range(n_bins)]
    bin_width = 1.0 / n_bins
    for i in range(len(labels)):
        nth_bin = int(preds[i]/bin_width)
        if labels[i]==1:
            pos_histogram[nth_bin] += 1
        else:
            neg_histogram[nth_bin] += 1
    accumulated_neg = 0
    satisfied_pair = 0
    for i in range(n_bins):
        satisfied_pair += (pos_histogram[i]*accumulated_neg + pos_histogram[i]*neg_histogram[i]*0.5)
        accumulated_neg += neg_histogram[i]
    return satisfied_pair / float(total_case)

if __name__ == '__main__':
    y = np.array([1,0,0,0,1,0,1,0,])
    pred = np.array([0.9, 0.8, 0.3, 0.1,0.4,0.9,0.66,0.7])

    fpr, tpr, thresholds = roc_curve(y, pred, pos_label=1)
    print("sklearn:",auc(fpr, tpr))
    print("驗證:",auc_calculate(y,pred))

sklearn: 0.5666666666666667
驗證: 0.5666666666666667

參考:
AUC計算的兩種實現(xiàn)方式以及python代碼
AUC詳解與python實現(xiàn)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容