Repository: open-mmlab/mmdetection

Issue:
APs of YOLOv3 pretrained models drop over 0.9 after updating to v2.7 and some other detectors drop 0.1  
**Checklist**

1. I have searched related issues but cannot get the expected help.
2. The bug has not been fixed in the latest version.

**Describe the bug**
In MMDetection v2.7, the APs of pre-trained models of [YOLOv3](https://github.com/open-mmlab/mmdetection/tree/master/configs/yolo) drop significantly. For YOLOv3-320, the AP falls from 27.9 to 27.0; YOLOv3-416, the AP falls from 30.9 to 29.8; YOLOv3-608, 33.4 -> 32.3. 

Average Precision  (AP) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = **0.270** 
Average Precision  (AP) @[ IoU=0.50      | area=   all | maxDets=1000 ] = 0.469 
Average Precision  (AP) @[ IoU=0.75      | area=   all | maxDets=1000 ] = 0.278 
Average Precision  (AP) @[ IoU=0.50:0.95 | area= small | maxDets=1000 ] = 0.101 
Average Precision  (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=1000 ] = 0.290 
Average Precision  (AP) @[ IoU=0.50:0.95 | area= large | maxDets=1000 ] = 0.426 
Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = 0.355 
Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=300 ] = 0.355 
Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=1000 ] = 0.355 
Average Recall     (AR) @[ IoU=0.50:0.95 | area= small | maxDets=1000 ] = 0.154 
Average Recall     (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=1000 ] = 0.374 
Average Recall     (AR) @[ IoU=0.50:0.95 | area= large | maxDets=1000 ] = 0.536 

Average Precision  (AP) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = **0.298** 
Average Precision  (AP) @[ IoU=0.50      | area=   all | maxDets=1000 ] = 0.502 
Average Precision  (AP) @[ IoU=0.75      | area=   all | maxDets=1000 ] = 0.313 
Average Precision  (AP) @[ IoU=0.50:0.95 | area= small | maxDets=1000 ] = 0.136 
Average Precision  (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=1000 ] = 0.321 
Average Precision  (AP) @[ IoU=0.50:0.95 | area= large | maxDets=1000 ] = 0.438 
Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = 0.386 
Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=300 ] = 0.386 
Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=1000 ] = 0.386 
Average Recall     (AR) @[ IoU=0.50:0.95 | area= small | maxDets=1000 ] = 0.189 
Average Recall     (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=1000 ] = 0.410 
Average Recall     (AR) @[ IoU=0.50:0.95 | area= large | maxDets=1000 ] = 0.549 

Average Precision  (AP) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = **0.323** 
Average Precision  (AP) @[ IoU=0.50      | area=   all | maxDets=1000 ] = 0.535 
Average Precision  (AP) @[ IoU=0.75      | area=   all | maxDets=1000 ] = 0.344 
Average Precision  (AP) @[ IoU=0.50:0.95 | area= small | maxDets=1000 ] = 0.184 
Average Precision  (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=1000 ] = 0.351 
Average Precision  (AP) @[ IoU=0.50:0.95 | area= large | maxDets=1000 ] = 0.426 
Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = 0.414 
Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=300 ] = 0.414 
Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=1000 ] = 0.414 
Average Recall     (AR) @[ IoU=0.50:0.95 | area= small | maxDets=1000 ] = 0.244 
Average Recall     (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=1000 ] = 0.436 
Average Recall     (AR) @[ IoU=0.50:0.95 | area= large | maxDets=1000 ] = 0.544 

For fcos_r50_caffe_fpn_gn-head_4x4_1x_coco.py, the AP drops from 36.6 to 36.5 and the same issue can be found with other detectors like Mask RCNN.

Average Precision  (AP) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = **0.365** 
Average Precision  (AP) @[ IoU=0.50      | area=   all | maxDets=1000 ] = 0.556 
Average Precision  (AP) @[ IoU=0.75      | area=   all | maxDets=1000 ] = 0.388 
Average Precision  (AP) @[ IoU=0.50:0.95 | area= small | maxDets=1000 ] = 0.206 
Average Precision  (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=1000 ] = 0.401 
Average Precision  (AP) @[ IoU=0.50:0.95 | area= large | maxDets=1000 ] = 0.474 
Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = 0.526 
Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=300 ] = 0.526 
Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=1000 ] = 0.526 
Average Recall     (AR) @[ IoU=0.50:0.95 | area= small | maxDets=1000 ] = 0.318 
Average Recall     (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=1000 ] = 0.570 
Average Recall     (AR) @[ IoU=0.50:0.95 | area= large | maxDets=1000 ] = 0.670 

**Reproduction**

1. What command or script did you run?

```
python tools/test.py configs/yolo/yolov3_d53_320_273e_coco.py  checkpoints/yolov3/yolov3_d53_320_273e_coco-421362b6.pth --eval bbox

python tools/test.py configs/yolo/yolov3_d53_mstrain-416_273e_coco.py  checkpoints/yolov3/yolov3_d53_mstrain-416_273e_coco-2b60fcd9.pth --eval bbox

python tools/test.py configs/yolo/yolov3_d53_mstrain-608_273e_coco.py  checkpoints/yolov3/yolov3_d53_mstrain-608_273e_coco-139f5633.pth --eval bbox

python tools/test.py configs/fcos/fcos_r50_caffe_fpn_gn-head_4x4_1x_coco.py  checkpoints/fcos/fcos_r50_caffe_fpn_gn-head_4x4_1x_coco/fcos_r50_caffe_fpn_gn_1x_4gpu_20200218-7831950c.pth --eval bbox

```

2. Did you make any modifications on the code or config? Did you understand what you have modified?
NO

3. What dataset did you use?
COCO

**Environment**

1. Please run `python mmdet/utils/collect_env.py` to collect necessary environment information and paste it here.

sys.platform: linux 

Python: 3.7.5 (default, Oct 25 2019, 15:51:11) [GCC 7.3.0] 

CUDA available: True 

GPU 0: GeForce GTX 1080 

CUDA_HOME: /usr/local/cuda 

NVCC: Cuda compilation tools, release 10.1, V10.1.243 

GCC: gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0 

PyTorch: 1.6.0 

PyTorch compiling details: PyTorch built with: 

  - GCC 7.3 

  - C++ Version: 201402 

  - Intel(R) Math Kernel Library Version 2019.0.4 Product Build 20190411 for Intel(R) 64 architecture applications 

  - Intel(R) MKL-DNN v1.5.0 (Git Hash e2ac1fac44c5078ca927cb9b90e1b3066a0b2ed0) 

  - OpenMP 201511 (a.k.a. OpenMP 4.5) 

  - NNPACK is enabled 

  - CPU capability usage: AVX2 

  - CUDA Runtime 10.1 

  - NVCC architecture flags: -gencode;arch=compute_37,code=sm_37;-gencode;arch=compute_50,code=sm_50;-gencode;arch=compute_60,code=sm_60;-gencode;arch=compute_61,code=sm_61;-gencode;arch=compute_70,code=sm_70;-gencode;arch=compute_75,code=sm_75;-gencode;arch=compute_37,code=compute_37 

  - CuDNN 7.6.3 

  - Magma 2.5.2 

  - Build settings: BLAS=MKL, BUILD_TYPE=Release, CXX_FLAGS= -Wno-deprecated -fvisibility-inlines-hidden -DUSE_PTHREADPOOL -fopenmp -DNDEBUG -DUSE_FBGEMM -DUSE_QNNPACK -DUSE_PYTORCH_QNNPACK -DUSE_XNNPACK -DUSE_VULKAN_WRAPPER -O2 -fPIC -Wno-narrowing -Wall -Wextra -Werror=return-type -Wno-missing-field-initializers -Wno-type-limits -Wno-array-bounds -Wno-unknown-pragmas -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wno-unused-function -Wno-unused-result -Wno-unused-local-typedefs -Wno-strict-overflow -Wno-strict-aliasing -Wno-error=deprecated-declarations -Wno-stringop-overflow -Wno-error=pedantic -Wno-error=redundant-decls -Wno-error=old-style-cast -fdiagnostics-color=always -faligned-new -Wno-unused-but-set-variable -Wno-maybe-uninitialized -fno-math-errno -fno-trapping-math -Werror=format -Wno-stringop-overflow, PERF_WITH_AVX=1, PERF_WITH_AVX2=1, PERF_WITH_AVX512=1, USE_CUDA=ON, USE_EXCEPTION_PTR=1, USE_GFLAGS=OFF, USE_GLOG=OFF, USE_MKL=ON, USE_MKLDNN=ON, USE_MPI=OFF, USE_NCCL=ON, USE_NNPACK=ON, USE_OPENMP=ON, USE_STATIC_DISPATCH=OFF,  

  

TorchVision: 0.7.0 
OpenCV: 4.2.0 
MMCV: 1.1.5 
MMCV Compiler: GCC 7.3 
MMCV CUDA Compiler: 10.1 
MMDetection: 2.7.0+2983c05 


**Bug fix**
I think the bug might be related to evaluation code as the AP drop happens to many detectors. 



Discussion:
Thanks for reporting the issue. We will check that.
In the regression benchmark, the performance of YOLO indeed dropped. We will check this issue in January.

Resolving patch:
diff --git a/mmdet/core/post_processing/bbox_nms.py b/mmdet/core/post_processing/bbox_nms.py
--- a/mmdet/core/post_processing/bbox_nms.py
+++ b/mmdet/core/post_processing/bbox_nms.py
@@ -40,8 +40,6 @@ def multiclass_nms(multi_bboxes,
             multi_scores.size(0), num_classes, 4)
 
     scores = multi_scores[:, :-1]
-    if score_factors is not None:
-        scores = scores * score_factors[:, None]
 
     labels = torch.arange(num_classes, dtype=torch.long)
     labels = labels.view(1, -1).expand_as(scores)
@@ -52,6 +50,14 @@ def multiclass_nms(multi_bboxes,
 
     # remove low scoring boxes
     valid_mask = scores > score_thr
+    # multiply score_factor after threshold to preserve more bboxes, improve
+    # mAP by 1% for YOLOv3
+    if score_factors is not None:
+        # expand the shape to match original shape of score
+        score_factors = score_factors.view(-1, 1).expand(
+            multi_scores.size(0), num_classes)
+        score_factors = score_factors.reshape(-1)
+        scores = scores * score_factors
     inds = valid_mask.nonzero(as_tuple=False).squeeze(1)
     bboxes, scores, labels = bboxes[inds], scores[inds], labels[inds]
     if inds.numel() == 0:


Test patch: