ROC曲線,AUC面積


  AUC(Area under Curve):Roc曲線下的面積,介於0.1和1之間。Auc作為數值可以直觀的評價分類器的好壞,值越大越好。

  首先AUC值是一個概率值,當你隨機挑選一個正樣本以及負樣本,當前的分類算法根據計算得到的Score值將這個正樣本排在負樣本前面的概率就是AUC值,AUC值越大,當前分類算法越有可能將正樣本排在負樣本前面,從而能夠更好地分類。

1. 什么是ROC曲線?

  ROC曲線是Receiver operating characteristic curve的簡稱,中文名為“受試者工作特征曲線”。ROC曲線源於軍事領域,橫坐標為假陽性率(False positive rate,FPR),縱坐標為真陽性率(True positive rate,TPR).

假陽性率 FPR = FP/N ---N個負樣本中被判斷為正樣本的個數占真實的負樣本的個數 

真陽性率 TPR = TP/P ---P個正樣本中被預測為正樣本的個數占真實的正樣本的個數

2. 如何繪制ROC曲線?

  ROC曲線是通過不斷移動分類器的“截斷點”來生成曲線上的一組關鍵點的,“截斷點”指的就是區分正負預測結果的閾值。

  通過動態地調整截斷點,從最高的得分開始,逐漸調整到最低得分,每一個截斷點都會對應一個FPR和TPR,在ROC圖上繪制出每個截斷點對應的位置,再連接所有點就得到最終的ROC曲線。

  ROC曲線一定程度上可以反映分類器的分類效果,但是不夠直觀,我們希望有這么一個指標,如果這個指標越大越好,越小越差,於是,就有了AUC。AUC實際上就是ROC曲線下的面積。AUC直觀地反映了ROC曲線表達的分類能力

  • AUC=1完美分類器,采用這個預測模型時,不管設定什么閾值都能得出完美預測。絕大多數預測的場合,不存在完美分類器。
  • 0.5<AUC<10,優於隨機猜測。這個分類器(模型)妥善設定閾值的話,能有預測價值。
  • AUC=0.5,跟隨機猜測一樣(例:丟銅板),模型沒有預測價值。
  • AUC<0.5,比隨機猜測還差;但只要總是反預測而行,就優於隨機猜測,因此不存在 AUC<0.5AUC<0.5 的情況。

3. 如何計算AUC?

(1)適合數據量少

  AUC是一個模型評價指標,只能用於二分類模型的評價,對於二分類模型,還有很多其他評價指標,比如logloss,accuracy,precision。為什么AUC和logloss比accuracy更常用呢?因為很多機器學習的模型對分類問題的預測結果都是概率,如果要計算accuracy,需要先把概率轉化成類別,這就需要手動設置一個閾值,如果一個樣本的預測概率高於這個預測,就把這個樣本放進一個類別里面,低於這個閾值,放進另一個類別里面。所以這個閾值很大程度上影響了accuracy的計算,使用AUC或logloss可以避免把預測概率轉換成類別。

  AUC是Area under curve的首字母縮寫,從字面上理解,就是ROC曲線下的面積大小,該值能夠量化地反映基於ROC曲線衡量出的模型性能。由於ROC曲線一般都處於y=x這條直線的上方(如果不是的話,只要把模型預測的概率反轉成1-p就可以得到一個更好的分類器),所以AUC的取值一般在0.5-1之間。AUC越大,說明分類器越可能把真正的正樣本排在前面,分類性能越好。

 

舉例:5個樣本,真實的類別(標簽)是

y 1 1 0 0 1
p 0.5 0.6 0.55 0.4 0.7

  如文章一開始多說,我們需要選定閾值才能把概率轉化為類別,選定不同的閾值會得到不同的結果。如果我們選定的閾值為0.1,那5個樣本被分進1的類別,如果選定0.3,結果仍然一樣。如果選了0.45作為閾值,那么只有樣本4被分進0,其余都進入1類。一旦得到了類別,我們就可以計算相應的真、偽陽性率,當我們把所有計算得到的不同真、偽陽性率連起來,就畫出了ROC曲線。

python代碼如下:

from sklearn import metrics
def aucfun(act,pred):
    fpr,tpr,thresholds = metrics.roc_curve(act,pred,pos_label=1)
    return metrics.auc(fpr,tpr)

(2)適合數據量大,時間復雜度O(N*M)

  一個關於AUC的很有趣的性質是,它和Wilcoxon-Mann-Witney Test是等價的。而Wilcoxon-Mann-Witney Test就是測試任意給一個正類樣本和一個負類樣本,正類樣本的score有多大的概率大於負類樣本的score。有了這個定義,我們就得到了另外一中計 算AUC的辦法:得到這個概率。我們知道,在有限樣本中我們常用的得到概率的辦法就是通過頻率來估計。這種估計隨着樣本規模的擴大而逐漸逼近真實值。這和上面的方法中,樣本數越多,計算的AUC越准確類似,也和計算積分的時候,小區間划分的越細,計算的越准確是同樣的道理。具體來說就是統計一下所有的 M×N(M為正類樣本的數目,N為負類樣本的數目)個正負樣本對中,有多少個組中的正樣本的score大於負樣本的score。當二元組中正負樣本的 score相等的時候,按照0.5計算。然后除以MN。實現這個方法的復雜度為O(n^2)。n為樣本數(即n=M+N) 

(3)適合數據量大,時間復雜度O(M+N)

  第三種方法實際上和上述第二種方法是一樣的,但是復雜度減小了。它也是首先對score從大到小排序,然后令最大score對應的sample 的rank為n,第二大score對應sample的rank為n-1,以此類推。然后把所有的正類樣本的rank相加,再減去M-1種兩個正樣本組合的情況。得到的就是所有的樣本中有多少對正類樣本的score大於負類樣本的score。然后再除以M×N。

詳細解釋如下: 隨機抽取一個樣本,對應每一潛在可能值X都對應有一個判定位正樣本的概率P。

  對一批已知正負的樣本集合進行分類。

  按概率從高到矮排序,對於正樣本中概率最高的,排序為rank_1,比它概率小的有M-1個正樣本(M為正樣本個數),(rank_1-M)個負樣本。

  正樣本概率第二高的,排序為rank_2,比它概率小的有M-2個正樣本,(rank_2-M+1)個負樣本。

  以此類推,正樣本中概率最小的,排序為rank_M,比它概率小的有0個正樣本,rank_M-1個負樣本。

  總共有M*N個正負樣本對(N為負樣本個數)。把所有比較中,正樣本概率大於負樣本概率的例子都算上,得到公式(rank_1-M+rank_2-M+1...+rank_M-1)/(M*N)就是正樣本概率大於負樣本概率的可能性了。化簡后得:【離散情況下】

 

 

4. ROC曲線相比P-R曲線有什么特點?

  當正負樣本的分布發生變化時,ROC曲線的形狀能夠基本保持不變,而P-R曲線的形狀一般會發生較劇烈的變化。ROC能夠盡量降低不同測試集帶來的干擾,更加客觀的衡量模型本身的性能。如果研究者希望更多地看到模型在特定數據集上的表現,P-R曲線能夠更直觀地反映其性能。

 

5. ROC實現

(1)pandas實現roc

隨機生成樣本和結果

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

%matplotlib inline
import warnings
warnings.filterwarnings("ignore")

#測試樣本數量
parameter = 30

#隨機生成結果集
data = pd.DataFrame(index=range(0,parameter),columns=('probability','label'))
data['label'] = np.random.randint(0,2,size=len(data))
data['probability'] = np.random.choice(np.arange(0.1,1.0,0.1),len(data['probability']))
data.columns  

計算混淆矩陣

#計算混淆矩陣
cm = np.arange(4).reshape(2,2)
cm[0,0] = len(data.query('label==0 and probability<0.5')) #TN
cm[0,1] = len(data.query('label==0 and probability>=0.5')) #FP
cm[1,0] = len(data.query('label==1 and probability<0.5')) #FN
cm[1,1] = len(data.query('label==1 and probability>=0.5')) #TP
cm

 畫出混淆矩陣

import itertools
classes = [0,1]
plt.figure()
plt.imshow(cm,interpolation='nearest',cmap=plt.cm.Blues)
plt.title('Confusion matrix')
tick_marks=np.arange(len(classes))
plt.xticks(tick_marks,classes,rotation=0)
plt.yticks(tick_marks,classes)
thresh = cm.max()/2
for i,j in itertools.product(range(cm.shape[0]),range(cm.shape[1])):
    plt.text(j,i,cm[i,j],horizontalalignment='center',color = 'white' if cm[i,j]>thresh else 'black')
plt.tight_layout()
plt.ylabel('True label')
plt.xlabel('Predicted label')

 

  ROC曲線是一系列threshold下的(FPR,TPR)數值點的連線。此時的threshold的取值分別為測試數據集中各樣本的預測概率。但,取各個概率的順序是從大到小的。

#按預測概率從大到小的順序排序
data.sort_values('probability',inplace=True,ascending=False)
data.head()

閾值分別取0.9,0.9,0.8,0.8,...比如,當threshold=0.9(第三個0.9),兩個“0”預測錯誤,一個“1”預測正確,

FPR=1/13,TPR=1/17

#計算全部概率值下的FPR,TPR
TFRandFPR = pd.DataFrame(index=range(len(data)),columns=('TP','FP'))

for j in range(len(data)):
    data1 = data.head(n=j+1)
    FP=len(data1[data1['label']==0] [data1['probability']>=data1.head(len(data1))['probability']])/float(len(data[data['label']==0]))
    TP=len(data1[data1['label']==1] [data1['probability']>=data1.head(len(data1))['probability']])/float(len(data[data['label']==1]))
    TFRandFPR.iloc[j] = [TP,FP]

from sklearn.metrics import auc
AUC = auc(TFRandFPR['FP'],TFRandFPR['TP'])

plt.scatter(x=TFRandFPR['FP'],y=TFRandFPR['TP'],label='(FPR,TPR)',color='k')
plt.plot(TFRandFPR['FP'],TFRandFPR['TP'],'k',label='AUC=%0.2f'%AUC)
plt.legend(loc='lower right')

plt.title('Receiver Operating Characteristic')
plt.plot([(0,0),(1,1)],'r--')
plt.xlim([-0.01,1.01])
plt.ylim([-0.01,01.01])
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
plt.show()

 

   在此例子中AUC=0.58,AUC越大,說明分類效果越好。

 

(2)直接計算直方圖面積

def roc_auc(labels,preds,n_bins=1500):
    pos_len = sum(labels)
    neg_len = len(labels) - pos_len
    total_case = pos_len * neg_len
    pos_hist = [0 for i in range(n_bins)]
    neg_hist = [0 for i in range(n_bins)]
    bin_width = 1.0 / float(n_bins)
    for i in range(len(labels)):
        nth_bin = int(preds[i]/bin_width)
        if labels[i]==1:
            pos_hist[nth_bin] += 1
        else:
            neg_hist[nth_bin] += 1
    accumulated_neg = 0
    satisfied_pair = 0
    for i in range(n_bins):
        satisfied_pair += (pos_hist[i]*accumulated_neg + pos_hist[i]*neg_hist[i]*0.5)
        accumulated_neg += neg_hist[i]
    return round(satisfied_pair/float(total_case),2)
N = int(input())
# labels,probs = [],[]
labels , preds = [1,0,1,1,0,1,0,0,1,0] , [0.90,0.70,0.60,0.55,0.52,0.40,0.38,0.35,0.31,0.10]
# for i in range(N):
#     label,pred = map(float,input().split())
#     labels.append(label)
#     preds.append(pred)

res = roc_auc(labels, preds)
print(res)

6. 總結

  • ROC曲線反映了分類器的分類能力,結合考慮了分類器輸出概率的准確性
  • AUC量化了ROC曲線的分類能力,越大分類效果越好,輸出概率越合理
  • AUC常用作CTR的離線評價,AUC越大,CTR的排序能力越強

7. 大牛的見解

  [1]From 機器學習和統計里面的auc怎么理解?

  [2]From 機器學習和統計里面的auc怎么理解?

  [3]From 精確率、召回率、F1 值、ROC、AUC 各自的優缺點是什么?

  [4]From 多高的AUC才算高?

 參考文獻:

【1】如何理解機器學習和統計中的AUC?

 【2】AUC的概率解釋

 【3】ROC曲線和AUC面積理解

 【4】ROC曲線-閾值評價標准

 【5】模型評價(一) AUC大法

 【6】ROC曲線與AUC值


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM