web-dev-qa-db-ja.com

COCO評価「最大検出」について

cocoapi を使用して Object Detection API を使用してトレーニングされたモデルを評価し始めました。平均平均精度(mAP)と再現率を説明するさまざまなソースを読んだ後、cocoapiで使用されている「最大検出」パラメーターと混同しています。

私が理解したこと(たとえば、 ここここ または ここ ))から、さまざまなモデルスコアのしきい値の精度と再現率を計算してmAPを計算します。これにより、精度-再現率曲線が得られ、mAPはこの曲線の下の面積の近似値として計算されます。または、定義された再現範囲(0:0.1:1)の最大精度の平均として別の表現をします。

ただし、cocoapiは、特定の数の最大検出(maxDet)の精度が高く、スコアが最も高いリコールを計算しているようです。そして、そこからmaxDets = 1, 10, 100の精度再現曲線を取得します。明らかに上記の方法と同じではない(データポイントを除外する可能性がある)ため、これはなぜ良い指標なのですか?

私の例では、画像ごとに約3000個のオブジェクトがあります。 cocoapiを使用して結果を評価すると、検出されたオブジェクトの数が100に制限されるため、ひどい再現率が得られます。

テストの目的で、評価データセットをグラウンドトゥルースおよび検出されたオブジェクト(人工スコア付き)としてフィードします。私は正確さを期待し、実際に起こっているかなり良い思い出します。しかし、100を超えるオブジェクトをフィードすると、「検出されたオブジェクト」の数が増えるにつれて、精度と再現率が低下します。それらはすべて「正しい」にもかかわらず!それはどういう意味ですか?

13
mincos

私は結論に達しました、これはcocoapiがそのメトリックを定義する方法に過ぎないということです。それはおそらく彼らの文脈では理にかなっていますが、私が読んだり、上記でリンクした記事に基づいて、自分の定義(私がしたこと)を定義することもできます。

3
mincos

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()
_

ここで、summarize_2()メソッドを_cocoeval.py_モジュールで次のように定義します。

_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
_
1
ashkan