背景
之前在研究Object Detection的時候,只是知道Precision這個指標,但是mAP(mean Average Precision)具體是如何計算的,暫時還不知道。最近做OD的任務迫在眉睫,所以仔細的研究了一下mAP的計算。其實說實話,mAP的計算,本身有很多現成的代碼可供調用了,公式也寫的很清楚,但是我認為仔細的研究清楚其中的原理更重要。
AP這個概念,其實主要是在信息檢索領域(information retrieval)中的概念,所以這里會比較快速的過一下這個在信息檢索領域是如何起作用的。
Precision,Recall,以及Accuracy
Precision和Recall
Precision其實就是在識別出來的圖片中,True positives所占的比率:
其中的n代表的是(True positives + False positives),也就是系統一共識別出來多少照片 。
Recall 是被正確識別出來的個數與測試集中所有的個數的比值:
Recall的分母是(True positives + False negatives),這兩個值的和,可以理解為一共有多少張飛機的照片。
如下圖所示,假如一個用戶向系統提交一個查詢(例如“什么是貓”),系統返回了一系列查詢的結果,這些結果是系統根據用戶提交的信息,判定出來系統內所有跟這個信息有關的結果。
在這個結果里,黃色的部分是系統返回的結果,綠色的部分是總共對用戶有用的結果。兩者的交集,也就是中間的地方,通常叫做True Positive(TP),中文譯名是真陽。而返回結果的剩下的部分,則是False Positive。也就是假陽,意思就是說這些本身是對用戶沒啥用的,但是系統判定這些對用戶有用並且提交給用戶了,所以叫“假陽”。而綠色部分剩下的,False Negative,假陰,則是本來對用戶有用的結果,但是被系統判定沒用,“假陰”。剩下的灰色地方則是True Negative,“真陰”,就是真的沒啥用的結果。
Precision是提交給用戶的結果里邊,究竟有多少是對的,或者反過來說,我們給了用戶多少沒用的垃圾。Recall是一共有這么多的有用結果,系統究竟能判定出來多少是有用的(能夠檢出多少?),或者反過來說,我們究竟丟了多少有用的。這兩個數是成對出現,單獨出現沒有意義。為什么這么說?一個例子是我可以輕輕松松將recall提高到100%,那就是不管用戶查詢啥,我都把系統內所有的文檔都給他,這樣肯定沒丟東西,但是用戶也沒法得到的好的結果。
為什么不用准確率(accuracy)?
准確率,也就是accuracy,
是系統究竟做對了多少。如果是對於平衡樣本來說,這個沒問題。但是對於樣本不平衡的情況,這就不行。例如信息檢索,有99.999%的信息都對用戶沒用,而且大部分系統肯定都能判別出來這些沒用,所以對於絕大部分系統,准確率都是99.999%,這個就不能很好的衡量系統性能了。再比如一個90個正樣本,10個負樣本數據,如果全部分類為正則准確率為90%,這樣評價不能客觀反映分類器對不平衡數據的性能。
F Score
但是我們還是希望有一個數能夠衡量系統的性能,否則系統A的precision比系統B高,但是recall卻比系統B低,那么我們就不太好選了。所以綜合Precision和Recall,我們得到一個F Score:
這個F Score是P和R的調和平均數(harmonic mean),β的作用是表明P與R誰比較重要。harmonic mean有個特點,就是假如其中一個P或者R比較小,那么整體就會很小,也就是對兩個數中如果有特別小的數的懲罰(penalty)比較大。這是代數平均數所沒有的特性。一般來說,會把β設置成1,這個時候就成為F1 Score。幾何表達如下圖所示。
Precision and Recall Over Ranks
用戶提交一個檢索Query,得到的結果其實是一個列表,也就是一個有序表,這個表里飽含着所有檢索的結果。這個表的序,其實也反映了系統的性能。如果系統把有用的信息排到特別后邊,把沒用的信息放到前邊,也是一個比較性能差的系統。對於一個ranking,我們如何評估它的性能呢?
如上圖所示,假設對於已經排好序的檢測結果:
我們首先在每一個元素上都計算一下precision和recall。計算的方法是:對於第N個元素的precision和recall,計算前N個元素的recall和precision。
舉例說明:對於Ranking #1,第一個元素,前1個元素也就是這個元素了,它的recall是1/6=0.17,因為檢出了1個,一共有6個需要檢出的元素,而precision則是1/1=1,因為一共有1個元素,檢出了1個元素,所以是1。
對於Ranking #1 第二個元素的precision和recall,則recall是1/6=0.17。第二個是錯的,所以precision是1/2=0.5,因為一共有2個元素。那么對比Ranking #1和#2,我們可以看到因為排序不同,所以precision不一樣。這是因為這種計算方法會給靠前的元素比較大的bias。這樣precision就可以衡量序在結果中的作用了。
如此我們便可以畫出Recall-Precision的關系,以及F1的結果。一般來說,F1 Score會在Recall-Precision相交的地方達到最大值,但是這也不一定。畢竟這個極值其實還是需要滿足一定的條件的。但是整體趨勢就如同右上的那個小圖那樣子。
P-R曲線
Interpolated Recall-Precision Plot
我們把上一節計算出來的Recall和Precision畫出來,得到如下圖所示的結果:
這個曲線就比較蛋疼了。它壓根不是一個函數。我們想知道Query 1 Recall = 0.5的情況下,Precision是多少,這事兒完全沒法用普通的插值來弄。但是我們知道的是,Precision-Recall的曲線,趨勢是下降的,所以前人就提出一種差值方法:任給一個Recall值,它對應的Precision值就等於它最近的右側的那個“有值”Precision值中最大的那個值。舉個例子,例如那個黑色的線,當recall=0.3的時候,它對應的precision值就是0.3右側最近的有值的,也就是recall=0.4的那個值,但是recall=0.4對應很多值,包括了0.75、0.5和0.4,則選那個最大的0.75,如下圖所示:
紅色的線和藍色的線就分別是Query 1和2的Interpolated Recall-precision plot。然后對於整體系統,就可以平均一下Q1和Q2的結果,得到一個平均性能。
有了這個插值完的曲線,我們就可以對不同系統進行一個性能分析,如上圖所示。圖中的結論都很簡單明了。
Mean Average Precision
到這里,mAP的定義其實就自然而然的明確了。Average Precision,就是對一個Query,計算其命中時的平均Precision,而mean則是在所有Query上去平均,例子如下圖所示,一看就明了了。
目標檢測中的mAP
回到我們目標檢測中的mAP,這個概念是PASCAL VOC比賽中所明確的metric。它的意思是輸出的結果是一個ranked list,里邊每一個元素包含了類別、框的信息,以及confidence,這個confidence就用來排序。有了排序,就可以計算AP了,然后再針對所有分類,取一個mean,就得到了mAP。這里為何要排序呢?是因為每一個框有一個confidence,mAP作為評估指標,需要考慮confidence進來。比方說我給出一個框,說我有99%的信心這里有一個貓,結果這里沒有,相比我給出一個框,說我有10%的信心這里有一個貓,結果也沒有,這兩個框的penalty和reward不能一樣的。因為99%信心說有,結果沒有,那就說明這個系統很有問題。反之,假如我給出一個框,99%的信心說有一個貓,然后真有貓,相比10%信心說有貓,結果也是有貓,這兩個框也不一樣。也就是越“靠譜”,reward越大。什么叫靠譜?靠譜的意思是信心足的時候,一般結果正確。所以我們根據confidence進行排序之后,就應該給排名靠前的結果,也就是confidence比較大的一些更大的權重。所以才會有ranked list。或者可以理解為,我有一個query,查詢的內容是,系統中的圖片里貓都在那兒?那么這個就肯定需要ranked list了。
值得一提的是在2010年之前,VOC比賽用的AP計算方法並不是上邊所述的計算方法,而是對interpolated 的那個圖均勻取11個點,[0.0 0.1 0.2 … 1.0]然后求平均。后來才成上邊所述的AP計算方法。
貼一段python的ap計算代碼放在下邊供參考:

def voc_ap(self, rec, prec, use_07_metric=True): if use_07_metric: ap = 0. # 2010年以前按recall等間隔取11個不同點處的精度值做平均(0., 0.1, 0.2, …, 0.9, 1.0) for t in np.arange(0., 1.1, 0.1): if np.sum(rec >= t) == 0: p = 0 else: # 取最大值等價於2010以后先計算包絡線的操作,保證precise非減 p = np.max(prec[rec >= t]) ap = ap + p / 11. else: # 2010年以后取所有不同的recall對應的點處的精度值做平均 # first append sentinel values at the end mrec = np.concatenate(([0.], rec, [1.])) mpre = np.concatenate(([0.], prec, [0.])) # 計算包絡線,從后往前取最大保證precise非減 for i in range(mpre.size - 1, 0, -1): mpre[i - 1] = np.maximum(mpre[i - 1], mpre[i]) # 找出所有檢測結果中recall不同的點 i = np.where(mrec[1:] != mrec[:-1])[0] # and sum (\Delta recall) * prec # 用recall的間隔對精度作加權平均 ap = np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1]) return ap
ROC曲線
(受試者操作特征(Receiver Operating Characteristic),roc曲線上每個點反映着對同一信號刺激的感受性)
對於0,1兩類分類問題,一些分類器得到的結果往往不是0,1這樣的標簽,如神經網絡,得到諸如0.5,0,8這樣的分類結果。這時,我們人為取一個閾值,比如0.4,那么小於0.4的為0類,大於等於0.4的為1類,可以得到一個分類結果。同樣,這個閾值我們可以取0.1,0.2等等。取不同的閾值,得到的最后的分類情況也就不同。
如下面這幅圖:
藍色表示原始為負類分類得到的統計圖,紅色為正類得到的統計圖。那么我們取一條直線,直線左邊分為負類,右邊分為正,這條直線也就是我們所取的閾值。
閾值不同,可以得到不同的結果,但是由分類器決定的統計圖始終是不變的。這時候就需要一個獨立於閾值,只與分類器有關的評價指標,來衡量特定分類器的好壞。
還有在類不平衡的情況下,如正樣本90個,負樣本10個,直接把所有樣本分類為正樣本,得到識別率為90%。但這顯然是沒有意義的。
如上就是ROC曲線的動機。
ROC空間將假正例率(False Positive Rate, 簡稱FPR)定義為 X軸,真正例率(True Positive Rate, 簡稱TPR)定義為 Y 軸。這兩個值由上面四個值計算得到,公式如下:
TPR:在所有實際為正例的樣本中,被正確地判斷為正例之比率。
FPR:在所有實際為反例的樣本中,被錯誤地判斷為正例之比率。
我們以FPR為橫軸,TPR為縱軸,得到如下ROC空間。
我們可以看出,左上角的點(TPR=1,FPR=0)(TPR=1,FPR=0),為完美分類。曲線距離左上角越近,證明分類器效果越好。點A(TPR>FPR)表明判斷大體是正確的。中線上的點B(TPR=FPR)表明判定一半對一半錯(這種最垃圾~~);下半平面的點C(TPR<FPR)說明判定大體錯誤。
如上,是三條ROC曲線,在0.23處取一條直線。那么,在同樣的低FPR=0.23的情況下,紅色分類器得到更高的PTR。也就表明,ROC越往上,分類器效果越好。我們用一個標量值AUC來量化它。
AUC(Area Under ROC Curve)
auc其實就是ROC曲線圍成的面積!!
在兩個分類器的ROC曲線交叉的情況下,無法判斷哪個分類器性能更好,這時可以計算ROC曲線下面積AUC,作為性能度量,面積越大則越好。
為什么使用Roc和Auc評價分類器
既然已經這么多標准,為什么還要使用ROC和AUC呢?因為ROC曲線有個很好的特性:當測試集中的正負樣本的分布變換的時候,ROC曲線能夠保持不變。在實際的數據集中經常會出現樣本類不平衡,即正負樣本比例差距較大,而且測試數據中的正負樣本也可能隨着時間變化。
ROC曲線和Presision-Recall曲線的對比:
在上圖中,(a)和(c)為Roc曲線,(b)和(d)為P-R曲線。
(a)和(b)展示的是分類其在原始測試集(正負樣本分布平衡)的結果,(c)(d)是將測試集中負樣本的數量增加到原來的10倍后,分類器的結果,可以明顯的看出,ROC曲線基本保持原貌,而Precision-Recall曲線變化較大。
以上的Python代碼實現大家可以參考這位的博客:https://www.jianshu.com/p/28ef55b779ca
線性回歸的決定系數
(也稱為判定系數,擬合優度)
相關系數是R哈~~~就是決定系數的開方!
正如題所說決定系數是來衡量回歸的好壞,換句話說就是回歸擬合的曲線它的擬合優度!也就是得分啦~~
決定系數它是表征回歸方程在多大程度上解釋了因變量的變化,或者說方程對觀測值的擬合程度如何。
計算公式為:
決定系數越大表擬合優度越好!
Python中可直接調用score()方法來計算決定系數值。
score(self, x_test, y_test, sample_weight=None)
版權聲明:本文為轉載文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。