以前在研究Object Detection的時候,只是知道Precision這個指標,可是mAP(mean Average Precision)具體是如何計算的,暫時還不知道。最近作OD的任務迫在眉睫,因此仔細的研究了一下mAP的計算。其實說實話,mAP的計算,自己有不少現成的代碼可供調用了,公式也寫的很清楚,可是我認爲仔細的研究清楚其中的原理更重要。html
AP這個概念,其實主要是在信息檢索領域(information retrieval)中的概念,因此這裏會比較快速的過一下這個在信息檢索領域是如何起做用的。python
Precision其實就是在識別出來的圖片中,True positives所佔的比率:
其中的n表明的是(True positives + False positives),也就是系統一共識別出來多少照片 。
網絡
Recall 是被正確識別出來的個數與測試集中全部的個數的比值:
Recall的分母是(True positives + False negatives),這兩個值的和,能夠理解爲一共有多少張飛機的照片。 app
以下圖所示,假如一個用戶向系統提交一個查詢(例如「什麼是貓」),系統返回了一系列查詢的結果,這些結果是系統根據用戶提交的信息,斷定出來系統內全部跟這個信息有關的結果。
ide
在這個結果裏,黃色的部分是系統返回的結果,綠色的部分是總共對用戶有用的結果。二者的交集,也就是中間的地方,一般叫作True Positive(TP),中文譯名是真陽。而返回結果的剩下的部分,則是False Positive。也就是假陽,意思就是說這些自己是對用戶沒啥用的,可是系統斷定這些對用戶有用而且提交給用戶了,因此叫「假陽」。而綠色部分剩下的,False Negative,假陰,則是原本對用戶有用的結果,可是被系統斷定沒用,「假陰」。剩下的灰色地方則是True Negative,「真陰」,就是真的沒啥用的結果。函數
Precision是提交給用戶的結果裏邊,究竟有多少是對的,或者反過來講,咱們給了用戶多少沒用的垃圾。Recall是一共有這麼多的有用結果,系統究竟能斷定出來多少是有用的(可以檢出多少?),或者反過來講,咱們究竟丟了多少有用的。這兩個數是成對出現,單獨出現沒有意義。爲何這麼說?一個例子是我能夠輕輕鬆鬆將recall提升到100%,那就是無論用戶查詢啥,我都把系統內全部的文檔都給他,這樣確定沒丟東西,可是用戶也無法獲得的好的結果。性能
準確率,也就是accuracy,測試
是系統究竟作對了多少。若是是對於平衡樣原本說,這個沒問題。可是對於樣本不平衡的狀況,這就不行。例如信息檢索,有99.999%的信息都對用戶沒用,並且大部分系統確定都能判別出來這些沒用,因此對於絕大部分系統,準確率都是99.999%,這個就不能很好的衡量系統性能了。再好比一個90個正樣本,10個負樣本數據,若是所有分類爲正則準確率爲90%,這樣評價不能客觀反映分類器對不平衡數據的性能。spa
可是咱們仍是但願有一個數可以衡量系統的性能,不然系統A的precision比系統B高,可是recall卻比系統B低,那麼咱們就不太好選了。因此綜合Precision和Recall,咱們獲得一個F Score:
.net
這個F Score是P和R的調和平均數(harmonic mean),β的做用是代表P與R誰比較重要。harmonic mean有個特色,就是假如其中一個P或者R比較小,那麼總體就會很小,也就是對兩個數中若是有特別小的數的懲罰(penalty)比較大。這是代數平均數所沒有的特性。通常來講,會把β設置成1,這個時候就成爲F1 Score。幾何表達以下圖所示。
用戶提交一個檢索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曲線
咱們把上一節計算出來的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.7五、0.5和0.4,則選那個最大的0.75,以下圖所示:
紅色的線和藍色的線就分別是Query 1和2的Interpolated Recall-precision plot。而後對於總體系統,就能夠平均一下Q1和Q2的結果,獲得一個平均性能。
有了這個插值完的曲線,咱們就能夠對不一樣系統進行一個性能分析,如上圖所示。圖中的結論都很簡單明瞭。
到這裏,mAP的定義其實就天然而然的明確了。Average Precision,就是對一個Query,計算其命中時的平均Precision,而mean則是在全部Query上去平均,例子以下圖所示,一看就明瞭了。
回到咱們目標檢測中的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
(受試者操做特徵(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其實就是ROC曲線圍成的面積!!
在兩個分類器的ROC曲線交叉的狀況下,沒法判斷哪一個分類器性能更好,這時能夠計算ROC曲線下面積AUC,做爲性能度量,面積越大則越好。
爲何使用Roc和Auc評價分類器
既然已經這麼多標準,爲何還要使用ROC和AUC呢?由於ROC曲線有個很好的特性:當測試集中的正負樣本的分佈變換的時候,ROC曲線可以保持不變。在實際的數據集中常常會出現樣本類不平衡,即正負樣本比例差距較大,並且測試數據中的正負樣本也可能隨着時間變化。
在上圖中,(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 版權協議,轉載請附上原文出處連接和本聲明。