mobilenet_v1.py 7.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
# Copyright (c) 2019 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.

import os
import time
import sys
import numpy as np
import argparse
import ast
import paddle
import paddle.fluid as fluid
from paddle.fluid.initializer import MSRA
from paddle.fluid.param_attr import ParamAttr
from paddle.fluid.layer_helper import LayerHelper
C
chajchaj 已提交
26
from paddle.fluid.dygraph.nn import Conv2D, Pool2D, BatchNorm, Linear
27 28 29 30 31 32 33 34
from paddle.fluid.dygraph.base import to_variable
from paddle.fluid import framework
import math
import sys


class ConvBNLayer(fluid.dygraph.Layer):
    def __init__(self,
C
chajchaj 已提交
35
                 num_channels,
36 37 38 39 40 41 42 43 44
                 filter_size,
                 num_filters,
                 stride,
                 padding,
                 channels=None,
                 num_groups=1,
                 act='relu',
                 use_cudnn=True,
                 name=None):
C
chajchaj 已提交
45
        super(ConvBNLayer, self).__init__()
46 47

        self._conv = Conv2D(
C
chajchaj 已提交
48
            num_channels=num_channels,
49 50 51 52 53 54 55 56 57 58 59 60 61 62
            num_filters=num_filters,
            filter_size=filter_size,
            stride=stride,
            padding=padding,
            groups=num_groups,
            act=None,
            use_cudnn=use_cudnn,
            param_attr=ParamAttr(
                initializer=MSRA(), name=self.full_name() + "_weights"),
            bias_attr=False)

        self._batch_norm = BatchNorm(
            num_filters,
            act=act,
C
chajchaj 已提交
63 64 65 66
            param_attr=ParamAttr(name=self.full_name() + "_bn" + "_scale"),
            bias_attr=ParamAttr(name=self.full_name() + "_bn" + "_offset"),
            moving_mean_name=self.full_name() + "_bn" + '_mean',
            moving_variance_name=self.full_name() + "_bn" + '_variance')
67 68 69 70 71 72 73 74 75

    def forward(self, inputs):
        y = self._conv(inputs)
        y = self._batch_norm(y)
        return y


class DepthwiseSeparable(fluid.dygraph.Layer):
    def __init__(self,
C
chajchaj 已提交
76
                 num_channels,
77 78 79 80 81 82
                 num_filters1,
                 num_filters2,
                 num_groups,
                 stride,
                 scale,
                 name=None):
C
chajchaj 已提交
83
        super(DepthwiseSeparable, self).__init__()
84 85

        self._depthwise_conv = ConvBNLayer(
C
chajchaj 已提交
86
            num_channels=num_channels,
87 88 89 90 91 92 93 94
            num_filters=int(num_filters1 * scale),
            filter_size=3,
            stride=stride,
            padding=1,
            num_groups=int(num_groups * scale),
            use_cudnn=False)

        self._pointwise_conv = ConvBNLayer(
C
chajchaj 已提交
95
            num_channels=int(num_filters1 * scale),
96 97 98 99 100 101 102 103 104 105 106 107
            filter_size=1,
            num_filters=int(num_filters2 * scale),
            stride=1,
            padding=0)

    def forward(self, inputs):
        y = self._depthwise_conv(inputs)
        y = self._pointwise_conv(y)
        return y


class MobileNetV1(fluid.dygraph.Layer):
C
chajchaj 已提交
108 109
    def __init__(self, scale=1.0, class_dim=1000):
        super(MobileNetV1, self).__init__()
110 111 112 113
        self.scale = scale
        self.dwsl = []

        self.conv1 = ConvBNLayer(
C
chajchaj 已提交
114
            num_channels=3,
115 116 117 118 119 120 121 122
            filter_size=3,
            channels=3,
            num_filters=int(32 * scale),
            stride=2,
            padding=1)

        dws21 = self.add_sublayer(
            sublayer=DepthwiseSeparable(
C
chajchaj 已提交
123
                num_channels=int(32 * scale),
124 125 126 127 128 129 130 131 132 133
                num_filters1=32,
                num_filters2=64,
                num_groups=32,
                stride=1,
                scale=scale),
            name="conv2_1")
        self.dwsl.append(dws21)

        dws22 = self.add_sublayer(
            sublayer=DepthwiseSeparable(
C
chajchaj 已提交
134
                num_channels=int(64 * scale),
135 136 137 138 139 140 141 142 143 144
                num_filters1=64,
                num_filters2=128,
                num_groups=64,
                stride=2,
                scale=scale),
            name="conv2_2")
        self.dwsl.append(dws22)

        dws31 = self.add_sublayer(
            sublayer=DepthwiseSeparable(
C
chajchaj 已提交
145
                num_channels=int(128 * scale),
146 147 148 149 150 151 152 153 154 155
                num_filters1=128,
                num_filters2=128,
                num_groups=128,
                stride=1,
                scale=scale),
            name="conv3_1")
        self.dwsl.append(dws31)

        dws32 = self.add_sublayer(
            sublayer=DepthwiseSeparable(
C
chajchaj 已提交
156
                num_channels=int(128 * scale),
157 158 159 160 161 162 163 164 165 166
                num_filters1=128,
                num_filters2=256,
                num_groups=128,
                stride=2,
                scale=scale),
            name="conv3_2")
        self.dwsl.append(dws32)

        dws41 = self.add_sublayer(
            sublayer=DepthwiseSeparable(
C
chajchaj 已提交
167
                num_channels=int(256 * scale),
168 169 170 171 172 173 174 175 176 177
                num_filters1=256,
                num_filters2=256,
                num_groups=256,
                stride=1,
                scale=scale),
            name="conv4_1")
        self.dwsl.append(dws41)

        dws42 = self.add_sublayer(
            sublayer=DepthwiseSeparable(
C
chajchaj 已提交
178
                num_channels=int(256 * scale),
179 180 181 182 183 184 185 186 187 188 189
                num_filters1=256,
                num_filters2=512,
                num_groups=256,
                stride=2,
                scale=scale),
            name="conv4_2")
        self.dwsl.append(dws42)

        for i in range(5):
            tmp = self.add_sublayer(
                sublayer=DepthwiseSeparable(
C
chajchaj 已提交
190
                    num_channels=int(512 * scale),
191 192 193 194 195 196 197 198 199 200
                    num_filters1=512,
                    num_filters2=512,
                    num_groups=512,
                    stride=1,
                    scale=scale),
                name="conv5_" + str(i + 1))
            self.dwsl.append(tmp)

        dws56 = self.add_sublayer(
            sublayer=DepthwiseSeparable(
C
chajchaj 已提交
201
                num_channels=int(512 * scale),
202 203 204 205 206 207 208 209 210 211
                num_filters1=512,
                num_filters2=1024,
                num_groups=512,
                stride=2,
                scale=scale),
            name="conv5_6")
        self.dwsl.append(dws56)

        dws6 = self.add_sublayer(
            sublayer=DepthwiseSeparable(
C
chajchaj 已提交
212
                num_channels=int(1024 * scale),
213 214 215 216 217 218 219 220
                num_filters1=1024,
                num_filters2=1024,
                num_groups=1024,
                stride=1,
                scale=scale),
            name="conv6")
        self.dwsl.append(dws6)

C
chajchaj 已提交
221
        self.pool2d_avg = Pool2D(pool_type='avg', global_pooling=True)
222

C
chajchaj 已提交
223 224 225 226 227 228
        self.out = Linear(
            int(1024 * scale),
            class_dim,
            param_attr=ParamAttr(
                initializer=MSRA(), name=self.full_name() + "fc7_weights"),
            bias_attr=ParamAttr(name="fc7_offset"))
229 230 231 232 233 234

    def forward(self, inputs):
        y = self.conv1(inputs)
        for dws in self.dwsl:
            y = dws(y)
        y = self.pool2d_avg(y)
C
chajchaj 已提交
235
        y = fluid.layers.reshape(y, shape=[-1, 1024])
236 237
        y = self.out(y)
        return y