mmdetection icon indicating copy to clipboard operation
mmdetection copied to clipboard

fix mean_ap

Open MambaWong opened this issue 2 years ago • 3 comments

When using scale_ranges in ***Metric, average_precision() returns ap as a list, which causes the round() exception in ***Metric.

TypeError: type list doesn't define round method

MambaWong avatar Nov 04 '22 05:11 MambaWong

Hi @MambaWong , Could you also post the results so that we could better understand the expected results?

ZwwWayne avatar Dec 19 '22 03:12 ZwwWayne

I've also encountered this issue and applied the patch.

With the applied patch, the exception is no longer raised. Instead a single mAP value is calculated and returned.

But the mAP should be taken with a grain of salt, since it will not equal to the mAP without scale_ranges. This pull request only averages between the scale ranges without factoring in the number of ground truths in each range.

E.g. when having two ranges

  • one for very small objects, of which there are not a lot, and which are very hard to detect and
  • one for regular sized objects, of which there exist plenty

then the mAP of the small objects will be overly represented in the resulting mAP.

E.g. the result would look somewhat like this:

---------------iou_thr: 0.5---------------
Scale range (0, 1024)
+------------+-----+------+--------+-------+
| class      | gts | dets | recall | ap    |
+------------+-----+------+--------+-------+
| Class 1    | 2   | 98   | 0.000  | 0.000 |
| Class 2    | 0   | 99   | 0.000  | 0.000 |
+------------+-----+------+--------+-------+
| mAP        |     |      |        | 0.000 |
+------------+-----+------+--------+-------+
Scale range (1024, 9999999)
+------------+-----+------+--------+-------+
| class      | gts | dets | recall | ap    |
+------------+-----+------+--------+-------+
| Class 1    | 98  | 98   | 1.000  | 1.000 |
| Class 2    | 98  | 99   | 1.000  | 1.000 |
+------------+-----+------+--------+-------+
| mAP        |     |      |        | 1.000 |
+------------+-----+------+--------+-------+
OrderedDict([('AP50', 0.5), ('mAP', 0.5)])

The mAP is 0.5, but actually nearly all objects except the two in the smaller scale range where detected.

I currently fixed it, by always specifying a range (0, 9999) as the first item and returning the mAP of the first result instead of the average with:

    if isinstance(mean_ap, list):
        mean_ap = mean_ap[0]

I guess it should first be discussed, what the expected result should be.

Lucas-Steinmann avatar Dec 19 '22 15:12 Lucas-Steinmann

I think that when using scale_ranges, we will focus on the mAP of each scale_range, rather than the mAP of the whole range.

MambaWong avatar Dec 24 '22 03:12 MambaWong

I think that when using scale_ranges, we will focus on the mAP of each scale_range, rather than the mAP of the whole range.

Yes, but sometimes we still need the overall AP. To be consistent with other metrics like COCO mAP for small/medium/large objects, the overall AP should not be the simple average of small/medium/large AP or the APs of different ranges.

ZwwWayne avatar Jan 29 '23 10:01 ZwwWayne