未验证 提交 a7eb5e5b 编写于 作者: T Teng Xi 提交者: GitHub

add SlimMobileNet models (#320)

* add SlimMobileNet models

* add SlimMobileNet model
上级 b5871048
...@@ -15,5 +15,5 @@ ...@@ -15,5 +15,5 @@
from __future__ import absolute_import from __future__ import absolute_import
from .util import image_classification from .util import image_classification
from .slimfacenet import SlimFaceNet_A_x0_60, SlimFaceNet_B_x0_75, SlimFaceNet_C_x0_75 from .slimfacenet import SlimFaceNet_A_x0_60, SlimFaceNet_B_x0_75, SlimFaceNet_C_x0_75
from .slim_mobilenet import SlimMobileNet_v1, SlimMobileNet_v2, SlimMobileNet_v3, SlimMobileNet_v4, SlimMobileNet_v5
__all__ = ["image_classification"] __all__ = ["image_classification"]
#copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve.
#
#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.
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import paddle.fluid as fluid
from paddle.fluid.initializer import MSRA
from paddle.fluid.param_attr import ParamAttr
__all__ = [
'SlimMobileNet_v1', 'SlimMobileNet_v2', 'SlimMobileNet_v3',
'SlimMobileNet_v4', 'SlimMobileNet_v5'
]
class SlimMobileNet():
def __init__(self, scale=1.0, model_name='large', token=[]):
assert len(token) >= 45
self.kernel_size_lis = token[:20]
self.exp_lis = token[20:40]
self.depth_lis = token[40:45]
self.scale = scale
self.inplanes = 16
if model_name == "large":
self.cfg_channel = [16, 24, 40, 80, 112, 160]
self.cfg_stride = [1, 2, 2, 2, 1, 2]
self.cfg_se = [False, False, True, False, True, True]
self.cfg_act = [
'relu', 'relu', 'relu', 'hard_swish', 'hard_swish',
'hard_swish'
]
self.cls_ch_squeeze = 960
self.cls_ch_expand = 1280
else:
raise NotImplementedError("mode[" + model_name +
"_model] is not implemented!")
def net(self, input, class_dim=1000):
scale = self.scale
inplanes = self.inplanes
kernel_size_lis = self.kernel_size_lis
exp_lis = self.exp_lis
depth_lis = self.depth_lis
cfg_channel = self.cfg_channel
cfg_stride = self.cfg_stride
cfg_se = self.cfg_se
cfg_act = self.cfg_act
cls_ch_squeeze = self.cls_ch_squeeze
cls_ch_expand = self.cls_ch_expand
#conv1
conv = self.conv_bn_layer(
input,
filter_size=3,
num_filters=self.make_divisible(inplanes * scale),
stride=2,
padding=1,
num_groups=1,
if_act=True,
act='hard_swish',
name='conv1')
inplanes = self.make_divisible(inplanes * scale)
#conv2
num_mid_filter = self.make_divisible(scale * inplanes)
_num_out_filter = cfg_channel[0]
num_out_filter = self.make_divisible(scale * _num_out_filter)
conv = self.residual_unit(
input=conv,
num_in_filter=inplanes,
num_mid_filter=num_mid_filter,
num_out_filter=num_out_filter,
act=cfg_act[0],
stride=cfg_stride[0],
filter_size=3,
use_se=cfg_se[0],
name='conv2',
short=True)
inplanes = self.make_divisible(scale * cfg_channel[0])
i = 3
for depth_id in range(len(depth_lis)):
for repeat_time in range(depth_lis[depth_id]):
num_mid_filter = self.make_divisible(
scale * _num_out_filter *
exp_lis[depth_id * 4 + repeat_time])
_num_out_filter = cfg_channel[depth_id + 1]
num_out_filter = self.make_divisible(scale * _num_out_filter)
stride = cfg_stride[depth_id + 1] if repeat_time == 0 else 1
conv = self.residual_unit(
input=conv,
num_in_filter=inplanes,
num_mid_filter=num_mid_filter,
num_out_filter=num_out_filter,
act=cfg_act[depth_id + 1],
stride=stride,
filter_size=kernel_size_lis[depth_id * 4 + repeat_time],
use_se=cfg_se[depth_id + 1],
name='conv' + str(i))
inplanes = self.make_divisible(scale *
cfg_channel[depth_id + 1])
i += 1
conv = self.conv_bn_layer(
input=conv,
filter_size=1,
num_filters=self.make_divisible(scale * cls_ch_squeeze),
stride=1,
padding=0,
num_groups=1,
if_act=True,
act='hard_swish',
name='conv_last')
conv = fluid.layers.pool2d(
input=conv, pool_type='avg', global_pooling=True, use_cudnn=False)
conv = fluid.layers.conv2d(
input=conv,
num_filters=cls_ch_expand,
filter_size=1,
stride=1,
padding=0,
act=None,
param_attr=ParamAttr(name='last_1x1_conv_weights'),
bias_attr=False)
conv = fluid.layers.hard_swish(conv)
drop = fluid.layers.dropout(x=conv, dropout_prob=0.2)
out = fluid.layers.fc(input=drop,
size=class_dim,
param_attr=ParamAttr(name='fc_weights'),
bias_attr=ParamAttr(name='fc_offset'))
return out
def conv_bn_layer(self,
input,
filter_size,
num_filters,
stride,
padding,
num_groups=1,
if_act=True,
act=None,
name=None,
use_cudnn=True,
res_last_bn_init=False):
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=ParamAttr(name=name + '_weights'),
bias_attr=False)
bn_name = name + '_bn'
bn = fluid.layers.batch_norm(
input=conv,
param_attr=ParamAttr(
name=bn_name + "_scale",
regularizer=fluid.regularizer.L2DecayRegularizer(
regularization_coeff=0.0)),
bias_attr=ParamAttr(
name=bn_name + "_offset",
regularizer=fluid.regularizer.L2DecayRegularizer(
regularization_coeff=0.0)),
moving_mean_name=bn_name + '_mean',
moving_variance_name=bn_name + '_variance')
if if_act:
if act == 'relu':
bn = fluid.layers.relu(bn)
elif act == 'hard_swish':
bn = fluid.layers.hard_swish(bn)
return bn
def make_divisible(self, v, divisor=8, min_value=None):
if min_value is None:
min_value = divisor
new_v = max(min_value, int(v + divisor / 2) // divisor * divisor)
if new_v < 0.9 * v:
new_v += divisor
return new_v
def se_block(self, input, num_out_filter, ratio=4, name=None):
num_mid_filter = num_out_filter // ratio
pool = fluid.layers.pool2d(
input=input, pool_type='avg', global_pooling=True, use_cudnn=False)
conv1 = fluid.layers.conv2d(
input=pool,
filter_size=1,
num_filters=num_mid_filter,
act='relu',
param_attr=ParamAttr(name=name + '_1_weights'),
bias_attr=ParamAttr(name=name + '_1_offset'))
conv2 = fluid.layers.conv2d(
input=conv1,
filter_size=1,
num_filters=num_out_filter,
act='hard_sigmoid',
param_attr=ParamAttr(name=name + '_2_weights'),
bias_attr=ParamAttr(name=name + '_2_offset'))
scale = fluid.layers.elementwise_mul(x=input, y=conv2, axis=0)
return scale
def residual_unit(self,
input,
num_in_filter,
num_mid_filter,
num_out_filter,
stride,
filter_size,
act=None,
use_se=False,
name=None,
short=False):
if not short:
conv0 = self.conv_bn_layer(
input=input,
filter_size=1,
num_filters=num_mid_filter,
stride=1,
padding=0,
if_act=True,
act=act,
name=name + '_expand')
else:
conv0 = input
conv1 = self.conv_bn_layer(
input=conv0,
filter_size=filter_size,
num_filters=num_mid_filter,
stride=stride,
padding=int((filter_size - 1) // 2),
if_act=True,
act=act,
num_groups=num_mid_filter,
use_cudnn=False,
name=name + '_depthwise')
if use_se:
conv1 = self.se_block(
input=conv1, num_out_filter=num_mid_filter, name=name + '_se')
conv2 = self.conv_bn_layer(
input=conv1,
filter_size=1,
num_filters=num_out_filter,
stride=1,
padding=0,
if_act=False,
name=name + '_linear',
res_last_bn_init=True)
if num_in_filter != num_out_filter or stride != 1:
return conv2
else:
return fluid.layers.elementwise_add(x=input, y=conv2, act=None)
def SlimMobileNet_v1(token):
token = [
5, 3, 3, 7, 3, 3, 5, 7, 3, 3, 3, 3, 3, 3, 7, 3, 5, 3, 3, 3, 3, 3, 3, 6,
3, 3, 3, 3, 4, 4, 4, 6, 4, 3, 4, 3, 6, 4, 3, 3, 2, 2, 2, 2, 4
]
model = SlimMobileNet(model_name='large', scale=1.0, token=token)
return model
def SlimMobileNet_v2(token):
token = [
5, 3, 5, 7, 3, 3, 7, 3, 5, 3, 3, 7, 3, 3, 3, 5, 5, 5, 3, 3, 3, 3, 4, 6,
3, 3, 6, 3, 4, 4, 3, 4, 4, 4, 3, 6, 6, 4, 3, 3, 2, 2, 3, 2, 4
]
model = SlimMobileNet(model_name='large', scale=1.0, token=token)
return model
def SlimMobileNet_v3(token):
token = [
3, 3, 3, 3, 5, 3, 7, 7, 7, 3, 3, 7, 5, 3, 5, 7, 5, 3, 3, 3, 3, 3, 3, 3,
3, 4, 3, 4, 3, 6, 4, 4, 4, 4, 6, 3, 6, 4, 6, 3, 2, 2, 3, 2, 4
]
model = SlimMobileNet(model_name='large', scale=1.0, token=token)
return model
def SlimMobileNet_v4(token):
token = [
3, 3, 3, 3, 5, 3, 3, 5, 7, 3, 5, 5, 5, 3, 3, 7, 3, 5, 3, 3, 3, 3, 4, 6,
3, 4, 4, 6, 4, 6, 4, 6, 4, 6, 4, 4, 6, 6, 6, 4, 2, 3, 3, 3, 4
]
model = SlimMobileNet(model_name='large', scale=1.0, token=token)
return model
def SlimMobileNet_v5(token):
token = [
7, 7, 3, 5, 7, 3, 5, 3, 7, 5, 3, 3, 5, 3, 7, 5, 7, 7, 5, 3, 3, 3, 6, 3,
4, 6, 3, 6, 6, 3, 6, 4, 6, 6, 4, 3, 6, 6, 6, 6, 4, 4, 4, 4, 4
]
model = SlimMobileNet(model_name='large', scale=1.0, token=token)
return model
if __name__ == "__main__":
pass
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册