mmdetection
mmdetection copied to clipboard
fix mean_ap
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
Hi @MambaWong , Could you also post the results so that we could better understand the expected results?
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.
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
.
I think that when using
scale_ranges
, we will focus on the mAP of eachscale_range
, rather than the mAP of thewhole 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.