Top mAP and mAP
預備知識——Precision§ & Recall®
Relevant | Non Relevant | |
---|---|---|
Retrieved | True Positives (tp) | False Positives (fp) |
Not Retrieved | False Negatives (fn) | True Negatives (tn) |
則:
如下圖所示,P和R的定義會更清楚一些:
-
F1 Measurement:
因爲 和 是此消彼長的關係,在某些情況下,兩者是矛盾的,因此爲了綜合考量兩種因素,提出了F1 Measurement,其是Precision和Recall的加權調和平均:
綜合考量了 和 的結果,當的結果比較高時,說明實驗方法是比較理想的 -
Average Precision:
AP是爲解決的單點值侷限性的。爲了得到一個能夠反映全局性能的指標,其計算公式如下:
也即:在準確率-召回率曲線中,曲線與座標軸之間所形成的面積越大,代表性能越好,同時,在工業界,曲線應當儘可能向上突出 -
mean Average Precision(mAP):
對應於AP,mAP可以看作是AP在數據集上的平均值:
Example
Data
首先利用自己已經訓練好的模型,得到所有測試樣本的Confidence Score,假設共有20個測試樣本,每個ID對應的Confidence Score 和Ground Truth Label如下表所示。
ID | Score | Label |
---|---|---|
1 | 0.23 | 0 |
2 | 0.76 | 1 |
3 | 0.01 | 0 |
4 | 0.91 | 1 |
5 | 0.13 | 0 |
6 | 0.45 | 0 |
7 | 0.12 | 1 |
8 | 0.03 | 0 |
9 | 0.38 | 1 |
10 | 0.11 | 0 |
11 | 0.03 | 0 |
12 | 0.09 | 0 |
13 | 0.65 | 0 |
14 | 0.07 | 0 |
15 | 0.12 | 0 |
16 | 0.24 | 1 |
17 | 0.1 | 0 |
18 | 0.23 | 0 |
19 | 0.46 | 0 |
20 | 0.08 | 1 |
對所有的Confidence Score進行排序,得到:
ID | Score | Label |
---|---|---|
4 | 0.91 | 1 |
2 | 0.76 | 1 |
13 | 0.65 | 0 |
19 | 0.46 | 0 |
6 | 0.45 | 0 |
9 | 0.38 | 1 |
16 | 0.24 | 1 |
1 | 0.23 | 0 |
18 | 0.23 | 0 |
5 | 0.13 | 0 |
7 | 0.12 | 1 |
15 | 0.12 | 0 |
10 | 0.11 | 0 |
17 | 0.1 | 0 |
12 | 0.09 | 0 |
20 | 0.08 | 1 |
14 | 0.07 | 0 |
8 | 0.03 | 0 |
11 | 0.03 | 0 |
3 | 0.01 | 0 |
Top-K mAP
如上表所示,我們根據Confidence的值對數據進行了排序,如果我們想得到Top-K的mAP的值的話,就按照降序原則,提取前K個數據作爲樣本,而不考慮後續的樣本所得到的結果,如我們想得到Top-5的結果,所以其子數據集就是:
ID | Score | Label |
---|---|---|
4 | 0.91 | 1 |
2 | 0.76 | 1 |
13 | 0.65 | 0 |
19 | 0.46 | 0 |
6 | 0.45 | 0 |
在這個例子中,True Positives就是指第4和第2個樣本,False Positives就是指第13,19,6個樣本
:對於某一二分類問題,我們選定了5個樣本,其中正確的有2個,即準確率爲40%;
:意思是在Top-K和測試樣本中,共有6個樣本,但是因爲我們只召回了2個,所以召回率爲30%
而在實際多類別分類任務中,我們通常不滿足只通過top-K來衡量一個模型的好壞,而是需要知道從top-1到top-N(N是所有測試樣本個數)對應的precision和recall。而當K取N時,即爲mAP。
Demo
此處,我們是隨機生成的數據,同時利用歐幾里得距離來生成Confidence
import numpy as np
import sklearn
import matplotlib.pyplot as plt
from sklearn.metrics import average_precision_score
from sklearn.metrics import precision_recall_curve
def dist(a,b):
dists= np.sqrt(np.sum(np.square(a-b)))
return dists
def compute_distances(Q,E):
num=E.shape[0]
connum=E.shape[1]
dists=[]
for i in range(num):
sum=0
for j in range(connum):
sum=sum+dist(Q[j],E[i,j])
dists.append(sum)
dists=np.array(dists)
return dists
def topmAP(Q,TX,FX,topk):
### label ###
Tnum=TX.shape[0]
Fnum=FX.shape[0]
Ta=np.ones((Tnum))
Fa=np.zeros((Fnum))
y_true=np.hstack((Ta,Fa))
### score ###
dTX=compute_distances(Q,TX)
dFX=compute_distances(Q,FX)
y_score=np.hstack((dTX,dFX))
### rank ###
data=zip(y_true,y_score)
data=sorted(data,key=lambda l:(l[1],l[0]))
data_true=[]
data_score=[]
con=0
### mAP ###
for _,i in enumerate(data):
if con != topk:
data_true.append(i[0])
data_score.append(i[1])
con=con+1
data_true=np.array(data_true)
data_score=np.array(data_score)
resmAP=average_precision_score(data_true,data_score)
return resmAP
def mAP(Q,TX,FX):
tnum=TX.shape[0]
fnum=FX.shape[0]
num=tnum+fnum
resmAP=topmAP(Q,TX,FX,num)
return resmAP
if __name__ == "__main__":
a = np.random.randn(10)
b = np.random.randn(20,10)
c = np.random.randn(10,10)
topk=5
topmap=topmAP(a,b,c,topk=topk)
mapall=mAP(a,b,c)
print('The Value of the Top-%d mAP is %f '%(topk,topmap))
print('The Value of the mAP is %f '%(mapall))
- Result:
The Value of the Top-5 mAP is 0.700000
The Value of the mAP is 0.558517
顯然隨着我們選定的樣本越來也多,recall一定會越來越高,而precision整體上會呈下降趨勢。把recall當成橫座標,precision當成縱座標,即可得到常用的precision-recall曲線。