未验证 提交 ed1cb0ce 编写于 作者: R ruri 提交者: GitHub

Fix shufflenet v2 bug (#3855)

* fix shufflenet v2 bug
上级 e95aee9c
...@@ -20,15 +20,19 @@ import paddle.fluid as fluid ...@@ -20,15 +20,19 @@ import paddle.fluid as fluid
from paddle.fluid.initializer import MSRA from paddle.fluid.initializer import MSRA
from paddle.fluid.param_attr import ParamAttr from paddle.fluid.param_attr import ParamAttr
__all__ = ['MobileNetV3','MobileNetV3_small_x0_25', 'MobileNetV3_small_x0_5', 'MobileNetV3_small_x0_75', __all__ = [
'MobileNetV3_small_x1_0', 'MobileNetV3_small_x1_25', 'MobileNetV3_large_x0_25', 'MobileNetV3_large_x0_5', 'MobileNetV3', 'MobileNetV3_small_x0_25', 'MobileNetV3_small_x0_5',
'MobileNetV3_large_x0_75', 'MobileNetV3_large_x1_0', 'MobileNetV3_large_x1_25'] 'MobileNetV3_small_x0_75', 'MobileNetV3_small_x1_0',
'MobileNetV3_small_x1_25', 'MobileNetV3_large_x0_25',
'MobileNetV3_large_x0_5', 'MobileNetV3_large_x0_75',
'MobileNetV3_large_x1_0', 'MobileNetV3_large_x1_25'
]
class MobileNetV3(): class MobileNetV3():
def __init__(self, scale=1.0, model_name='small'): def __init__(self, scale=1.0, model_name='small'):
self.scale = scale self.scale = scale
self.inplanes=16 self.inplanes = 16
if model_name == "large": if model_name == "large":
self.cfg = [ self.cfg = [
# k, exp, c, se, nl, s, # k, exp, c, se, nl, s,
...@@ -47,7 +51,7 @@ class MobileNetV3(): ...@@ -47,7 +51,7 @@ class MobileNetV3():
[5, 672, 160, True, 'hard_swish', 2], [5, 672, 160, True, 'hard_swish', 2],
[5, 960, 160, True, 'hard_swish', 1], [5, 960, 160, True, 'hard_swish', 1],
[5, 960, 160, True, 'hard_swish', 1], [5, 960, 160, True, 'hard_swish', 1],
] ]
self.cls_ch_squeeze = 960 self.cls_ch_squeeze = 960
self.cls_ch_expand = 1280 self.cls_ch_expand = 1280
elif model_name == "small": elif model_name == "small":
...@@ -64,11 +68,12 @@ class MobileNetV3(): ...@@ -64,11 +68,12 @@ class MobileNetV3():
[5, 288, 96, True, 'hard_swish', 2], [5, 288, 96, True, 'hard_swish', 2],
[5, 576, 96, True, 'hard_swish', 1], [5, 576, 96, True, 'hard_swish', 1],
[5, 576, 96, True, 'hard_swish', 1], [5, 576, 96, True, 'hard_swish', 1],
] ]
self.cls_ch_squeeze = 576 self.cls_ch_squeeze = 576
self.cls_ch_expand = 1280 self.cls_ch_expand = 1280
else: else:
raise NotImplementedError raise NotImplementedError("mode[" + model_name +
"_model] is not implemented!")
def net(self, input, class_dim=1000): def net(self, input, class_dim=1000):
scale = self.scale scale = self.scale
...@@ -76,41 +81,45 @@ class MobileNetV3(): ...@@ -76,41 +81,45 @@ class MobileNetV3():
cfg = self.cfg cfg = self.cfg
cls_ch_squeeze = self.cls_ch_squeeze cls_ch_squeeze = self.cls_ch_squeeze
cls_ch_expand = self.cls_ch_expand cls_ch_expand = self.cls_ch_expand
#conv1 #conv1
conv = self.conv_bn_layer(input, conv = self.conv_bn_layer(
filter_size=3, input,
num_filters=int(scale*inplanes), filter_size=3,
stride=2, num_filters=int(scale * inplanes),
padding=1, stride=2,
num_groups=1, padding=1,
if_act=True, num_groups=1,
act='hard_swish', if_act=True,
name='conv1') act='hard_swish',
name='conv1')
i = 0 i = 0
for layer_cfg in cfg: for layer_cfg in cfg:
conv = self.residual_unit(input=conv, conv = self.residual_unit(
num_in_filter=inplanes, input=conv,
num_mid_filter=int(scale*layer_cfg[1]), num_in_filter=inplanes,
num_out_filter=int(scale*layer_cfg[2]), num_mid_filter=int(scale * layer_cfg[1]),
act=layer_cfg[4], num_out_filter=int(scale * layer_cfg[2]),
stride=layer_cfg[5], act=layer_cfg[4],
filter_size=layer_cfg[0], stride=layer_cfg[5],
use_se=layer_cfg[3], filter_size=layer_cfg[0],
name='conv' + str(i+2)) use_se=layer_cfg[3],
inplanes = int(scale*layer_cfg[2]) name='conv' + str(i + 2))
inplanes = int(scale * layer_cfg[2])
i += 1 i += 1
conv = self.conv_bn_layer(input=conv, conv = self.conv_bn_layer(
filter_size=1, input=conv,
num_filters=int(scale*cls_ch_squeeze), filter_size=1,
stride=1, num_filters=int(scale * cls_ch_squeeze),
padding=0, stride=1,
num_groups=1, padding=0,
if_act=True, num_groups=1,
act='hard_swish', if_act=True,
name='conv_last') act='hard_swish',
conv = fluid.layers.pool2d(input=conv, pool_type='avg', global_pooling=True, use_cudnn=False) name='conv_last')
conv = fluid.layers.pool2d(
input=conv, pool_type='avg', global_pooling=True, use_cudnn=False)
conv = fluid.layers.conv2d( conv = fluid.layers.conv2d(
input=conv, input=conv,
num_filters=cls_ch_expand, num_filters=cls_ch_expand,
...@@ -127,21 +136,18 @@ class MobileNetV3(): ...@@ -127,21 +136,18 @@ class MobileNetV3():
param_attr=ParamAttr(name='fc_weights'), param_attr=ParamAttr(name='fc_weights'),
bias_attr=ParamAttr(name='fc_offset')) bias_attr=ParamAttr(name='fc_offset'))
return out return out
def conv_bn_layer(self, def conv_bn_layer(self,
input, input,
filter_size, filter_size,
num_filters, num_filters,
stride, stride,
padding, padding,
num_groups=1, num_groups=1,
if_act=True, if_act=True,
act=None, act=None,
name=None, name=None,
use_cudnn=True): use_cudnn=True):
conv = fluid.layers.conv2d( conv = fluid.layers.conv2d(
input=input, input=input,
num_filters=num_filters, num_filters=num_filters,
...@@ -151,73 +157,93 @@ class MobileNetV3(): ...@@ -151,73 +157,93 @@ class MobileNetV3():
groups=num_groups, groups=num_groups,
act=None, act=None,
use_cudnn=use_cudnn, use_cudnn=use_cudnn,
param_attr=ParamAttr(name=name+'_weights'), param_attr=ParamAttr(name=name + '_weights'),
bias_attr=False) bias_attr=False)
bn_name = name + '_bn' bn_name = name + '_bn'
bn = fluid.layers.batch_norm(input=conv, bn = fluid.layers.batch_norm(
param_attr = ParamAttr(name=bn_name+"_scale"), input=conv,
bias_attr=ParamAttr(name=bn_name+"_offset"), param_attr=ParamAttr(name=bn_name + "_scale"),
moving_mean_name=bn_name + '_mean', bias_attr=ParamAttr(name=bn_name + "_offset"),
moving_variance_name=bn_name + '_variance') moving_mean_name=bn_name + '_mean',
moving_variance_name=bn_name + '_variance')
if if_act: if if_act:
if act == 'relu': if act == 'relu':
bn = fluid.layers.relu(bn) bn = fluid.layers.relu(bn)
elif act == 'hard_swish': elif act == 'hard_swish':
bn = self.hard_swish(bn) bn = self.hard_swish(bn)
return bn return bn
def hard_swish(self, x): def hard_swish(self, x):
return x * fluid.layers.relu6(x+3) / 6. return x * fluid.layers.relu6(x + 3) / 6.
def se_block(self, input, num_out_filter, ratio=4, name=None): def se_block(self, input, num_out_filter, ratio=4, name=None):
num_mid_filter = int(num_out_filter // ratio) num_mid_filter = int(num_out_filter // ratio)
pool = fluid.layers.pool2d( pool = fluid.layers.pool2d(
input=input, pool_type='avg', global_pooling=True, use_cudnn=False) 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', conv1 = fluid.layers.conv2d(
param_attr=ParamAttr(name=name+'_1_weights'), input=pool,
bias_attr=ParamAttr(name=name+'_1_offset')) filter_size=1,
conv2 = fluid.layers.conv2d(input=conv1, filter_size=1, num_filters=num_out_filter, act='hard_sigmoid', num_filters=num_mid_filter,
param_attr=ParamAttr(name=name+'_2_weights'), act='relu',
bias_attr=ParamAttr(name=name+'_2_offset')) 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) scale = fluid.layers.elementwise_mul(x=input, y=conv2, axis=0)
return scale return scale
def residual_unit(self, input, num_in_filter, num_mid_filter, num_out_filter, stride, def residual_unit(self,
filter_size, act=None, use_se=False, name=None): input,
num_in_filter,
num_mid_filter,
num_out_filter,
stride,
filter_size,
act=None,
use_se=False,
name=None):
first_conv = (num_out_filter != num_mid_filter) first_conv = (num_out_filter != num_mid_filter)
input_data=input input_data = input
if first_conv: if first_conv:
input = self.conv_bn_layer(input=input, input = self.conv_bn_layer(
filter_size=1, input=input,
num_filters=num_mid_filter, filter_size=1,
stride=1, num_filters=num_mid_filter,
padding=0, stride=1,
if_act=True, padding=0,
act=act, if_act=True,
name=name + '_expand') act=act,
name=name + '_expand')
conv1 = self.conv_bn_layer(input=input,
filter_size=filter_size, conv1 = self.conv_bn_layer(
num_filters=num_mid_filter, input=input,
stride=stride, filter_size=filter_size,
padding=int((filter_size-1)//2), num_filters=num_mid_filter,
if_act=True, stride=stride,
act=act, padding=int((filter_size - 1) // 2),
num_groups=num_mid_filter, if_act=True,
use_cudnn=True, act=act,
name=name + '_depthwise') num_groups=num_mid_filter,
use_cudnn=True,
name=name + '_depthwise')
if use_se: if use_se:
conv1 = self.se_block(input=conv1, num_out_filter=num_mid_filter, name=name+'_se') conv1 = self.se_block(
input=conv1, num_out_filter=num_mid_filter, name=name + '_se')
conv2 = self.conv_bn_layer(input=conv1, conv2 = self.conv_bn_layer(
filter_size=1, input=conv1,
num_filters=num_out_filter, filter_size=1,
stride=1, num_filters=num_out_filter,
padding=0, stride=1,
if_act=False, padding=0,
name=name + '_linear') if_act=False,
name=name + '_linear')
if num_in_filter != num_out_filter or stride != 1: if num_in_filter != num_out_filter or stride != 1:
return conv2 return conv2
else: else:
...@@ -225,41 +251,50 @@ class MobileNetV3(): ...@@ -225,41 +251,50 @@ class MobileNetV3():
def MobileNetV3_small_x0_25(): def MobileNetV3_small_x0_25():
model=MobileNetV3(model_name='small', scale=0.25) model = MobileNetV3(model_name='small', scale=0.25)
return model return model
def MobileNetV3_small_x0_5(): def MobileNetV3_small_x0_5():
model=MobileNetV3(model_name='small', scale=0.5) model = MobileNetV3(model_name='small', scale=0.5)
return model return model
def MobileNetV3_small_x0_75(): def MobileNetV3_small_x0_75():
model=MobileNetV3(model_name='small', scale=0.75) model = MobileNetV3(model_name='small', scale=0.75)
return model return model
def MobileNetV3_small_x1_0(): def MobileNetV3_small_x1_0():
model=MobileNetV3(model_name='small', scale=1.0) model = MobileNetV3(model_name='small', scale=1.0)
return model return model
def MobileNetV3_small_x1_25(): def MobileNetV3_small_x1_25():
model=MobileNetV3(model_name='small', scale=1.25) model = MobileNetV3(model_name='small', scale=1.25)
return model return model
def MobileNetV3_large_x0_25(): def MobileNetV3_large_x0_25():
model=MobileNetV3(model_name='large', scale=0.25) model = MobileNetV3(model_name='large', scale=0.25)
return model return model
def MobileNetV3_large_x0_5(): def MobileNetV3_large_x0_5():
model=MobileNetV3(model_name='large', scale=0.5) model = MobileNetV3(model_name='large', scale=0.5)
return model return model
def MobileNetV3_large_x0_75(): def MobileNetV3_large_x0_75():
model=MobileNetV3(model_name='large', scale=0.75) model = MobileNetV3(model_name='large', scale=0.75)
return model return model
def MobileNetV3_large_x1_0(): def MobileNetV3_large_x1_0():
model=MobileNetV3(model_name='large', scale=1.0) model = MobileNetV3(model_name='large', scale=1.0)
return model return model
def MobileNetV3_large_x1_25(): def MobileNetV3_large_x1_25():
model=MobileNetV3(model_name='large', scale=1.25) model = MobileNetV3(model_name='large', scale=1.25)
return model return model
...@@ -50,9 +50,8 @@ class ShuffleNetV2(): ...@@ -50,9 +50,8 @@ class ShuffleNetV2():
elif scale == 2.0: elif scale == 2.0:
stage_out_channels = [-1, 24, 224, 488, 976, 2048] stage_out_channels = [-1, 24, 224, 488, 976, 2048]
else: else:
raise ValueError("""{} groups is not supported for raise NotImplementedError("This scale size:[" + str(scale) +
1x1 Grouped Convolutions""".format(num_groups)) "] is not implemented!")
#conv1 #conv1
input_channel = stage_out_channels[1] input_channel = stage_out_channels[1]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册