了解 COCO 评估 "maximum detections"

Understanding COCO evaluation "maximum detections"

我开始使用 cocoapi to evaluate a model trained using the Object Detection API。 在阅读了各种解释平均精度 (mAP) 和召回率的资料后,我对 cocoapi 中使用的 "maximum detections" 参数感到困惑。

据我了解(例如here, here or here),通过计算各种模型分数阈值的精度和召回率来计算 mAP。这给出了精确召回曲线,并且 mAP 计算为该曲线下面积的近似值。或者,换句话说,作为定义的召回范围 (0:0.1:1) 中最大精度的平均值。

但是,cocoapi 似乎计算了给定数量的最高检测 (maxDet) 的精确率和召回率。从那里得到 maxDets = 1, 10, 100 的精确召回曲线。为什么这是一个很好的指标,因为它显然与上述方法不同(它可能排除数据点)?

在我的示例中,每张图像有大约 3000 个对象。使用 cocoapi 评估结果的召回率很差,因为它将检测到的对象数量限制为 100。

出于测试目的,我将评估数据集作为基本事实和检测到的对象(带有一些人工分数)提供。我希望精确度和召回率相当好,这实际上正在发生。但是一旦我输入超过 100 个对象,精度和召回率就会随着 "detected objects" 数量的增加而下降。虽然都是"correct"!这有什么意义?

我得出的结论是,这正是 cocoapi 定义其指标的方式。这在他们的上下文中可能是有意义的,但我也可以根据我阅读和上面链接的文章来定义我自己的(我就是这样做的)。

您可以更改 maxDets 参数并定义新的 summarize() 实例方法。

让我们创建一个 COCOeval 对象:

cocoEval = COCOeval(cocoGt,cocoDt,annType)
cocoEval.params.maxDets = [200]
cocoEval.params.imgIds  = imgIdsDt
cocoEval.evaluate()
cocoEval.accumulate()
cocoEval.summarize_2() # instead of calling cocoEval.summarize()

现在,在cocoeval.py模块中定义summarize_2()方法如下:

def summarize_2(self):
    # Copy everything from `summarize` method here except
    # the function `_summarizeDets()`.
    def _summarizeDets():
        stats = np.zeros((12,))
        stats[0] = _summarize(1, maxDets=self.params.maxDets[0])
        stats[1] = _summarize(1, iouThr=.5, maxDets=self.params.maxDets[0])
        stats[2] = _summarize(1, iouThr=.75, maxDets=self.params.maxDets[0])
        stats[3] = _summarize(1, areaRng='small', maxDets=self.params.maxDets[0])
        stats[4] = _summarize(1, areaRng='medium', maxDets=self.params.maxDets[0])
        stats[5] = _summarize(1, areaRng='large', maxDets=self.params.maxDets[0])
        stats[6] = _summarize(0, maxDets=self.params.maxDets[0])
        stats[9] = _summarize(0, areaRng='small', maxDets=self.params.maxDets[0])
        stats[10] = _summarize(0, areaRng='medium', maxDets=self.params.maxDets[0])
        stats[11] = _summarize(0, areaRng='large', maxDets=self.params.maxDets[0])
        return stats
    # Copy other things which are left from `summarize()` here.

如果你 运行 对你的数据集使用上述方法,你将得到类似于这样的输出:

 Average Precision  (AP) @[ IoU=0.50:0.95 | area=   all | maxDets=200 ] = 0.507
 Average Precision  (AP) @[ IoU=0.50      | area=   all | maxDets=200 ] = 0.699
 Average Precision  (AP) @[ IoU=0.75      | area=   all | maxDets=200 ] = 0.575
 Average Precision  (AP) @[ IoU=0.50:0.95 | area= small | maxDets=200 ] = 0.586
 Average Precision  (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=200 ] = 0.519
 Average Precision  (AP) @[ IoU=0.50:0.95 | area= large | maxDets=200 ] = 0.501
 Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=200 ] = 0.598
 Average Recall     (AR) @[ IoU=0.50:0.95 | area= small | maxDets=200 ] = 0.640
 Average Recall     (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=200 ] = 0.566
 Average Recall     (AR) @[ IoU=0.50:0.95 | area= large | maxDets=200 ] = 0.564