Repository: PaddlePaddle/models

Issue:
MobileNet-SSD 的 backbone 存在 bug
如下图1， 2中，`_extra_block` 函数调用的地方已经写死 `num_groups` 为 1，而 `scale` 参数为传入的，假设 `scale` < 1，比如 0.5 或者 0.25，则会出现调用 `self._conv_norm` 的时候 `num_groups` 为 0 的情况。

![image](https://user-images.githubusercontent.com/37564754/61533480-a1856600-aa5f-11e9-821a-f29add347860.png)

![image](https://user-images.githubusercontent.com/37564754/61533542-c679d900-aa5f-11e9-86e4-a2d895aa87d1.png)

具体代码位于：
[code](https://github.com/PaddlePaddle/models/blob/develop/PaddleCV/PaddleDetection/ppdet/modeling/backbones/mobilenet.py#L122-L146) 和 [code](https://github.com/PaddlePaddle/models/blob/develop/PaddleCV/PaddleDetection/ppdet/modeling/backbones/mobilenet.py#L188-L195)



Discussion:
@mzchtx 感谢指出，在 https://github.com/PaddlePaddle/models/blob/develop/PaddleCV/ssd/mobilenet_ssd.py  中实际不支持更换scale。 我们会在PaddleDetection中改进下。

Resolving patch:
diff --git a/PaddleCV/PaddleDetection/ppdet/modeling/backbones/mobilenet.py b/PaddleCV/PaddleDetection/ppdet/modeling/backbones/mobilenet.py
--- a/PaddleCV/PaddleDetection/ppdet/modeling/backbones/mobilenet.py
+++ b/PaddleCV/PaddleDetection/ppdet/modeling/backbones/mobilenet.py
@@ -57,7 +57,6 @@ def _conv_norm(self,
                    num_filters,
                    stride,
                    padding,
-                   channels=None,
                    num_groups=1,
                    act='relu',
                    use_cudnn=True,
@@ -125,22 +124,21 @@ def _extra_block(self,
                      num_filters2,
                      num_groups,
                      stride,
-                     scale,
                      name=None):
         pointwise_conv = self._conv_norm(
             input=input,
             filter_size=1,
-            num_filters=int(num_filters1 * scale),
+            num_filters=int(num_filters1),
             stride=1,
-            num_groups=int(num_groups * scale),
+            num_groups=int(num_groups),
             padding=0,
             name=name + "_extra1")
         normal_conv = self._conv_norm(
             input=pointwise_conv,
             filter_size=3,
-            num_filters=int(num_filters2 * scale),
+            num_filters=int(num_filters2),
             stride=2,
-            num_groups=int(num_groups * scale),
+            num_groups=int(num_groups),
             padding=1,
             name=name + "_extra2")
         return normal_conv
@@ -150,7 +148,7 @@ def __call__(self, input):
 
         blocks = []
         # input 1/1
-        out = self._conv_norm(input, 3, int(32 * scale), 2, 1, 3, name="conv1")
+        out = self._conv_norm(input, 3, int(32 * scale), 2, 1, name="conv1")
         # 1/2
         out = self.depthwise_separable(
             out, 32, 64, 32, 1, scale, name="conv2_1")
@@ -186,11 +184,11 @@ def __call__(self, input):
 
         num_filters = self.extra_block_filters
         module14 = self._extra_block(module13, num_filters[0][0],
-                                     num_filters[0][1], 1, 2, scale, "conv7_1")
+                                     num_filters[0][1], 1, 2, "conv7_1")
         module15 = self._extra_block(module14, num_filters[1][0],
-                                     num_filters[1][1], 1, 2, scale, "conv7_2")
+                                     num_filters[1][1], 1, 2, "conv7_2")
         module16 = self._extra_block(module15, num_filters[2][0],
-                                     num_filters[2][1], 1, 2, scale, "conv7_3")
+                                     num_filters[2][1], 1, 2, "conv7_3")
         module17 = self._extra_block(module16, num_filters[3][0],
-                                     num_filters[3][1], 1, 2, scale, "conv7_4")
+                                     num_filters[3][1], 1, 2, "conv7_4")
         return module11, module13, module14, module15, module16, module17
diff --git a/PaddleCV/ssd/mobilenet_ssd.py b/PaddleCV/ssd/mobilenet_ssd.py
--- a/PaddleCV/ssd/mobilenet_ssd.py
+++ b/PaddleCV/ssd/mobilenet_ssd.py
@@ -11,7 +11,7 @@ def __init__(self, img, num_classes, img_shape):
 
     def ssd_net(self, scale=1.0):
         # 300x300
-        tmp = self.conv_bn(self.img, 3, int(32 * scale), 2, 1, 3)
+        tmp = self.conv_bn(self.img, 3, int(32 * scale), 2, 1)
         # 150x150
         tmp = self.depthwise_separable(tmp, 32, 64, 32, 1, scale)
         tmp = self.depthwise_separable(tmp, 64, 128, 64, 2, scale)
@@ -30,13 +30,13 @@ def ssd_net(self, scale=1.0):
 
         # 10x10
         module13 = self.depthwise_separable(tmp, 1024, 1024, 1024, 1, scale)
-        module14 = self.extra_block(module13, 256, 512, 1, 2, scale)
+        module14 = self.extra_block(module13, 256, 512, 1, 2)
         # 5x5
-        module15 = self.extra_block(module14, 128, 256, 1, 2, scale)
+        module15 = self.extra_block(module14, 128, 256, 1, 2)
         # 3x3
-        module16 = self.extra_block(module15, 128, 256, 1, 2, scale)
+        module16 = self.extra_block(module15, 128, 256, 1, 2)
         # 2x2
-        module17 = self.extra_block(module16, 64, 128, 1, 2, scale)
+        module17 = self.extra_block(module16, 64, 128, 1, 2)
 
         mbox_locs, mbox_confs, box, box_var = fluid.layers.multi_box_head(
             inputs=[
@@ -62,7 +62,6 @@ def conv_bn(self,
                 num_filters,
                 stride,
                 padding,
-                channels=None,
                 num_groups=1,
                 act='relu',
                 use_cudnn=True):
@@ -99,24 +98,23 @@ def depthwise_separable(self, input, num_filters1, num_filters2, num_groups,
             padding=0)
         return pointwise_conv
 
-    def extra_block(self, input, num_filters1, num_filters2, num_groups, stride,
-                    scale):
+    def extra_block(self, input, num_filters1, num_filters2, num_groups, stride):
         # 1x1 conv
         pointwise_conv = self.conv_bn(
             input=input,
             filter_size=1,
-            num_filters=int(num_filters1 * scale),
+            num_filters=int(num_filters1),
             stride=1,
-            num_groups=int(num_groups * scale),
+            num_groups=int(num_groups),
             padding=0)
 
         # 3x3 conv
         normal_conv = self.conv_bn(
             input=pointwise_conv,
             filter_size=3,
-            num_filters=int(num_filters2 * scale),
+            num_filters=int(num_filters2),
             stride=2,
-            num_groups=int(num_groups * scale),
+            num_groups=int(num_groups),
             padding=1)
         return normal_conv
 


Test patch: