深度理解VOC中的准确率Precision与召回率Recall(P-R图)

在二分类问题中,我们根据预测结果与真实结果的关系,可以将它们分为四类:

(TP,FP,TN,FN)

从预测结果的角度来看:TP+FP=预测结果为正例的集合,同理FN+TN=预测结果为反例的集合;

从真实情况的角度来看:TP+FN=真实情况为正例的集合,同理FP+TN=真实情况为反例的集合。

clip_image001

查准率(Precision)与查全率(Recall)是常用的分类器性能衡量标准,查准率衡量的是“预测为正的结果中有多少是真正的正例”,而查全率衡量的是“真正的正例中有多少被预测为正例”。通常情况下,它们是一对矛盾的度量,查准率高时,查全率往往偏低;而查全率高时,查准率往往偏低。

计算公式为:

clip_image002

clip_image003

下图形象得描述了上述4个量中3个的关系,黄色区域为真实情况为正例的集合,虚线区域为预测为正例的集合,其重叠区域A即为TP,区域B为FN,区域C为FP,TN并没有在图中描绘出来,但是可以想象,它是整个集合中去除上述3个区域后剩下的区域。

clip_image005

很多情况下,我们可以根据学习器的预测结果(对于Faster-RCNN之类的检测算法,根据score)对样例进行降序排列,排在前面的样例是学习器认为的最有可能是正例的结果,反之则可能性较小。分类的界限即我们所谓的阈值(Threshold),对于N个样本,最多可以有N(N-1个来自相邻score的中间值,最后一个阈值为0)个阈值。通过改变阈值的大小,可以计算出一系列当前阈值下的查全率与查准率,进而绘制出P-R曲线。

clip_image007

目前为止,我们只解决了输出样例中谁为预测正例,谁为预测反例的问题, 要判断输出样例的真实情况,需要人为的标定,或者参考别的性能更好的分类器。对于VOC,输出结果与Groundtruth的overlap大于等于0.5则判定为正例。

举个例子,我有10个输出,根据score降序排列,T&F代表真实情况:

T T T F T F F T F F

取相邻结果score的中间值为阈值再加上0阈值,我们可以得到10组不同的(P,R)值:

(1.00,0.20),(1.00,0.40),(1.00,0.60),(0.75,0.60),(0.80,0.80)

(0.67,0.80),(0.57,0.80),(0.63,1.00),(0.56,1.00),(0.50 , 1.00)

clip_image009

可以看出P-R曲线并不一定是单减的,在局部可能存在上升的情况,但是由于实际输出样例数目都足够大,所以曲线看上去都很光滑,单调性较为显著。

在VOC官方给出的Evaluation代码VOCevaldet.m中,很巧妙的利用累加函数cumsum实现了最大数量的阈值划分。

%VOCevaldet.m
    % assign detections to ground truth objects
    nd=length(confidence);
    tp=zeros(nd,1);
    fp=zeros(nd,1);
    tic;
    for d=1:nd
        % display progress
        if toc>1
            fprintf('%s: pr: compute: %d/%d\n',cls,d,nd);
            drawnow;
            tic;
        end
        
        % find ground truth image
        i=strmatch(ids{d},gtids,'exact');
        if isempty(i)
            error('unrecognized image "%s"',ids{d});
        elseif length(i)>1
            error('multiple image "%s"',ids{d});
        end
    
        % assign detection to ground truth object if any
        bb=BB(:,d);
        ovmax=-inf;
        for j=1:size(gt(i).BB,2)
            bbgt=gt(i).BB(:,j);
            bi=[max(bb(1),bbgt(1)) ; max(bb(2),bbgt(2)) ; min(bb(3),bbgt(3)) ; min(bb(4),bbgt(4))];
            iw=bi(3)-bi(1)+1;
            ih=bi(4)-bi(2)+1;
            if iw>0 & ih>0                
                % compute overlap as area of intersection / area of union
                ua=(bb(3)-bb(1)+1)*(bb(4)-bb(2)+1)+...
                   (bbgt(3)-bbgt(1)+1)*(bbgt(4)-bbgt(2)+1)-...
                   iw*ih;
                ov=iw*ih/ua;
                if ov>ovmax
                    ovmax=ov;
                    jmax=j;
                end
            end
        end
        % assign detection as true positive/don't care/false positive
        if ovmax>=VOCopts.minoverlap
            if ~gt(i).diff(jmax)
                if ~gt(i).det(jmax)
                    tp(d)=1;            % true positive
            gt(i).det(jmax)=true;
                else
                    fp(d)=1;            % false positive (multiple detection)
                end
            end
        else
            fp(d)=1;                    % false positive
        end
    end
    
    % compute precision/recall
    fp=cumsum(fp);
    tp=cumsum(tp);
    rec=tp/npos;
    prec=tp./(fp+tp);

 

 

最近我着手的项目主要是在Faser-RCNN的基础上,根据局部检测结果融合出全局目标的BoundingBox,但是不可避免的带入了一些score较小的反例。

T T T T F T F F T F F F

根据我对P-R曲线的理解,我预计,最后结果将会是:在thres较高的阶段,也就是曲线的左上角部分,由于加入了score较高的真正例(TP),较高的precision能保持更长的时间,也就是说,在相同的recall条件下,我的precision会高于之前的结果;但在曲线后半部分,也就是右下角区域,由于加入了较多的假正例(FP),precision会快速下降,但最终的recall仍然高于之前的结果。

clip_image011

posted @ 2016-11-17 20:00  Drum&Heart  阅读(1397)  评论(0)    收藏  举报