mobilenet_ssd.py 4.7 KB
Newer Older
X
xiaoting 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13
#   Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
G
gaoyuan 已提交
14 15 16 17 18
import paddle.fluid as fluid
from paddle.fluid.initializer import MSRA
from paddle.fluid.param_attr import ParamAttr


19 20 21 22 23
class MobileNetSSD:
    def __init__(self, img, num_classes, img_shape):
        self.img = img
        self.num_classes = num_classes
        self.img_shape = img_shape
G
gaoyuan 已提交
24

25 26
    def ssd_net(self, scale=1.0):
        # 300x300
27
        tmp = self.conv_bn(self.img, 3, int(32 * scale), 2, 1)
28 29 30 31 32 33 34 35 36
        # 150x150
        tmp = self.depthwise_separable(tmp, 32, 64, 32, 1, scale)
        tmp = self.depthwise_separable(tmp, 64, 128, 64, 2, scale)
        # 75x75
        tmp = self.depthwise_separable(tmp, 128, 128, 128, 1, scale)
        tmp = self.depthwise_separable(tmp, 128, 256, 128, 2, scale)
        # 38x38
        tmp = self.depthwise_separable(tmp, 256, 256, 256, 1, scale)
        tmp = self.depthwise_separable(tmp, 256, 512, 256, 2, scale)
G
gaoyuan 已提交
37

38 39 40 41 42
        # 19x19
        for i in range(5):
            tmp = self.depthwise_separable(tmp, 512, 512, 512, 1, scale)
        module11 = tmp
        tmp = self.depthwise_separable(tmp, 512, 1024, 512, 2, scale)
G
gaoyuan 已提交
43

44 45
        # 10x10
        module13 = self.depthwise_separable(tmp, 1024, 1024, 1024, 1, scale)
46
        module14 = self.extra_block(module13, 256, 512, 1, 2)
47
        # 5x5
48
        module15 = self.extra_block(module14, 128, 256, 1, 2)
49
        # 3x3
50
        module16 = self.extra_block(module15, 128, 256, 1, 2)
51
        # 2x2
52
        module17 = self.extra_block(module16, 64, 128, 1, 2)
G
gaoyuan 已提交
53

54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
        mbox_locs, mbox_confs, box, box_var = fluid.layers.multi_box_head(
            inputs=[
                module11, module13, module14, module15, module16, module17
            ],
            image=self.img,
            num_classes=self.num_classes,
            min_ratio=20,
            max_ratio=90,
            min_sizes=[60.0, 105.0, 150.0, 195.0, 240.0, 285.0],
            max_sizes=[[], 150.0, 195.0, 240.0, 285.0, 300.0],
            aspect_ratios=[[2.], [2., 3.], [2., 3.], [2., 3.], [2., 3.],
                           [2., 3.]],
            base_size=self.img_shape[2],
            offset=0.5,
            flip=True)
G
gaoyuan 已提交
69

70
        return mbox_locs, mbox_confs, box, box_var
G
gaoyuan 已提交
71

72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
    def conv_bn(self,
                input,
                filter_size,
                num_filters,
                stride,
                padding,
                num_groups=1,
                act='relu',
                use_cudnn=True):
        parameter_attr = ParamAttr(learning_rate=0.1, initializer=MSRA())
        conv = fluid.layers.conv2d(
            input=input,
            num_filters=num_filters,
            filter_size=filter_size,
            stride=stride,
            padding=padding,
            groups=num_groups,
            act=None,
            use_cudnn=use_cudnn,
            param_attr=parameter_attr,
            bias_attr=False)
        return fluid.layers.batch_norm(input=conv, act=act)
G
gaoyuan 已提交
94

95 96 97 98 99 100 101 102 103 104
    def depthwise_separable(self, input, num_filters1, num_filters2, num_groups,
                            stride, scale):
        depthwise_conv = self.conv_bn(
            input=input,
            filter_size=3,
            num_filters=int(num_filters1 * scale),
            stride=stride,
            padding=1,
            num_groups=int(num_groups * scale),
            use_cudnn=False)
G
gaoyuan 已提交
105

106 107 108 109 110 111 112
        pointwise_conv = self.conv_bn(
            input=depthwise_conv,
            filter_size=1,
            num_filters=int(num_filters2 * scale),
            stride=1,
            padding=0)
        return pointwise_conv
G
gaoyuan 已提交
113

114
    def extra_block(self, input, num_filters1, num_filters2, num_groups, stride):
115 116 117 118
        # 1x1 conv
        pointwise_conv = self.conv_bn(
            input=input,
            filter_size=1,
119
            num_filters=int(num_filters1),
120
            stride=1,
121
            num_groups=int(num_groups),
122
            padding=0)
G
gaoyuan 已提交
123

124 125 126 127
        # 3x3 conv
        normal_conv = self.conv_bn(
            input=pointwise_conv,
            filter_size=3,
128
            num_filters=int(num_filters2),
129
            stride=2,
130
            num_groups=int(num_groups),
131 132
            padding=1)
        return normal_conv
X
Xingyuan Bu 已提交
133

G
gaoyuan 已提交
134

135 136 137
def build_mobilenet_ssd(img, num_classes, img_shape):
    ssd_model = MobileNetSSD(img, num_classes, img_shape)
    return ssd_model.ssd_net()