找了蠻久也沒有找到這些指標定義的paper(還是太菜了),於是隻好直接對照代碼來看,具體代碼參考:zhunzhong07/person-re-ranking

以Market_1501數據為例,計算指標的入口文件是Market_1501_evaluation.m,顯示讀取gallery和query(proba)的embedding,計算pair distance,然後就進入到了evaluation函數,這個函數返回2個變數,就是我們要說的CMC和mAP,其中CMC是一個數組,cmc[k]表示top K accuracy。下面就具體來說下怎麼計算這2個值:

首先聲明一下:

  1. 這裡的mAP是mean of 所有query,跟detection裡面mean of classes還是有所不同。
  2. 這裡ap的計算方式是precision/recall曲線的面積
  3. CMC是Cumulative Matching Characteristics,Evaluation Metrics

具體做法:

  1. 遍歷每個query,對於每個query,找到GT中跟當前query屬於同一個ID但是是不同camera下的圖片,這些圖片被認為是good_image,其他的圖片就是junk_image,然後對所有gallery與當前query的距離做個升序排序,接著就對當前query計算ap,cmc

對應的代碼片段是:

for k = 1:size(dist, 2)
k;
score = dist(:, k);
q_label = label_query(k);
q_cam = cam_query(k);
pos = find(label_gallery == q_label);
pos2 = cam_gallery(pos) ~= q_cam;
good_image = pos(pos2);
pos3 = cam_gallery(pos) == q_cam;
junk = pos(pos3);
junk_image = [junk0; junk];
[~, index] = sort(score, ascend);
[ap(k), CMC(:, k)] = compute_AP(good_image, junk_image, index);
%ap_pairwise(k, :) = compute_AP_multiCam(good_image, junk, index, q_cam, cam_gallery); % compute pairwise AP for single query
%r1_pairwise(k, :) = compute_r1_multiCam(good_image, junk, index, q_cam, cam_gallery); % pairwise rank 1 precision with single query
end

在得到所有query對應的ap和cmc後,對所有query去個平均就是最後的mAP和CMC

CMC = sum(CMC, 2)./size(dist, 2);
CMC = CMC;
ap(isnan(ap) == 1) = 0;
map = sum(ap)/length(ap);

2. 計算每個query的ap和CMC對應的函數是compute_AP,然後代碼裡面是求了precision在0-1範圍內下的recall,以及top N(N為gallery的大小),所以直接遍歷所有的gallery

  1. 對於ap來說:每一次遍歷可以理解為在某個閾值下求precision/recall,相當於就在構建precision/recall這個圖一樣。對於某個gallery,如果是good_image,就good_now++,否則njunk++,然後就算出當前閾值下的precision/recall。因為ap求的是precision/recall圖下的面經,所以每次遍歷的時候順便也把這個對應的小矩形的面積累加起來,ap = ap + (recall - old_recall)*((old_precision+precision)/2);
  2. 對於CMC來說:每一次遍歷可以理解為在算某個topK的accuracy,因為pair distance數組是排好序的嘛。因為是累積accuracy,在遍歷第i位的時候,如果當前gallery是good_image,那說明,這個gallery image在算topX(X>=i)的時候一定是算在裡面的,所以纔有cmc(n-njunk:end) = 1; 個人感覺這個會被賦值多遍,但是隻有第一次賦值纔是有效的,纔是賦值範圍最大的。

對應的代碼為:

for n = 1:length(index)
flag = 0;
if ~isempty(find(good_image == index(n), 1))
cmc(n-njunk:end) = 1;
flag = 1; % good image
good_now = good_now+1;
end
if ~isempty(find(junk_image == index(n), 1))
njunk = njunk + 1;
continue; % junk image
end

if flag == 1%good
intersect_size = intersect_size + 1;
end
recall = intersect_size/ngood;
precision = intersect_size/(j + 1);
ap = ap + (recall - old_recall)*((old_precision+precision)/2);
old_recall = recall;
old_precision = precision;
j = j+1;

if good_now == ngood
return;
end
end

疑問

liangzheng.com.cn/Proje中說的single query和Multiple query的區別在哪裡?Evaluation Metrics這裡面似乎說的也不是很明白,不知道有沒有對應的code可以觀摩debug一下?

推薦閱讀:

相關文章