理解ROC(受試者工作特徵)曲線以及AUC

我們通常使用ROC和AUC來衡量分類演算法在二分類問題上表現的好壞,在具體介紹ROC和AUC之前,我首先要講解一下分類結果混淆矩陣。

1.分類結果混淆矩陣

在二分類問題上,可將樣例根據其真實類別和分類模型預測的類別分為如下四種(1表示類別為真,0表示類別為假):

真正例TP(true postive):樣本真實類別為1,學習模型預測的類別也為1

假正例FP(false postive):樣本真實類別為0,學習模型預測的類別為1

真反例TN(true negative):樣本真實類別為0,學習模型預測的類別也為0

假反例FN(false negative):樣本真實類別為1,學習模型預測的類別也為0

分類結果混淆矩陣

舉個例子,假如我們有100個正例,其中85個被預測為正例,15個被預測為反例;80個反例,其中70個被預測成為反例,10個被預測成為正例。那麼:

TP=85; FP=15;TN=70;FP=10

此時的分類結果矩陣如下:

分類結果混淆矩陣

2.ROC和AUC

我們現在有了混淆矩陣,我們就可以設計一個指標來判斷分類器的好壞,這裡我們使用

真正例率TPR和假正例率FPR來判斷,它們的定義如下:

TPR=TP/(TP+FN)

FPR=FP/(FP+TN)

TPR越高,FPR越低,則可以證明分類器分類效果越好。

但是兩者又是相互矛盾的,我們為了降低假正例率,讓樣本被分為正例的要求變得更高,這樣反例被誤判為正例的個數FP(假正例)就會減少,那麼FPR的值就會降低,但與此同時,有一部分不是很像正例的正例會被我們錯誤的歸為反例,FN(假反例)的個數就會升高,TPR的值也會降低。反之,TPR的值增大,FPR的值也會增大。

所以單單憑TPR和FPR的兩個值是沒有辦法比較兩個分類器的好壞。這裡就提出了ROC曲線。我們使用TPR作為縱軸,FPR作為橫軸作圖,就可以得到ROC曲線。

ROC曲線

繪圖過程如下:給定 m^{+} 個正例, m^{-} 個反例,根據學習器預測結果對樣例進行排序,然後把分類器閾值設為最大,此時所有的樣例均預測為反例,此時真正例率和假正例率均為0,在坐標(0,0)處標一個點。然後,將分類閾值依次設為每個樣例的預測值,即預測模型每次將每個樣例判斷為正例,設前一個標記坐標點為( x,y ),如果當樣例真實類別也為正例,則對應的標記點坐標為( x,y+1/m^{+} ),如果樣例真實類別為反例,則對應的標記點坐標為( x+1/m^{-},y )。然後用線段連接相鄰點即得ROC曲線。(看這麼一大段話我開始也是拒絕的)。

下面舉幾個例子幫助大家理解,使用邏輯回歸對數據進行分類,可以得到如下的表格

這個邏輯回歸分類器很好的預測了類別,這個樣本有4個正例,3個反例。我們可以按照如下方式繪製ROC曲線圖,首先設置第一個坐標點在原點(0,0),此時我們的真正例率和假正例率均為0,因此此時正例數為0。然後從大到小依次取概率值,取概率為0.9的時候,我們假設概率大於等於0.9的樣本點均為正例。如果此時這個樣例的真實類別也為正例,那麼此時我們的坐標點移動到(0,1/4),否則樣本點移動到(1/3,0)。

接下來我們取概率值為0.7的時候,此時我們假設概率大於等於0.7的樣本點均為正例,那麼此時我們還有必要考慮概率值為0.9的樣本點么,答案是不需要,因為當我們設置模型判斷一個樣本為正例的閾值概率0.9的時候,此時如果我們把一個反例錯判為正例,那麼在閾值概率為0.7的時候,依舊會把這個反例錯認為是正例,如果在閾值概率為0.9的時候,我們判斷一個正例為正例,那麼在閾值為0.7的時候我們依舊會做出同樣的判斷。因為此時樣本點真實類別也是正例,所以此時樣本點坐標為(0, 2/4)。也就是說我們用0.7作為閾值概率時,TPR為0.5而FPR為0。

重複上述步驟,就可以得到一條ROC曲線。通過ROC曲線我們就可以判斷兩個分類器的好壞,如下圖:

通過ROC比較分類器好壞

我們就可以說分類器1的分類效果好於分類器2。因為在相同的FPR的條件下,分類器1的TPR要高於分類器2的TPR。

3.AUC

但是如果出現了下面的情況:

通過ROC比較分類器好壞

我們此時沒有辦法直觀的說明兩個分類器那個更好一些,這種情況我們一般使用AUC的值來進行判斷。AUC(Area Under ROC Curve)也就是直ROC曲線下面的面積,通常我們認為AUC值大的分類器性能較好

使用python我們可以自己編寫代碼繪製ROC曲線:

def anotherPlotROC(predStrengths, classLabels): #0--->1
import matplotlib.pyplot as plt
cur = (0.0, 0.0)
ySum = 0.0
numPosClas = sum(np.array(classLabels) == 1.0)
yStep = 1/float(numPosClas); xStep = 1/float(len(classLabels) - numPosClas)
sortedIndicies = predStrengths.argsort()
fig = plt.figure()
fig.clf()
ax = plt.subplot(111)

for index in sortedIndicies.tolist()[0][::-1]:
if classLabels[index] == 1.0: #TP真正例
delX = 0; delY = yStep
else:
delX = xStep; delY = 0 #FP假正例
ySum += cur[1]

ax.plot([cur[0], cur[0] + delX], [cur[1], cur[1]+delY], c=b)
cur = (cur[0]+delX, cur[1]+delY)

ax.plot([0,1], [0,1], b--)
plt.xlabel("False positive rate"); plt.ylabel("True positive rate")
plt.title(ROC)
ax.axis([0,1,0,1])
print("the Area Under the Curve is", ySum*xStep)
plt.show()

我使用《機器學習實戰》中第五章的病馬預測數據使用第八章adaboost分類演算法進行分類得到的ROC曲線如下 :

後續會繼續更新機器學習相關知識,覺得不錯的小夥伴們可以關注一下

超愛學習:《尋夢環遊記》基於豆瓣熱門評論生成的詞雲圖?

zhuanlan.zhihu.com圖標如何用數學方法來定義一個人與人的社交距離??

www.zhihu.com圖標yinchuandong/MachineLearningInAction?

github.com圖標

還有我最近在慢慢寫的面向小白的數據結構專欄~

數據結構入門?

zhuanlan.zhihu.com圖標
推薦閱讀:

Andrej Karpathy提到的神經網路六大坑
總是從蠢模型開始
Data Fountain光伏發電量預測 Top1 開源分享
8 個超贊的深度學習課程(附評分)
關於深度學習的13個常見問答

TAG:機器學習 | 計算機 | Python |