標籤:

機器學習篇-指標:AUC

AUC是什麼東西?

AUC是一個模型評價指標,只能夠用於二分類模型的評價,對於二分類模型來說還有很多其他的評價指標:

比如:logloss,accuracy,precision

在上述的評價指標當中,數據挖掘類比賽中,AUC和logloss是比較常見的模型評價指標

那麼問題來了||ヽ(* ̄▽ ̄*)ノミ|Ю為啥是AUC和logloss?

因為很多機器學習的模型對分類問題的預測結果都是概率,如果要計算accuracy的話,需要先將概率轉換成類別,這就需要手動設置一個閾值,如果對一個樣本的預測概率高於這個預測,就把這個樣本放進一個類別當中,如果低於這個閾值,就放在另一個類別當中,閾值在很大程度上影響了accuracy的計算

使用AUC或者logloss的好處就是可以避免將預測概率轉換成類別

AUC: Area under curve

字面理解:某條曲線下面區域的面積

問題來了,到底是哪一條曲線?

曲線的名字叫做:ROC曲線

ROC曲線講解

(該內容來自於維基百科)

ROC分析的是二元分類模型,也就是輸出結果只有兩種類別的模型(垃圾郵件/非垃圾郵件)

當觀測量的結果是一個連續值的時候,類與類的邊界必須用一個閾值threshold來界定

舉例來說,用血壓值來檢測一個人是否有高血壓,測出的血壓值是連續的實數(從0~200都有可能),以收縮壓140/舒張壓90為閾值,閾值以上便診斷為有高血壓,閾值未滿者診斷為無高血壓。二元分類模型的個案預測有四種結局:P:positive N:negative

  1. 真陽性(TP):診斷為有實際上也有高血壓。
  2. 偽陽性(FP):診斷為有實際卻沒有高血壓。
  3. 真陰性(TN):診斷為沒有實際上也沒有高血壓。
  4. 偽陰性(FN):診斷為沒有實際卻有高血壓。

這四種結局可以畫成2 × 2的混淆矩陣:

ROC空間將偽陽性率FPR定義為X軸,將真陽性率TPR定義為Y軸

TPR:在所有實際為陽性的樣本中,被正確地判斷為陽性之比率。

FPR:在所有實際為陰性的樣本中,被錯誤地判斷為陽性之比率。

給定一個二元分類模型和它的閾值,就能從所有樣本的(陽性/陰性)真實值和預測值計算出一個 (X=FPR, Y=TPR) 座標點。

從 (0, 0) 到 (1,1) 的對角線將ROC空間劃分為左上/右下兩個區域,在這條線的以上的點代表了一個好的分類結果(勝過隨機分類),而在這條線以下的點代表了差的分類結果(劣於隨機分類)。

完美的預測是一個在左上角的點,在ROC空間座標 (0,1)點,X=0 代表著沒有偽陽性,Y=1 代表著沒有偽陰性(所有的陽性都是真陽性);也就是說,不管分類器輸出結果是陽性或陰性,都是100%正確。一個隨機的預測會得到位於從 (0, 0) 到 (1, 1) 對角線(也叫無識別率線)上的一個點;最直觀的隨機預測的例子就是拋硬幣。

讓我們來看在實際有100個陽性和100個陰性的案例時,四種預測方法(可能是四種分類器,或是同一分類器的四種閾值設定)的結果差異:

將這4種結果畫在ROC空間里:

離左上角越近的點預測(診斷)準確率越高。離右下角越近的點,預測越不準。

ABC三者當中,最好的結果是A方法。

B方法的結果位於隨機猜測線(對角線)上,在例子中我們可以看到B的準確度是50%。

C雖然預測準確度最差,甚至劣於隨機分類,也就是低於0.5(低於對角線)。然而,當將C以 (0.5, 0.5) 為中點作一個鏡像後,C的結果甚至要比A還要好。這個作鏡像的方法,簡單說,不管C(或任何ROC點低於對角線的情況)預測了什麼,就做相反的結論。

上述ROC空間里的單點,是給定分類模型且給定閾值後得出的。但同一個二元分類模型的閾值可能設定為高或低,每種閾值的設定會得出不同的FPR和TPR

同一模型每個閾值 的 (FPR, TPR) 座標都畫在ROC空間里,就成為特定模型的ROC曲線

在同一個分類器之內,閾值的不同設定對ROC曲線的影響,仍有一些規律可循:

  • 當閾值設定為最高時,亦即所有樣本都被預測為陰性,沒有樣本被預測為陽性,此時在偽陽性率 FPR = FP / ( FP + TN ) 算式中的 FP = 0,所以 FPR = 0%。同時在真陽性率(TPR)算式中, TPR = TP / ( TP + FN ) 算式中的 TP = 0,所以 TPR = 0%

當閾值設定為最高時,必得出ROC座標系左下角的點 (0, 0)。

  • 當閾值設定為最低時,亦即所有樣本都被預測為陽性,沒有樣本被預測為陰性,此時在偽陽性率FPR = FP / ( FP + TN ) 算式中的 TN = 0,所以 FPR = 100%。同時在真陽性率 TPR = TP / ( TP + FN ) 算式中的 FN = 0,所以 TPR=100%

當閾值設定為最低時,必得出ROC座標系右上角的點 (1, 1)。

因為TP、FP、TN、FN都是累積次數,TN和FN隨著閾值調低而減少(或持平),TP和FP隨著閾值調低而增加(或持平),所以FPR和TPR皆必隨著閾值調低而增加(或持平)。

隨著閾值調低,ROC點 往右上(或右/或上)移動,或不動;但絕不會往左下(或左/或下)移動

接下來就是我們本節的內容了:(~ ̄▽ ̄)~

曲線下面積(AUC)

在比較不同的分類模型時,可以將每個模型的ROC曲線都畫出來,比較曲線下面積做為模型優劣的指標。

意義

ROC曲線下方的面積(英語:Area under the Curve of ROC (AUC ROC)),其意義是:

因為是在1x1的方格里求面積,AUC必在0~1之間。

假設閾值以上是陽性,以下是陰性;

若隨機抽取一個陽性樣本和一個陰性樣本,分類器正確判斷陽性樣本的值高於陰性樣本之機率=AUC

簡單說:AUC值越大的分類器,正確率越高。

從AUC判斷分類器(預測模型)優劣的標準:

AUC = 1,是完美分類器,採用這個預測模型時,存在至少一個閾值能得出完美預測。絕大多數預測的場合,不存在完美分類器。

0.5 < AUC < 1,優於隨機猜測。這個分類器(模型)妥善設定閾值的話,能有預測價值。

AUC = 0.5,跟隨機猜測一樣(例:丟銅板),模型沒有預測價值。

AUC < 0.5,比隨機猜測還差;但只要總是反預測而行,就優於隨機猜測。

計算

AUC的計算有兩種方式,都是以逼近法求近似值。

AUC為什麼可以衡量分類的效果?

  • AUC就是從所有1樣本中隨機選取一個樣本,從所有0樣本中隨機選取一個樣本,然後根據你的分類器對兩個隨機樣本進行預測,把1樣本預測為1的概率為p1,把0樣本預測為1的概率為p2,p1>p2的概率就是AUC。所以AUC應該反映的是分類器對樣本的排序能力,另外,AUC對樣本類別是否均衡並不敏感,這也是不均衡樣本通常採用AUC評價分類性能的原因

根據上面的推斷,那麼隨機抽取一個樣本,對應每一潛在可能值X都有對應一個判定正樣本的概率P。

對一批已知正負的樣本集合進行分類,按照預測概率從高到低進行排序,

對於正樣本中概率最高的,排序為rank_1,

比它概率小的有M-1個正樣本(M為正樣本個數),(ranl_1-M)個負樣本。

正樣本中概率第二高的,排序為rank_2,

比它概率小的有M-2個正樣本,(rank_2-(M-1))個負樣本,

以此類推,正樣本中概率最小的,排序為rank_M,

比它概率小的有0個正樣本,(rank_M-1)個負樣本。

總共有M*N個正負樣本對,把所有比較中正樣本概率大於負樣本概率的例子都算上,

得到公式: (rank_1-M + rank_2 - (M-1) + ... + rank_M - 1)/(M*N)

就是正樣本概率大於負樣本概率的可能性,將上述結果化簡之後:

AUC = frac{sum_{ins_{i}in positive}^{}{rank_{ins_{i}}}-M*(M+1)/2}{M*N}

上述結果就是,AUC公式

AUC是現在分類模型中,特別是二分類模型使用的主要離線評測指標之一,相比於準確率,召回率,AUC有一個獨特的優勢,就是不管具體的得分,只關注於排序結果,這使得它特別適用於排序問題的效果評估

根據上面的公式求解AUC

首先對score從大到小排序,然後令最大score對應的sample的rank值為n,第二大score對應sample的rank值為n-1,以此類推從n到1。然後把所有的正類樣本的rank相加,再減去正類樣本的score為最小的那M個值的情況。得到的結果就是有多少對正類樣本的score值大於負類樣本的score值,最後再除以M×N即可。值得注意的是,當存在score相等的時候,對於score相等的樣本,需要賦予相同的rank值(無論這個相等的score是出現在同類樣本還是不同類的樣本之間,都需要這樣處理)。具體操作就是再把所有這些score相等的樣本 的rank取平均。然後再使用上述公式。此公式描述如下:

def naive_auc(labels,preds): """ 最簡單粗暴的方法   先排序,然後統計有多少正負樣本對滿足:正樣本預測值>負樣本預測值, 再除以總的正負樣本對個數。複雜度 O(NlogN), N為樣本數 """ n_pos = sum(labels) n_neg = len(labels) - n_pos total_pair = n_pos * n_neg labels_preds = zip(labels,preds) labels_preds = sorted(labels_preds,key=lambda x:x[1])//從小到大倒序計算 accumulated_neg = 0 satisfied_pair = 0 for i in range(len(labels_preds)): if labels_preds[i][0] == 1: satisfied_pair += accumulated_neg else: accumulated_neg += 1 return satisfied_pair / float(total_pair)

接下來還可以採用進一步加速的方法:

使用近似方式,將預測值分桶,對正負樣本分別構建直方圖,再統計滿足條件的正負樣本對

關於AUC還有一個很有趣的性質,它和Wilcoxon-Mann-Witney Test類似(可以去google搜一下),而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),公式表示如下:

def approximate_auc(labels,preds,n_bins=100): """ 近似方法,將預測值分桶(n_bins),對正負樣本分別構建直方圖,再統計滿足條件的正負樣本對 複雜度 O(N) 這種方法有什麼缺點?怎麼分桶? """ n_pos = sum(labels) n_neg = len(labels) - n_pos total_pair = n_pos * n_neg 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統計當前bins之前有多少負樣本桶,將其*pos_histogram[i] 等價於當前正樣本桶有大於負樣本桶 pos_histogram[i]*neg_histogram[i]*0.5,有可能正樣本桶和負樣本桶落在同一個區間,當前區間無法計算,近似 accumulated_neg += neg_histogram[i] return satisfied_pair / float(total_pair)

但是上述方法的問題在於:

預測值大多不是均勻分布在0-1之間的,分布特別不平衡的話,均勻分出來的桶就不太好,

採用頻率進行劃分桶,(均勻劃分,等頻劃分)

進一步的嘗試MapReduce如何計算AUC

MAP階段:統計直方圖

Reduce階段:計算AUC的結果

上述完整代碼:

# coding=utf-8# auc值的大小可以理解為: 隨機抽一個正樣本和一個負樣本,正樣本預測值比負樣本大的概率# 根據這個定義,我們可以自己實現計算aucimport randomimport timedef timeit(func): """ 裝飾器,計算函數執行時間 """ def wrapper(*args, **kwargs): time_start = time.time() result = func(*args, **kwargs) time_end = time.time() exec_time = time_end - time_start print "{function} exec time: {time}s".format(function=func.__name__,time=exec_time) return result return wrapperdef gen_label_pred(n_sample): """ 隨機生成n個樣本的標籤和預測值 """ labels = [random.randint(0,1) for _ in range(n_sample)] preds = [random.random() for _ in range(n_sample)] return labels,preds@timeitdef naive_auc(labels,preds): """ 最簡單粗暴的方法   先排序,然後統計有多少正負樣本對滿足:正樣本預測值>負樣本預測值, 再除以總的正負樣本對個數 複雜度 O(NlogN), N為樣本數 """ n_pos = sum(labels) n_neg = len(labels) - n_pos total_pair = n_pos * n_neg labels_preds = zip(labels,preds) labels_preds = sorted(labels_preds,key=lambda x:x[1]) accumulated_neg = 0 satisfied_pair = 0 for i in range(len(labels_preds)): if labels_preds[i][0] == 1: satisfied_pair += accumulated_neg else: accumulated_neg += 1 return satisfied_pair / float(total_pair)@timeitdef approximate_auc(labels,preds,n_bins=100): """ 近似方法,將預測值分桶(n_bins),對正負樣本分別構建直方圖,再統計滿足條件的正負樣本對 複雜度 O(N) 這種方法有什麼缺點?怎麼分桶? """ n_pos = sum(labels) n_neg = len(labels) - n_pos total_pair = n_pos * n_neg 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_pair)# 思考:mapreduce版本的auc該怎麼寫if __name__ == "__main__": labels,preds = gen_label_pred(10000000) naive_auc_rst = naive_auc(labels,preds) approximate_auc_rst = approximate_auc(labels,preds) print "naive auc result:{},approximate auc result:{}".format(naive_auc_rst,approximate_auc_rst) """ naive_auc exec time: 31.7306630611s approximate_auc exec time: 2.32403683662s naive auc result:0.500267265728,approximate auc result:0.50026516844 """

參考:

分類之性能評估指標www.csuldw.com圖標https://en.wikipedia.org/wiki/Mann%E2%80%93Whitney_U_testen.wikipedia.org

https://gist.github.com/wepe/02e3842cc5224016b50d7e403c117bbagist.github.com

AUC理解與實現 - CSDN博客blog.csdn.net圖標天池錄播tianchi.aliyun.com

機器學習和統計裡面的auc怎麼理解?www.zhihu.com圖標
推薦閱讀:

如何六個月內學會深度學習
機器學習基礎與實踐(二)----數據轉換
機器學習篇-評估機器學習的模型
關鍵詞提取Part1(A Quick Review)

TAG:機器學習 |