提交 7f80e25c 编写于 作者: C cuicheng01

add mobilenet, resnet and senet series dymodels

上级 0e7bea51
...@@ -12,7 +12,19 @@ ...@@ -12,7 +12,19 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from .resnet_name import * from .resnet import ResNet18, ResNet34, ResNet50, ResNet101, ResNet152
from .resnet_vc import ResNet18_vc, ResNet34_vc, ResNet50_vc, ResNet101_vc, ResNet152_vc
from .resnet_vd import ResNet18_vd, ResNet34_vd, ResNet50_vd, ResNet101_vd, ResNet152_vd, ResNet200_vd
from .resnext import ResNeXt50_32x4d, ResNeXt50_64x4d, ResNeXt101_32x4d, ResNeXt101_64x4d, ResNeXt152_32x4d, ResNeXt152_64x4d
from .resnext_vd import ResNeXt50_vd_32x4d, ResNeXt50_vd_64x4d, ResNeXt101_vd_32x4d, ResNeXt101_vd_64x4d, ResNeXt152_vd_32x4d, ResNeXt152_vd_64x4d
from .res2net import Res2Net50_48w_2s, Res2Net50_26w_4s, Res2Net50_14w_8s, Res2Net50_48w_2s, Res2Net50_26w_6s, Res2Net50_26w_8s, Res2Net101_26w_4s, Res2Net152_26w_4s, Res2Net200_26w_4s
from .res2net_vd import Res2Net50_vd_48w_2s, Res2Net50_vd_26w_4s, Res2Net50_vd_14w_8s, Res2Net50_vd_48w_2s, Res2Net50_vd_26w_6s, Res2Net50_vd_26w_8s, Res2Net101_vd_26w_4s, Res2Net152_vd_26w_4s, Res2Net200_vd_26w_4s
from .se_resnet_vd import SE_ResNet18_vd, SE_ResNet34_vd, SE_ResNet50_vd, SE_ResNet101_vd, SE_ResNet152_vd, SE_ResNet200_vd
from .se_resnext_vd import SE_ResNeXt50_vd_32x4d, SE_ResNeXt50_vd_32x4d, SENet154_vd
from .dpn import DPN68 from .dpn import DPN68
from .densenet import DenseNet121 from .densenet import DenseNet121
from .hrnet import HRNet_W18_C from .hrnet import HRNet_W18_C
from .mobilenet_v1 import MobileNetV1_x0_25, MobileNetV1_x0_5, MobileNetV1_x0_75, MobileNetV1
from .mobilenet_v2 import MobileNetV2_x0_25, MobileNetV2_x0_5, MobileNetV2_x0_75, MobileNetV2, MobileNetV2_x1_5, MobileNetV2_x2_0
from .mobilenet_v3 import MobileNetV3_small_x0_35, MobileNetV3_small_x0_5, MobileNetV3_small_x0_75, MobileNetV3_small_x1_0, MobileNetV3_small_x1_25, MobileNetV3_large_x0_35, MobileNetV3_large_x0_5, MobileNetV3_large_x0_75, MobileNetV3_large_x1_0, MobileNetV3_large_x1_25
from .shufflenet_v2 import ShuffleNetV2_x0_25, ShuffleNetV2_x0_33, ShuffleNetV2_x0_5, ShuffleNetV2, ShuffleNetV2_x1_5, ShuffleNetV2_x2_0, ShuffleNetV2_swish
#copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. # copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve.
# #
#Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
#You may obtain a copy of the License at # You may obtain a copy of the License at
# #
# http://www.apache.org/licenses/LICENSE-2.0 # http://www.apache.org/licenses/LICENSE-2.0
# #
#Unless required by applicable law or agreed to in writing, software # Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS, # distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
#limitations under the License. # limitations under the License.
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import division from __future__ import division
from __future__ import print_function from __future__ import print_function
import numpy as np
import paddle
import paddle.fluid as fluid import paddle.fluid as fluid
from paddle.fluid.initializer import MSRA
from paddle.fluid.param_attr import ParamAttr from paddle.fluid.param_attr import ParamAttr
from paddle.fluid.layer_helper import LayerHelper
from paddle.fluid.dygraph.nn import Conv2D, Pool2D, BatchNorm, Linear, Dropout
from paddle.fluid.initializer import MSRA
import math
__all__ = [ __all__ = [
'MobileNetV1', 'MobileNetV1_x0_25', 'MobileNetV1_x0_5', 'MobileNetV1_x1_0', "MobileNetV1_x0_25", "MobileNetV1_x0_5", "MobileNetV1_x0_75", "MobileNetV1"
'MobileNetV1_x0_75'
] ]
class MobileNetV1(): class ConvBNLayer(fluid.dygraph.Layer):
def __init__(self, scale=1.0): def __init__(self,
num_channels,
filter_size,
num_filters,
stride,
padding,
channels=None,
num_groups=1,
act='relu',
use_cudnn=True,
name=None):
super(ConvBNLayer, self).__init__()
self._conv = Conv2D(
num_channels=num_channels,
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=name + "_weights"),
bias_attr=False)
self._batch_norm = BatchNorm(
num_filters,
act=act,
param_attr=ParamAttr(name + "_bn_scale"),
bias_attr=ParamAttr(name + "_bn_offset"),
moving_mean_name=name + "_bn_mean",
moving_variance_name=name + "_bn_variance")
def forward(self, inputs):
y = self._conv(inputs)
y = self._batch_norm(y)
return y
class DepthwiseSeparable(fluid.dygraph.Layer):
def __init__(self,
num_channels,
num_filters1,
num_filters2,
num_groups,
stride,
scale,
name=None):
super(DepthwiseSeparable, self).__init__()
self._depthwise_conv = ConvBNLayer(
num_channels=num_channels,
num_filters=int(num_filters1 * scale),
filter_size=3,
stride=stride,
padding=1,
num_groups=int(num_groups * scale),
use_cudnn=False,
name=name + "_dw")
self._pointwise_conv = ConvBNLayer(
num_channels=int(num_filters1 * scale),
filter_size=1,
num_filters=int(num_filters2 * scale),
stride=1,
padding=0,
name=name + "_sep")
def forward(self, inputs):
y = self._depthwise_conv(inputs)
y = self._pointwise_conv(y)
return y
class MobileNet(fluid.dygraph.Layer):
def __init__(self, scale=1.0, class_dim=1000):
super(MobileNet, self).__init__()
self.scale = scale self.scale = scale
self.block_list = []
def net(self, input, class_dim=1000): self.conv1 = ConvBNLayer(
scale = self.scale num_channels=3,
# conv1: 112x112
input = self.conv_bn_layer(
input,
filter_size=3, filter_size=3,
channels=3, channels=3,
num_filters=int(32 * scale), num_filters=int(32 * scale),
...@@ -42,177 +121,149 @@ class MobileNetV1(): ...@@ -42,177 +121,149 @@ class MobileNetV1():
padding=1, padding=1,
name="conv1") name="conv1")
# 56x56 conv2_1 = self.add_sublayer(
input = self.depthwise_separable( "conv2_1",
input, sublayer=DepthwiseSeparable(
num_channels=int(32 * scale),
num_filters1=32, num_filters1=32,
num_filters2=64, num_filters2=64,
num_groups=32, num_groups=32,
stride=1, stride=1,
scale=scale, scale=scale,
name="conv2_1") name="conv2_1"))
self.block_list.append(conv2_1)
input = self.depthwise_separable( conv2_2 = self.add_sublayer(
input, "conv2_2",
sublayer=DepthwiseSeparable(
num_channels=int(64 * scale),
num_filters1=64, num_filters1=64,
num_filters2=128, num_filters2=128,
num_groups=64, num_groups=64,
stride=2, stride=2,
scale=scale, scale=scale,
name="conv2_2") name="conv2_2"))
self.block_list.append(conv2_2)
# 28x28 conv3_1 = self.add_sublayer(
input = self.depthwise_separable( "conv3_1",
input, sublayer=DepthwiseSeparable(
num_channels=int(128 * scale),
num_filters1=128, num_filters1=128,
num_filters2=128, num_filters2=128,
num_groups=128, num_groups=128,
stride=1, stride=1,
scale=scale, scale=scale,
name="conv3_1") name="conv3_1"))
self.block_list.append(conv3_1)
input = self.depthwise_separable( conv3_2 = self.add_sublayer(
input, "conv3_2",
sublayer=DepthwiseSeparable(
num_channels=int(128 * scale),
num_filters1=128, num_filters1=128,
num_filters2=256, num_filters2=256,
num_groups=128, num_groups=128,
stride=2, stride=2,
scale=scale, scale=scale,
name="conv3_2") name="conv3_2"))
self.block_list.append(conv3_2)
# 14x14 conv4_1 = self.add_sublayer(
input = self.depthwise_separable( "conv4_1",
input, sublayer=DepthwiseSeparable(
num_channels=int(256 * scale),
num_filters1=256, num_filters1=256,
num_filters2=256, num_filters2=256,
num_groups=256, num_groups=256,
stride=1, stride=1,
scale=scale, scale=scale,
name="conv4_1") name="conv4_1"))
self.block_list.append(conv4_1)
input = self.depthwise_separable( conv4_2 = self.add_sublayer(
input, "conv4_2",
sublayer=DepthwiseSeparable(
num_channels=int(256 * scale),
num_filters1=256, num_filters1=256,
num_filters2=512, num_filters2=512,
num_groups=256, num_groups=256,
stride=2, stride=2,
scale=scale, scale=scale,
name="conv4_2") name="conv4_2"))
self.block_list.append(conv4_2)
# 14x14
for i in range(5): for i in range(5):
input = self.depthwise_separable( conv5 = self.add_sublayer(
input, "conv5_" + str(i + 1),
sublayer=DepthwiseSeparable(
num_channels=int(512 * scale),
num_filters1=512, num_filters1=512,
num_filters2=512, num_filters2=512,
num_groups=512, num_groups=512,
stride=1, stride=1,
scale=scale, scale=scale,
name="conv5" + "_" + str(i + 1)) name="conv5_" + str(i + 1)))
# 7x7 self.block_list.append(conv5)
input = self.depthwise_separable(
input, conv5_6 = self.add_sublayer(
"conv5_6",
sublayer=DepthwiseSeparable(
num_channels=int(512 * scale),
num_filters1=512, num_filters1=512,
num_filters2=1024, num_filters2=1024,
num_groups=512, num_groups=512,
stride=2, stride=2,
scale=scale, scale=scale,
name="conv5_6") name="conv5_6"))
self.block_list.append(conv5_6)
input = self.depthwise_separable( conv6 = self.add_sublayer(
input, "conv6",
sublayer=DepthwiseSeparable(
num_channels=int(1024 * scale),
num_filters1=1024, num_filters1=1024,
num_filters2=1024, num_filters2=1024,
num_groups=1024, num_groups=1024,
stride=1, stride=1,
scale=scale, scale=scale,
name="conv6") name="conv6"))
self.block_list.append(conv6)
input = fluid.layers.pool2d( self.pool2d_avg = Pool2D(pool_type='avg', global_pooling=True)
input=input, pool_type='avg', global_pooling=True)
output = fluid.layers.fc(input=input, self.out = Linear(
size=class_dim, int(1024 * scale),
class_dim,
param_attr=ParamAttr( param_attr=ParamAttr(
initializer=MSRA(), name="fc7_weights"), initializer=MSRA(), name="fc7_weights"),
bias_attr=ParamAttr(name="fc7_offset")) bias_attr=ParamAttr(name="fc7_offset"))
return output
def conv_bn_layer(self,
input,
filter_size,
num_filters,
stride,
padding,
channels=None,
num_groups=1,
act='relu',
use_cudnn=True,
name=None):
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(
initializer=MSRA(), name=name + "_weights"),
bias_attr=False)
bn_name = name + "_bn"
return fluid.layers.batch_norm(
input=conv,
act=act,
param_attr=ParamAttr(name=bn_name + "_scale"),
bias_attr=ParamAttr(name=bn_name + "_offset"),
moving_mean_name=bn_name + '_mean',
moving_variance_name=bn_name + '_variance')
def depthwise_separable(self, def forward(self, inputs):
input, y = self.conv1(inputs)
num_filters1, for block in self.block_list:
num_filters2, y = block(y)
num_groups, y = self.pool2d_avg(y)
stride, y = fluid.layers.reshape(y, shape=[-1, int(1024 * self.scale)])
scale, y = self.out(y)
name=None): return y
depthwise_conv = self.conv_bn_layer(
input=input,
filter_size=3,
num_filters=int(num_filters1 * scale),
stride=stride,
padding=1,
num_groups=int(num_groups * scale),
use_cudnn=False,
name=name + "_dw")
pointwise_conv = self.conv_bn_layer(
input=depthwise_conv,
filter_size=1,
num_filters=int(num_filters2 * scale),
stride=1,
padding=0,
name=name + "_sep")
return pointwise_conv
def MobileNetV1_x0_25(): def MobileNetV1_x0_25(**args):
model = MobileNetV1(scale=0.25) model = MobileNet(scale=0.25, **args)
return model return model
def MobileNetV1_x0_5(): def MobileNetV1_x0_5(**args):
model = MobileNetV1(scale=0.5) model = MobileNet(scale=0.5, **args)
return model return model
def MobileNetV1_x1_0(): def MobileNetV1_x0_75(**args):
model = MobileNetV1(scale=1.0) model = MobileNet(scale=0.75, **args)
return model return model
def MobileNetV1_x0_75(): def MobileNetV1(**args):
model = MobileNetV1(scale=0.75) model = MobileNet(scale=1.0, **args)
return model return model
#copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. # copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve.
# #
#Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
#You may obtain a copy of the License at # You may obtain a copy of the License at
# #
# http://www.apache.org/licenses/LICENSE-2.0 # http://www.apache.org/licenses/LICENSE-2.0
# #
#Unless required by applicable law or agreed to in writing, software # Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS, # distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
#limitations under the License. # limitations under the License.
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import division from __future__ import division
from __future__ import print_function from __future__ import print_function
import numpy as np
import paddle
import paddle.fluid as fluid import paddle.fluid as fluid
from paddle.fluid.initializer import MSRA
from paddle.fluid.param_attr import ParamAttr from paddle.fluid.param_attr import ParamAttr
from paddle.fluid.layer_helper import LayerHelper
from paddle.fluid.dygraph.nn import Conv2D, Pool2D, BatchNorm, Linear, Dropout
import math
__all__ = [ __all__ = [
'MobileNetV2_x0_25', 'MobileNetV2_x0_5' "MobileNetV2_x0_25", "MobileNetV2_x0_5", "MobileNetV2_x0_75",
'MobileNetV2_x0_75', 'MobileNetV2_x1_0', 'MobileNetV2_x1_5', "MobileNetV2", "MobileNetV2_x1_5", "MobileNetV2_x2_0"
'MobileNetV2_x2_0', 'MobileNetV2'
] ]
class MobileNetV2(): class ConvBNLayer(fluid.dygraph.Layer):
def __init__(self, scale=1.0): def __init__(self,
self.scale = scale num_channels,
def net(self, input, class_dim=1000):
scale = self.scale
bottleneck_params_list = [
(1, 16, 1, 1),
(6, 24, 2, 2),
(6, 32, 3, 2),
(6, 64, 4, 2),
(6, 96, 3, 1),
(6, 160, 3, 2),
(6, 320, 1, 1),
]
#conv1
input = self.conv_bn_layer(
input,
num_filters=int(32 * scale),
filter_size=3,
stride=2,
padding=1,
if_act=True,
name='conv1_1')
# bottleneck sequences
i = 1
in_c = int(32 * scale)
for layer_setting in bottleneck_params_list:
t, c, n, s = layer_setting
i += 1
input = self.invresi_blocks(
input=input,
in_c=in_c,
t=t,
c=int(c * scale),
n=n,
s=s,
name='conv' + str(i))
in_c = int(c * scale)
#last_conv
input = self.conv_bn_layer(
input=input,
num_filters=int(1280 * scale) if scale > 1.0 else 1280,
filter_size=1,
stride=1,
padding=0,
if_act=True,
name='conv9')
input = fluid.layers.pool2d(
input=input, pool_type='avg', global_pooling=True)
output = fluid.layers.fc(input=input,
size=class_dim,
param_attr=ParamAttr(name='fc10_weights'),
bias_attr=ParamAttr(name='fc10_offset'))
return output
def conv_bn_layer(self,
input,
filter_size, filter_size,
num_filters, num_filters,
stride, stride,
padding, padding,
channels=None, channels=None,
num_groups=1, num_groups=1,
if_act=True,
name=None, name=None,
use_cudnn=True): use_cudnn=True):
conv = fluid.layers.conv2d( super(ConvBNLayer, self).__init__()
input=input,
self._conv = Conv2D(
num_channels=num_channels,
num_filters=num_filters, num_filters=num_filters,
filter_size=filter_size, filter_size=filter_size,
stride=stride, stride=stride,
...@@ -106,125 +53,197 @@ class MobileNetV2(): ...@@ -106,125 +53,197 @@ class MobileNetV2():
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 = fluid.layers.batch_norm( self._batch_norm = BatchNorm(
input=conv, num_filters,
param_attr=ParamAttr(name=bn_name + "_scale"), param_attr=ParamAttr(name=name + "_bn_scale"),
bias_attr=ParamAttr(name=bn_name + "_offset"), bias_attr=ParamAttr(name=name + "_bn_offset"),
moving_mean_name=bn_name + '_mean', moving_mean_name=name + "_bn_mean",
moving_variance_name=bn_name + '_variance') moving_variance_name=name + "_bn_variance")
def forward(self, inputs, if_act=True):
y = self._conv(inputs)
y = self._batch_norm(y)
if if_act: if if_act:
return fluid.layers.relu6(bn) y = fluid.layers.relu6(y)
else: return y
return bn
def shortcut(self, input, data_residual):
return fluid.layers.elementwise_add(input, data_residual)
def inverted_residual_unit(self, class InvertedResidualUnit(fluid.dygraph.Layer):
input, def __init__(self, num_channels, num_in_filter, num_filters, stride,
num_in_filter, filter_size, padding, expansion_factor, name):
num_filters, super(InvertedResidualUnit, self).__init__()
ifshortcut,
stride,
filter_size,
padding,
expansion_factor,
name=None):
num_expfilter = int(round(num_in_filter * expansion_factor)) num_expfilter = int(round(num_in_filter * expansion_factor))
self._expand_conv = ConvBNLayer(
channel_expand = self.conv_bn_layer( num_channels=num_channels,
input=input,
num_filters=num_expfilter, num_filters=num_expfilter,
filter_size=1, filter_size=1,
stride=1, stride=1,
padding=0, padding=0,
num_groups=1, num_groups=1,
if_act=True, name=name + "_expand")
name=name + '_expand')
bottleneck_conv = self.conv_bn_layer( self._bottleneck_conv = ConvBNLayer(
input=channel_expand, num_channels=num_expfilter,
num_filters=num_expfilter, num_filters=num_expfilter,
filter_size=filter_size, filter_size=filter_size,
stride=stride, stride=stride,
padding=padding, padding=padding,
num_groups=num_expfilter, num_groups=num_expfilter,
if_act=True, use_cudnn=False,
name=name + '_dwise', name=name + "_dwise")
use_cudnn=False)
linear_out = self.conv_bn_layer( self._linear_conv = ConvBNLayer(
input=bottleneck_conv, num_channels=num_expfilter,
num_filters=num_filters, num_filters=num_filters,
filter_size=1, filter_size=1,
stride=1, stride=1,
padding=0, padding=0,
num_groups=1, num_groups=1,
if_act=False, name=name + "_linear")
name=name + '_linear')
def forward(self, inputs, ifshortcut):
y = self._expand_conv(inputs, if_act=True)
y = self._bottleneck_conv(y, if_act=True)
y = self._linear_conv(y, if_act=False)
if ifshortcut: if ifshortcut:
out = self.shortcut(input=input, data_residual=linear_out) y = fluid.layers.elementwise_add(inputs, y)
return out return y
else:
return linear_out
class InvresiBlocks(fluid.dygraph.Layer):
def invresi_blocks(self, input, in_c, t, c, n, s, name=None): def __init__(self, in_c, t, c, n, s, name):
first_block = self.inverted_residual_unit( super(InvresiBlocks, self).__init__()
input=input,
self._first_block = InvertedResidualUnit(
num_channels=in_c,
num_in_filter=in_c, num_in_filter=in_c,
num_filters=c, num_filters=c,
ifshortcut=False,
stride=s, stride=s,
filter_size=3, filter_size=3,
padding=1, padding=1,
expansion_factor=t, expansion_factor=t,
name=name + '_1') name=name + "_1")
last_residual_block = first_block
last_c = c
self._block_list = []
for i in range(1, n): for i in range(1, n):
last_residual_block = self.inverted_residual_unit( block = self.add_sublayer(
input=last_residual_block, name + "_" + str(i + 1),
num_in_filter=last_c, sublayer=InvertedResidualUnit(
num_channels=c,
num_in_filter=c,
num_filters=c, num_filters=c,
ifshortcut=True,
stride=1, stride=1,
filter_size=3, filter_size=3,
padding=1, padding=1,
expansion_factor=t, expansion_factor=t,
name=name + '_' + str(i + 1)) name=name + "_" + str(i + 1)))
return last_residual_block self._block_list.append(block)
def forward(self, inputs):
y = self._first_block(inputs, ifshortcut=False)
for block in self._block_list:
y = block(y, ifshortcut=True)
return y
class MobileNet(fluid.dygraph.Layer):
def __init__(self, class_dim=1000, scale=1.0):
super(MobileNet, self).__init__()
self.scale = scale
self.class_dim = class_dim
bottleneck_params_list = [
(1, 16, 1, 1),
(6, 24, 2, 2),
(6, 32, 3, 2),
(6, 64, 4, 2),
(6, 96, 3, 1),
(6, 160, 3, 2),
(6, 320, 1, 1),
]
self.conv1 = ConvBNLayer(
num_channels=3,
num_filters=int(32 * scale),
filter_size=3,
stride=2,
padding=1,
name="conv1_1")
self.block_list = []
i = 1
in_c = int(32 * scale)
for layer_setting in bottleneck_params_list:
t, c, n, s = layer_setting
i += 1
block = self.add_sublayer(
"conv" + str(i),
sublayer=InvresiBlocks(
in_c=in_c,
t=t,
c=int(c * scale),
n=n,
s=s,
name="conv" + str(i)))
self.block_list.append(block)
in_c = int(c * scale)
self.out_c = int(1280 * scale) if scale > 1.0 else 1280
self.conv9 = ConvBNLayer(
num_channels=in_c,
num_filters=self.out_c,
filter_size=1,
stride=1,
padding=0,
name="conv9")
self.pool2d_avg = Pool2D(pool_type="avg", global_pooling=True)
self.out = Linear(
self.out_c,
class_dim,
param_attr=ParamAttr(name="fc10_weights"),
bias_attr=ParamAttr(name="fc10_offset"))
def forward(self, inputs):
y = self.conv1(inputs, if_act=True)
for block in self.block_list:
y = block(y)
y = self.conv9(y, if_act=True)
y = self.pool2d_avg(y)
y = fluid.layers.reshape(y, shape=[-1, self.out_c])
y = self.out(y)
return y
def MobileNetV2_x0_25(): def MobileNetV2_x0_25(**args):
model = MobileNetV2(scale=0.25) model = MobileNet(scale=0.25, **args)
return model return model
def MobileNetV2_x0_5(): def MobileNetV2_x0_5(**args):
model = MobileNetV2(scale=0.5) model = MobileNet(scale=0.5, **args)
return model return model
def MobileNetV2_x0_75(): def MobileNetV2_x0_75(**args):
model = MobileNetV2(scale=0.75) model = MobileNet(scale=0.75, **args)
return model return model
def MobileNetV2_x1_0(): def MobileNetV2(**args):
model = MobileNetV2(scale=1.0) model = MobileNet(scale=1.0, **args)
return model return model
def MobileNetV2_x1_5(): def MobileNetV2_x1_5(**args):
model = MobileNetV2(scale=1.5) model = MobileNet(scale=1.5, **args)
return model return model
def MobileNetV2_x2_0(): def MobileNetV2_x2_0(**args):
model = MobileNetV2(scale=2.0) model = MobileNet(scale=2.0, **args)
return model return model
...@@ -16,320 +16,342 @@ from __future__ import absolute_import ...@@ -16,320 +16,342 @@ from __future__ import absolute_import
from __future__ import division from __future__ import division
from __future__ import print_function from __future__ import print_function
import numpy as np
import paddle
import paddle.fluid as fluid import paddle.fluid as fluid
from paddle.fluid.param_attr import ParamAttr from paddle.fluid.param_attr import ParamAttr
from paddle.fluid.layer_helper import LayerHelper
from paddle.fluid.dygraph.nn import Conv2D, Pool2D, BatchNorm, Linear, Dropout
import math
__all__ = [ __all__ = [
'MobileNetV3', 'MobileNetV3_small_x0_35', 'MobileNetV3_small_x0_5', "MobileNetV3_small_x0_35", "MobileNetV3_small_x0_5",
'MobileNetV3_small_x0_75', 'MobileNetV3_small_x1_0', "MobileNetV3_small_x0_75", "MobileNetV3_small_x1_0",
'MobileNetV3_small_x1_25', 'MobileNetV3_large_x0_35', "MobileNetV3_small_x1_25", "MobileNetV3_large_x0_35",
'MobileNetV3_large_x0_5', 'MobileNetV3_large_x0_75', "MobileNetV3_large_x0_5", "MobileNetV3_large_x0_75",
'MobileNetV3_large_x1_0', 'MobileNetV3_large_x1_25' "MobileNetV3_large_x1_0", "MobileNetV3_large_x1_25"
] ]
class MobileNetV3(): def make_divisible(v, divisor=8, min_value=None):
def __init__(self, if min_value is None:
scale=1.0, min_value = divisor
model_name='small', new_v = max(min_value, int(v + divisor / 2) // divisor * divisor)
lr_mult_list=[1.0, 1.0, 1.0, 1.0, 1.0]): if new_v < 0.9 * v:
self.scale = scale new_v += divisor
self.inplanes = 16 return new_v
self.lr_mult_list = lr_mult_list
assert len(self.lr_mult_list) == 5, \ class MobileNetV3(fluid.dygraph.Layer):
"lr_mult_list length in MobileNetV3 must be 5 but got {}!!".format( def __init__(self, scale=1.0, model_name="small", class_dim=1000):
len(self.lr_mult_list)) super(MobileNetV3, self).__init__()
self.curr_stage = 0
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,
[3, 16, 16, False, 'relu', 1], [3, 16, 16, False, "relu", 1],
[3, 64, 24, False, 'relu', 2], [3, 64, 24, False, "relu", 2],
[3, 72, 24, False, 'relu', 1], [3, 72, 24, False, "relu", 1],
[5, 72, 40, True, 'relu', 2], [5, 72, 40, True, "relu", 2],
[5, 120, 40, True, 'relu', 1], [5, 120, 40, True, "relu", 1],
[5, 120, 40, True, 'relu', 1], [5, 120, 40, True, "relu", 1],
[3, 240, 80, False, 'hard_swish', 2], [3, 240, 80, False, "hard_swish", 2],
[3, 200, 80, False, 'hard_swish', 1], [3, 200, 80, False, "hard_swish", 1],
[3, 184, 80, False, 'hard_swish', 1], [3, 184, 80, False, "hard_swish", 1],
[3, 184, 80, False, 'hard_swish', 1], [3, 184, 80, False, "hard_swish", 1],
[3, 480, 112, True, 'hard_swish', 1], [3, 480, 112, True, "hard_swish", 1],
[3, 672, 112, True, 'hard_swish', 1], [3, 672, 112, True, "hard_swish", 1],
[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
self.lr_interval = 3
elif model_name == "small": elif model_name == "small":
self.cfg = [ self.cfg = [
# k, exp, c, se, nl, s, # k, exp, c, se, nl, s,
[3, 16, 16, True, 'relu', 2], [3, 16, 16, True, "relu", 2],
[3, 72, 24, False, 'relu', 2], [3, 72, 24, False, "relu", 2],
[3, 88, 24, False, 'relu', 1], [3, 88, 24, False, "relu", 1],
[5, 96, 40, True, 'hard_swish', 2], [5, 96, 40, True, "hard_swish", 2],
[5, 240, 40, True, 'hard_swish', 1], [5, 240, 40, True, "hard_swish", 1],
[5, 240, 40, True, 'hard_swish', 1], [5, 240, 40, True, "hard_swish", 1],
[5, 120, 48, True, 'hard_swish', 1], [5, 120, 48, True, "hard_swish", 1],
[5, 144, 48, True, 'hard_swish', 1], [5, 144, 48, True, "hard_swish", 1],
[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
self.lr_interval = 2
else: else:
raise NotImplementedError( raise NotImplementedError(
"mode[{}_model] is not implemented!".format(model_name)) "mode[{}_model] is not implemented!".format(model_name))
def net(self, input, class_dim=1000): self.conv1 = ConvBNLayer(
scale = self.scale in_c=3,
inplanes = self.inplanes out_c=make_divisible(inplanes * scale),
cfg = self.cfg
cls_ch_squeeze = self.cls_ch_squeeze
cls_ch_expand = self.cls_ch_expand
# conv1
conv = self.conv_bn_layer(
input,
filter_size=3, filter_size=3,
num_filters=self.make_divisible(inplanes * scale),
stride=2, stride=2,
padding=1, padding=1,
num_groups=1, num_groups=1,
if_act=True, if_act=True,
act='hard_swish', act="hard_swish",
name='conv1') name="conv1")
self.block_list = []
i = 0 i = 0
inplanes = self.make_divisible(inplanes * scale) inplanes = make_divisible(inplanes * scale)
for layer_cfg in cfg: for (k, exp, c, se, nl, s) in self.cfg:
conv = self.residual_unit( self.block_list.append(
input=conv, ResidualUnit(
num_in_filter=inplanes, in_c=inplanes,
num_mid_filter=self.make_divisible(scale * layer_cfg[1]), mid_c=make_divisible(scale * exp),
num_out_filter=self.make_divisible(scale * layer_cfg[2]), out_c=make_divisible(scale * c),
act=layer_cfg[4], filter_size=k,
stride=layer_cfg[5], stride=s,
filter_size=layer_cfg[0], use_se=se,
use_se=layer_cfg[3], act=nl,
name='conv' + str(i + 2)) name="conv" + str(i + 2)))
inplanes = self.make_divisible(scale * layer_cfg[2]) self.add_sublayer(
sublayer=self.block_list[-1], name="conv" + str(i + 2))
inplanes = make_divisible(scale * c)
i += 1 i += 1
self.curr_stage = i
conv = self.conv_bn_layer( self.last_second_conv = ConvBNLayer(
input=conv, in_c=inplanes,
out_c=make_divisible(scale * self.cls_ch_squeeze),
filter_size=1, filter_size=1,
num_filters=self.make_divisible(scale * cls_ch_squeeze),
stride=1, stride=1,
padding=0, padding=0,
num_groups=1, num_groups=1,
if_act=True, if_act=True,
act='hard_swish', act="hard_swish",
name='conv_last') name="conv_last")
conv = fluid.layers.pool2d(
input=conv, pool_type='avg', global_pooling=True, use_cudnn=False) self.pool = Pool2D(
conv = fluid.layers.conv2d( pool_type="avg", global_pooling=True, use_cudnn=False)
input=conv,
num_filters=cls_ch_expand, self.last_conv = Conv2D(
num_channels=make_divisible(scale * self.cls_ch_squeeze),
num_filters=self.cls_ch_expand,
filter_size=1, filter_size=1,
stride=1, stride=1,
padding=0, padding=0,
act=None, act=None,
param_attr=ParamAttr(name='last_1x1_conv_weights'), param_attr=ParamAttr(name="last_1x1_conv_weights"),
bias_attr=False) bias_attr=False)
conv = fluid.layers.hard_swish(conv)
drop = fluid.layers.dropout(x=conv, dropout_prob=0.2) self.out = Linear(
out = fluid.layers.fc(input=drop, input_dim=self.cls_ch_expand,
size=class_dim, output_dim=class_dim,
param_attr=ParamAttr(name='fc_weights'), param_attr=ParamAttr("fc_weights"),
bias_attr=ParamAttr(name='fc_offset')) bias_attr=ParamAttr(name="fc_offset"))
return out
def forward(self, inputs, label=None, dropout_prob=0.2):
def conv_bn_layer(self, x = self.conv1(inputs)
input, for block in self.block_list:
x = block(x)
x = self.last_second_conv(x)
x = self.pool(x)
x = self.last_conv(x)
x = fluid.layers.hard_swish(x)
x = fluid.layers.dropout(x=x, dropout_prob=dropout_prob)
x = fluid.layers.reshape(x, shape=[x.shape[0], x.shape[1]])
x = self.out(x)
return x
class ConvBNLayer(fluid.dygraph.Layer):
def __init__(self,
in_c,
out_c,
filter_size, filter_size,
num_filters,
stride, stride,
padding, padding,
num_groups=1, num_groups=1,
if_act=True, if_act=True,
act=None, act=None,
name=None,
use_cudnn=True, use_cudnn=True,
res_last_bn_init=False): name=""):
lr_idx = self.curr_stage // self.lr_interval super(ConvBNLayer, self).__init__()
lr_idx = min(lr_idx, len(self.lr_mult_list) - 1) self.if_act = if_act
lr_mult = self.lr_mult_list[lr_idx] self.act = act
self.conv = fluid.dygraph.Conv2D(
conv = fluid.layers.conv2d( num_channels=in_c,
input=input, num_filters=out_c,
num_filters=num_filters,
filter_size=filter_size, filter_size=filter_size,
stride=stride, stride=stride,
padding=padding, padding=padding,
groups=num_groups, groups=num_groups,
act=None, param_attr=ParamAttr(name=name + "_weights"),
bias_attr=False,
use_cudnn=use_cudnn, use_cudnn=use_cudnn,
act=None)
self.bn = fluid.dygraph.BatchNorm(
num_channels=out_c,
act=None,
param_attr=ParamAttr( param_attr=ParamAttr(
name=name + '_weights', learning_rate=lr_mult), name=name + "_bn_scale",
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( regularizer=fluid.regularizer.L2DecayRegularizer(
regularization_coeff=0.0)), regularization_coeff=0.0)),
bias_attr=ParamAttr( bias_attr=ParamAttr(
name=bn_name + "_offset", name=name + "_bn_offset",
regularizer=fluid.regularizer.L2DecayRegularizer( regularizer=fluid.regularizer.L2DecayRegularizer(
regularization_coeff=0.0)), regularization_coeff=0.0)),
moving_mean_name=bn_name + '_mean', moving_mean_name=name + "_bn_mean",
moving_variance_name=bn_name + '_variance') moving_variance_name=name + "_bn_variance")
if if_act:
if act == 'relu': def forward(self, x):
bn = fluid.layers.relu(bn) x = self.conv(x)
elif act == 'hard_swish': x = self.bn(x)
bn = fluid.layers.hard_swish(bn) if self.if_act:
return bn if self.act == "relu":
x = fluid.layers.relu(x)
def make_divisible(self, v, divisor=8, min_value=None): elif self.act == "hard_swish":
if min_value is None: x = fluid.layers.hard_swish(x)
min_value = divisor else:
new_v = max(min_value, int(v + divisor / 2) // divisor * divisor) print("The activation function is selected incorrectly.")
if new_v < 0.9 * v: exit()
new_v += divisor return x
return new_v
def se_block(self, input, num_out_filter, ratio=4, name=None):
lr_idx = self.curr_stage // self.lr_interval
lr_idx = min(lr_idx, len(self.lr_mult_list) - 1)
lr_mult = self.lr_mult_list[lr_idx]
num_mid_filter = num_out_filter // ratio class ResidualUnit(fluid.dygraph.Layer):
pool = fluid.layers.pool2d( def __init__(self,
input=input, pool_type='avg', global_pooling=True, use_cudnn=False) in_c,
conv1 = fluid.layers.conv2d( mid_c,
input=pool, out_c,
filter_size=1,
num_filters=num_mid_filter,
act='relu',
param_attr=ParamAttr(
name=name + '_1_weights', learning_rate=lr_mult),
bias_attr=ParamAttr(
name=name + '_1_offset', learning_rate=lr_mult))
conv2 = fluid.layers.conv2d(
input=conv1,
filter_size=1,
num_filters=num_out_filter,
act='hard_sigmoid',
param_attr=ParamAttr(
name=name + '_2_weights', learning_rate=lr_mult),
bias_attr=ParamAttr(
name=name + '_2_offset', learning_rate=lr_mult))
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, filter_size,
stride,
use_se,
act=None, act=None,
use_se=False, name=''):
name=None): super(ResidualUnit, self).__init__()
self.if_shortcut = stride == 1 and in_c == out_c
conv0 = self.conv_bn_layer( self.if_se = use_se
input=input,
self.expand_conv = ConvBNLayer(
in_c=in_c,
out_c=mid_c,
filter_size=1, filter_size=1,
num_filters=num_mid_filter,
stride=1, stride=1,
padding=0, padding=0,
if_act=True, if_act=True,
act=act, act=act,
name=name + '_expand') name=name + "_expand")
self.bottleneck_conv = ConvBNLayer(
conv1 = self.conv_bn_layer( in_c=mid_c,
input=conv0, out_c=mid_c,
filter_size=filter_size, filter_size=filter_size,
num_filters=num_mid_filter,
stride=stride, stride=stride,
padding=int((filter_size - 1) // 2), padding=int((filter_size - 1) // 2),
num_groups=mid_c,
if_act=True, if_act=True,
act=act, act=act,
num_groups=num_mid_filter, name=name + "_depthwise")
use_cudnn=False, if self.if_se:
name=name + '_depthwise') self.mid_se = SEModule(mid_c, name=name + "_se")
if use_se: self.linear_conv = ConvBNLayer(
conv1 = self.se_block( in_c=mid_c,
input=conv1, num_out_filter=num_mid_filter, name=name + '_se') out_c=out_c,
conv2 = self.conv_bn_layer(
input=conv1,
filter_size=1, filter_size=1,
num_filters=num_out_filter,
stride=1, stride=1,
padding=0, padding=0,
if_act=False, if_act=False,
name=name + '_linear', act=None,
res_last_bn_init=True) name=name + "_linear")
if num_in_filter != num_out_filter or stride != 1:
return conv2 def forward(self, inputs):
else: x = self.expand_conv(inputs)
return fluid.layers.elementwise_add(x=input, y=conv2, act=None) x = self.bottleneck_conv(x)
if self.if_se:
x = self.mid_se(x)
x = self.linear_conv(x)
if self.if_shortcut:
x = fluid.layers.elementwise_add(inputs, x)
return x
class SEModule(fluid.dygraph.Layer):
def __init__(self, channel, reduction=4, name=""):
super(SEModule, self).__init__()
self.avg_pool = fluid.dygraph.Pool2D(
pool_type="avg", global_pooling=True, use_cudnn=False)
self.conv1 = fluid.dygraph.Conv2D(
num_channels=channel,
num_filters=channel // reduction,
filter_size=1,
stride=1,
padding=0,
act="relu",
param_attr=ParamAttr(name=name + "_1_weights"),
bias_attr=ParamAttr(name=name + "_1_offset"))
self.conv2 = fluid.dygraph.Conv2D(
num_channels=channel // reduction,
num_filters=channel,
filter_size=1,
stride=1,
padding=0,
act=None,
param_attr=ParamAttr(name + "_2_weights"),
bias_attr=ParamAttr(name=name + "_2_offset"))
def forward(self, inputs):
outputs = self.avg_pool(inputs)
outputs = self.conv1(outputs)
outputs = self.conv2(outputs)
outputs = fluid.layers.hard_sigmoid(outputs)
return fluid.layers.elementwise_mul(x=inputs, y=outputs, axis=0)
def MobileNetV3_small_x0_35(): def MobileNetV3_small_x0_35(**args):
model = MobileNetV3(model_name='small', scale=0.35) model = MobileNetV3(model_name="small", scale=0.35, **args)
return model return model
def MobileNetV3_small_x0_5(): def MobileNetV3_small_x0_5(**args):
model = MobileNetV3(model_name='small', scale=0.5) model = MobileNetV3(model_name="small", scale=0.5, **args)
return model return model
def MobileNetV3_small_x0_75(): def MobileNetV3_small_x0_75(**args):
model = MobileNetV3(model_name='small', scale=0.75) model = MobileNetV3(model_name="small", scale=0.75, **args)
return model return model
def MobileNetV3_small_x1_0(**args): def MobileNetV3_small_x1_0(**args):
model = MobileNetV3(model_name='small', scale=1.0, **args) model = MobileNetV3(model_name="small", scale=1.0, **args)
return model return model
def MobileNetV3_small_x1_25(): def MobileNetV3_small_x1_25(**args):
model = MobileNetV3(model_name='small', scale=1.25) model = MobileNetV3(model_name="small", scale=1.25, **args)
return model return model
def MobileNetV3_large_x0_35(): def MobileNetV3_large_x0_35(**args):
model = MobileNetV3(model_name='large', scale=0.35) model = MobileNetV3(model_name="large", scale=0.35, **args)
return model return model
def MobileNetV3_large_x0_5(): def MobileNetV3_large_x0_5(**args):
model = MobileNetV3(model_name='large', scale=0.5) model = MobileNetV3(model_name="large", scale=0.5, **args)
return model return model
def MobileNetV3_large_x0_75(): def MobileNetV3_large_x0_75(**args):
model = MobileNetV3(model_name='large', scale=0.75) model = MobileNetV3(model_name="large", scale=0.75, **args)
return model return model
def MobileNetV3_large_x1_0(**args): def MobileNetV3_large_x1_0(**args):
model = MobileNetV3(model_name='large', scale=1.0, **args) model = MobileNetV3(model_name="large", scale=1.0, **args)
return model return model
def MobileNetV3_large_x1_25(): def MobileNetV3_large_x1_25(**args):
model = MobileNetV3(model_name='large', scale=1.25) model = MobileNetV3(model_name="large", scale=1.25, **args)
return model return model
#copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. # copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve.
# #
#Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
#You may obtain a copy of the License at # You may obtain a copy of the License at
# #
# http://www.apache.org/licenses/LICENSE-2.0 # http://www.apache.org/licenses/LICENSE-2.0
# #
#Unless required by applicable law or agreed to in writing, software # Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS, # distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
#limitations under the License. # limitations under the License.
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import division from __future__ import division
from __future__ import print_function from __future__ import print_function
import numpy as np
import paddle import paddle
import paddle.fluid as fluid import paddle.fluid as fluid
import math
from paddle.fluid.param_attr import ParamAttr from paddle.fluid.param_attr import ParamAttr
from paddle.fluid.layer_helper import LayerHelper
from paddle.fluid.dygraph.nn import Conv2D, Pool2D, BatchNorm, Linear, Dropout
import math
__all__ = [ __all__ = [
"Res2Net", "Res2Net50_48w_2s", "Res2Net50_26w_4s", "Res2Net50_14w_8s", "Res2Net50_48w_2s", "Res2Net50_26w_4s", "Res2Net50_14w_8s",
"Res2Net50_26w_6s", "Res2Net50_26w_8s", "Res2Net101_26w_4s", "Res2Net50_48w_2s", "Res2Net50_26w_6s", "Res2Net50_26w_8s",
"Res2Net152_26w_4s" "Res2Net101_26w_4s", "Res2Net152_26w_4s", "Res2Net200_26w_4s"
] ]
class Res2Net(): class ConvBNLayer(fluid.dygraph.Layer):
def __init__(self, layers=50, scales=4, width=26): def __init__(
self.layers = layers self,
self.scales = scales num_channels,
self.width = width
def net(self, input, class_dim=1000):
layers = self.layers
supported_layers = [50, 101, 152]
assert layers in supported_layers, \
"supported layers are {} but input layer is {}".format(supported_layers, layers)
basic_width = self.width * self.scales
num_filters1 = [basic_width * t for t in [1, 2, 4, 8]]
num_filters2 = [256 * t for t in [1, 2, 4, 8]]
if layers == 50:
depth = [3, 4, 6, 3]
elif layers == 101:
depth = [3, 4, 23, 3]
elif layers == 152:
depth = [3, 8, 36, 3]
conv = self.conv_bn_layer(
input=input,
num_filters=64,
filter_size=7,
stride=2,
act='relu',
name="conv1")
conv = fluid.layers.pool2d(
input=conv,
pool_size=3,
pool_stride=2,
pool_padding=1,
pool_type='max')
for block in range(len(depth)):
for i in range(depth[block]):
if layers in [101, 152] and block == 2:
if i == 0:
conv_name = "res" + str(block + 2) + "a"
else:
conv_name = "res" + str(block + 2) + "b" + str(i)
else:
conv_name = "res" + str(block + 2) + chr(97 + i)
conv = self.bottleneck_block(
input=conv,
num_filters1=num_filters1[block],
num_filters2=num_filters2[block],
stride=2 if i == 0 and block != 0 else 1,
name=conv_name)
pool = fluid.layers.pool2d(
input=conv,
pool_size=7,
pool_stride=1,
pool_type='avg',
global_pooling=True)
stdv = 1.0 / math.sqrt(pool.shape[1] * 1.0)
out = fluid.layers.fc(
input=pool,
size=class_dim,
param_attr=fluid.param_attr.ParamAttr(
initializer=fluid.initializer.Uniform(-stdv, stdv),
name='fc_weights'),
bias_attr=fluid.param_attr.ParamAttr(name='fc_offset'))
return out
def conv_bn_layer(self,
input,
num_filters, num_filters,
filter_size, filter_size,
stride=1, stride=1,
groups=1, groups=1,
act=None, act=None,
name=None): name=None, ):
conv = fluid.layers.conv2d( super(ConvBNLayer, self).__init__()
input=input,
self._conv = Conv2D(
num_channels=num_channels,
num_filters=num_filters, num_filters=num_filters,
filter_size=filter_size, filter_size=filter_size,
stride=stride, stride=stride,
...@@ -114,112 +54,227 @@ class Res2Net(): ...@@ -114,112 +54,227 @@ class Res2Net():
act=None, act=None,
param_attr=ParamAttr(name=name + "_weights"), param_attr=ParamAttr(name=name + "_weights"),
bias_attr=False) bias_attr=False)
if name == "conv1": if name == "conv1":
bn_name = "bn_" + name bn_name = "bn_" + name
else: else:
bn_name = "bn" + name[3:] bn_name = "bn" + name[3:]
self._batch_norm = BatchNorm(
return fluid.layers.batch_norm( num_filters,
input=conv,
act=act, act=act,
param_attr=ParamAttr(name=bn_name + '_scale'), param_attr=ParamAttr(name=bn_name + '_scale'),
bias_attr=ParamAttr(bn_name + '_offset'), bias_attr=ParamAttr(bn_name + '_offset'),
moving_mean_name=bn_name + '_mean', moving_mean_name=bn_name + '_mean',
moving_variance_name=bn_name + '_variance') moving_variance_name=bn_name + '_variance')
def shortcut(self, input, ch_out, stride, name): def forward(self, inputs):
ch_in = input.shape[1] y = self._conv(inputs)
if ch_in != ch_out or stride != 1: y = self._batch_norm(y)
return self.conv_bn_layer(input, ch_out, 1, stride, name=name) return y
else:
return input
def bottleneck_block(self, input, num_filters1, num_filters2, stride, class BottleneckBlock(fluid.dygraph.Layer):
name): def __init__(self,
conv0 = self.conv_bn_layer( num_channels1,
input=input, num_channels2,
num_filters=num_filters1, num_filters,
stride,
scales,
shortcut=True,
if_first=False,
name=None):
super(BottleneckBlock, self).__init__()
self.stride = stride
self.scales = scales
self.conv0 = ConvBNLayer(
num_channels=num_channels1,
num_filters=num_filters,
filter_size=1, filter_size=1,
stride=1,
act='relu', act='relu',
name=name + '_branch2a') name=name + "_branch2a")
xs = fluid.layers.split(conv0, self.scales, 1) self.conv1_list = []
ys = [] for s in range(scales - 1):
for s in range(self.scales - 1): conv1 = self.add_sublayer(
if s == 0 or stride == 2: name + '_branch2b_' + str(s + 1),
ys.append( ConvBNLayer(
self.conv_bn_layer( num_channels=num_filters // scales,
input=xs[s], num_filters=num_filters // scales,
num_filters=num_filters1 // self.scales,
stride=stride,
filter_size=3, filter_size=3,
act='relu',
name=name + '_branch2b_' + str(s + 1)))
else:
ys.append(
self.conv_bn_layer(
input=xs[s] + ys[-1],
num_filters=num_filters1 // self.scales,
stride=stride, stride=stride,
filter_size=3,
act='relu', act='relu',
name=name + '_branch2b_' + str(s + 1))) name=name + '_branch2b_' + str(s + 1)))
if stride == 1: self.conv1_list.append(conv1)
ys.append(xs[-1]) self.pool2d_avg = Pool2D(
else: pool_size=3, pool_stride=stride, pool_padding=1, pool_type='avg')
ys.append(
fluid.layers.pool2d(
input=xs[-1],
pool_size=3,
pool_stride=stride,
pool_padding=1,
pool_type='avg'))
conv1 = fluid.layers.concat(ys, axis=1) self.conv2 = ConvBNLayer(
conv2 = self.conv_bn_layer( num_channels=num_filters,
input=conv1, num_filters=num_channels2,
num_filters=num_filters2,
filter_size=1, filter_size=1,
act=None, act=None,
name=name + "_branch2c") name=name + "_branch2c")
short = self.shortcut( if not shortcut:
input, num_filters2, stride, name=name + "_branch1") self.short = ConvBNLayer(
num_channels=num_channels1,
num_filters=num_channels2,
filter_size=1,
stride=stride,
name=name + "_branch1")
self.shortcut = shortcut
def forward(self, inputs):
y = self.conv0(inputs)
xs = fluid.layers.split(y, self.scales, 1)
ys = []
for s, conv1 in enumerate(self.conv1_list):
if s == 0 or self.stride == 2:
ys.append(conv1(xs[s]))
else:
ys.append(conv1(xs[s] + ys[-1]))
if self.stride == 1:
ys.append(xs[-1])
else:
ys.append(self.pool2d_avg(xs[-1]))
conv1 = fluid.layers.concat(ys, axis=1)
conv2 = self.conv2(conv1)
if self.shortcut:
short = inputs
else:
short = self.short(inputs)
y = fluid.layers.elementwise_add(x=short, y=conv2)
layer_helper = LayerHelper(self.full_name(), act='relu')
return layer_helper.append_activation(y)
return fluid.layers.elementwise_add(x=short, y=conv2, act='relu')
class Res2Net(fluid.dygraph.Layer):
def __init__(self, layers=50, scales=4, width=26, class_dim=1000):
super(Res2Net, self).__init__()
self.layers = layers
self.scales = scales
self.width = width
basic_width = self.width * self.scales
supported_layers = [50, 101, 152, 200]
assert layers in supported_layers, \
"supported layers are {} but input layer is {}".format(
supported_layers, layers)
if layers == 50:
depth = [3, 4, 6, 3]
elif layers == 101:
depth = [3, 4, 23, 3]
elif layers == 152:
depth = [3, 8, 36, 3]
elif layers == 200:
depth = [3, 12, 48, 3]
num_channels = [64, 256, 512, 1024]
num_channels2 = [256, 512, 1024, 2048]
num_filters = [basic_width * t for t in [1, 2, 4, 8]]
self.conv1 = ConvBNLayer(
num_channels=3,
num_filters=64,
filter_size=7,
stride=2,
act='relu',
name="conv1")
self.pool2d_max = Pool2D(
pool_size=3, pool_stride=2, pool_padding=1, pool_type='max')
self.block_list = []
for block in range(len(depth)):
shortcut = False
for i in range(depth[block]):
if layers in [101, 152] and block == 2:
if i == 0:
conv_name = "res" + str(block + 2) + "a"
else:
conv_name = "res" + str(block + 2) + "b" + str(i)
else:
conv_name = "res" + str(block + 2) + chr(97 + i)
bottleneck_block = self.add_sublayer(
'bb_%d_%d' % (block, i),
BottleneckBlock(
num_channels1=num_channels[block]
if i == 0 else num_channels2[block],
num_channels2=num_channels2[block],
num_filters=num_filters[block],
stride=2 if i == 0 and block != 0 else 1,
scales=scales,
shortcut=shortcut,
if_first=block == i == 0,
name=conv_name))
self.block_list.append(bottleneck_block)
shortcut = True
self.pool2d_avg = Pool2D(
pool_size=7, pool_type='avg', global_pooling=True)
self.pool2d_avg_channels = num_channels[-1] * 2
stdv = 1.0 / math.sqrt(self.pool2d_avg_channels * 1.0)
self.out = Linear(
self.pool2d_avg_channels,
class_dim,
param_attr=ParamAttr(
initializer=fluid.initializer.Uniform(-stdv, stdv),
name="fc_weights"),
bias_attr=ParamAttr(name="fc_offset"))
def forward(self, inputs):
y = self.conv1(inputs)
y = self.pool2d_max(y)
for block in self.block_list:
y = block(y)
y = self.pool2d_avg(y)
y = fluid.layers.reshape(y, shape=[-1, self.pool2d_avg_channels])
y = self.out(y)
return y
def Res2Net50_48w_2s(**args):
model = Res2Net(layers=50, scales=2, width=48, **args)
return model
def Res2Net50_26w_4s(**args):
model = Res2Net(layers=50, scales=4, width=26, **args)
return model
def Res2Net50_48w_2s(): def Res2Net50_14w_8s(**args):
model = Res2Net(layers=50, scales=2, width=48) model = Res2Net(layers=50, scales=8, width=14, **args)
return model return model
def Res2Net50_26w_4s(): def Res2Net50_48w_2s(**args):
model = Res2Net(layers=50, scales=4, width=26) model = Res2Net(layers=50, scales=2, width=48, **args)
return model return model
def Res2Net50_14w_8s(): def Res2Net50_26w_6s(**args):
model = Res2Net(layers=50, scales=8, width=14) model = Res2Net(layers=50, scales=6, width=26, **args)
return model return model
def Res2Net50_26w_6s(): def Res2Net50_26w_8s(**args):
model = Res2Net(layers=50, scales=6, width=26) model = Res2Net(layers=50, scales=8, width=26, **args)
return model return model
def Res2Net50_26w_8s(): def Res2Net101_26w_4s(**args):
model = Res2Net(layers=50, scales=8, width=26) model = Res2Net(layers=101, scales=4, width=26, **args)
return model return model
def Res2Net101_26w_4s(): def Res2Net152_26w_4s(**args):
model = Res2Net(layers=101, scales=4, width=26) model = Res2Net(layers=152, scales=4, width=26, **args)
return model return model
def Res2Net152_26w_4s(): def Res2Net200_26w_4s(**args):
model = Res2Net(layers=152, scales=4, width=26) model = Res2Net(layers=200, scales=4, width=26, **args)
return model return model
...@@ -16,33 +16,158 @@ from __future__ import absolute_import ...@@ -16,33 +16,158 @@ from __future__ import absolute_import
from __future__ import division from __future__ import division
from __future__ import print_function from __future__ import print_function
import math import numpy as np
import paddle
import paddle.fluid as fluid import paddle.fluid as fluid
from paddle.fluid.param_attr import ParamAttr from paddle.fluid.param_attr import ParamAttr
from paddle.fluid.layer_helper import LayerHelper
from paddle.fluid.dygraph.nn import Conv2D, Pool2D, BatchNorm, Linear, Dropout
import math
__all__ = [ __all__ = [
"Res2Net_vd", "Res2Net50_vd_48w_2s", "Res2Net50_vd_26w_4s", "Res2Net50_vd_48w_2s", "Res2Net50_vd_26w_4s", "Res2Net50_vd_14w_8s",
"Res2Net50_vd_14w_8s", "Res2Net50_vd_26w_6s", "Res2Net50_vd_26w_8s", "Res2Net50_vd_48w_2s", "Res2Net50_vd_26w_6s", "Res2Net50_vd_26w_8s",
"Res2Net101_vd_26w_4s", "Res2Net152_vd_26w_4s", "Res2Net200_vd_26w_4s" "Res2Net101_vd_26w_4s", "Res2Net152_vd_26w_4s", "Res2Net200_vd_26w_4s"
] ]
class Res2Net_vd(): class ConvBNLayer(fluid.dygraph.Layer):
def __init__(self, layers=50, scales=4, width=26): def __init__(
self,
num_channels,
num_filters,
filter_size,
stride=1,
groups=1,
is_vd_mode=False,
act=None,
name=None, ):
super(ConvBNLayer, self).__init__()
self.is_vd_mode = is_vd_mode
self._pool2d_avg = Pool2D(
pool_size=2, pool_stride=2, pool_padding=0, pool_type='avg')
self._conv = Conv2D(
num_channels=num_channels,
num_filters=num_filters,
filter_size=filter_size,
stride=stride,
padding=(filter_size - 1) // 2,
groups=groups,
act=None,
param_attr=ParamAttr(name=name + "_weights"),
bias_attr=False)
if name == "conv1":
bn_name = "bn_" + name
else:
bn_name = "bn" + name[3:]
self._batch_norm = BatchNorm(
num_filters,
act=act,
param_attr=ParamAttr(name=bn_name + '_scale'),
bias_attr=ParamAttr(bn_name + '_offset'),
moving_mean_name=bn_name + '_mean',
moving_variance_name=bn_name + '_variance')
def forward(self, inputs):
if self.is_vd_mode:
inputs = self._pool2d_avg(inputs)
y = self._conv(inputs)
y = self._batch_norm(y)
return y
class BottleneckBlock(fluid.dygraph.Layer):
def __init__(self,
num_channels1,
num_channels2,
num_filters,
stride,
scales,
shortcut=True,
if_first=False,
name=None):
super(BottleneckBlock, self).__init__()
self.stride = stride
self.scales = scales
self.conv0 = ConvBNLayer(
num_channels=num_channels1,
num_filters=num_filters,
filter_size=1,
act='relu',
name=name + "_branch2a")
self.conv1_list = []
for s in range(scales - 1):
conv1 = self.add_sublayer(
name + '_branch2b_' + str(s + 1),
ConvBNLayer(
num_channels=num_filters // scales,
num_filters=num_filters // scales,
filter_size=3,
stride=stride,
act='relu',
name=name + '_branch2b_' + str(s + 1)))
self.conv1_list.append(conv1)
self.pool2d_avg = Pool2D(
pool_size=3, pool_stride=stride, pool_padding=1, pool_type='avg')
self.conv2 = ConvBNLayer(
num_channels=num_filters,
num_filters=num_channels2,
filter_size=1,
act=None,
name=name + "_branch2c")
if not shortcut:
self.short = ConvBNLayer(
num_channels=num_channels1,
num_filters=num_channels2,
filter_size=1,
stride=1,
is_vd_mode=False if if_first else True,
name=name + "_branch1")
self.shortcut = shortcut
def forward(self, inputs):
y = self.conv0(inputs)
xs = fluid.layers.split(y, self.scales, 1)
ys = []
for s, conv1 in enumerate(self.conv1_list):
if s == 0 or self.stride == 2:
ys.append(conv1(xs[s]))
else:
ys.append(conv1(xs[s] + ys[-1]))
if self.stride == 1:
ys.append(xs[-1])
else:
ys.append(self.pool2d_avg(xs[-1]))
conv1 = fluid.layers.concat(ys, axis=1)
conv2 = self.conv2(conv1)
if self.shortcut:
short = inputs
else:
short = self.short(inputs)
y = fluid.layers.elementwise_add(x=short, y=conv2)
layer_helper = LayerHelper(self.full_name(), act='relu')
return layer_helper.append_activation(y)
class Res2Net_vd(fluid.dygraph.Layer):
def __init__(self, layers=50, scales=4, width=26, class_dim=1000):
super(Res2Net_vd, self).__init__()
self.layers = layers self.layers = layers
self.scales = scales self.scales = scales
self.width = width self.width = width
basic_width = self.width * self.scales
def net(self, input, class_dim=1000):
layers = self.layers
supported_layers = [50, 101, 152, 200] supported_layers = [50, 101, 152, 200]
assert layers in supported_layers, \ assert layers in supported_layers, \
"supported layers are {} but input layer is {}".format( "supported layers are {} but input layer is {}".format(
supported_layers, layers) supported_layers, layers)
basic_width = self.width * self.scales
num_filters1 = [basic_width * t for t in [1, 2, 4, 8]]
num_filters2 = [256 * t for t in [1, 2, 4, 8]]
if layers == 50: if layers == 50:
depth = [3, 4, 6, 3] depth = [3, 4, 6, 3]
elif layers == 101: elif layers == 101:
...@@ -51,35 +176,37 @@ class Res2Net_vd(): ...@@ -51,35 +176,37 @@ class Res2Net_vd():
depth = [3, 8, 36, 3] depth = [3, 8, 36, 3]
elif layers == 200: elif layers == 200:
depth = [3, 12, 48, 3] depth = [3, 12, 48, 3]
conv = self.conv_bn_layer( num_channels = [64, 256, 512, 1024]
input=input, num_channels2 = [256, 512, 1024, 2048]
num_filters = [basic_width * t for t in [1, 2, 4, 8]]
self.conv1_1 = ConvBNLayer(
num_channels=3,
num_filters=32, num_filters=32,
filter_size=3, filter_size=3,
stride=2, stride=2,
act='relu', act='relu',
name='conv1_1') name="conv1_1")
conv = self.conv_bn_layer( self.conv1_2 = ConvBNLayer(
input=conv, num_channels=32,
num_filters=32, num_filters=32,
filter_size=3, filter_size=3,
stride=1, stride=1,
act='relu', act='relu',
name='conv1_2') name="conv1_2")
conv = self.conv_bn_layer( self.conv1_3 = ConvBNLayer(
input=conv, num_channels=32,
num_filters=64, num_filters=64,
filter_size=3, filter_size=3,
stride=1, stride=1,
act='relu', act='relu',
name='conv1_3') name="conv1_3")
self.pool2d_max = Pool2D(
conv = fluid.layers.pool2d( pool_size=3, pool_stride=2, pool_padding=1, pool_type='max')
input=conv,
pool_size=3, self.block_list = []
pool_stride=2,
pool_padding=1,
pool_type='max')
for block in range(len(depth)): for block in range(len(depth)):
shortcut = False
for i in range(depth[block]): for i in range(depth[block]):
if layers in [101, 152, 200] and block == 2: if layers in [101, 152, 200] and block == 2:
if i == 0: if i == 0:
...@@ -88,207 +215,89 @@ class Res2Net_vd(): ...@@ -88,207 +215,89 @@ class Res2Net_vd():
conv_name = "res" + str(block + 2) + "b" + str(i) conv_name = "res" + str(block + 2) + "b" + str(i)
else: else:
conv_name = "res" + str(block + 2) + chr(97 + i) conv_name = "res" + str(block + 2) + chr(97 + i)
conv = self.bottleneck_block( bottleneck_block = self.add_sublayer(
input=conv, 'bb_%d_%d' % (block, i),
num_filters1=num_filters1[block], BottleneckBlock(
num_filters2=num_filters2[block], num_channels1=num_channels[block]
if i == 0 else num_channels2[block],
num_channels2=num_channels2[block],
num_filters=num_filters[block],
stride=2 if i == 0 and block != 0 else 1, stride=2 if i == 0 and block != 0 else 1,
scales=scales,
shortcut=shortcut,
if_first=block == i == 0, if_first=block == i == 0,
name=conv_name) name=conv_name))
pool = fluid.layers.pool2d( self.block_list.append(bottleneck_block)
input=conv, shortcut = True
pool_size=7,
pool_stride=1,
pool_type='avg',
global_pooling=True)
stdv = 1.0 / math.sqrt(pool.shape[1] * 1.0)
out = fluid.layers.fc(
input=pool,
size=class_dim,
param_attr=fluid.param_attr.ParamAttr(
initializer=fluid.initializer.Uniform(-stdv, stdv),
name='fc_weights'),
bias_attr=fluid.param_attr.ParamAttr(name='fc_offset'))
return out
def conv_bn_layer(self,
input,
num_filters,
filter_size,
stride=1,
groups=1,
act=None,
name=None):
conv = fluid.layers.conv2d(
input=input,
num_filters=num_filters,
filter_size=filter_size,
stride=stride,
padding=(filter_size - 1) // 2,
groups=groups,
act=None,
param_attr=ParamAttr(name=name + "_weights"),
bias_attr=False)
if name == "conv1":
bn_name = "bn_" + name
else:
bn_name = "bn" + name[3:]
return fluid.layers.batch_norm(
input=conv,
act=act,
param_attr=ParamAttr(name=bn_name + '_scale'),
bias_attr=ParamAttr(bn_name + '_offset'),
moving_mean_name=bn_name + '_mean',
moving_variance_name=bn_name + '_variance')
def conv_bn_layer_new(self,
input,
num_filters,
filter_size,
stride=1,
groups=1,
act=None,
name=None):
pool = fluid.layers.pool2d(
input=input,
pool_size=2,
pool_stride=2,
pool_padding=0,
pool_type='avg',
ceil_mode=True)
conv = fluid.layers.conv2d(
input=pool,
num_filters=num_filters,
filter_size=filter_size,
stride=1,
padding=(filter_size - 1) // 2,
groups=groups,
act=None,
param_attr=ParamAttr(name=name + "_weights"),
bias_attr=False)
if name == "conv1":
bn_name = "bn_" + name
else:
bn_name = "bn" + name[3:]
return fluid.layers.batch_norm(
input=conv,
act=act,
param_attr=ParamAttr(name=bn_name + '_scale'),
bias_attr=ParamAttr(bn_name + '_offset'),
moving_mean_name=bn_name + '_mean',
moving_variance_name=bn_name + '_variance')
def shortcut(self, input, ch_out, stride, name, if_first=False):
ch_in = input.shape[1]
if ch_in != ch_out or stride != 1:
if if_first:
return self.conv_bn_layer(input, ch_out, 1, stride, name=name)
else:
return self.conv_bn_layer_new(
input, ch_out, 1, stride, name=name)
elif if_first:
return self.conv_bn_layer(input, ch_out, 1, stride, name=name)
else:
return input
def bottleneck_block(self, input, num_filters1, num_filters2, stride, name,
if_first):
conv0 = self.conv_bn_layer(
input=input,
num_filters=num_filters1,
filter_size=1,
stride=1,
act='relu',
name=name + '_branch2a')
xs = fluid.layers.split(conv0, self.scales, 1)
ys = []
for s in range(self.scales - 1):
if s == 0 or stride == 2:
ys.append(
self.conv_bn_layer(
input=xs[s],
num_filters=num_filters1 // self.scales,
stride=stride,
filter_size=3,
act='relu',
name=name + '_branch2b_' + str(s + 1)))
else:
ys.append(
self.conv_bn_layer(
input=xs[s] + ys[-1],
num_filters=num_filters1 // self.scales,
stride=stride,
filter_size=3,
act='relu',
name=name + '_branch2b_' + str(s + 1)))
if stride == 1: self.pool2d_avg = Pool2D(
ys.append(xs[-1]) pool_size=7, pool_type='avg', global_pooling=True)
else:
ys.append(
fluid.layers.pool2d(
input=xs[-1],
pool_size=3,
pool_stride=stride,
pool_padding=1,
pool_type='avg'))
conv1 = fluid.layers.concat(ys, axis=1) self.pool2d_avg_channels = num_channels[-1] * 2
conv2 = self.conv_bn_layer(
input=conv1,
num_filters=num_filters2,
filter_size=1,
act=None,
name=name + "_branch2c")
short = self.shortcut( stdv = 1.0 / math.sqrt(self.pool2d_avg_channels * 1.0)
input,
num_filters2,
stride,
if_first=if_first,
name=name + "_branch1")
return fluid.layers.elementwise_add(x=short, y=conv2, act='relu') self.out = Linear(
self.pool2d_avg_channels,
class_dim,
param_attr=ParamAttr(
initializer=fluid.initializer.Uniform(-stdv, stdv),
name="fc_weights"),
bias_attr=ParamAttr(name="fc_offset"))
def forward(self, inputs):
y = self.conv1_1(inputs)
y = self.conv1_2(y)
y = self.conv1_3(y)
y = self.pool2d_max(y)
for block in self.block_list:
y = block(y)
y = self.pool2d_avg(y)
y = fluid.layers.reshape(y, shape=[-1, self.pool2d_avg_channels])
y = self.out(y)
return y
def Res2Net50_vd_48w_2s(**args):
model = Res2Net_vd(layers=50, scales=2, width=48, **args)
return model
def Res2Net50_vd_48w_2s(): def Res2Net50_vd_26w_4s(**args):
model = Res2Net_vd(layers=50, scales=2, width=48) model = Res2Net_vd(layers=50, scales=4, width=26, **args)
return model return model
def Res2Net50_vd_26w_4s(): def Res2Net50_vd_14w_8s(**args):
model = Res2Net_vd(layers=50, scales=4, width=26) model = Res2Net_vd(layers=50, scales=8, width=14, **args)
return model return model
def Res2Net50_vd_14w_8s(): def Res2Net50_vd_48w_2s(**args):
model = Res2Net_vd(layers=50, scales=8, width=14) model = Res2Net_vd(layers=50, scales=2, width=48, **args)
return model return model
def Res2Net50_vd_26w_6s(): def Res2Net50_vd_26w_6s(**args):
model = Res2Net_vd(layers=50, scales=6, width=26) model = Res2Net_vd(layers=50, scales=6, width=26, **args)
return model return model
def Res2Net50_vd_26w_8s(): def Res2Net50_vd_26w_8s(**args):
model = Res2Net_vd(layers=50, scales=8, width=26) model = Res2Net_vd(layers=50, scales=8, width=26, **args)
return model return model
def Res2Net101_vd_26w_4s(): def Res2Net101_vd_26w_4s(**args):
model = Res2Net_vd(layers=101, scales=4, width=26) model = Res2Net_vd(layers=101, scales=4, width=26, **args)
return model return model
def Res2Net152_vd_26w_4s(): def Res2Net152_vd_26w_4s(**args):
model = Res2Net_vd(layers=152, scales=4, width=26) model = Res2Net_vd(layers=152, scales=4, width=26, **args)
return model return model
def Res2Net200_vd_26w_4s(): def Res2Net200_vd_26w_4s(**args):
model = Res2Net_vd(layers=200, scales=4, width=26) model = Res2Net_vd(layers=200, scales=4, width=26, **args)
return model return model
...@@ -12,19 +12,20 @@ ...@@ -12,19 +12,20 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import numpy as np
import paddle
import paddle.fluid as fluid import paddle.fluid as fluid
from paddle.fluid.param_attr import ParamAttr
from paddle.fluid.layer_helper import LayerHelper from paddle.fluid.layer_helper import LayerHelper
from paddle.fluid.dygraph.nn import Conv2D, Pool2D, BatchNorm, Linear from paddle.fluid.dygraph.nn import Conv2D, Pool2D, BatchNorm, Linear, Dropout
import math import math
__all__ = [ __all__ = ["ResNet18", "ResNet34", "ResNet50", "ResNet101", "ResNet152"]
"ResNet18",
"ResNet34",
"ResNet50",
"ResNet101",
"ResNet152",
]
class ConvBNLayer(fluid.dygraph.Layer): class ConvBNLayer(fluid.dygraph.Layer):
...@@ -34,7 +35,8 @@ class ConvBNLayer(fluid.dygraph.Layer): ...@@ -34,7 +35,8 @@ class ConvBNLayer(fluid.dygraph.Layer):
filter_size, filter_size,
stride=1, stride=1,
groups=1, groups=1,
act=None): act=None,
name=None):
super(ConvBNLayer, self).__init__() super(ConvBNLayer, self).__init__()
self._conv = Conv2D( self._conv = Conv2D(
...@@ -45,44 +47,62 @@ class ConvBNLayer(fluid.dygraph.Layer): ...@@ -45,44 +47,62 @@ class ConvBNLayer(fluid.dygraph.Layer):
padding=(filter_size - 1) // 2, padding=(filter_size - 1) // 2,
groups=groups, groups=groups,
act=None, act=None,
param_attr=ParamAttr(name=name + "_weights"),
bias_attr=False) bias_attr=False)
if name == "conv1":
self._batch_norm = BatchNorm(num_filters, act=act) bn_name = "bn_" + name
else:
bn_name = "bn" + name[3:]
self._batch_norm = BatchNorm(
num_filters,
act=act,
param_attr=ParamAttr(name=bn_name + "_scale"),
bias_attr=ParamAttr(bn_name + "_offset"),
moving_mean_name=bn_name + "_mean",
moving_variance_name=bn_name + "_variance")
def forward(self, inputs): def forward(self, inputs):
y = self._conv(inputs) y = self._conv(inputs)
y = self._batch_norm(y) y = self._batch_norm(y)
return y return y
class BottleneckBlock(fluid.dygraph.Layer): class BottleneckBlock(fluid.dygraph.Layer):
def __init__(self, num_channels, num_filters, stride, shortcut=True): def __init__(self,
num_channels,
num_filters,
stride,
shortcut=True,
name=None):
super(BottleneckBlock, self).__init__() super(BottleneckBlock, self).__init__()
self.conv0 = ConvBNLayer( self.conv0 = ConvBNLayer(
num_channels=num_channels, num_channels=num_channels,
num_filters=num_filters, num_filters=num_filters,
filter_size=1, filter_size=1,
act='relu') act="relu",
name=name + "_branch2a")
self.conv1 = ConvBNLayer( self.conv1 = ConvBNLayer(
num_channels=num_filters, num_channels=num_filters,
num_filters=num_filters, num_filters=num_filters,
filter_size=3, filter_size=3,
stride=stride, stride=stride,
act='relu') act="relu",
name=name + "_branch2b")
self.conv2 = ConvBNLayer( self.conv2 = ConvBNLayer(
num_channels=num_filters, num_channels=num_filters,
num_filters=num_filters * 4, num_filters=num_filters * 4,
filter_size=1, filter_size=1,
act=None) act=None,
name=name + "_branch2c")
if not shortcut: if not shortcut:
self.short = ConvBNLayer( self.short = ConvBNLayer(
num_channels=num_channels, num_channels=num_channels,
num_filters=num_filters * 4, num_filters=num_filters * 4,
filter_size=1, filter_size=1,
stride=stride) stride=stride,
name=name + "_branch1")
self.shortcut = shortcut self.shortcut = shortcut
...@@ -100,7 +120,54 @@ class BottleneckBlock(fluid.dygraph.Layer): ...@@ -100,7 +120,54 @@ class BottleneckBlock(fluid.dygraph.Layer):
y = fluid.layers.elementwise_add(x=short, y=conv2) y = fluid.layers.elementwise_add(x=short, y=conv2)
layer_helper = LayerHelper(self.full_name(), act='relu') layer_helper = LayerHelper(self.full_name(), act="relu")
return layer_helper.append_activation(y)
class BisicBlock(fluid.dygraph.Layer):
def __init__(self,
num_channels,
num_filters,
stride,
shortcut=True,
name=None):
super(BisicBlock, self).__init__()
self.stride = stride
self.conv0 = ConvBNLayer(
num_channels=num_channels,
num_filters=num_filters,
filter_size=3,
stride=stride,
act="relu",
name=name + "_branch2a")
self.conv1 = ConvBNLayer(
num_channels=num_filters,
num_filters=num_filters,
filter_size=3,
act=None,
name=name + "_branch2b")
if not shortcut:
self.short = ConvBNLayer(
num_channels=num_channels,
num_filters=num_filters,
filter_size=1,
stride=stride,
name=name + "_branch1")
self.shortcut = shortcut
def forward(self, inputs):
y = self.conv0(inputs)
conv1 = self.conv1(y)
if self.shortcut:
short = inputs
else:
short = self.short(inputs)
y = fluid.layers.elementwise_add(x=short, y=conv1)
layer_helper = LayerHelper(self.full_name(), act="relu")
return layer_helper.append_activation(y) return layer_helper.append_activation(y)
...@@ -109,18 +176,21 @@ class ResNet(fluid.dygraph.Layer): ...@@ -109,18 +176,21 @@ class ResNet(fluid.dygraph.Layer):
super(ResNet, self).__init__() super(ResNet, self).__init__()
self.layers = layers self.layers = layers
supported_layers = [50, 101, 152] supported_layers = [18, 34, 50, 101, 152]
assert layers in supported_layers, \ assert layers in supported_layers, \
"supported layers are {} but input layer is {}".format( "supported layers are {} but input layer is {}".format(
supported_layers, layers) supported_layers, layers)
if layers == 50: if layers == 18:
depth = [2, 2, 2, 2]
elif layers == 34 or layers == 50:
depth = [3, 4, 6, 3] depth = [3, 4, 6, 3]
elif layers == 101: elif layers == 101:
depth = [3, 4, 23, 3] depth = [3, 4, 23, 3]
elif layers == 152: elif layers == 152:
depth = [3, 8, 36, 3] depth = [3, 8, 36, 3]
num_channels = [64, 256, 512, 1024] num_channels = [64, 256, 512,
1024] if layers >= 50 else [64, 64, 128, 256]
num_filters = [64, 128, 256, 512] num_filters = [64, 128, 256, 512]
self.conv = ConvBNLayer( self.conv = ConvBNLayer(
...@@ -128,69 +198,97 @@ class ResNet(fluid.dygraph.Layer): ...@@ -128,69 +198,97 @@ class ResNet(fluid.dygraph.Layer):
num_filters=64, num_filters=64,
filter_size=7, filter_size=7,
stride=2, stride=2,
act='relu') act="relu",
name="conv1")
self.pool2d_max = Pool2D( self.pool2d_max = Pool2D(
pool_size=3, pool_stride=2, pool_padding=1, pool_type='max') pool_size=3, pool_stride=2, pool_padding=1, pool_type="max")
self.bottleneck_block_list = [] self.block_list = []
if layers >= 50:
for block in range(len(depth)): for block in range(len(depth)):
shortcut = False shortcut = False
for i in range(depth[block]): for i in range(depth[block]):
if layers in [101, 152] and block == 2:
if i == 0:
conv_name = "res" + str(block + 2) + "a"
else:
conv_name = "res" + str(block + 2) + "b" + str(i)
else:
conv_name = "res" + str(block + 2) + chr(97 + i)
bottleneck_block = self.add_sublayer( bottleneck_block = self.add_sublayer(
'bb_%d_%d' % (block, i), conv_name,
BottleneckBlock( BottleneckBlock(
num_channels=num_channels[block] num_channels=num_channels[block]
if i == 0 else num_filters[block] * 4, if i == 0 else num_filters[block] * 4,
num_filters=num_filters[block], num_filters=num_filters[block],
stride=2 if i == 0 and block != 0 else 1, stride=2 if i == 0 and block != 0 else 1,
shortcut=shortcut)) shortcut=shortcut,
self.bottleneck_block_list.append(bottleneck_block) name=conv_name))
self.block_list.append(bottleneck_block)
shortcut = True
else:
for block in range(len(depth)):
shortcut = False
for i in range(depth[block]):
conv_name = "res" + str(block + 2) + chr(97 + i)
bisic_block = self.add_sublayer(
conv_name,
BisicBlock(
num_channels=num_channels[block]
if i == 0 else num_filters[block],
num_filters=num_filters[block],
stride=2 if i == 0 and block != 0 else 1,
shortcut=shortcut,
name=conv_name))
self.block_list.append(bisic_block)
shortcut = True shortcut = True
self.pool2d_avg = Pool2D( self.pool2d_avg = Pool2D(
pool_size=7, pool_type='avg', global_pooling=True) pool_size=7, pool_type='avg', global_pooling=True)
self.pool2d_avg_output = num_filters[len(num_filters) - 1] * 4 * 1 * 1 self.pool2d_avg_channels = num_channels[-1] * 2
stdv = 1.0 / math.sqrt(2048 * 1.0) stdv = 1.0 / math.sqrt(self.pool2d_avg_channels * 1.0)
self.out = Linear( self.out = Linear(
self.pool2d_avg_output, self.pool2d_avg_channels,
class_dim, class_dim,
param_attr=fluid.param_attr.ParamAttr( param_attr=ParamAttr(
initializer=fluid.initializer.Uniform(-stdv, stdv))) initializer=fluid.initializer.Uniform(-stdv, stdv),
name="fc_0.w_0"),
bias_attr=ParamAttr(name="fc_0.b_0"))
def forward(self, inputs): def forward(self, inputs):
y = self.conv(inputs) y = self.conv(inputs)
y = self.pool2d_max(y) y = self.pool2d_max(y)
for bottleneck_block in self.bottleneck_block_list: for block in self.block_list:
y = bottleneck_block(y) y = block(y)
y = self.pool2d_avg(y) y = self.pool2d_avg(y)
y = fluid.layers.reshape(y, shape=[-1, self.pool2d_avg_output]) y = fluid.layers.reshape(y, shape=[-1, self.pool2d_avg_channels])
y = self.out(y) y = self.out(y)
return y return y
def ResNet18(**kwargs): def ResNet18(**args):
model = ResNet(layers=18, **kwargs) model = ResNet(layers=18, **args)
return model return model
def ResNet34(**kwargs): def ResNet34(**args):
model = ResNet(layers=34, **kwargs) model = ResNet(layers=34, **args)
return model return model
def ResNet50(**kwargs): def ResNet50(**args):
model = ResNet(layers=50, **kwargs) model = ResNet(layers=50, **args)
return model return model
def ResNet101(**kwargs): def ResNet101(**args):
model = ResNet(layers=101, **kwargs) model = ResNet(layers=101, **args)
return model return model
def ResNet152(class_dim=1000): def ResNet152(**args):
model = ResNet(layers=152, class_dim=class_dim) model = ResNet(layers=152, **args)
return model return model
#copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. # copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve.
# #
#Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
#You may obtain a copy of the License at # You may obtain a copy of the License at
# #
# http://www.apache.org/licenses/LICENSE-2.0 # http://www.apache.org/licenses/LICENSE-2.0
# #
#Unless required by applicable law or agreed to in writing, software # Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS, # distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
#limitations under the License. # limitations under the License.
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import division from __future__ import division
from __future__ import print_function from __future__ import print_function
import math import numpy as np
import paddle import paddle
import paddle.fluid as fluid import paddle.fluid as fluid
from paddle.fluid.param_attr import ParamAttr from paddle.fluid.param_attr import ParamAttr
from paddle.fluid.layer_helper import LayerHelper
from paddle.fluid.dygraph.nn import Conv2D, Pool2D, BatchNorm, Linear, Dropout
__all__ = ["ResNet", "ResNet50_vc", "ResNet101_vc", "ResNet152_vc"] import math
train_parameters = { __all__ = [
"input_size": [3, 224, 224], "ResNet18_vc", "ResNet34_vc", "ResNet50_vc", "ResNet101_vc", "ResNet152_vc"
"input_mean": [0.485, 0.456, 0.406], ]
"input_std": [0.229, 0.224, 0.225],
"learning_strategy": {
"name": "piecewise_decay",
"batch_size": 256,
"epochs": [30, 60, 90],
"steps": [0.1, 0.01, 0.001, 0.0001]
}
}
class ResNet(): class ConvBNLayer(fluid.dygraph.Layer):
def __init__(self, layers=50): def __init__(self,
self.params = train_parameters num_channels,
self.layers = layers num_filters,
filter_size,
stride=1,
groups=1,
act=None,
name=None):
super(ConvBNLayer, self).__init__()
def net(self, input, class_dim=1000): self._conv = Conv2D(
layers = self.layers num_channels=num_channels,
supported_layers = [50, 101, 152] num_filters=num_filters,
filter_size=filter_size,
stride=stride,
padding=(filter_size - 1) // 2,
groups=groups,
act=None,
param_attr=ParamAttr(name=name + "_weights"),
bias_attr=False)
if name == "conv1":
bn_name = "bn_" + name
else:
bn_name = "bn" + name[3:]
self._batch_norm = BatchNorm(
num_filters,
act=act,
param_attr=ParamAttr(name=bn_name + '_scale'),
bias_attr=ParamAttr(bn_name + '_offset'),
moving_mean_name=bn_name + '_mean',
moving_variance_name=bn_name + '_variance')
def forward(self, inputs):
y = self._conv(inputs)
y = self._batch_norm(y)
return y
class BottleneckBlock(fluid.dygraph.Layer):
def __init__(self,
num_channels,
num_filters,
stride,
shortcut=True,
name=None):
super(BottleneckBlock, self).__init__()
self.conv0 = ConvBNLayer(
num_channels=num_channels,
num_filters=num_filters,
filter_size=1,
act='relu',
name=name + "_branch2a")
self.conv1 = ConvBNLayer(
num_channels=num_filters,
num_filters=num_filters,
filter_size=3,
stride=stride,
act='relu',
name=name + "_branch2b")
self.conv2 = ConvBNLayer(
num_channels=num_filters,
num_filters=num_filters * 4,
filter_size=1,
act=None,
name=name + "_branch2c")
if not shortcut:
self.short = ConvBNLayer(
num_channels=num_channels,
num_filters=num_filters * 4,
filter_size=1,
stride=stride,
name=name + "_branch1")
self.shortcut = shortcut
self._num_channels_out = num_filters * 4
def forward(self, inputs):
y = self.conv0(inputs)
conv1 = self.conv1(y)
conv2 = self.conv2(conv1)
if self.shortcut:
short = inputs
else:
short = self.short(inputs)
y = fluid.layers.elementwise_add(x=short, y=conv2)
layer_helper = LayerHelper(self.full_name(), act='relu')
return layer_helper.append_activation(y)
class BisicBlock(fluid.dygraph.Layer):
def __init__(self,
num_channels,
num_filters,
stride,
shortcut=True,
name=None):
super(BisicBlock, self).__init__()
self.stride = stride
self.conv0 = ConvBNLayer(
num_channels=num_channels,
num_filters=num_filters,
filter_size=3,
stride=stride,
act='relu',
name=name + "_branch2a")
self.conv1 = ConvBNLayer(
num_channels=num_filters,
num_filters=num_filters,
filter_size=3,
act=None,
name=name + "_branch2b")
if not shortcut:
self.short = ConvBNLayer(
num_channels=num_channels,
num_filters=num_filters,
filter_size=1,
stride=stride,
name=name + "_branch1")
self.shortcut = shortcut
def forward(self, inputs):
y = self.conv0(inputs)
conv1 = self.conv1(y)
if self.shortcut:
short = inputs
else:
short = self.short(inputs)
y = fluid.layers.elementwise_add(x=short, y=conv1)
layer_helper = LayerHelper(self.full_name(), act='relu')
return layer_helper.append_activation(y)
class ResNet_vc(fluid.dygraph.Layer):
def __init__(self, layers=50, class_dim=1000):
super(ResNet_vc, self).__init__()
self.layers = layers
supported_layers = [18, 34, 50, 101, 152]
assert layers in supported_layers, \ assert layers in supported_layers, \
"supported layers are {} but input layer is {}".format(supported_layers, layers) "supported layers are {} but input layer is {}".format(
supported_layers, layers)
if layers == 50: if layers == 18:
depth = [2, 2, 2, 2]
elif layers == 34 or layers == 50:
depth = [3, 4, 6, 3] depth = [3, 4, 6, 3]
elif layers == 101: elif layers == 101:
depth = [3, 4, 23, 3] depth = [3, 4, 23, 3]
elif layers == 152: elif layers == 152:
depth = [3, 8, 36, 3] depth = [3, 8, 36, 3]
num_channels = [64, 256, 512,
1024] if layers >= 50 else [64, 64, 128, 256]
num_filters = [64, 128, 256, 512] num_filters = [64, 128, 256, 512]
conv = self.conv_bn_layer( self.conv1_1 = ConvBNLayer(
input=input, num_channels=3,
num_filters=32, num_filters=32,
filter_size=3, filter_size=3,
stride=2, stride=2,
act='relu', act='relu',
name='conv1_1') name="conv1_1")
conv = self.conv_bn_layer( self.conv1_2 = ConvBNLayer(
input=conv, num_channels=32,
num_filters=32, num_filters=32,
filter_size=3, filter_size=3,
stride=1, stride=1,
act='relu', act='relu',
name='conv1_2') name="conv1_2")
conv = self.conv_bn_layer( self.conv1_3 = ConvBNLayer(
input=conv, num_channels=32,
num_filters=64, num_filters=64,
filter_size=3, filter_size=3,
stride=1, stride=1,
act='relu', act='relu',
name='conv1_3') name="conv1_3")
conv = fluid.layers.pool2d( self.pool2d_max = Pool2D(
input=conv, pool_size=3, pool_stride=2, pool_padding=1, pool_type='max')
pool_size=3,
pool_stride=2,
pool_padding=1,
pool_type='max')
self.block_list = []
if layers >= 50:
for block in range(len(depth)): for block in range(len(depth)):
shortcut = False
for i in range(depth[block]): for i in range(depth[block]):
if layers in [101, 152] and block == 2: if layers in [101, 152] and block == 2:
if i == 0: if i == 0:
...@@ -94,101 +232,82 @@ class ResNet(): ...@@ -94,101 +232,82 @@ class ResNet():
conv_name = "res" + str(block + 2) + "b" + str(i) conv_name = "res" + str(block + 2) + "b" + str(i)
else: else:
conv_name = "res" + str(block + 2) + chr(97 + i) conv_name = "res" + str(block + 2) + chr(97 + i)
conv = self.bottleneck_block( bottleneck_block = self.add_sublayer(
input=conv, 'bb_%d_%d' % (block, i),
BottleneckBlock(
num_channels=num_channels[block]
if i == 0 else num_filters[block] * 4,
num_filters=num_filters[block],
stride=2 if i == 0 and block != 0 else 1,
shortcut=shortcut,
name=conv_name))
self.block_list.append(bottleneck_block)
shortcut = True
else:
for block in range(len(depth)):
shortcut = False
for i in range(depth[block]):
conv_name = "res" + str(block + 2) + chr(97 + i)
bisic_block = self.add_sublayer(
'bb_%d_%d' % (block, i),
BisicBlock(
num_channels=num_channels[block]
if i == 0 else num_filters[block],
num_filters=num_filters[block], num_filters=num_filters[block],
stride=2 if i == 0 and block != 0 else 1, stride=2 if i == 0 and block != 0 else 1,
name=conv_name) shortcut=shortcut,
name=conv_name))
pool = fluid.layers.pool2d( self.block_list.append(bisic_block)
input=conv, pool_type='avg', global_pooling=True) shortcut = True
stdv = 1.0 / math.sqrt(pool.shape[1] * 1.0)
out = fluid.layers.fc(input=pool, self.pool2d_avg = Pool2D(
size=class_dim, pool_size=7, pool_type='avg', global_pooling=True)
param_attr=fluid.param_attr.ParamAttr(
name="fc_0.w_0", self.pool2d_avg_channels = num_channels[-1] * 2
initializer=fluid.initializer.Uniform(-stdv,
stdv)), stdv = 1.0 / math.sqrt(self.pool2d_avg_channels * 1.0)
self.out = Linear(
self.pool2d_avg_channels,
class_dim,
param_attr=ParamAttr(
initializer=fluid.initializer.Uniform(-stdv, stdv),
name="fc_0.w_0"),
bias_attr=ParamAttr(name="fc_0.b_0")) bias_attr=ParamAttr(name="fc_0.b_0"))
return out
def conv_bn_layer(self, def forward(self, inputs):
input, y = self.conv1_1(inputs)
num_filters, y = self.conv1_2(y)
filter_size, y = self.conv1_3(y)
stride=1, y = self.pool2d_max(y)
groups=1, for block in self.block_list:
act=None, y = block(y)
name=None): y = self.pool2d_avg(y)
conv = fluid.layers.conv2d( y = fluid.layers.reshape(y, shape=[-1, self.pool2d_avg_channels])
input=input, y = self.out(y)
num_filters=num_filters, return y
filter_size=filter_size,
stride=stride,
padding=(filter_size - 1) // 2,
groups=groups,
act=None,
param_attr=ParamAttr(name=name + "_weights"),
bias_attr=False,
name=name + '.conv2d.output.1')
if name == "conv1":
bn_name = "bn_" + name
else:
bn_name = "bn" + name[3:]
return fluid.layers.batch_norm(
input=conv,
act=act,
name=bn_name + '.output.1',
param_attr=ParamAttr(name=bn_name + '_scale'),
bias_attr=ParamAttr(bn_name + '_offset'),
moving_mean_name=bn_name + '_mean',
moving_variance_name=bn_name + '_variance', )
def shortcut(self, input, ch_out, stride, name):
ch_in = input.shape[1]
if ch_in != ch_out or stride != 1:
return self.conv_bn_layer(input, ch_out, 1, stride, name=name)
else:
return input
def bottleneck_block(self, input, num_filters, stride, name): def ResNet18_vc(**args):
conv0 = self.conv_bn_layer( model = ResNet_vc(layers=18, **args)
input=input, return model
num_filters=num_filters,
filter_size=1,
act='relu',
name=name + "_branch2a")
conv1 = self.conv_bn_layer(
input=conv0,
num_filters=num_filters,
filter_size=3,
stride=stride,
act='relu',
name=name + "_branch2b")
conv2 = self.conv_bn_layer(
input=conv1,
num_filters=num_filters * 4,
filter_size=1,
act=None,
name=name + "_branch2c")
short = self.shortcut(
input, num_filters * 4, stride, name=name + "_branch1")
return fluid.layers.elementwise_add( def ResNet34_vc(**args):
x=short, y=conv2, act='relu', name=name + ".add.output.5") model = ResNet_vc(layers=34, **args)
return model
def ResNet50_vc(): def ResNet50_vc(**args):
model = ResNet(layers=50) model = ResNet_vc(layers=50, **args)
return model return model
def ResNet101_vc(): def ResNet101_vc(**args):
model = ResNet(layers=101) model = ResNet_vc(layers=101, **args)
return model return model
def ResNet152_vc(): def ResNet152_vc(**args):
model = ResNet(layers=152) model = ResNet_vc(layers=152, **args)
return model return model
#copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. # copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve.
# #
#Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
#You may obtain a copy of the License at # You may obtain a copy of the License at
# #
# http://www.apache.org/licenses/LICENSE-2.0 # http://www.apache.org/licenses/LICENSE-2.0
# #
#Unless required by applicable law or agreed to in writing, software # Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS, # distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
#limitations under the License. # limitations under the License.
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import division from __future__ import division
from __future__ import print_function from __future__ import print_function
import math import numpy as np
import paddle import paddle
import paddle.fluid as fluid import paddle.fluid as fluid
from paddle.fluid.param_attr import ParamAttr from paddle.fluid.param_attr import ParamAttr
from paddle.fluid.layer_helper import LayerHelper
from paddle.fluid.dygraph.nn import Conv2D, Pool2D, BatchNorm, Linear, Dropout
import math
__all__ = [ __all__ = [
"ResNet", "ResNet18_vd", "ResNet34_vd", "ResNet50_vd", "ResNet101_vd", "ResNet18_vd", "ResNet34_vd", "ResNet50_vd", "ResNet101_vd", "ResNet152_vd"
"ResNet152_vd", "ResNet200_vd"
] ]
class ResNet(): class ConvBNLayer(fluid.dygraph.Layer):
def __init__(
self,
num_channels,
num_filters,
filter_size,
stride=1,
groups=1,
is_vd_mode=False,
act=None,
name=None, ):
super(ConvBNLayer, self).__init__()
self.is_vd_mode = is_vd_mode
self._pool2d_avg = Pool2D(
pool_size=2, pool_stride=2, pool_padding=0, pool_type='avg')
self._conv = Conv2D(
num_channels=num_channels,
num_filters=num_filters,
filter_size=filter_size,
stride=stride,
padding=(filter_size - 1) // 2,
groups=groups,
act=None,
param_attr=ParamAttr(name=name + "_weights"),
bias_attr=False)
if name == "conv1":
bn_name = "bn_" + name
else:
bn_name = "bn" + name[3:]
self._batch_norm = BatchNorm(
num_filters,
act=act,
param_attr=ParamAttr(name=bn_name + '_scale'),
bias_attr=ParamAttr(bn_name + '_offset'),
moving_mean_name=bn_name + '_mean',
moving_variance_name=bn_name + '_variance')
def forward(self, inputs):
if self.is_vd_mode:
inputs = self._pool2d_avg(inputs)
y = self._conv(inputs)
y = self._batch_norm(y)
return y
class BottleneckBlock(fluid.dygraph.Layer):
def __init__(self, def __init__(self,
layers=50, num_channels,
is_3x3=False, num_filters,
postfix_name="", stride,
lr_mult_list=[1.0, 1.0, 1.0, 1.0, 1.0]): shortcut=True,
if_first=False,
name=None):
super(BottleneckBlock, self).__init__()
self.conv0 = ConvBNLayer(
num_channels=num_channels,
num_filters=num_filters,
filter_size=1,
act='relu',
name=name + "_branch2a")
self.conv1 = ConvBNLayer(
num_channels=num_filters,
num_filters=num_filters,
filter_size=3,
stride=stride,
act='relu',
name=name + "_branch2b")
self.conv2 = ConvBNLayer(
num_channels=num_filters,
num_filters=num_filters * 4,
filter_size=1,
act=None,
name=name + "_branch2c")
if not shortcut:
self.short = ConvBNLayer(
num_channels=num_channels,
num_filters=num_filters * 4,
filter_size=1,
stride=1,
is_vd_mode=False if if_first else True,
name=name + "_branch1")
self.shortcut = shortcut
def forward(self, inputs):
y = self.conv0(inputs)
conv1 = self.conv1(y)
conv2 = self.conv2(conv1)
if self.shortcut:
short = inputs
else:
short = self.short(inputs)
y = fluid.layers.elementwise_add(x=short, y=conv2)
layer_helper = LayerHelper(self.full_name(), act='relu')
return layer_helper.append_activation(y)
class BisicBlock(fluid.dygraph.Layer):
def __init__(self,
num_channels,
num_filters,
stride,
shortcut=True,
if_first=False,
name=None):
super(BisicBlock, self).__init__()
self.stride = stride
self.conv0 = ConvBNLayer(
num_channels=num_channels,
num_filters=num_filters,
filter_size=3,
stride=stride,
act='relu',
name=name + "_branch2a")
self.conv1 = ConvBNLayer(
num_channels=num_filters,
num_filters=num_filters,
filter_size=3,
act=None,
name=name + "_branch2b")
if not shortcut:
self.short = ConvBNLayer(
num_channels=num_channels,
num_filters=num_filters,
filter_size=1,
stride=1,
is_vd_mode=False if if_first else True,
name=name + "_branch1")
self.shortcut = shortcut
def forward(self, inputs):
y = self.conv0(inputs)
conv1 = self.conv1(y)
if self.shortcut:
short = inputs
else:
short = self.short(inputs)
y = fluid.layers.elementwise_add(x=short, y=conv1)
layer_helper = LayerHelper(self.full_name(), act='relu')
return layer_helper.append_activation(y)
class ResNet_vd(fluid.dygraph.Layer):
def __init__(self, layers=50, class_dim=1000):
super(ResNet_vd, self).__init__()
self.layers = layers self.layers = layers
self.is_3x3 = is_3x3
self.postfix_name = "" if postfix_name is None else postfix_name
self.lr_mult_list = lr_mult_list
assert len(
self.lr_mult_list
) == 5, "lr_mult_list length in ResNet must be 5 but got {}!!".format(
len(self.lr_mult_list))
self.curr_stage = 0
def net(self, input, class_dim=1000):
is_3x3 = self.is_3x3
layers = self.layers
supported_layers = [18, 34, 50, 101, 152, 200] supported_layers = [18, 34, 50, 101, 152, 200]
assert layers in supported_layers, \ assert layers in supported_layers, \
"supported layers are {} but input layer is {}".format(supported_layers, layers) "supported layers are {} but input layer is {}".format(
supported_layers, layers)
if layers == 18: if layers == 18:
depth = [2, 2, 2, 2] depth = [2, 2, 2, 2]
...@@ -61,254 +201,129 @@ class ResNet(): ...@@ -61,254 +201,129 @@ class ResNet():
depth = [3, 8, 36, 3] depth = [3, 8, 36, 3]
elif layers == 200: elif layers == 200:
depth = [3, 12, 48, 3] depth = [3, 12, 48, 3]
num_channels = [64, 256, 512,
1024] if layers >= 50 else [64, 64, 128, 256]
num_filters = [64, 128, 256, 512] num_filters = [64, 128, 256, 512]
if is_3x3 == False:
conv = self.conv_bn_layer( self.conv1_1 = ConvBNLayer(
input=input, num_channels=3,
num_filters=64,
filter_size=7,
stride=2,
act='relu')
else:
conv = self.conv_bn_layer(
input=input,
num_filters=32, num_filters=32,
filter_size=3, filter_size=3,
stride=2, stride=2,
act='relu', act='relu',
name='conv1_1') name="conv1_1")
conv = self.conv_bn_layer( self.conv1_2 = ConvBNLayer(
input=conv, num_channels=32,
num_filters=32, num_filters=32,
filter_size=3, filter_size=3,
stride=1, stride=1,
act='relu', act='relu',
name='conv1_2') name="conv1_2")
conv = self.conv_bn_layer( self.conv1_3 = ConvBNLayer(
input=conv, num_channels=32,
num_filters=64, num_filters=64,
filter_size=3, filter_size=3,
stride=1, stride=1,
act='relu', act='relu',
name='conv1_3') name="conv1_3")
self.pool2d_max = Pool2D(
conv = fluid.layers.pool2d( pool_size=3, pool_stride=2, pool_padding=1, pool_type='max')
input=conv,
pool_size=3,
pool_stride=2,
pool_padding=1,
pool_type='max')
self.block_list = []
if layers >= 50: if layers >= 50:
for block in range(len(depth)): for block in range(len(depth)):
self.curr_stage += 1 shortcut = False
for i in range(depth[block]): for i in range(depth[block]):
if layers in [101, 152, 200] and block == 2: if layers in [101, 152] and block == 2:
if i == 0: if i == 0:
conv_name = "res" + str(block + 2) + "a" conv_name = "res" + str(block + 2) + "a"
else: else:
conv_name = "res" + str(block + 2) + "b" + str(i) conv_name = "res" + str(block + 2) + "b" + str(i)
else: else:
conv_name = "res" + str(block + 2) + chr(97 + i) conv_name = "res" + str(block + 2) + chr(97 + i)
conv = self.bottleneck_block( bottleneck_block = self.add_sublayer(
input=conv, 'bb_%d_%d' % (block, i),
BottleneckBlock(
num_channels=num_channels[block]
if i == 0 else num_filters[block] * 4,
num_filters=num_filters[block], num_filters=num_filters[block],
stride=2 if i == 0 and block != 0 else 1, stride=2 if i == 0 and block != 0 else 1,
shortcut=shortcut,
if_first=block == i == 0, if_first=block == i == 0,
name=conv_name) name=conv_name))
self.block_list.append(bottleneck_block)
shortcut = True
else: else:
for block in range(len(depth)): for block in range(len(depth)):
self.curr_stage += 1 shortcut = False
for i in range(depth[block]): for i in range(depth[block]):
conv_name = "res" + str(block + 2) + chr(97 + i) conv_name = "res" + str(block + 2) + chr(97 + i)
conv = self.basic_block( bisic_block = self.add_sublayer(
input=conv, 'bb_%d_%d' % (block, i),
BisicBlock(
num_channels=num_channels[block]
if i == 0 else num_filters[block],
num_filters=num_filters[block], num_filters=num_filters[block],
stride=2 if i == 0 and block != 0 else 1, stride=2 if i == 0 and block != 0 else 1,
shortcut=shortcut,
if_first=block == i == 0, if_first=block == i == 0,
name=conv_name) name=conv_name))
self.block_list.append(bisic_block)
pool = fluid.layers.pool2d( shortcut = True
input=conv, pool_type='avg', global_pooling=True)
stdv = 1.0 / math.sqrt(pool.shape[1] * 1.0)
out = fluid.layers.fc( self.pool2d_avg = Pool2D(
input=pool, pool_size=7, pool_type='avg', global_pooling=True)
size=class_dim,
param_attr=fluid.param_attr.ParamAttr(
name="fc_0.w_0" + self.postfix_name,
initializer=fluid.initializer.Uniform(-stdv, stdv)),
bias_attr=ParamAttr(name="fc_0.b_0" + self.postfix_name))
return out self.pool2d_avg_channels = num_channels[-1] * 2
def conv_bn_layer(self, stdv = 1.0 / math.sqrt(self.pool2d_avg_channels * 1.0)
input,
num_filters,
filter_size,
stride=1,
groups=1,
act=None,
name=None):
lr_mult = self.lr_mult_list[self.curr_stage]
conv = fluid.layers.conv2d(
input=input,
num_filters=num_filters,
filter_size=filter_size,
stride=stride,
padding=(filter_size - 1) // 2,
groups=groups,
act=None,
param_attr=ParamAttr(name=name + "_weights" + self.postfix_name),
bias_attr=False)
if name == "conv1":
bn_name = "bn_" + name
else:
bn_name = "bn" + name[3:]
return fluid.layers.batch_norm(
input=conv,
act=act,
param_attr=ParamAttr(name=bn_name + '_scale' + self.postfix_name),
bias_attr=ParamAttr(bn_name + '_offset' + self.postfix_name),
moving_mean_name=bn_name + '_mean' + self.postfix_name,
moving_variance_name=bn_name + '_variance' + self.postfix_name)
def conv_bn_layer_new(self, self.out = Linear(
input, self.pool2d_avg_channels,
num_filters, class_dim,
filter_size,
stride=1,
groups=1,
act=None,
name=None):
lr_mult = self.lr_mult_list[self.curr_stage]
pool = fluid.layers.pool2d(
input=input,
pool_size=2,
pool_stride=2,
pool_padding=0,
pool_type='avg',
ceil_mode=True)
conv = fluid.layers.conv2d(
input=pool,
num_filters=num_filters,
filter_size=filter_size,
stride=1,
padding=(filter_size - 1) // 2,
groups=groups,
act=None,
param_attr=ParamAttr( param_attr=ParamAttr(
name=name + "_weights" + self.postfix_name, initializer=fluid.initializer.Uniform(-stdv, stdv),
learning_rate=lr_mult), name="fc_0.w_0"),
bias_attr=False) bias_attr=ParamAttr(name="fc_0.b_0"))
if name == "conv1":
bn_name = "bn_" + name def forward(self, inputs):
else: y = self.conv1_1(inputs)
bn_name = "bn" + name[3:] y = self.conv1_2(y)
return fluid.layers.batch_norm( y = self.conv1_3(y)
input=conv, y = self.pool2d_max(y)
act=act, for block in self.block_list:
param_attr=ParamAttr( y = block(y)
name=bn_name + '_scale' + self.postfix_name, y = self.pool2d_avg(y)
learning_rate=lr_mult), y = fluid.layers.reshape(y, shape=[-1, self.pool2d_avg_channels])
bias_attr=ParamAttr( y = self.out(y)
bn_name + '_offset' + self.postfix_name, return y
learning_rate=lr_mult),
moving_mean_name=bn_name + '_mean' + self.postfix_name,
moving_variance_name=bn_name + '_variance' + self.postfix_name) def ResNet18_vd(**args):
model = ResNet_vd(layers=18, **args)
def shortcut(self, input, ch_out, stride, name, if_first=False):
ch_in = input.shape[1]
if ch_in != ch_out or stride != 1:
if if_first:
return self.conv_bn_layer(input, ch_out, 1, stride, name=name)
else:
return self.conv_bn_layer_new(
input, ch_out, 1, stride, name=name)
elif if_first:
return self.conv_bn_layer(input, ch_out, 1, stride, name=name)
else:
return input
def bottleneck_block(self, input, num_filters, stride, name, if_first):
conv0 = self.conv_bn_layer(
input=input,
num_filters=num_filters,
filter_size=1,
act='relu',
name=name + "_branch2a")
conv1 = self.conv_bn_layer(
input=conv0,
num_filters=num_filters,
filter_size=3,
stride=stride,
act='relu',
name=name + "_branch2b")
conv2 = self.conv_bn_layer(
input=conv1,
num_filters=num_filters * 4,
filter_size=1,
act=None,
name=name + "_branch2c")
short = self.shortcut(
input,
num_filters * 4,
stride,
if_first=if_first,
name=name + "_branch1")
return fluid.layers.elementwise_add(x=short, y=conv2, act='relu')
def basic_block(self, input, num_filters, stride, name, if_first):
conv0 = self.conv_bn_layer(
input=input,
num_filters=num_filters,
filter_size=3,
act='relu',
stride=stride,
name=name + "_branch2a")
conv1 = self.conv_bn_layer(
input=conv0,
num_filters=num_filters,
filter_size=3,
act=None,
name=name + "_branch2b")
short = self.shortcut(
input,
num_filters,
stride,
if_first=if_first,
name=name + "_branch1")
return fluid.layers.elementwise_add(x=short, y=conv1, act='relu')
def ResNet18_vd():
model = ResNet(layers=18, is_3x3=True)
return model return model
def ResNet34_vd(): def ResNet34_vd(**args):
model = ResNet(layers=34, is_3x3=True) model = ResNet_vd(layers=34, **args)
return model return model
def ResNet50_vd(**args): def ResNet50_vd(**args):
model = ResNet(layers=50, is_3x3=True, **args) model = ResNet_vd(layers=50, **args)
return model return model
def ResNet101_vd(): def ResNet101_vd(**args):
model = ResNet(layers=101, is_3x3=True) model = ResNet_vd(layers=101, **args)
return model return model
def ResNet152_vd(): def ResNet152_vd(**args):
model = ResNet(layers=152, is_3x3=True) model = ResNet_vd(layers=152, **args)
return model return model
def ResNet200_vd(): def ResNet200_vd(**args):
model = ResNet(layers=200, is_3x3=True) model = ResNet_vd(layers=200, **args)
return model return model
#copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. # copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve.
# #
#Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
#You may obtain a copy of the License at # You may obtain a copy of the License at
# #
# http://www.apache.org/licenses/LICENSE-2.0 # http://www.apache.org/licenses/LICENSE-2.0
# #
#Unless required by applicable law or agreed to in writing, software # Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS, # distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
#limitations under the License. # limitations under the License.
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import division from __future__ import division
from __future__ import print_function from __future__ import print_function
import math import numpy as np
import paddle import paddle
import paddle.fluid as fluid import paddle.fluid as fluid
from paddle.fluid.param_attr import ParamAttr from paddle.fluid.param_attr import ParamAttr
from paddle.fluid.layer_helper import LayerHelper
from paddle.fluid.dygraph.nn import Conv2D, Pool2D, BatchNorm, Linear, Dropout
import math
__all__ = [ __all__ = [
"ResNeXt", "ResNeXt50_64x4d", "ResNeXt101_64x4d", "ResNeXt152_64x4d", "ResNeXt50_32x4d", "ResNeXt50_64x4d", "ResNeXt101_32x4d",
"ResNeXt50_32x4d", "ResNeXt101_32x4d", "ResNeXt152_32x4d" "ResNeXt101_64x4d", "ResNeXt152_32x4d", "ResNeXt152_64x4d"
] ]
class ResNeXt(): class ConvBNLayer(fluid.dygraph.Layer):
def __init__(self, layers=50, cardinality=64): def __init__(self,
self.layers = layers num_channels,
self.cardinality = cardinality
def net(self, input, class_dim=1000):
layers = self.layers
cardinality = self.cardinality
supported_layers = [50, 101, 152]
assert layers in supported_layers, \
"supported layers are {} but input layer is {}".format(supported_layers, layers)
if layers == 50:
depth = [3, 4, 6, 3]
elif layers == 101:
depth = [3, 4, 23, 3]
elif layers == 152:
depth = [3, 8, 36, 3]
num_filters1 = [256, 512, 1024, 2048]
num_filters2 = [128, 256, 512, 1024]
conv = self.conv_bn_layer(
input=input,
num_filters=64,
filter_size=7,
stride=2,
act='relu',
name="res_conv1") #debug
conv = fluid.layers.pool2d(
input=conv,
pool_size=3,
pool_stride=2,
pool_padding=1,
pool_type='max')
for block in range(len(depth)):
for i in range(depth[block]):
if layers in [101, 152] and block == 2:
if i == 0:
conv_name = "res" + str(block + 2) + "a"
else:
conv_name = "res" + str(block + 2) + "b" + str(i)
else:
conv_name = "res" + str(block + 2) + chr(97 + i)
conv = self.bottleneck_block(
input=conv,
num_filters=num_filters1[block]
if cardinality == 64 else num_filters2[block],
stride=2 if i == 0 and block != 0 else 1,
cardinality=cardinality,
name=conv_name)
pool = fluid.layers.pool2d(
input=conv, pool_type='avg', global_pooling=True)
stdv = 1.0 / math.sqrt(pool.shape[1] * 1.0)
out = fluid.layers.fc(
input=pool,
size=class_dim,
param_attr=fluid.param_attr.ParamAttr(
initializer=fluid.initializer.Uniform(-stdv, stdv),
name='fc_weights'),
bias_attr=fluid.param_attr.ParamAttr(name='fc_offset'))
return out
def conv_bn_layer(self,
input,
num_filters, num_filters,
filter_size, filter_size,
stride=1, stride=1,
groups=1, groups=1,
act=None, act=None,
name=None): name=None):
conv = fluid.layers.conv2d( super(ConvBNLayer, self).__init__()
input=input,
self._conv = Conv2D(
num_channels=num_channels,
num_filters=num_filters, num_filters=num_filters,
filter_size=filter_size, filter_size=filter_size,
stride=stride, stride=stride,
...@@ -110,86 +51,192 @@ class ResNeXt(): ...@@ -110,86 +51,192 @@ class ResNeXt():
groups=groups, groups=groups,
act=None, act=None,
param_attr=ParamAttr(name=name + "_weights"), param_attr=ParamAttr(name=name + "_weights"),
bias_attr=False, bias_attr=False)
name=name + '.conv2d.output.1')
if name == "conv1": if name == "conv1":
bn_name = "bn_" + name bn_name = "bn_" + name
else: else:
bn_name = "bn" + name[3:] bn_name = "bn" + name[3:]
return fluid.layers.batch_norm( self._batch_norm = BatchNorm(
input=conv, num_filters,
act=act, act=act,
name=bn_name + '.output.1',
param_attr=ParamAttr(name=bn_name + '_scale'), param_attr=ParamAttr(name=bn_name + '_scale'),
bias_attr=ParamAttr(bn_name + '_offset'), bias_attr=ParamAttr(bn_name + '_offset'),
moving_mean_name=bn_name + '_mean', moving_mean_name=bn_name + '_mean',
moving_variance_name=bn_name + '_variance', ) moving_variance_name=bn_name + '_variance')
def shortcut(self, input, ch_out, stride, name): def forward(self, inputs):
ch_in = input.shape[1] y = self._conv(inputs)
if ch_in != ch_out or stride != 1: y = self._batch_norm(y)
return self.conv_bn_layer(input, ch_out, 1, stride, name=name) return y
else:
return input
class BottleneckBlock(fluid.dygraph.Layer):
def __init__(self,
num_channels,
num_filters,
stride,
cardinality,
shortcut=True,
name=None):
super(BottleneckBlock, self).__init__()
def bottleneck_block(self, input, num_filters, stride, cardinality, name): self.conv0 = ConvBNLayer(
cardinality = self.cardinality num_channels=num_channels,
conv0 = self.conv_bn_layer(
input=input,
num_filters=num_filters, num_filters=num_filters,
filter_size=1, filter_size=1,
act='relu', act='relu',
name=name + "_branch2a") name=name + "_branch2a")
conv1 = self.conv_bn_layer( self.conv1 = ConvBNLayer(
input=conv0, num_channels=num_filters,
num_filters=num_filters, num_filters=num_filters,
filter_size=3, filter_size=3,
stride=stride,
groups=cardinality, groups=cardinality,
stride=stride,
act='relu', act='relu',
name=name + "_branch2b") name=name + "_branch2b")
conv2 = self.conv_bn_layer( self.conv2 = ConvBNLayer(
input=conv1, num_channels=num_filters,
num_filters=num_filters if cardinality == 64 else num_filters * 2, num_filters=num_filters * 2 if cardinality == 32 else num_filters,
filter_size=1, filter_size=1,
act=None, act=None,
name=name + "_branch2c") name=name + "_branch2c")
short = self.shortcut( if not shortcut:
input, self.short = ConvBNLayer(
num_filters if cardinality == 64 else num_filters * 2, num_channels=num_channels,
stride, num_filters=num_filters * 2
if cardinality == 32 else num_filters,
filter_size=1,
stride=stride,
name=name + "_branch1") name=name + "_branch1")
return fluid.layers.elementwise_add( self.shortcut = shortcut
x=short, y=conv2, act='relu', name=name + ".add.output.5")
def forward(self, inputs):
y = self.conv0(inputs)
conv1 = self.conv1(y)
conv2 = self.conv2(conv1)
if self.shortcut:
short = inputs
else:
short = self.short(inputs)
y = fluid.layers.elementwise_add(x=short, y=conv2)
layer_helper = LayerHelper(self.full_name(), act='relu')
return layer_helper.append_activation(y)
class ResNeXt(fluid.dygraph.Layer):
def __init__(self, layers=50, class_dim=1000, cardinality=32):
super(ResNeXt, self).__init__()
self.layers = layers
self.cardinality = cardinality
supported_layers = [50, 101, 152]
assert layers in supported_layers, \
"supported layers are {} but input layer is {}".format(
supported_layers, layers)
supported_cardinality = [32, 64]
assert cardinality in supported_cardinality, \
"supported cardinality is {} but input cardinality is {}" \
.format(supported_cardinality, cardinality)
if layers == 50:
depth = [3, 4, 6, 3]
elif layers == 101:
depth = [3, 4, 23, 3]
elif layers == 152:
depth = [3, 8, 36, 3]
num_channels = [64, 256, 512, 1024]
num_filters = [128, 256, 512,
1024] if cardinality == 32 else [256, 512, 1024, 2048]
self.conv = ConvBNLayer(
num_channels=3,
num_filters=64,
filter_size=7,
stride=2,
act='relu',
name="res_conv1")
self.pool2d_max = Pool2D(
pool_size=3, pool_stride=2, pool_padding=1, pool_type='max')
self.block_list = []
for block in range(len(depth)):
shortcut = False
for i in range(depth[block]):
if layers in [101, 152] and block == 2:
if i == 0:
conv_name = "res" + str(block + 2) + "a"
else:
conv_name = "res" + str(block + 2) + "b" + str(i)
else:
conv_name = "res" + str(block + 2) + chr(97 + i)
bottleneck_block = self.add_sublayer(
'bb_%d_%d' % (block, i),
BottleneckBlock(
num_channels=num_channels[block] if i == 0 else
num_filters[block] * int(64 // self.cardinality),
num_filters=num_filters[block],
stride=2 if i == 0 and block != 0 else 1,
cardinality=self.cardinality,
shortcut=shortcut,
name=conv_name))
self.block_list.append(bottleneck_block)
shortcut = True
self.pool2d_avg = Pool2D(
pool_size=7, pool_type='avg', global_pooling=True)
self.pool2d_avg_channels = num_channels[-1] * 2
def ResNeXt50_64x4d(): stdv = 1.0 / math.sqrt(self.pool2d_avg_channels * 1.0)
model = ResNeXt(layers=50, cardinality=64)
self.out = Linear(
self.pool2d_avg_channels,
class_dim,
param_attr=ParamAttr(
initializer=fluid.initializer.Uniform(-stdv, stdv),
name="fc_weights"),
bias_attr=ParamAttr(name="fc_offset"))
def forward(self, inputs):
y = self.conv(inputs)
y = self.pool2d_max(y)
for block in self.block_list:
y = block(y)
y = self.pool2d_avg(y)
y = fluid.layers.reshape(y, shape=[-1, self.pool2d_avg_channels])
y = self.out(y)
return y
def ResNeXt50_32x4d(**args):
model = ResNeXt(layers=50, cardinality=32, **args)
return model return model
def ResNeXt50_32x4d(): def ResNeXt50_64x4d(**args):
model = ResNeXt(layers=50, cardinality=32) model = ResNeXt(layers=50, cardinality=64, **args)
return model return model
def ResNeXt101_64x4d(): def ResNeXt101_32x4d(**args):
model = ResNeXt(layers=101, cardinality=64) model = ResNeXt(layers=101, cardinality=32, **args)
return model return model
def ResNeXt101_32x4d(): def ResNeXt101_64x4d(**args):
model = ResNeXt(layers=101, cardinality=32) model = ResNeXt(layers=101, cardinality=64, **args)
return model return model
def ResNeXt152_64x4d(): def ResNeXt152_32x4d(**args):
model = ResNeXt(layers=152, cardinality=64) model = ResNeXt(layers=152, cardinality=32, **args)
return model return model
def ResNeXt152_32x4d(): def ResNeXt152_64x4d(**args):
model = ResNeXt(layers=152, cardinality=32) model = ResNeXt(layers=152, cardinality=64, **args)
return model return model
#copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. # copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve.
# #
#Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
#You may obtain a copy of the License at # You may obtain a copy of the License at
# #
# http://www.apache.org/licenses/LICENSE-2.0 # http://www.apache.org/licenses/LICENSE-2.0
# #
#Unless required by applicable law or agreed to in writing, software # Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS, # distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
#limitations under the License. # limitations under the License.
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import numpy as np
import paddle import paddle
import paddle.fluid as fluid import paddle.fluid as fluid
from paddle.fluid.param_attr import ParamAttr from paddle.fluid.param_attr import ParamAttr
from paddle.fluid.layer_helper import LayerHelper
from paddle.fluid.dygraph.nn import Conv2D, Pool2D, BatchNorm, Linear, Dropout
import math import math
__all__ = [ __all__ = [
"ResNeXt", "ResNeXt50_vd_64x4d", "ResNeXt101_vd_64x4d", "ResNeXt50_vd_32x4d", "ResNeXt50_vd_64x4d", "ResNeXt101_vd_32x4d",
"ResNeXt152_vd_64x4d", "ResNeXt50_vd_32x4d", "ResNeXt101_vd_32x4d", "ResNeXt101_vd_64x4d", "ResNeXt152_vd_32x4d", "ResNeXt152_vd_64x4d"
"ResNeXt152_vd_32x4d"
] ]
class ResNeXt(): class ConvBNLayer(fluid.dygraph.Layer):
def __init__(self, layers=50, is_3x3=False, cardinality=64): def __init__(
self.layers = layers self,
self.is_3x3 = is_3x3 num_channels,
self.cardinality = cardinality
def net(self, input, class_dim=1000):
is_3x3 = self.is_3x3
layers = self.layers
cardinality = self.cardinality
supported_layers = [50, 101, 152]
assert layers in supported_layers, \
"supported layers are {} but input layer is {}".format(supported_layers, layers)
if layers == 50:
depth = [3, 4, 6, 3]
elif layers == 101:
depth = [3, 4, 23, 3]
elif layers == 152:
depth = [3, 8, 36, 3]
num_filters1 = [256, 512, 1024, 2048]
num_filters2 = [128, 256, 512, 1024]
if is_3x3 == False:
conv = self.conv_bn_layer(
input=input,
num_filters=64,
filter_size=7,
stride=2,
act='relu')
else:
conv = self.conv_bn_layer(
input=input,
num_filters=32,
filter_size=3,
stride=2,
act='relu',
name='conv1_1')
conv = self.conv_bn_layer(
input=conv,
num_filters=32,
filter_size=3,
stride=1,
act='relu',
name='conv1_2')
conv = self.conv_bn_layer(
input=conv,
num_filters=64,
filter_size=3,
stride=1,
act='relu',
name='conv1_3')
conv = fluid.layers.pool2d(
input=conv,
pool_size=3,
pool_stride=2,
pool_padding=1,
pool_type='max')
for block in range(len(depth)):
for i in range(depth[block]):
if layers in [101, 152, 200] and block == 2:
if i == 0:
conv_name = "res" + str(block + 2) + "a"
else:
conv_name = "res" + str(block + 2) + "b" + str(i)
else:
conv_name = "res" + str(block + 2) + chr(97 + i)
conv = self.bottleneck_block(
input=conv,
num_filters=num_filters1[block]
if cardinality == 64 else num_filters2[block],
stride=2 if i == 0 and block != 0 else 1,
cardinality=cardinality,
if_first=block == 0,
name=conv_name)
pool = fluid.layers.pool2d(
input=conv, pool_type='avg', global_pooling=True)
stdv = 1.0 / math.sqrt(pool.shape[1] * 1.0)
out = fluid.layers.fc(
input=pool,
size=class_dim,
param_attr=fluid.param_attr.ParamAttr(
initializer=fluid.initializer.Uniform(-stdv, stdv),
name='fc_weights'),
bias_attr=fluid.param_attr.ParamAttr(name='fc_offset'))
return out
def conv_bn_layer(self,
input,
num_filters, num_filters,
filter_size, filter_size,
stride=1, stride=1,
groups=1, groups=1,
is_vd_mode=False,
act=None, act=None,
name=None): name=None, ):
conv = fluid.layers.conv2d( super(ConvBNLayer, self).__init__()
input=input,
self.is_vd_mode = is_vd_mode
self._pool2d_avg = Pool2D(
pool_size=2, pool_stride=2, pool_padding=0, pool_type='avg')
self._conv = Conv2D(
num_channels=num_channels,
num_filters=num_filters, num_filters=num_filters,
filter_size=filter_size, filter_size=filter_size,
stride=stride, stride=stride,
...@@ -137,121 +61,209 @@ class ResNeXt(): ...@@ -137,121 +61,209 @@ class ResNeXt():
bn_name = "bn_" + name bn_name = "bn_" + name
else: else:
bn_name = "bn" + name[3:] bn_name = "bn" + name[3:]
return fluid.layers.batch_norm( self._batch_norm = BatchNorm(
input=conv, num_filters,
act=act, act=act,
param_attr=ParamAttr(name=bn_name + '_scale'), param_attr=ParamAttr(name=bn_name + '_scale'),
bias_attr=ParamAttr(bn_name + '_offset'), bias_attr=ParamAttr(bn_name + '_offset'),
moving_mean_name=bn_name + '_mean', moving_mean_name=bn_name + '_mean',
moving_variance_name=bn_name + '_variance') moving_variance_name=bn_name + '_variance')
def conv_bn_layer_new(self, def forward(self, inputs):
input, if self.is_vd_mode:
inputs = self._pool2d_avg(inputs)
y = self._conv(inputs)
y = self._batch_norm(y)
return y
class BottleneckBlock(fluid.dygraph.Layer):
def __init__(self,
num_channels,
num_filters, num_filters,
filter_size, stride,
stride=1, cardinality,
groups=1, shortcut=True,
act=None, if_first=False,
name=None): name=None):
pool = fluid.layers.pool2d( super(BottleneckBlock, self).__init__()
input=input,
pool_size=2,
pool_stride=2,
pool_padding=0,
pool_type='avg',
ceil_mode=True)
conv = fluid.layers.conv2d(
input=pool,
num_filters=num_filters,
filter_size=filter_size,
stride=1,
padding=(filter_size - 1) // 2,
groups=groups,
act=None,
param_attr=ParamAttr(name=name + "_weights"),
bias_attr=False)
if name == "conv1":
bn_name = "bn_" + name
else:
bn_name = "bn" + name[3:]
return fluid.layers.batch_norm(
input=conv,
act=act,
param_attr=ParamAttr(name=bn_name + '_scale'),
bias_attr=ParamAttr(bn_name + '_offset'),
moving_mean_name=bn_name + '_mean',
moving_variance_name=bn_name + '_variance')
def shortcut(self, input, ch_out, stride, name, if_first=False):
ch_in = input.shape[1]
if ch_in != ch_out or stride != 1:
if if_first:
return self.conv_bn_layer(input, ch_out, 1, stride, name=name)
else:
return self.conv_bn_layer_new(
input, ch_out, 1, stride, name=name)
else:
return input
def bottleneck_block(self, input, num_filters, stride, cardinality, name, self.conv0 = ConvBNLayer(
if_first): num_channels=num_channels,
conv0 = self.conv_bn_layer(
input=input,
num_filters=num_filters, num_filters=num_filters,
filter_size=1, filter_size=1,
act='relu', act='relu',
name=name + "_branch2a") name=name + "_branch2a")
conv1 = self.conv_bn_layer( self.conv1 = ConvBNLayer(
input=conv0, num_channels=num_filters,
num_filters=num_filters, num_filters=num_filters,
filter_size=3, filter_size=3,
groups=cardinality,
stride=stride, stride=stride,
act='relu', act='relu',
groups=cardinality,
name=name + "_branch2b") name=name + "_branch2b")
conv2 = self.conv_bn_layer( self.conv2 = ConvBNLayer(
input=conv1, num_channels=num_filters,
num_filters=num_filters if cardinality == 64 else num_filters * 2, num_filters=num_filters * 2 if cardinality == 32 else num_filters,
filter_size=1, filter_size=1,
act=None, act=None,
name=name + "_branch2c") name=name + "_branch2c")
short = self.shortcut( if not shortcut:
input, self.short = ConvBNLayer(
num_filters if cardinality == 64 else num_filters * 2, num_channels=num_channels,
stride, num_filters=num_filters * 2
if_first=if_first, if cardinality == 32 else num_filters,
filter_size=1,
stride=1,
is_vd_mode=False if if_first else True,
name=name + "_branch1") name=name + "_branch1")
return fluid.layers.elementwise_add(x=short, y=conv2, act='relu') self.shortcut = shortcut
def forward(self, inputs):
y = self.conv0(inputs)
conv1 = self.conv1(y)
conv2 = self.conv2(conv1)
if self.shortcut:
short = inputs
else:
short = self.short(inputs)
y = fluid.layers.elementwise_add(x=short, y=conv2)
layer_helper = LayerHelper(self.full_name(), act='relu')
return layer_helper.append_activation(y)
class ResNeXt(fluid.dygraph.Layer):
def __init__(self, layers=50, class_dim=1000, cardinality=32):
super(ResNeXt, self).__init__()
self.layers = layers
self.cardinality = cardinality
supported_layers = [50, 101, 152]
assert layers in supported_layers, \
"supported layers are {} but input layer is {}".format(
supported_layers, layers)
supported_cardinality = [32, 64]
assert cardinality in supported_cardinality, \
"supported cardinality is {} but input cardinality is {}" \
.format(supported_cardinality, cardinality)
if layers == 50:
depth = [3, 4, 6, 3]
elif layers == 101:
depth = [3, 4, 23, 3]
elif layers == 152:
depth = [3, 8, 36, 3]
num_channels = [64, 256, 512, 1024]
num_filters = [128, 256, 512,
1024] if cardinality == 32 else [256, 512, 1024, 2048]
self.conv1_1 = ConvBNLayer(
num_channels=3,
num_filters=32,
filter_size=3,
stride=2,
act='relu',
name="conv1_1")
self.conv1_2 = ConvBNLayer(
num_channels=32,
num_filters=32,
filter_size=3,
stride=1,
act='relu',
name="conv1_2")
self.conv1_3 = ConvBNLayer(
num_channels=32,
num_filters=64,
filter_size=3,
stride=1,
act='relu',
name="conv1_3")
self.pool2d_max = Pool2D(
pool_size=3, pool_stride=2, pool_padding=1, pool_type='max')
self.block_list = []
for block in range(len(depth)):
shortcut = False
for i in range(depth[block]):
if layers in [101, 152] and block == 2:
if i == 0:
conv_name = "res" + str(block + 2) + "a"
else:
conv_name = "res" + str(block + 2) + "b" + str(i)
else:
conv_name = "res" + str(block + 2) + chr(97 + i)
bottleneck_block = self.add_sublayer(
'bb_%d_%d' % (block, i),
BottleneckBlock(
num_channels=num_channels[block] if i == 0 else
num_filters[block] * int(64 // self.cardinality),
num_filters=num_filters[block],
stride=2 if i == 0 and block != 0 else 1,
cardinality=self.cardinality,
shortcut=shortcut,
if_first=block == i == 0,
name=conv_name))
self.block_list.append(bottleneck_block)
shortcut = True
self.pool2d_avg = Pool2D(
pool_size=7, pool_type='avg', global_pooling=True)
self.pool2d_avg_channels = num_channels[-1] * 2
stdv = 1.0 / math.sqrt(self.pool2d_avg_channels * 1.0)
self.out = Linear(
self.pool2d_avg_channels,
class_dim,
param_attr=ParamAttr(
initializer=fluid.initializer.Uniform(-stdv, stdv),
name="fc_weights"),
bias_attr=ParamAttr(name="fc_offset"))
def forward(self, inputs):
y = self.conv1_1(inputs)
y = self.conv1_2(y)
y = self.conv1_3(y)
y = self.pool2d_max(y)
for block in self.block_list:
y = block(y)
y = self.pool2d_avg(y)
y = fluid.layers.reshape(y, shape=[-1, self.pool2d_avg_channels])
y = self.out(y)
return y
def ResNeXt50_vd_64x4d(): def ResNeXt50_vd_32x4d(**args):
model = ResNeXt(layers=50, is_3x3=True) model = ResNeXt(layers=50, cardinality=32, **args)
return model return model
def ResNeXt50_vd_32x4d(): def ResNeXt50_vd_64x4d(**args):
model = ResNeXt(layers=50, cardinality=32, is_3x3=True) model = ResNeXt(layers=50, cardinality=64, **args)
return model return model
def ResNeXt101_vd_64x4d(): def ResNeXt101_vd_32x4d(**args):
model = ResNeXt(layers=101, is_3x3=True) model = ResNeXt(layers=101, cardinality=32, **args)
return model return model
def ResNeXt101_vd_32x4d(): def ResNeXt101_vd_64x4d(**args):
model = ResNeXt(layers=101, cardinality=32, is_3x3=True) model = ResNeXt(layers=101, cardinality=64, **args)
return model return model
def ResNeXt152_vd_64x4d(): def ResNeXt152_vd_32x4d(**args):
model = ResNeXt(layers=152, is_3x3=True) model = ResNeXt(layers=152, cardinality=32, **args)
return model return model
def ResNeXt152_vd_32x4d(): def ResNeXt152_vd_64x4d(**args):
model = ResNeXt(layers=152, cardinality=32, is_3x3=True) model = ResNeXt(layers=152, cardinality=64, **args)
return model return model
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册