Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
PaddlePaddle
PaddleClas
提交
7f80e25c
P
PaddleClas
项目概览
PaddlePaddle
/
PaddleClas
大约 1 年 前同步成功
通知
115
Star
4999
Fork
1114
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
19
列表
看板
标记
里程碑
合并请求
6
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
PaddleClas
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
19
Issue
19
列表
看板
标记
里程碑
合并请求
6
合并请求
6
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
7f80e25c
编写于
7月 31, 2020
作者:
C
cuicheng01
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add mobilenet, resnet and senet series dymodels
上级
0e7bea51
变更
15
显示空白变更内容
内联
并排
Showing
15 changed file
with
2916 addition
and
2692 deletion
+2916
-2692
ppcls/modeling/architectures/__init__.py
ppcls/modeling/architectures/__init__.py
+14
-2
ppcls/modeling/architectures/mobilenet_v1.py
ppcls/modeling/architectures/mobilenet_v1.py
+217
-166
ppcls/modeling/architectures/mobilenet_v2.py
ppcls/modeling/architectures/mobilenet_v2.py
+182
-163
ppcls/modeling/architectures/mobilenet_v3.py
ppcls/modeling/architectures/mobilenet_v3.py
+240
-218
ppcls/modeling/architectures/res2net.py
ppcls/modeling/architectures/res2net.py
+213
-158
ppcls/modeling/architectures/res2net_vd.py
ppcls/modeling/architectures/res2net_vd.py
+216
-207
ppcls/modeling/architectures/resnet.py
ppcls/modeling/architectures/resnet.py
+154
-56
ppcls/modeling/architectures/resnet_vc.py
ppcls/modeling/architectures/resnet_vc.py
+255
-136
ppcls/modeling/architectures/resnet_vd.py
ppcls/modeling/architectures/resnet_vd.py
+256
-241
ppcls/modeling/architectures/resnext.py
ppcls/modeling/architectures/resnext.py
+177
-130
ppcls/modeling/architectures/resnext_vd.py
ppcls/modeling/architectures/resnext_vd.py
+202
-190
ppcls/modeling/architectures/se_resnet_vd.py
ppcls/modeling/architectures/se_resnet_vd.py
+297
-249
ppcls/modeling/architectures/se_resnext_vd.py
ppcls/modeling/architectures/se_resnext_vd.py
+245
-283
ppcls/modeling/architectures/shufflenet_v2.py
ppcls/modeling/architectures/shufflenet_v2.py
+248
-200
ppcls/modeling/architectures/shufflenet_v2_swish.py
ppcls/modeling/architectures/shufflenet_v2_swish.py
+0
-293
未找到文件。
ppcls/modeling/architectures/__init__.py
浏览文件 @
7f80e25c
...
...
@@ -12,7 +12,19 @@
# See the License for the specific language governing permissions and
# 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
.densenet
import
DenseNet121
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
ppcls/modeling/architectures/mobilenet_v1.py
浏览文件 @
7f80e25c
#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");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
Licensed under the Apache License, Version 2.0 (the "License");
#
you may not use this file except in compliance with the License.
#
You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
#
Unless required by applicable law or agreed to in writing, software
#
distributed under the License is distributed on an "AS IS" BASIS,
#
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
See the License for the specific language governing permissions and
#
limitations under the License.
from
__future__
import
absolute_import
from
__future__
import
division
from
__future__
import
print_function
import
numpy
as
np
import
paddle
import
paddle.fluid
as
fluid
from
paddle.fluid.initializer
import
MSRA
from
paddle.fluid.param_attr
import
ParamAttr
from
paddle.fluid.layer_helper
import
LayerHelper
from
paddle.fluid.dygraph.nn
import
Conv2D
,
Pool2D
,
BatchNorm
,
Linear
,
Dropout
from
paddle.fluid.initializer
import
MSRA
import
math
__all__
=
[
'MobileNetV1'
,
'MobileNetV1_x0_25'
,
'MobileNetV1_x0_5'
,
'MobileNetV1_x1_0'
,
'MobileNetV1_x0_75'
"MobileNetV1_x0_25"
,
"MobileNetV1_x0_5"
,
"MobileNetV1_x0_75"
,
"MobileNetV1"
]
class
MobileNetV1
():
def
__init__
(
self
,
scale
=
1.0
):
class
ConvBNLayer
(
fluid
.
dygraph
.
Layer
):
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
.
block_list
=
[]
def
net
(
self
,
input
,
class_dim
=
1000
):
scale
=
self
.
scale
# conv1: 112x112
input
=
self
.
conv_bn_layer
(
input
,
self
.
conv1
=
ConvBNLayer
(
num_channels
=
3
,
filter_size
=
3
,
channels
=
3
,
num_filters
=
int
(
32
*
scale
),
...
...
@@ -42,177 +121,149 @@ class MobileNetV1():
padding
=
1
,
name
=
"conv1"
)
# 56x56
input
=
self
.
depthwise_separable
(
input
,
conv2_1
=
self
.
add_sublayer
(
"conv2_1"
,
sublayer
=
DepthwiseSeparable
(
num_channels
=
int
(
32
*
scale
),
num_filters1
=
32
,
num_filters2
=
64
,
num_groups
=
32
,
stride
=
1
,
scale
=
scale
,
name
=
"conv2_1"
)
name
=
"conv2_1"
))
self
.
block_list
.
append
(
conv2_1
)
input
=
self
.
depthwise_separable
(
input
,
conv2_2
=
self
.
add_sublayer
(
"conv2_2"
,
sublayer
=
DepthwiseSeparable
(
num_channels
=
int
(
64
*
scale
),
num_filters1
=
64
,
num_filters2
=
128
,
num_groups
=
64
,
stride
=
2
,
scale
=
scale
,
name
=
"conv2_2"
)
name
=
"conv2_2"
))
self
.
block_list
.
append
(
conv2_2
)
# 28x28
input
=
self
.
depthwise_separable
(
input
,
conv3_1
=
self
.
add_sublayer
(
"conv3_1"
,
sublayer
=
DepthwiseSeparable
(
num_channels
=
int
(
128
*
scale
),
num_filters1
=
128
,
num_filters2
=
128
,
num_groups
=
128
,
stride
=
1
,
scale
=
scale
,
name
=
"conv3_1"
)
name
=
"conv3_1"
))
self
.
block_list
.
append
(
conv3_1
)
input
=
self
.
depthwise_separable
(
input
,
conv3_2
=
self
.
add_sublayer
(
"conv3_2"
,
sublayer
=
DepthwiseSeparable
(
num_channels
=
int
(
128
*
scale
),
num_filters1
=
128
,
num_filters2
=
256
,
num_groups
=
128
,
stride
=
2
,
scale
=
scale
,
name
=
"conv3_2"
)
name
=
"conv3_2"
))
self
.
block_list
.
append
(
conv3_2
)
# 14x14
input
=
self
.
depthwise_separable
(
input
,
conv4_1
=
self
.
add_sublayer
(
"conv4_1"
,
sublayer
=
DepthwiseSeparable
(
num_channels
=
int
(
256
*
scale
),
num_filters1
=
256
,
num_filters2
=
256
,
num_groups
=
256
,
stride
=
1
,
scale
=
scale
,
name
=
"conv4_1"
)
name
=
"conv4_1"
))
self
.
block_list
.
append
(
conv4_1
)
input
=
self
.
depthwise_separable
(
input
,
conv4_2
=
self
.
add_sublayer
(
"conv4_2"
,
sublayer
=
DepthwiseSeparable
(
num_channels
=
int
(
256
*
scale
),
num_filters1
=
256
,
num_filters2
=
512
,
num_groups
=
256
,
stride
=
2
,
scale
=
scale
,
name
=
"conv4_2"
)
name
=
"conv4_2"
))
self
.
block_list
.
append
(
conv4_2
)
# 14x14
for
i
in
range
(
5
):
input
=
self
.
depthwise_separable
(
input
,
conv5
=
self
.
add_sublayer
(
"conv5_"
+
str
(
i
+
1
),
sublayer
=
DepthwiseSeparable
(
num_channels
=
int
(
512
*
scale
),
num_filters1
=
512
,
num_filters2
=
512
,
num_groups
=
512
,
stride
=
1
,
scale
=
scale
,
name
=
"conv5"
+
"_"
+
str
(
i
+
1
))
# 7x7
input
=
self
.
depthwise_separable
(
input
,
name
=
"conv5_"
+
str
(
i
+
1
)))
self
.
block_list
.
append
(
conv5
)
conv5_6
=
self
.
add_sublayer
(
"conv5_6"
,
sublayer
=
DepthwiseSeparable
(
num_channels
=
int
(
512
*
scale
),
num_filters1
=
512
,
num_filters2
=
1024
,
num_groups
=
512
,
stride
=
2
,
scale
=
scale
,
name
=
"conv5_6"
)
name
=
"conv5_6"
))
self
.
block_list
.
append
(
conv5_6
)
input
=
self
.
depthwise_separable
(
input
,
conv6
=
self
.
add_sublayer
(
"conv6"
,
sublayer
=
DepthwiseSeparable
(
num_channels
=
int
(
1024
*
scale
),
num_filters1
=
1024
,
num_filters2
=
1024
,
num_groups
=
1024
,
stride
=
1
,
scale
=
scale
,
name
=
"conv6"
)
name
=
"conv6"
))
self
.
block_list
.
append
(
conv6
)
input
=
fluid
.
layers
.
pool2d
(
input
=
input
,
pool_type
=
'avg'
,
global_pooling
=
True
)
self
.
pool2d_avg
=
Pool2D
(
pool_type
=
'avg'
,
global_pooling
=
True
)
output
=
fluid
.
layers
.
fc
(
input
=
input
,
size
=
class_dim
,
self
.
out
=
Linear
(
int
(
1024
*
scale
),
class_dim
,
param_attr
=
ParamAttr
(
initializer
=
MSRA
(),
name
=
"fc7_weights"
),
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
,
input
,
num_filters1
,
num_filters2
,
num_groups
,
stride
,
scale
,
name
=
None
):
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
forward
(
self
,
inputs
):
y
=
self
.
conv1
(
inputs
)
for
block
in
self
.
block_list
:
y
=
block
(
y
)
y
=
self
.
pool2d_avg
(
y
)
y
=
fluid
.
layers
.
reshape
(
y
,
shape
=
[
-
1
,
int
(
1024
*
self
.
scale
)])
y
=
self
.
out
(
y
)
return
y
def
MobileNetV1_x0_25
():
model
=
MobileNet
V1
(
scale
=
0.25
)
def
MobileNetV1_x0_25
(
**
args
):
model
=
MobileNet
(
scale
=
0.25
,
**
args
)
return
model
def
MobileNetV1_x0_5
():
model
=
MobileNet
V1
(
scale
=
0.5
)
def
MobileNetV1_x0_5
(
**
args
):
model
=
MobileNet
(
scale
=
0.5
,
**
args
)
return
model
def
MobileNetV1_x
1_0
(
):
model
=
MobileNet
V1
(
scale
=
1.0
)
def
MobileNetV1_x
0_75
(
**
args
):
model
=
MobileNet
(
scale
=
0.75
,
**
args
)
return
model
def
MobileNetV1
_x0_75
(
):
model
=
MobileNet
V1
(
scale
=
0.75
)
def
MobileNetV1
(
**
args
):
model
=
MobileNet
(
scale
=
1.0
,
**
args
)
return
model
ppcls/modeling/architectures/mobilenet_v2.py
浏览文件 @
7f80e25c
#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");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
Licensed under the Apache License, Version 2.0 (the "License");
#
you may not use this file except in compliance with the License.
#
You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
#
Unless required by applicable law or agreed to in writing, software
#
distributed under the License is distributed on an "AS IS" BASIS,
#
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
See the License for the specific language governing permissions and
#
limitations under the License.
from
__future__
import
absolute_import
from
__future__
import
division
from
__future__
import
print_function
import
numpy
as
np
import
paddle
import
paddle.fluid
as
fluid
from
paddle.fluid.initializer
import
MSRA
from
paddle.fluid.param_attr
import
ParamAttr
from
paddle.fluid.layer_helper
import
LayerHelper
from
paddle.fluid.dygraph.nn
import
Conv2D
,
Pool2D
,
BatchNorm
,
Linear
,
Dropout
import
math
__all__
=
[
'MobileNetV2_x0_25'
,
'MobileNetV2_x0_5'
'MobileNetV2_x0_75'
,
'MobileNetV2_x1_0'
,
'MobileNetV2_x1_5'
,
'MobileNetV2_x2_0'
,
'MobileNetV2'
"MobileNetV2_x0_25"
,
"MobileNetV2_x0_5"
,
"MobileNetV2_x0_75"
,
"MobileNetV2"
,
"MobileNetV2_x1_5"
,
"MobileNetV2_x2_0"
]
class
MobileNetV2
():
def
__init__
(
self
,
scale
=
1.0
):
self
.
scale
=
scale
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
,
class
ConvBNLayer
(
fluid
.
dygraph
.
Layer
):
def
__init__
(
self
,
num_channels
,
filter_size
,
num_filters
,
stride
,
padding
,
channels
=
None
,
num_groups
=
1
,
if_act
=
True
,
name
=
None
,
use_cudnn
=
True
):
conv
=
fluid
.
layers
.
conv2d
(
input
=
input
,
super
(
ConvBNLayer
,
self
).
__init__
()
self
.
_conv
=
Conv2D
(
num_channels
=
num_channels
,
num_filters
=
num_filters
,
filter_size
=
filter_size
,
stride
=
stride
,
...
...
@@ -106,125 +53,197 @@ class MobileNetV2():
groups
=
num_groups
,
act
=
None
,
use_cudnn
=
use_cudnn
,
param_attr
=
ParamAttr
(
name
=
name
+
'_weights'
),
param_attr
=
ParamAttr
(
name
=
name
+
"_weights"
),
bias_attr
=
False
)
bn_name
=
name
+
'_bn'
bn
=
fluid
.
layers
.
batch_norm
(
input
=
conv
,
param_attr
=
ParamAttr
(
name
=
bn_name
+
"_scale"
),
bias_attr
=
ParamAttr
(
name
=
bn_name
+
"_offset"
),
moving_mean_name
=
bn_name
+
'_mean'
,
moving_variance_name
=
bn_name
+
'_variance'
)
self
.
_batch_norm
=
BatchNorm
(
num_filters
,
param_attr
=
ParamAttr
(
name
=
name
+
"_bn_scale"
),
bias_attr
=
ParamAttr
(
name
=
name
+
"_bn_offset"
),
moving_mean_name
=
name
+
"_bn_mean"
,
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
:
return
fluid
.
layers
.
relu6
(
bn
)
else
:
return
bn
y
=
fluid
.
layers
.
relu6
(
y
)
return
y
def
shortcut
(
self
,
input
,
data_residual
):
return
fluid
.
layers
.
elementwise_add
(
input
,
data_residual
)
def
inverted_residual_unit
(
self
,
input
,
num_in_filter
,
num_filters
,
ifshortcut
,
stride
,
filter_size
,
padding
,
expansion_factor
,
name
=
None
):
class
InvertedResidualUnit
(
fluid
.
dygraph
.
Layer
):
def
__init__
(
self
,
num_channels
,
num_in_filter
,
num_filters
,
stride
,
filter_size
,
padding
,
expansion_factor
,
name
):
super
(
InvertedResidualUnit
,
self
).
__init__
()
num_expfilter
=
int
(
round
(
num_in_filter
*
expansion_factor
))
channel_expand
=
self
.
conv_bn_layer
(
input
=
input
,
self
.
_expand_conv
=
ConvBNLayer
(
num_channels
=
num_channels
,
num_filters
=
num_expfilter
,
filter_size
=
1
,
stride
=
1
,
padding
=
0
,
num_groups
=
1
,
if_act
=
True
,
name
=
name
+
'_expand'
)
name
=
name
+
"_expand"
)
bottleneck_conv
=
self
.
conv_bn_l
ayer
(
input
=
channel_expand
,
self
.
_bottleneck_conv
=
ConvBNL
ayer
(
num_channels
=
num_expfilter
,
num_filters
=
num_expfilter
,
filter_size
=
filter_size
,
stride
=
stride
,
padding
=
padding
,
num_groups
=
num_expfilter
,
if_act
=
True
,
name
=
name
+
'_dwise'
,
use_cudnn
=
False
)
use_cudnn
=
False
,
name
=
name
+
"_dwise"
)
linear_out
=
self
.
conv_bn_l
ayer
(
input
=
bottleneck_conv
,
self
.
_linear_conv
=
ConvBNL
ayer
(
num_channels
=
num_expfilter
,
num_filters
=
num_filters
,
filter_size
=
1
,
stride
=
1
,
padding
=
0
,
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
:
out
=
self
.
shortcut
(
input
=
input
,
data_residual
=
linear_out
)
return
out
else
:
return
linear_out
def
invresi_blocks
(
self
,
input
,
in_c
,
t
,
c
,
n
,
s
,
name
=
None
):
first_block
=
self
.
inverted_residual_unit
(
input
=
input
,
y
=
fluid
.
layers
.
elementwise_add
(
inputs
,
y
)
return
y
class
InvresiBlocks
(
fluid
.
dygraph
.
Layer
):
def
__init__
(
self
,
in_c
,
t
,
c
,
n
,
s
,
name
):
super
(
InvresiBlocks
,
self
).
__init__
()
self
.
_first_block
=
InvertedResidualUnit
(
num_channels
=
in_c
,
num_in_filter
=
in_c
,
num_filters
=
c
,
ifshortcut
=
False
,
stride
=
s
,
filter_size
=
3
,
padding
=
1
,
expansion_factor
=
t
,
name
=
name
+
'_1'
)
last_residual_block
=
first_block
last_c
=
c
name
=
name
+
"_1"
)
self
.
_block_list
=
[]
for
i
in
range
(
1
,
n
):
last_residual_block
=
self
.
inverted_residual_unit
(
input
=
last_residual_block
,
num_in_filter
=
last_c
,
block
=
self
.
add_sublayer
(
name
+
"_"
+
str
(
i
+
1
),
sublayer
=
InvertedResidualUnit
(
num_channels
=
c
,
num_in_filter
=
c
,
num_filters
=
c
,
ifshortcut
=
True
,
stride
=
1
,
filter_size
=
3
,
padding
=
1
,
expansion_factor
=
t
,
name
=
name
+
'_'
+
str
(
i
+
1
))
return
last_residual_block
name
=
name
+
"_"
+
str
(
i
+
1
)))
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
():
model
=
MobileNet
V2
(
scale
=
0.25
)
def
MobileNetV2_x0_25
(
**
args
):
model
=
MobileNet
(
scale
=
0.25
,
**
args
)
return
model
def
MobileNetV2_x0_5
():
model
=
MobileNet
V2
(
scale
=
0.5
)
def
MobileNetV2_x0_5
(
**
args
):
model
=
MobileNet
(
scale
=
0.5
,
**
args
)
return
model
def
MobileNetV2_x0_75
():
model
=
MobileNet
V2
(
scale
=
0.75
)
def
MobileNetV2_x0_75
(
**
args
):
model
=
MobileNet
(
scale
=
0.75
,
**
args
)
return
model
def
MobileNetV2
_x1_0
(
):
model
=
MobileNet
V2
(
scale
=
1.0
)
def
MobileNetV2
(
**
args
):
model
=
MobileNet
(
scale
=
1.0
,
**
args
)
return
model
def
MobileNetV2_x1_5
():
model
=
MobileNet
V2
(
scale
=
1.5
)
def
MobileNetV2_x1_5
(
**
args
):
model
=
MobileNet
(
scale
=
1.5
,
**
args
)
return
model
def
MobileNetV2_x2_0
():
model
=
MobileNet
V2
(
scale
=
2.0
)
def
MobileNetV2_x2_0
(
**
args
):
model
=
MobileNet
(
scale
=
2.0
,
**
args
)
return
model
ppcls/modeling/architectures/mobilenet_v3.py
浏览文件 @
7f80e25c
...
...
@@ -16,320 +16,342 @@ 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
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__
=
[
'MobileNetV3'
,
'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'
"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"
]
class
MobileNetV3
():
def
__init__
(
self
,
scale
=
1.0
,
model_name
=
'small'
,
lr_mult_list
=
[
1.0
,
1.0
,
1.0
,
1.0
,
1.0
]):
self
.
scale
=
scale
self
.
inplanes
=
16
self
.
lr_mult_list
=
lr_mult_list
assert
len
(
self
.
lr_mult_list
)
==
5
,
\
"lr_mult_list length in MobileNetV3 must be 5 but got {}!!"
.
format
(
len
(
self
.
lr_mult_list
))
self
.
curr_stage
=
0
def
make_divisible
(
v
,
divisor
=
8
,
min_value
=
None
):
if
min_value
is
None
:
min_value
=
divisor
new_v
=
max
(
min_value
,
int
(
v
+
divisor
/
2
)
//
divisor
*
divisor
)
if
new_v
<
0.9
*
v
:
new_v
+=
divisor
return
new_v
class
MobileNetV3
(
fluid
.
dygraph
.
Layer
):
def
__init__
(
self
,
scale
=
1.0
,
model_name
=
"small"
,
class_dim
=
1000
):
super
(
MobileNetV3
,
self
).
__init__
()
inplanes
=
16
if
model_name
==
"large"
:
self
.
cfg
=
[
# k, exp, c, se, nl, s,
[
3
,
16
,
16
,
False
,
'relu'
,
1
],
[
3
,
64
,
24
,
False
,
'relu'
,
2
],
[
3
,
72
,
24
,
False
,
'relu'
,
1
],
[
5
,
72
,
40
,
True
,
'relu'
,
2
],
[
5
,
120
,
40
,
True
,
'relu'
,
1
],
[
5
,
120
,
40
,
True
,
'relu'
,
1
],
[
3
,
240
,
80
,
False
,
'hard_swish'
,
2
],
[
3
,
200
,
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
,
672
,
112
,
True
,
'hard_swish'
,
1
],
[
5
,
672
,
160
,
True
,
'hard_swish'
,
2
],
[
5
,
960
,
160
,
True
,
'hard_swish'
,
1
],
[
5
,
960
,
160
,
True
,
'hard_swish'
,
1
],
[
3
,
16
,
16
,
False
,
"relu"
,
1
],
[
3
,
64
,
24
,
False
,
"relu"
,
2
],
[
3
,
72
,
24
,
False
,
"relu"
,
1
],
[
5
,
72
,
40
,
True
,
"relu"
,
2
],
[
5
,
120
,
40
,
True
,
"relu"
,
1
],
[
5
,
120
,
40
,
True
,
"relu"
,
1
],
[
3
,
240
,
80
,
False
,
"hard_swish"
,
2
],
[
3
,
200
,
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
,
672
,
112
,
True
,
"hard_swish"
,
1
],
[
5
,
672
,
160
,
True
,
"hard_swish"
,
2
],
[
5
,
960
,
160
,
True
,
"hard_swish"
,
1
],
[
5
,
960
,
160
,
True
,
"hard_swish"
,
1
],
]
self
.
cls_ch_squeeze
=
960
self
.
cls_ch_expand
=
1280
self
.
lr_interval
=
3
elif
model_name
==
"small"
:
self
.
cfg
=
[
# k, exp, c, se, nl, s,
[
3
,
16
,
16
,
True
,
'relu'
,
2
],
[
3
,
72
,
24
,
False
,
'relu'
,
2
],
[
3
,
88
,
24
,
False
,
'relu'
,
1
],
[
5
,
96
,
40
,
True
,
'hard_swish'
,
2
],
[
5
,
240
,
40
,
True
,
'hard_swish'
,
1
],
[
5
,
240
,
40
,
True
,
'hard_swish'
,
1
],
[
5
,
120
,
48
,
True
,
'hard_swish'
,
1
],
[
5
,
144
,
48
,
True
,
'hard_swish'
,
1
],
[
5
,
288
,
96
,
True
,
'hard_swish'
,
2
],
[
5
,
576
,
96
,
True
,
'hard_swish'
,
1
],
[
5
,
576
,
96
,
True
,
'hard_swish'
,
1
],
[
3
,
16
,
16
,
True
,
"relu"
,
2
],
[
3
,
72
,
24
,
False
,
"relu"
,
2
],
[
3
,
88
,
24
,
False
,
"relu"
,
1
],
[
5
,
96
,
40
,
True
,
"hard_swish"
,
2
],
[
5
,
240
,
40
,
True
,
"hard_swish"
,
1
],
[
5
,
240
,
40
,
True
,
"hard_swish"
,
1
],
[
5
,
120
,
48
,
True
,
"hard_swish"
,
1
],
[
5
,
144
,
48
,
True
,
"hard_swish"
,
1
],
[
5
,
288
,
96
,
True
,
"hard_swish"
,
2
],
[
5
,
576
,
96
,
True
,
"hard_swish"
,
1
],
[
5
,
576
,
96
,
True
,
"hard_swish"
,
1
],
]
self
.
cls_ch_squeeze
=
576
self
.
cls_ch_expand
=
1280
self
.
lr_interval
=
2
else
:
raise
NotImplementedError
(
"mode[{}_model] is not implemented!"
.
format
(
model_name
))
def
net
(
self
,
input
,
class_dim
=
1000
):
scale
=
self
.
scale
inplanes
=
self
.
inplanes
cfg
=
self
.
cfg
cls_ch_squeeze
=
self
.
cls_ch_squeeze
cls_ch_expand
=
self
.
cls_ch_expand
# conv1
conv
=
self
.
conv_bn_layer
(
input
,
self
.
conv1
=
ConvBNLayer
(
in_c
=
3
,
out_c
=
make_divisible
(
inplanes
*
scale
),
filter_size
=
3
,
num_filters
=
self
.
make_divisible
(
inplanes
*
scale
),
stride
=
2
,
padding
=
1
,
num_groups
=
1
,
if_act
=
True
,
act
=
'hard_swish'
,
name
=
'conv1'
)
act
=
"hard_swish"
,
name
=
"conv1"
)
self
.
block_list
=
[]
i
=
0
inplanes
=
self
.
make_divisible
(
inplanes
*
scale
)
for
layer_cfg
in
cfg
:
conv
=
self
.
residual_unit
(
input
=
conv
,
num_in_filter
=
inplanes
,
num_mid_filter
=
self
.
make_divisible
(
scale
*
layer_cfg
[
1
]),
num_out_filter
=
self
.
make_divisible
(
scale
*
layer_cfg
[
2
]),
act
=
layer_cfg
[
4
],
stride
=
layer_cfg
[
5
],
filter_size
=
layer_cfg
[
0
],
use_se
=
layer_cfg
[
3
],
name
=
'conv'
+
str
(
i
+
2
))
inplanes
=
self
.
make_divisible
(
scale
*
layer_cfg
[
2
])
inplanes
=
make_divisible
(
inplanes
*
scale
)
for
(
k
,
exp
,
c
,
se
,
nl
,
s
)
in
self
.
cfg
:
self
.
block_list
.
append
(
ResidualUnit
(
in_c
=
inplanes
,
mid_c
=
make_divisible
(
scale
*
exp
),
out_c
=
make_divisible
(
scale
*
c
),
filter_size
=
k
,
stride
=
s
,
use_se
=
se
,
act
=
nl
,
name
=
"conv"
+
str
(
i
+
2
)))
self
.
add_sublayer
(
sublayer
=
self
.
block_list
[
-
1
],
name
=
"conv"
+
str
(
i
+
2
))
inplanes
=
make_divisible
(
scale
*
c
)
i
+=
1
self
.
curr_stage
=
i
conv
=
self
.
conv_bn_layer
(
input
=
conv
,
self
.
last_second_conv
=
ConvBNLayer
(
in_c
=
inplanes
,
out_c
=
make_divisible
(
scale
*
self
.
cls_ch_squeeze
),
filter_size
=
1
,
num_filters
=
self
.
make_divisible
(
scale
*
cls_ch_squeeze
),
stride
=
1
,
padding
=
0
,
num_groups
=
1
,
if_act
=
True
,
act
=
'hard_swish'
,
name
=
'conv_last'
)
conv
=
fluid
.
layers
.
pool2d
(
input
=
conv
,
pool_type
=
'avg'
,
global_pooling
=
True
,
use_cudnn
=
False
)
conv
=
fluid
.
layers
.
conv2d
(
input
=
conv
,
num_filters
=
cls_ch_expand
,
act
=
"hard_swish"
,
name
=
"conv_last"
)
self
.
pool
=
Pool2D
(
pool_type
=
"avg"
,
global_pooling
=
True
,
use_cudnn
=
False
)
self
.
last_conv
=
Conv2D
(
num_channels
=
make_divisible
(
scale
*
self
.
cls_ch_squeeze
),
num_filters
=
self
.
cls_ch_expand
,
filter_size
=
1
,
stride
=
1
,
padding
=
0
,
act
=
None
,
param_attr
=
ParamAttr
(
name
=
'last_1x1_conv_weights'
),
param_attr
=
ParamAttr
(
name
=
"last_1x1_conv_weights"
),
bias_attr
=
False
)
conv
=
fluid
.
layers
.
hard_swish
(
conv
)
drop
=
fluid
.
layers
.
dropout
(
x
=
conv
,
dropout_prob
=
0.2
)
out
=
fluid
.
layers
.
fc
(
input
=
drop
,
size
=
class_dim
,
param_attr
=
ParamAttr
(
name
=
'fc_weights'
),
bias_attr
=
ParamAttr
(
name
=
'fc_offset'
))
return
out
def
conv_bn_layer
(
self
,
input
,
self
.
out
=
Linear
(
input_dim
=
self
.
cls_ch_expand
,
output_dim
=
class_dim
,
param_attr
=
ParamAttr
(
"fc_weights"
),
bias_attr
=
ParamAttr
(
name
=
"fc_offset"
))
def
forward
(
self
,
inputs
,
label
=
None
,
dropout_prob
=
0.2
):
x
=
self
.
conv1
(
inputs
)
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
,
num_filters
,
stride
,
padding
,
num_groups
=
1
,
if_act
=
True
,
act
=
None
,
name
=
None
,
use_cudnn
=
True
,
res_last_bn_init
=
False
):
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
]
conv
=
fluid
.
layers
.
conv2d
(
input
=
input
,
num_filters
=
num_filters
,
name
=
""
):
super
(
ConvBNLayer
,
self
).
__init__
()
self
.
if_act
=
if_act
self
.
act
=
act
self
.
conv
=
fluid
.
dygraph
.
Conv2D
(
num_channels
=
in_c
,
num_filters
=
out_c
,
filter_size
=
filter_size
,
stride
=
stride
,
padding
=
padding
,
groups
=
num_groups
,
act
=
None
,
param_attr
=
ParamAttr
(
name
=
name
+
"_weights"
),
bias_attr
=
False
,
use_cudnn
=
use_cudnn
,
act
=
None
)
self
.
bn
=
fluid
.
dygraph
.
BatchNorm
(
num_channels
=
out_c
,
act
=
None
,
param_attr
=
ParamAttr
(
name
=
name
+
'_weights'
,
learning_rate
=
lr_mult
),
bias_attr
=
False
)
bn_name
=
name
+
'_bn'
bn
=
fluid
.
layers
.
batch_norm
(
input
=
conv
,
param_attr
=
ParamAttr
(
name
=
bn_name
+
"_scale"
,
name
=
name
+
"_bn_scale"
,
regularizer
=
fluid
.
regularizer
.
L2DecayRegularizer
(
regularization_coeff
=
0.0
)),
bias_attr
=
ParamAttr
(
name
=
bn_name
+
"
_offset"
,
name
=
name
+
"_bn
_offset"
,
regularizer
=
fluid
.
regularizer
.
L2DecayRegularizer
(
regularization_coeff
=
0.0
)),
moving_mean_name
=
bn_name
+
'_mean'
,
moving_variance_name
=
bn_name
+
'_variance'
)
if
if_act
:
if
act
==
'relu'
:
bn
=
fluid
.
layers
.
relu
(
bn
)
elif
act
==
'hard_swish'
:
bn
=
fluid
.
layers
.
hard_swish
(
bn
)
return
bn
def
make_divisible
(
self
,
v
,
divisor
=
8
,
min_value
=
None
):
if
min_value
is
None
:
min_value
=
divisor
new_v
=
max
(
min_value
,
int
(
v
+
divisor
/
2
)
//
divisor
*
divisor
)
if
new_v
<
0.9
*
v
:
new_v
+=
divisor
return
new_v
moving_mean_name
=
name
+
"_bn_mean"
,
moving_variance_name
=
name
+
"_bn_variance"
)
def
forward
(
self
,
x
):
x
=
self
.
conv
(
x
)
x
=
self
.
bn
(
x
)
if
self
.
if_act
:
if
self
.
act
==
"relu"
:
x
=
fluid
.
layers
.
relu
(
x
)
elif
self
.
act
==
"hard_swish"
:
x
=
fluid
.
layers
.
hard_swish
(
x
)
else
:
print
(
"The activation function is selected incorrectly."
)
exit
()
return
x
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
pool
=
fluid
.
layers
.
pool2d
(
input
=
input
,
pool_type
=
'avg'
,
global_pooling
=
True
,
use_cudnn
=
False
)
conv1
=
fluid
.
layers
.
conv2d
(
input
=
pool
,
filter_size
=
1
,
num_filters
=
num_mid_filter
,
act
=
'relu'
,
param_attr
=
ParamAttr
(
name
=
name
+
'_1_weights'
,
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
,
class
ResidualUnit
(
fluid
.
dygraph
.
Layer
):
def
__init__
(
self
,
in_c
,
mid_c
,
out_c
,
filter_size
,
stride
,
use_se
,
act
=
None
,
use_se
=
False
,
name
=
None
):
conv0
=
self
.
conv_bn_layer
(
input
=
input
,
name
=
''
):
super
(
ResidualUnit
,
self
).
__init__
()
self
.
if_shortcut
=
stride
==
1
and
in_c
==
out_c
self
.
if_se
=
use_se
self
.
expand_conv
=
ConvBNLayer
(
in_c
=
in_c
,
out_c
=
mid_c
,
filter_size
=
1
,
num_filters
=
num_mid_filter
,
stride
=
1
,
padding
=
0
,
if_act
=
True
,
act
=
act
,
name
=
name
+
'_expand'
)
conv1
=
self
.
conv_bn_layer
(
input
=
conv0
,
name
=
name
+
"_expand"
)
self
.
bottleneck_conv
=
ConvBNLayer
(
in_c
=
mid_c
,
out_c
=
mid_c
,
filter_size
=
filter_size
,
num_filters
=
num_mid_filter
,
stride
=
stride
,
padding
=
int
((
filter_size
-
1
)
//
2
),
num_groups
=
mid_c
,
if_act
=
True
,
act
=
act
,
num_groups
=
num_mid_filter
,
use_cudnn
=
False
,
name
=
name
+
'_depthwise'
)
if
use_se
:
conv1
=
self
.
se_block
(
input
=
conv1
,
num_out_filter
=
num_mid_filter
,
name
=
name
+
'_se'
)
conv2
=
self
.
conv_bn_layer
(
input
=
conv1
,
name
=
name
+
"_depthwise"
)
if
self
.
if_se
:
self
.
mid_se
=
SEModule
(
mid_c
,
name
=
name
+
"_se"
)
self
.
linear_conv
=
ConvBNLayer
(
in_c
=
mid_c
,
out_c
=
out_c
,
filter_size
=
1
,
num_filters
=
num_out_filter
,
stride
=
1
,
padding
=
0
,
if_act
=
False
,
name
=
name
+
'_linear'
,
res_last_bn_init
=
True
)
if
num_in_filter
!=
num_out_filter
or
stride
!=
1
:
return
conv2
else
:
return
fluid
.
layers
.
elementwise_add
(
x
=
input
,
y
=
conv2
,
act
=
None
)
act
=
None
,
name
=
name
+
"_linear"
)
def
forward
(
self
,
inputs
):
x
=
self
.
expand_conv
(
inputs
)
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
():
model
=
MobileNetV3
(
model_name
=
'small'
,
scale
=
0.35
)
def
MobileNetV3_small_x0_35
(
**
args
):
model
=
MobileNetV3
(
model_name
=
"small"
,
scale
=
0.35
,
**
args
)
return
model
def
MobileNetV3_small_x0_5
():
model
=
MobileNetV3
(
model_name
=
'small'
,
scale
=
0.5
)
def
MobileNetV3_small_x0_5
(
**
args
):
model
=
MobileNetV3
(
model_name
=
"small"
,
scale
=
0.5
,
**
args
)
return
model
def
MobileNetV3_small_x0_75
():
model
=
MobileNetV3
(
model_name
=
'small'
,
scale
=
0.75
)
def
MobileNetV3_small_x0_75
(
**
args
):
model
=
MobileNetV3
(
model_name
=
"small"
,
scale
=
0.75
,
**
args
)
return
model
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
def
MobileNetV3_small_x1_25
():
model
=
MobileNetV3
(
model_name
=
'small'
,
scale
=
1.25
)
def
MobileNetV3_small_x1_25
(
**
args
):
model
=
MobileNetV3
(
model_name
=
"small"
,
scale
=
1.25
,
**
args
)
return
model
def
MobileNetV3_large_x0_35
():
model
=
MobileNetV3
(
model_name
=
'large'
,
scale
=
0.35
)
def
MobileNetV3_large_x0_35
(
**
args
):
model
=
MobileNetV3
(
model_name
=
"large"
,
scale
=
0.35
,
**
args
)
return
model
def
MobileNetV3_large_x0_5
():
model
=
MobileNetV3
(
model_name
=
'large'
,
scale
=
0.5
)
def
MobileNetV3_large_x0_5
(
**
args
):
model
=
MobileNetV3
(
model_name
=
"large"
,
scale
=
0.5
,
**
args
)
return
model
def
MobileNetV3_large_x0_75
():
model
=
MobileNetV3
(
model_name
=
'large'
,
scale
=
0.75
)
def
MobileNetV3_large_x0_75
(
**
args
):
model
=
MobileNetV3
(
model_name
=
"large"
,
scale
=
0.75
,
**
args
)
return
model
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
def
MobileNetV3_large_x1_25
():
model
=
MobileNetV3
(
model_name
=
'large'
,
scale
=
1.25
)
def
MobileNetV3_large_x1_25
(
**
args
):
model
=
MobileNetV3
(
model_name
=
"large"
,
scale
=
1.25
,
**
args
)
return
model
ppcls/modeling/architectures/res2net.py
浏览文件 @
7f80e25c
#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");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
Licensed under the Apache License, Version 2.0 (the "License");
#
you may not use this file except in compliance with the License.
#
You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
#
Unless required by applicable law or agreed to in writing, software
#
distributed under the License is distributed on an "AS IS" BASIS,
#
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
See the License for the specific language governing permissions and
#
limitations under the License.
from
__future__
import
absolute_import
from
__future__
import
division
from
__future__
import
print_function
import
numpy
as
np
import
paddle
import
paddle.fluid
as
fluid
import
math
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__
=
[
"Res2Net
"
,
"Res2Net
50_48w_2s"
,
"Res2Net50_26w_4s"
,
"Res2Net50_14w_8s"
,
"Res2Net50_
26w_6s"
,
"Res2Net50_26w_8s"
,
"Res2Net101_26w_4
s"
,
"Res2Net1
52
_26w_4s"
"Res2Net50_48w_2s"
,
"Res2Net50_26w_4s"
,
"Res2Net50_14w_8s"
,
"Res2Net50_
48w_2s"
,
"Res2Net50_26w_6s"
,
"Res2Net50_26w_8
s"
,
"Res2Net1
01_26w_4s"
,
"Res2Net152_26w_4s"
,
"Res2Net200
_26w_4s"
]
class
Res2Net
():
def
__init__
(
self
,
layers
=
50
,
scales
=
4
,
width
=
26
):
self
.
layers
=
layers
self
.
scales
=
scales
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
,
class
ConvBNLayer
(
fluid
.
dygraph
.
Layer
):
def
__init__
(
self
,
num_channels
,
num_filters
,
filter_size
,
stride
=
1
,
groups
=
1
,
act
=
None
,
name
=
None
):
conv
=
fluid
.
layers
.
conv2d
(
input
=
input
,
name
=
None
,
):
super
(
ConvBNLayer
,
self
).
__init__
()
self
.
_conv
=
Conv2D
(
num_channels
=
num_channels
,
num_filters
=
num_filters
,
filter_size
=
filter_size
,
stride
=
stride
,
...
...
@@ -114,112 +54,227 @@ class Res2Net():
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
,
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
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
forward
(
self
,
inputs
):
y
=
self
.
_conv
(
inputs
)
y
=
self
.
_batch_norm
(
y
)
return
y
def
bottleneck_block
(
self
,
input
,
num_filters1
,
num_filters2
,
stride
,
name
):
conv0
=
self
.
conv_bn_layer
(
input
=
input
,
num_filters
=
num_filters1
,
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
,
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
,
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
,
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
:
ys
.
append
(
xs
[
-
1
])
else
:
ys
.
append
(
fluid
.
layers
.
pool2d
(
input
=
xs
[
-
1
],
pool_size
=
3
,
pool_stride
=
stride
,
pool_padding
=
1
,
pool_type
=
'avg'
))
self
.
conv1_list
.
append
(
conv1
)
self
.
pool2d_avg
=
Pool2D
(
pool_size
=
3
,
pool_stride
=
stride
,
pool_padding
=
1
,
pool_type
=
'avg'
)
conv1
=
fluid
.
layers
.
concat
(
ys
,
axis
=
1
)
conv2
=
self
.
conv_bn_layer
(
input
=
conv1
,
num_filters
=
num_filters2
,
self
.
conv2
=
ConvBNLayer
(
num_channels
=
num_filters
,
num_filters
=
num_channels2
,
filter_size
=
1
,
act
=
None
,
name
=
name
+
"_branch2c"
)
short
=
self
.
shortcut
(
input
,
num_filters2
,
stride
,
name
=
name
+
"_branch1"
)
if
not
shortcut
:
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
(
):
model
=
Res2Net
(
layers
=
50
,
scales
=
2
,
width
=
48
)
def
Res2Net50_
14w_8s
(
**
args
):
model
=
Res2Net
(
layers
=
50
,
scales
=
8
,
width
=
14
,
**
args
)
return
model
def
Res2Net50_
26w_4s
(
):
model
=
Res2Net
(
layers
=
50
,
scales
=
4
,
width
=
26
)
def
Res2Net50_
48w_2s
(
**
args
):
model
=
Res2Net
(
layers
=
50
,
scales
=
2
,
width
=
48
,
**
args
)
return
model
def
Res2Net50_
14w_8s
(
):
model
=
Res2Net
(
layers
=
50
,
scales
=
8
,
width
=
14
)
def
Res2Net50_
26w_6s
(
**
args
):
model
=
Res2Net
(
layers
=
50
,
scales
=
6
,
width
=
26
,
**
args
)
return
model
def
Res2Net50_26w_
6s
(
):
model
=
Res2Net
(
layers
=
50
,
scales
=
6
,
width
=
26
)
def
Res2Net50_26w_
8s
(
**
args
):
model
=
Res2Net
(
layers
=
50
,
scales
=
8
,
width
=
26
,
**
args
)
return
model
def
Res2Net
50_26w_8s
(
):
model
=
Res2Net
(
layers
=
50
,
scales
=
8
,
width
=
26
)
def
Res2Net
101_26w_4s
(
**
args
):
model
=
Res2Net
(
layers
=
101
,
scales
=
4
,
width
=
26
,
**
args
)
return
model
def
Res2Net1
01_26w_4s
(
):
model
=
Res2Net
(
layers
=
1
01
,
scales
=
4
,
width
=
26
)
def
Res2Net1
52_26w_4s
(
**
args
):
model
=
Res2Net
(
layers
=
1
52
,
scales
=
4
,
width
=
26
,
**
args
)
return
model
def
Res2Net
152_26w_4s
(
):
model
=
Res2Net
(
layers
=
152
,
scales
=
4
,
width
=
26
)
def
Res2Net
200_26w_4s
(
**
args
):
model
=
Res2Net
(
layers
=
200
,
scales
=
4
,
width
=
26
,
**
args
)
return
model
ppcls/modeling/architectures/res2net_vd.py
浏览文件 @
7f80e25c
...
...
@@ -16,33 +16,158 @@ from __future__ import absolute_import
from
__future__
import
division
from
__future__
import
print_function
import
math
import
numpy
as
np
import
paddle
import
paddle.fluid
as
fluid
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__
=
[
"Res2Net
_vd"
,
"Res2Net50_vd_48w_2s"
,
"Res2Net50_vd_26w_4
s"
,
"Res2Net50_vd_
14w_8
s"
,
"Res2Net50_vd_26w_6s"
,
"Res2Net50_vd_26w_8s"
,
"Res2Net
50_vd_48w_2s"
,
"Res2Net50_vd_26w_4s"
,
"Res2Net50_vd_14w_8
s"
,
"Res2Net50_vd_
48w_2
s"
,
"Res2Net50_vd_26w_6s"
,
"Res2Net50_vd_26w_8s"
,
"Res2Net101_vd_26w_4s"
,
"Res2Net152_vd_26w_4s"
,
"Res2Net200_vd_26w_4s"
]
class
Res2Net_vd
():
def
__init__
(
self
,
layers
=
50
,
scales
=
4
,
width
=
26
):
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
,
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
.
scales
=
scales
self
.
width
=
width
def
net
(
self
,
input
,
class_dim
=
1000
):
layers
=
self
.
layers
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
)
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
:
...
...
@@ -51,35 +176,37 @@ class Res2Net_vd():
depth
=
[
3
,
8
,
36
,
3
]
elif
layers
==
200
:
depth
=
[
3
,
12
,
48
,
3
]
conv
=
self
.
conv_bn_layer
(
input
=
input
,
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_1
=
ConvBNLayer
(
num_channels
=
3
,
num_filters
=
32
,
filter_size
=
3
,
stride
=
2
,
act
=
'relu'
,
name
=
'conv1_1'
)
conv
=
self
.
conv_bn_l
ayer
(
input
=
conv
,
name
=
"conv1_1"
)
self
.
conv1_2
=
ConvBNL
ayer
(
num_channels
=
32
,
num_filters
=
32
,
filter_size
=
3
,
stride
=
1
,
act
=
'relu'
,
name
=
'conv1_2'
)
conv
=
self
.
conv_bn_l
ayer
(
input
=
conv
,
name
=
"conv1_2"
)
self
.
conv1_3
=
ConvBNL
ayer
(
num_channels
=
32
,
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'
)
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
,
200
]
and
block
==
2
:
if
i
==
0
:
...
...
@@ -88,207 +215,89 @@ class Res2Net_vd():
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
],
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
)
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
,
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
)))
name
=
conv_name
))
self
.
block_list
.
append
(
bottleneck_block
)
shortcut
=
True
if
stride
==
1
:
ys
.
append
(
xs
[
-
1
])
else
:
ys
.
append
(
fluid
.
layers
.
pool2d
(
input
=
xs
[
-
1
],
pool_size
=
3
,
pool_stride
=
stride
,
pool_padding
=
1
,
pool_type
=
'avg'
))
self
.
pool2d_avg
=
Pool2D
(
pool_size
=
7
,
pool_type
=
'avg'
,
global_pooling
=
True
)
conv1
=
fluid
.
layers
.
concat
(
ys
,
axis
=
1
)
conv2
=
self
.
conv_bn_layer
(
input
=
conv1
,
num_filters
=
num_filters2
,
filter_size
=
1
,
act
=
None
,
name
=
name
+
"_branch2c"
)
self
.
pool2d_avg_channels
=
num_channels
[
-
1
]
*
2
short
=
self
.
shortcut
(
input
,
num_filters2
,
stride
,
if_first
=
if_first
,
name
=
name
+
"_branch1"
)
stdv
=
1.0
/
math
.
sqrt
(
self
.
pool2d_avg_channels
*
1.0
)
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
(
):
model
=
Res2Net_vd
(
layers
=
50
,
scales
=
2
,
width
=
48
)
def
Res2Net50_vd_
26w_4s
(
**
args
):
model
=
Res2Net_vd
(
layers
=
50
,
scales
=
4
,
width
=
26
,
**
args
)
return
model
def
Res2Net50_vd_
26w_4s
(
):
model
=
Res2Net_vd
(
layers
=
50
,
scales
=
4
,
width
=
26
)
def
Res2Net50_vd_
14w_8s
(
**
args
):
model
=
Res2Net_vd
(
layers
=
50
,
scales
=
8
,
width
=
14
,
**
args
)
return
model
def
Res2Net50_vd_
14w_8s
(
):
model
=
Res2Net_vd
(
layers
=
50
,
scales
=
8
,
width
=
14
)
def
Res2Net50_vd_
48w_2s
(
**
args
):
model
=
Res2Net_vd
(
layers
=
50
,
scales
=
2
,
width
=
48
,
**
args
)
return
model
def
Res2Net50_vd_26w_6s
():
model
=
Res2Net_vd
(
layers
=
50
,
scales
=
6
,
width
=
26
)
def
Res2Net50_vd_26w_6s
(
**
args
):
model
=
Res2Net_vd
(
layers
=
50
,
scales
=
6
,
width
=
26
,
**
args
)
return
model
def
Res2Net50_vd_26w_8s
():
model
=
Res2Net_vd
(
layers
=
50
,
scales
=
8
,
width
=
26
)
def
Res2Net50_vd_26w_8s
(
**
args
):
model
=
Res2Net_vd
(
layers
=
50
,
scales
=
8
,
width
=
26
,
**
args
)
return
model
def
Res2Net101_vd_26w_4s
():
model
=
Res2Net_vd
(
layers
=
101
,
scales
=
4
,
width
=
26
)
def
Res2Net101_vd_26w_4s
(
**
args
):
model
=
Res2Net_vd
(
layers
=
101
,
scales
=
4
,
width
=
26
,
**
args
)
return
model
def
Res2Net152_vd_26w_4s
():
model
=
Res2Net_vd
(
layers
=
152
,
scales
=
4
,
width
=
26
)
def
Res2Net152_vd_26w_4s
(
**
args
):
model
=
Res2Net_vd
(
layers
=
152
,
scales
=
4
,
width
=
26
,
**
args
)
return
model
def
Res2Net200_vd_26w_4s
():
model
=
Res2Net_vd
(
layers
=
200
,
scales
=
4
,
width
=
26
)
def
Res2Net200_vd_26w_4s
(
**
args
):
model
=
Res2Net_vd
(
layers
=
200
,
scales
=
4
,
width
=
26
,
**
args
)
return
model
ppcls/modeling/architectures/resnet.py
浏览文件 @
7f80e25c
...
...
@@ -12,19 +12,20 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from
__future__
import
absolute_import
from
__future__
import
division
from
__future__
import
print_function
import
numpy
as
np
import
paddle
import
paddle.fluid
as
fluid
from
paddle.fluid.param_attr
import
ParamAttr
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
__all__
=
[
"ResNet18"
,
"ResNet34"
,
"ResNet50"
,
"ResNet101"
,
"ResNet152"
,
]
__all__
=
[
"ResNet18"
,
"ResNet34"
,
"ResNet50"
,
"ResNet101"
,
"ResNet152"
]
class
ConvBNLayer
(
fluid
.
dygraph
.
Layer
):
...
...
@@ -34,7 +35,8 @@ class ConvBNLayer(fluid.dygraph.Layer):
filter_size
,
stride
=
1
,
groups
=
1
,
act
=
None
):
act
=
None
,
name
=
None
):
super
(
ConvBNLayer
,
self
).
__init__
()
self
.
_conv
=
Conv2D
(
...
...
@@ -45,44 +47,62 @@ class ConvBNLayer(fluid.dygraph.Layer):
padding
=
(
filter_size
-
1
)
//
2
,
groups
=
groups
,
act
=
None
,
param_attr
=
ParamAttr
(
name
=
name
+
"_weights"
),
bias_attr
=
False
)
self
.
_batch_norm
=
BatchNorm
(
num_filters
,
act
=
act
)
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
):
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'
)
act
=
"relu"
,
name
=
name
+
"_branch2a"
)
self
.
conv1
=
ConvBNLayer
(
num_channels
=
num_filters
,
num_filters
=
num_filters
,
filter_size
=
3
,
stride
=
stride
,
act
=
'relu'
)
act
=
"relu"
,
name
=
name
+
"_branch2b"
)
self
.
conv2
=
ConvBNLayer
(
num_channels
=
num_filters
,
num_filters
=
num_filters
*
4
,
filter_size
=
1
,
act
=
None
)
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
)
stride
=
stride
,
name
=
name
+
"_branch1"
)
self
.
shortcut
=
shortcut
...
...
@@ -100,7 +120,54 @@ class BottleneckBlock(fluid.dygraph.Layer):
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
)
...
...
@@ -109,18 +176,21 @@ class ResNet(fluid.dygraph.Layer):
super
(
ResNet
,
self
).
__init__
()
self
.
layers
=
layers
supported_layers
=
[
50
,
101
,
152
]
supported_layers
=
[
18
,
34
,
50
,
101
,
152
]
assert
layers
in
supported_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
]
elif
layers
==
101
:
depth
=
[
3
,
4
,
23
,
3
]
elif
layers
==
152
:
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
]
self
.
conv
=
ConvBNLayer
(
...
...
@@ -128,69 +198,97 @@ class ResNet(fluid.dygraph.Layer):
num_filters
=
64
,
filter_size
=
7
,
stride
=
2
,
act
=
'relu'
)
act
=
"relu"
,
name
=
"conv1"
)
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
)):
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
)
,
conv_name
,
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
))
self
.
bottleneck_block_list
.
append
(
bottleneck_block
)
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
(
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
self
.
pool2d_avg
=
Pool2D
(
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
.
pool2d_avg_
output
,
self
.
pool2d_avg_
channels
,
class_dim
,
param_attr
=
fluid
.
param_attr
.
ParamAttr
(
initializer
=
fluid
.
initializer
.
Uniform
(
-
stdv
,
stdv
)))
param_attr
=
ParamAttr
(
initializer
=
fluid
.
initializer
.
Uniform
(
-
stdv
,
stdv
),
name
=
"fc_0.w_0"
),
bias_attr
=
ParamAttr
(
name
=
"fc_0.b_0"
))
def
forward
(
self
,
inputs
):
y
=
self
.
conv
(
inputs
)
y
=
self
.
pool2d_max
(
y
)
for
b
ottleneck_block
in
self
.
bottleneck_
block_list
:
y
=
b
ottleneck_b
lock
(
y
)
for
b
lock
in
self
.
block_list
:
y
=
block
(
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
)
return
y
def
ResNet18
(
**
kw
args
):
model
=
ResNet
(
layers
=
18
,
**
kw
args
)
def
ResNet18
(
**
args
):
model
=
ResNet
(
layers
=
18
,
**
args
)
return
model
def
ResNet34
(
**
kw
args
):
model
=
ResNet
(
layers
=
34
,
**
kw
args
)
def
ResNet34
(
**
args
):
model
=
ResNet
(
layers
=
34
,
**
args
)
return
model
def
ResNet50
(
**
kw
args
):
model
=
ResNet
(
layers
=
50
,
**
kw
args
)
def
ResNet50
(
**
args
):
model
=
ResNet
(
layers
=
50
,
**
args
)
return
model
def
ResNet101
(
**
kw
args
):
model
=
ResNet
(
layers
=
101
,
**
kw
args
)
def
ResNet101
(
**
args
):
model
=
ResNet
(
layers
=
101
,
**
args
)
return
model
def
ResNet152
(
class_dim
=
1000
):
model
=
ResNet
(
layers
=
152
,
class_dim
=
class_dim
)
def
ResNet152
(
**
args
):
model
=
ResNet
(
layers
=
152
,
**
args
)
return
model
ppcls/modeling/architectures/resnet_vc.py
浏览文件 @
7f80e25c
#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");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
Licensed under the Apache License, Version 2.0 (the "License");
#
you may not use this file except in compliance with the License.
#
You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
#
Unless required by applicable law or agreed to in writing, software
#
distributed under the License is distributed on an "AS IS" BASIS,
#
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
See the License for the specific language governing permissions and
#
limitations under the License.
from
__future__
import
absolute_import
from
__future__
import
division
from
__future__
import
print_function
import
math
import
numpy
as
np
import
paddle
import
paddle.fluid
as
fluid
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
=
{
"input_size"
:
[
3
,
224
,
224
],
"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
]
}
}
__all__
=
[
"ResNet18_vc"
,
"ResNet34_vc"
,
"ResNet50_vc"
,
"ResNet101_vc"
,
"ResNet152_vc"
]
class
ResNet
():
def
__init__
(
self
,
layers
=
50
):
self
.
params
=
train_parameters
self
.
layers
=
layers
class
ConvBNLayer
(
fluid
.
dygraph
.
Layer
):
def
__init__
(
self
,
num_channels
,
num_filters
,
filter_size
,
stride
=
1
,
groups
=
1
,
act
=
None
,
name
=
None
):
super
(
ConvBNLayer
,
self
).
__init__
()
def
net
(
self
,
input
,
class_dim
=
1000
):
layers
=
self
.
layers
supported_layers
=
[
50
,
101
,
152
]
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
):
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
,
\
"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
]
elif
layers
==
101
:
depth
=
[
3
,
4
,
23
,
3
]
elif
layers
==
152
:
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
]
conv
=
self
.
conv_bn_l
ayer
(
input
=
input
,
self
.
conv1_1
=
ConvBNL
ayer
(
num_channels
=
3
,
num_filters
=
32
,
filter_size
=
3
,
stride
=
2
,
act
=
'relu'
,
name
=
'conv1_1'
)
conv
=
self
.
conv_bn_l
ayer
(
input
=
conv
,
name
=
"conv1_1"
)
self
.
conv1_2
=
ConvBNL
ayer
(
num_channels
=
32
,
num_filters
=
32
,
filter_size
=
3
,
stride
=
1
,
act
=
'relu'
,
name
=
'conv1_2'
)
conv
=
self
.
conv_bn_l
ayer
(
input
=
conv
,
name
=
"conv1_2"
)
self
.
conv1_3
=
ConvBNL
ayer
(
num_channels
=
32
,
num_filters
=
64
,
filter_size
=
3
,
stride
=
1
,
act
=
'relu'
,
name
=
'conv1_3'
)
name
=
"conv1_3"
)
conv
=
fluid
.
layers
.
pool2d
(
input
=
conv
,
pool_size
=
3
,
pool_stride
=
2
,
pool_padding
=
1
,
pool_type
=
'max'
)
self
.
pool2d_max
=
Pool2D
(
pool_size
=
3
,
pool_stride
=
2
,
pool_padding
=
1
,
pool_type
=
'max'
)
self
.
block_list
=
[]
if
layers
>=
50
:
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
:
...
...
@@ -94,101 +232,82 @@ class ResNet():
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
,
bottleneck_block
=
self
.
add_sublayer
(
'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
],
stride
=
2
if
i
==
0
and
block
!=
0
else
1
,
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
(
name
=
"fc_0.w_0"
,
initializer
=
fluid
.
initializer
.
Uniform
(
-
stdv
,
stdv
)),
shortcut
=
shortcut
,
name
=
conv_name
))
self
.
block_list
.
append
(
bisic_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_0.w_0"
),
bias_attr
=
ParamAttr
(
name
=
"fc_0.b_0"
))
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
,
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
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
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
):
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"
)
def
ResNet18_vc
(
**
args
):
model
=
ResNet_vc
(
layers
=
18
,
**
args
)
return
model
short
=
self
.
shortcut
(
input
,
num_filters
*
4
,
stride
,
name
=
name
+
"_branch1"
)
return
fluid
.
layers
.
elementwise_add
(
x
=
short
,
y
=
conv2
,
act
=
'relu'
,
name
=
name
+
".add.output.5"
)
def
ResNet34_vc
(
**
args
):
model
=
ResNet_vc
(
layers
=
34
,
**
args
)
return
model
def
ResNet50_vc
():
model
=
ResNet
(
layers
=
50
)
def
ResNet50_vc
(
**
args
):
model
=
ResNet
_vc
(
layers
=
50
,
**
args
)
return
model
def
ResNet101_vc
():
model
=
ResNet
(
layers
=
101
)
def
ResNet101_vc
(
**
args
):
model
=
ResNet
_vc
(
layers
=
101
,
**
args
)
return
model
def
ResNet152_vc
():
model
=
ResNet
(
layers
=
152
)
def
ResNet152_vc
(
**
args
):
model
=
ResNet
_vc
(
layers
=
152
,
**
args
)
return
model
ppcls/modeling/architectures/resnet_vd.py
浏览文件 @
7f80e25c
#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");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
Licensed under the Apache License, Version 2.0 (the "License");
#
you may not use this file except in compliance with the License.
#
You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
#
Unless required by applicable law or agreed to in writing, software
#
distributed under the License is distributed on an "AS IS" BASIS,
#
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
See the License for the specific language governing permissions and
#
limitations under the License.
from
__future__
import
absolute_import
from
__future__
import
division
from
__future__
import
print_function
import
math
import
numpy
as
np
import
paddle
import
paddle.fluid
as
fluid
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__
=
[
"ResNet"
,
"ResNet18_vd"
,
"ResNet34_vd"
,
"ResNet50_vd"
,
"ResNet101_vd"
,
"ResNet152_vd"
,
"ResNet200_vd"
"ResNet18_vd"
,
"ResNet34_vd"
,
"ResNet50_vd"
,
"ResNet101_vd"
,
"ResNet152_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
,
layers
=
50
,
is_3x3
=
False
,
postfix_name
=
""
,
lr_mult_list
=
[
1.0
,
1.0
,
1.0
,
1.0
,
1.0
]):
num_channels
,
num_filters
,
stride
,
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
.
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
]
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
:
depth
=
[
2
,
2
,
2
,
2
]
...
...
@@ -61,254 +201,129 @@ class ResNet():
depth
=
[
3
,
8
,
36
,
3
]
elif
layers
==
200
:
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
]
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
,
self
.
conv1_1
=
ConvBNLayer
(
num_channels
=
3
,
num_filters
=
32
,
filter_size
=
3
,
stride
=
2
,
act
=
'relu'
,
name
=
'conv1_1'
)
conv
=
self
.
conv_bn_l
ayer
(
input
=
conv
,
name
=
"conv1_1"
)
self
.
conv1_2
=
ConvBNL
ayer
(
num_channels
=
32
,
num_filters
=
32
,
filter_size
=
3
,
stride
=
1
,
act
=
'relu'
,
name
=
'conv1_2'
)
conv
=
self
.
conv_bn_l
ayer
(
input
=
conv
,
name
=
"conv1_2"
)
self
.
conv1_3
=
ConvBNL
ayer
(
num_channels
=
32
,
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'
)
name
=
"conv1_3"
)
self
.
pool2d_max
=
Pool2D
(
pool_size
=
3
,
pool_stride
=
2
,
pool_padding
=
1
,
pool_type
=
'max'
)
self
.
block_list
=
[]
if
layers
>=
50
:
for
block
in
range
(
len
(
depth
)):
s
elf
.
curr_stage
+=
1
s
hortcut
=
False
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
:
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
,
bottleneck_block
=
self
.
add_sublayer
(
'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
,
if_first
=
block
==
i
==
0
,
name
=
conv_name
)
name
=
conv_name
))
self
.
block_list
.
append
(
bottleneck_block
)
shortcut
=
True
else
:
for
block
in
range
(
len
(
depth
)):
s
elf
.
curr_stage
+=
1
s
hortcut
=
False
for
i
in
range
(
depth
[
block
]):
conv_name
=
"res"
+
str
(
block
+
2
)
+
chr
(
97
+
i
)
conv
=
self
.
basic_block
(
input
=
conv
,
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
],
stride
=
2
if
i
==
0
and
block
!=
0
else
1
,
shortcut
=
shortcut
,
if_first
=
block
==
i
==
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
)
name
=
conv_name
))
self
.
block_list
.
append
(
bisic_block
)
shortcut
=
True
out
=
fluid
.
layers
.
fc
(
input
=
pool
,
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
))
self
.
pool2d_avg
=
Pool2D
(
pool_size
=
7
,
pool_type
=
'avg'
,
global_pooling
=
True
)
return
out
self
.
pool2d_avg_channels
=
num_channels
[
-
1
]
*
2
def
conv_bn_layer
(
self
,
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
)
stdv
=
1.0
/
math
.
sqrt
(
self
.
pool2d_avg_channels
*
1.0
)
def
conv_bn_layer_new
(
self
,
input
,
num_filters
,
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
,
self
.
out
=
Linear
(
self
.
pool2d_avg_channels
,
class_dim
,
param_attr
=
ParamAttr
(
name
=
name
+
"_weights"
+
self
.
postfix_name
,
learning_rate
=
lr_mult
),
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
,
learning_rate
=
lr_mult
),
bias_attr
=
ParamAttr
(
bn_name
+
'_offset'
+
self
.
postfix_name
,
learning_rate
=
lr_mult
),
moving_mean_name
=
bn_name
+
'_mean'
+
self
.
postfix_name
,
moving_variance_name
=
bn_name
+
'_variance'
+
self
.
postfix_name
)
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
)
initializer
=
fluid
.
initializer
.
Uniform
(
-
stdv
,
stdv
),
name
=
"fc_0.w_0"
),
bias_attr
=
ParamAttr
(
name
=
"fc_0.b_0"
))
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
ResNet18_vd
(
**
args
):
model
=
ResNet_vd
(
layers
=
18
,
**
args
)
return
model
def
ResNet34_vd
():
model
=
ResNet
(
layers
=
34
,
is_3x3
=
True
)
def
ResNet34_vd
(
**
args
):
model
=
ResNet
_vd
(
layers
=
34
,
**
args
)
return
model
def
ResNet50_vd
(
**
args
):
model
=
ResNet
(
layers
=
50
,
is_3x3
=
True
,
**
args
)
model
=
ResNet
_vd
(
layers
=
50
,
**
args
)
return
model
def
ResNet101_vd
():
model
=
ResNet
(
layers
=
101
,
is_3x3
=
True
)
def
ResNet101_vd
(
**
args
):
model
=
ResNet
_vd
(
layers
=
101
,
**
args
)
return
model
def
ResNet152_vd
():
model
=
ResNet
(
layers
=
152
,
is_3x3
=
True
)
def
ResNet152_vd
(
**
args
):
model
=
ResNet
_vd
(
layers
=
152
,
**
args
)
return
model
def
ResNet200_vd
():
model
=
ResNet
(
layers
=
200
,
is_3x3
=
True
)
def
ResNet200_vd
(
**
args
):
model
=
ResNet
_vd
(
layers
=
200
,
**
args
)
return
model
ppcls/modeling/architectures/resnext.py
浏览文件 @
7f80e25c
#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");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
Licensed under the Apache License, Version 2.0 (the "License");
#
you may not use this file except in compliance with the License.
#
You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
#
Unless required by applicable law or agreed to in writing, software
#
distributed under the License is distributed on an "AS IS" BASIS,
#
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
See the License for the specific language governing permissions and
#
limitations under the License.
from
__future__
import
absolute_import
from
__future__
import
division
from
__future__
import
print_function
import
math
import
numpy
as
np
import
paddle
import
paddle.fluid
as
fluid
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__
=
[
"ResNeXt
"
,
"ResNeXt50_64x4d"
,
"ResNeXt101_64x4d"
,
"ResNeXt152_64
x4d"
,
"ResNeXt
50_32x4d"
,
"ResNeXt101_32x4d"
,
"ResNeXt152_32
x4d"
"ResNeXt
50_32x4d"
,
"ResNeXt50_64x4d"
,
"ResNeXt101_32
x4d"
,
"ResNeXt
101_64x4d"
,
"ResNeXt152_32x4d"
,
"ResNeXt152_64
x4d"
]
class
ResNeXt
():
def
__init__
(
self
,
layers
=
50
,
cardinality
=
64
):
self
.
layers
=
layers
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
,
class
ConvBNLayer
(
fluid
.
dygraph
.
Layer
):
def
__init__
(
self
,
num_channels
,
num_filters
,
filter_size
,
stride
=
1
,
groups
=
1
,
act
=
None
,
name
=
None
):
conv
=
fluid
.
layers
.
conv2d
(
input
=
input
,
super
(
ConvBNLayer
,
self
).
__init__
()
self
.
_conv
=
Conv2D
(
num_channels
=
num_channels
,
num_filters
=
num_filters
,
filter_size
=
filter_size
,
stride
=
stride
,
...
...
@@ -110,86 +51,192 @@ class ResNeXt():
groups
=
groups
,
act
=
None
,
param_attr
=
ParamAttr
(
name
=
name
+
"_weights"
),
bias_attr
=
False
,
name
=
name
+
'.conv2d.output.1'
)
bias_attr
=
False
)
if
name
==
"conv1"
:
bn_name
=
"bn_"
+
name
else
:
bn_name
=
"bn"
+
name
[
3
:]
return
fluid
.
layers
.
batch_n
orm
(
input
=
conv
,
self
.
_batch_norm
=
BatchN
orm
(
num_filters
,
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'
,
)
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
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
,
cardinality
,
shortcut
=
True
,
name
=
None
):
super
(
BottleneckBlock
,
self
).
__init__
()
def
bottleneck_block
(
self
,
input
,
num_filters
,
stride
,
cardinality
,
name
):
cardinality
=
self
.
cardinality
conv0
=
self
.
conv_bn_layer
(
input
=
input
,
self
.
conv0
=
ConvBNLayer
(
num_channels
=
num_channels
,
num_filters
=
num_filters
,
filter_size
=
1
,
act
=
'relu'
,
name
=
name
+
"_branch2a"
)
conv1
=
self
.
conv_bn_l
ayer
(
input
=
conv0
,
self
.
conv1
=
ConvBNL
ayer
(
num_channels
=
num_filters
,
num_filters
=
num_filters
,
filter_size
=
3
,
stride
=
stride
,
groups
=
cardinality
,
stride
=
stride
,
act
=
'relu'
,
name
=
name
+
"_branch2b"
)
conv2
=
self
.
conv_bn_l
ayer
(
input
=
conv1
,
num_filters
=
num_filters
if
cardinality
==
64
else
num_filters
*
2
,
self
.
conv2
=
ConvBNL
ayer
(
num_channels
=
num_filters
,
num_filters
=
num_filters
*
2
if
cardinality
==
32
else
num_filters
,
filter_size
=
1
,
act
=
None
,
name
=
name
+
"_branch2c"
)
short
=
self
.
shortcut
(
input
,
num_filters
if
cardinality
==
64
else
num_filters
*
2
,
stride
,
if
not
shortcut
:
self
.
short
=
ConvBNLayer
(
num_channels
=
num_channels
,
num_filters
=
num_filters
*
2
if
cardinality
==
32
else
num_filters
,
filter_size
=
1
,
stride
=
stride
,
name
=
name
+
"_branch1"
)
return
fluid
.
layers
.
elementwise_add
(
x
=
short
,
y
=
conv2
,
act
=
'relu'
,
name
=
name
+
".add.output.5"
)
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
.
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
():
model
=
ResNeXt
(
layers
=
50
,
cardinality
=
64
)
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
.
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
def
ResNeXt50_
32x4d
(
):
model
=
ResNeXt
(
layers
=
50
,
cardinality
=
32
)
def
ResNeXt50_
64x4d
(
**
args
):
model
=
ResNeXt
(
layers
=
50
,
cardinality
=
64
,
**
args
)
return
model
def
ResNeXt101_
64x4d
(
):
model
=
ResNeXt
(
layers
=
101
,
cardinality
=
64
)
def
ResNeXt101_
32x4d
(
**
args
):
model
=
ResNeXt
(
layers
=
101
,
cardinality
=
32
,
**
args
)
return
model
def
ResNeXt101_
32x4d
(
):
model
=
ResNeXt
(
layers
=
101
,
cardinality
=
32
)
def
ResNeXt101_
64x4d
(
**
args
):
model
=
ResNeXt
(
layers
=
101
,
cardinality
=
64
,
**
args
)
return
model
def
ResNeXt152_
64x4d
(
):
model
=
ResNeXt
(
layers
=
152
,
cardinality
=
64
)
def
ResNeXt152_
32x4d
(
**
args
):
model
=
ResNeXt
(
layers
=
152
,
cardinality
=
32
,
**
args
)
return
model
def
ResNeXt152_
32x4d
(
):
model
=
ResNeXt
(
layers
=
152
,
cardinality
=
32
)
def
ResNeXt152_
64x4d
(
**
args
):
model
=
ResNeXt
(
layers
=
152
,
cardinality
=
64
,
**
args
)
return
model
ppcls/modeling/architectures/resnext_vd.py
浏览文件 @
7f80e25c
#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");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
Licensed under the Apache License, Version 2.0 (the "License");
#
you may not use this file except in compliance with the License.
#
You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
#
Unless required by applicable law or agreed to in writing, software
#
distributed under the License is distributed on an "AS IS" BASIS,
#
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
See the License for the specific language governing permissions and
#
limitations under the License.
from
__future__
import
absolute_import
from
__future__
import
division
from
__future__
import
print_function
import
numpy
as
np
import
paddle
import
paddle.fluid
as
fluid
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__
=
[
"ResNeXt"
,
"ResNeXt50_vd_64x4d"
,
"ResNeXt101_vd_64x4d"
,
"ResNeXt152_vd_64x4d"
,
"ResNeXt50_vd_32x4d"
,
"ResNeXt101_vd_32x4d"
,
"ResNeXt152_vd_32x4d"
"ResNeXt50_vd_32x4d"
,
"ResNeXt50_vd_64x4d"
,
"ResNeXt101_vd_32x4d"
,
"ResNeXt101_vd_64x4d"
,
"ResNeXt152_vd_32x4d"
,
"ResNeXt152_vd_64x4d"
]
class
ResNeXt
():
def
__init__
(
self
,
layers
=
50
,
is_3x3
=
False
,
cardinality
=
64
):
self
.
layers
=
layers
self
.
is_3x3
=
is_3x3
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
,
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
):
conv
=
fluid
.
layers
.
conv2d
(
input
=
input
,
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
,
...
...
@@ -137,121 +61,209 @@ class ResNeXt():
bn_name
=
"bn_"
+
name
else
:
bn_name
=
"bn"
+
name
[
3
:]
return
fluid
.
layers
.
batch_n
orm
(
input
=
conv
,
self
.
_batch_norm
=
BatchN
orm
(
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
conv_bn_layer_new
(
self
,
input
,
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_channels
,
num_filters
,
filter_siz
e
,
stride
=
1
,
groups
=
1
,
act
=
Non
e
,
strid
e
,
cardinality
,
shortcut
=
True
,
if_first
=
Fals
e
,
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
)
else
:
return
input
super
(
BottleneckBlock
,
self
).
__init__
()
def
bottleneck_block
(
self
,
input
,
num_filters
,
stride
,
cardinality
,
name
,
if_first
):
conv0
=
self
.
conv_bn_layer
(
input
=
input
,
self
.
conv0
=
ConvBNLayer
(
num_channels
=
num_channels
,
num_filters
=
num_filters
,
filter_size
=
1
,
act
=
'relu'
,
name
=
name
+
"_branch2a"
)
conv1
=
self
.
conv_bn_l
ayer
(
input
=
conv0
,
self
.
conv1
=
ConvBNL
ayer
(
num_channels
=
num_filters
,
num_filters
=
num_filters
,
filter_size
=
3
,
groups
=
cardinality
,
stride
=
stride
,
act
=
'relu'
,
groups
=
cardinality
,
name
=
name
+
"_branch2b"
)
conv2
=
self
.
conv_bn_l
ayer
(
input
=
conv1
,
num_filters
=
num_filters
if
cardinality
==
64
else
num_filters
*
2
,
self
.
conv2
=
ConvBNL
ayer
(
num_channels
=
num_filters
,
num_filters
=
num_filters
*
2
if
cardinality
==
32
else
num_filters
,
filter_size
=
1
,
act
=
None
,
name
=
name
+
"_branch2c"
)
short
=
self
.
shortcut
(
input
,
num_filters
if
cardinality
==
64
else
num_filters
*
2
,
stride
,
if_first
=
if_first
,
if
not
shortcut
:
self
.
short
=
ConvBNLayer
(
num_channels
=
num_channels
,
num_filters
=
num_filters
*
2
if
cardinality
==
32
else
num_filters
,
filter_size
=
1
,
stride
=
1
,
is_vd_mode
=
False
if
if_first
else
True
,
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
(
):
model
=
ResNeXt
(
layers
=
50
,
is_3x3
=
True
)
def
ResNeXt50_vd_
32x4d
(
**
args
):
model
=
ResNeXt
(
layers
=
50
,
cardinality
=
32
,
**
args
)
return
model
def
ResNeXt50_vd_
32x4d
(
):
model
=
ResNeXt
(
layers
=
50
,
cardinality
=
32
,
is_3x3
=
True
)
def
ResNeXt50_vd_
64x4d
(
**
args
):
model
=
ResNeXt
(
layers
=
50
,
cardinality
=
64
,
**
args
)
return
model
def
ResNeXt101_vd_
64x4d
(
):
model
=
ResNeXt
(
layers
=
101
,
is_3x3
=
True
)
def
ResNeXt101_vd_
32x4d
(
**
args
):
model
=
ResNeXt
(
layers
=
101
,
cardinality
=
32
,
**
args
)
return
model
def
ResNeXt101_vd_
32x4d
(
):
model
=
ResNeXt
(
layers
=
101
,
cardinality
=
32
,
is_3x3
=
True
)
def
ResNeXt101_vd_
64x4d
(
**
args
):
model
=
ResNeXt
(
layers
=
101
,
cardinality
=
64
,
**
args
)
return
model
def
ResNeXt152_vd_
64x4d
(
):
model
=
ResNeXt
(
layers
=
152
,
is_3x3
=
True
)
def
ResNeXt152_vd_
32x4d
(
**
args
):
model
=
ResNeXt
(
layers
=
152
,
cardinality
=
32
,
**
args
)
return
model
def
ResNeXt152_vd_
32x4d
(
):
model
=
ResNeXt
(
layers
=
152
,
cardinality
=
32
,
is_3x3
=
True
)
def
ResNeXt152_vd_
64x4d
(
**
args
):
model
=
ResNeXt
(
layers
=
152
,
cardinality
=
64
,
**
args
)
return
model
ppcls/modeling/architectures/se_resnet_vd.py
浏览文件 @
7f80e25c
#copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve.
#
#Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
Licensed under the Apache License, Version 2.0 (the "License");
#
you may not use this file except in compliance with the License.
#
You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
#
Unless required by applicable law or agreed to in writing, software
#
distributed under the License is distributed on an "AS IS" BASIS,
#
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
See the License for the specific language governing permissions and
#
limitations under the License.
from
__future__
import
absolute_import
from
__future__
import
division
from
__future__
import
print_function
import
math
import
numpy
as
np
import
paddle
import
paddle.fluid
as
fluid
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__
=
[
"SE_ResNet
_vd"
,
"SE_ResNet18_vd"
,
"SE_ResNet34_vd"
,
"SE_ResNet50
_vd"
,
"SE_ResNet1
01_vd"
,
"SE_ResNet1
52_vd"
,
"SE_ResNet200_vd"
"SE_ResNet
18_vd"
,
"SE_ResNet34_vd"
,
"SE_ResNet50_vd"
,
"SE_ResNet101
_vd"
,
"SE_ResNet152_vd"
,
"SE_ResNet200_vd"
]
class
SE_ResNet_vd
():
def
__init__
(
self
,
layers
=
50
,
is_3x3
=
False
):
self
.
layers
=
layers
self
.
is_3x3
=
is_3x3
def
net
(
self
,
input
,
class_dim
=
1000
):
is_3x3
=
self
.
is_3x3
layers
=
self
.
layers
supported_layers
=
[
18
,
34
,
50
,
101
,
152
,
200
]
assert
layers
in
supported_layers
,
\
"supported layers are {} but input layer is {}"
.
format
(
supported_layers
,
layers
)
if
layers
==
18
:
depth
=
[
2
,
2
,
2
,
2
]
elif
layers
==
34
or
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_filters
=
[
64
,
128
,
256
,
512
]
reduction_ratio
=
16
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'
)
if
layers
>=
50
:
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_filters
[
block
],
stride
=
2
if
i
==
0
and
block
!=
0
else
1
,
if_first
=
block
==
i
==
0
,
reduction_ratio
=
reduction_ratio
,
name
=
conv_name
)
else
:
for
block
in
range
(
len
(
depth
)):
for
i
in
range
(
depth
[
block
]):
conv_name
=
"res"
+
str
(
block
+
2
)
+
chr
(
97
+
i
)
conv
=
self
.
basic_block
(
input
=
conv
,
num_filters
=
num_filters
[
block
],
stride
=
2
if
i
==
0
and
block
!=
0
else
1
,
if_first
=
block
==
i
==
0
,
reduction_ratio
=
reduction_ratio
,
name
=
conv_name
)
pool
=
fluid
.
layers
.
pool2d
(
input
=
conv
,
pool_size
=
7
,
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
=
'fc6_weights'
),
bias_attr
=
ParamAttr
(
name
=
'fc6_offset'
))
return
out
def
conv_bn_layer
(
self
,
input
,
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
):
conv
=
fluid
.
layers
.
conv2d
(
input
=
input
,
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
,
...
...
@@ -154,183 +60,325 @@ class SE_ResNet_vd():
bn_name
=
"bn_"
+
name
else
:
bn_name
=
"bn"
+
name
[
3
:]
return
fluid
.
layers
.
batch_n
orm
(
input
=
conv
,
self
.
_batch_norm
=
BatchN
orm
(
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
conv_bn_layer_new
(
self
,
input
,
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_channels
,
num_filters
,
filter_siz
e
,
stride
=
1
,
groups
=
1
,
act
=
None
,
strid
e
,
shortcut
=
True
,
if_first
=
False
,
reduction_ratio
=
16
,
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'
)
super
(
BottleneckBlock
,
self
).
__init__
()
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
,
reduction_ratio
):
conv0
=
self
.
conv_bn_layer
(
input
=
input
,
self
.
conv0
=
ConvBNLayer
(
num_channels
=
num_channels
,
num_filters
=
num_filters
,
filter_size
=
1
,
act
=
'relu'
,
name
=
name
+
"_branch2a"
)
conv1
=
self
.
conv_bn_l
ayer
(
input
=
conv0
,
self
.
conv1
=
ConvBNL
ayer
(
num_channels
=
num_filters
,
num_filters
=
num_filters
,
filter_size
=
3
,
stride
=
stride
,
act
=
'relu'
,
name
=
name
+
"_branch2b"
)
conv2
=
self
.
conv_bn_l
ayer
(
input
=
conv1
,
self
.
conv2
=
ConvBNL
ayer
(
num_channels
=
num_filters
,
num_filters
=
num_filters
*
4
,
filter_size
=
1
,
act
=
None
,
name
=
name
+
"_branch2c"
)
scale
=
self
.
squeeze_excitation
(
input
=
conv2
,
self
.
scale
=
SELayer
(
num_channels
=
num_filters
*
4
,
num_filters
=
num_filters
*
4
,
reduction_ratio
=
reduction_ratio
,
name
=
'fc_'
+
name
)
short
=
self
.
shortcut
(
input
,
num_filters
*
4
,
stride
,
if_first
=
if_first
,
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"
)
return
fluid
.
layers
.
elementwise_add
(
x
=
short
,
y
=
scale
,
act
=
'relu'
)
self
.
shortcut
=
shortcut
def
basic_block
(
self
,
input
,
num_filters
,
stride
,
name
,
if_first
,
reduction_ratio
):
conv0
=
self
.
conv_bn_layer
(
input
=
input
,
def
forward
(
self
,
inputs
):
y
=
self
.
conv0
(
inputs
)
conv1
=
self
.
conv1
(
y
)
conv2
=
self
.
conv2
(
conv1
)
scale
=
self
.
scale
(
conv2
)
if
self
.
shortcut
:
short
=
inputs
else
:
short
=
self
.
short
(
inputs
)
y
=
fluid
.
layers
.
elementwise_add
(
x
=
short
,
y
=
scale
)
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
,
reduction_ratio
=
16
,
name
=
None
):
super
(
BisicBlock
,
self
).
__init__
()
self
.
stride
=
stride
self
.
conv0
=
ConvBNLayer
(
num_channels
=
num_channels
,
num_filters
=
num_filters
,
filter_size
=
3
,
act
=
'relu'
,
stride
=
stride
,
act
=
'relu'
,
name
=
name
+
"_branch2a"
)
conv1
=
self
.
conv_bn_l
ayer
(
input
=
conv0
,
self
.
conv1
=
ConvBNL
ayer
(
num_channels
=
num_filters
,
num_filters
=
num_filters
,
filter_size
=
3
,
act
=
None
,
name
=
name
+
"_branch2b"
)
scale
=
self
.
squeeze_excitation
(
input
=
conv1
,
self
.
scale
=
SELayer
(
num_channels
=
num_filters
,
num_filters
=
num_filters
,
reduction_ratio
=
reduction_ratio
,
name
=
'fc_'
+
name
)
short
=
self
.
shortcut
(
input
,
num_filters
,
stride
,
if_first
=
if_first
,
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"
)
return
fluid
.
layers
.
elementwise_add
(
x
=
short
,
y
=
scale
,
act
=
'relu'
)
def
squeeze_excitation
(
self
,
input
,
self
.
shortcut
=
shortcut
def
forward
(
self
,
inputs
):
y
=
self
.
conv0
(
inputs
)
conv1
=
self
.
conv1
(
y
)
scale
=
self
.
scale
(
conv1
)
if
self
.
shortcut
:
short
=
inputs
else
:
short
=
self
.
short
(
inputs
)
y
=
fluid
.
layers
.
elementwise_add
(
x
=
short
,
y
=
scale
)
layer_helper
=
LayerHelper
(
self
.
full_name
(),
act
=
'relu'
)
return
layer_helper
.
append_activation
(
y
)
class
SELayer
(
fluid
.
dygraph
.
Layer
):
def
__init__
(
self
,
num_channels
,
num_filters
,
reduction_ratio
,
name
=
None
):
super
(
SELayer
,
self
).
__init__
()
self
.
pool2d_gap
=
Pool2D
(
pool_type
=
'avg'
,
global_pooling
=
True
)
self
.
_num_channels
=
num_channels
med_ch
=
int
(
num_channels
/
reduction_ratio
)
stdv
=
1.0
/
math
.
sqrt
(
num_channels
*
1.0
)
self
.
squeeze
=
Linear
(
num_channels
,
reduction_ratio
,
name
=
None
):
pool
=
fluid
.
layers
.
pool2d
(
input
=
input
,
pool_size
=
0
,
pool_type
=
'avg'
,
global_pooling
=
True
)
stdv
=
1.0
/
math
.
sqrt
(
pool
.
shape
[
1
]
*
1.0
)
squeeze
=
fluid
.
layers
.
fc
(
input
=
pool
,
size
=
num_channels
//
reduction_ratio
,
act
=
'relu'
,
param_attr
=
fluid
.
param_attr
.
ParamAttr
(
med_ch
,
act
=
"relu"
,
param_attr
=
ParamAttr
(
initializer
=
fluid
.
initializer
.
Uniform
(
-
stdv
,
stdv
),
name
=
name
+
'_sqz_weights'
),
name
=
name
+
"_sqz_weights"
),
bias_attr
=
ParamAttr
(
name
=
name
+
'_sqz_offset'
))
stdv
=
1.0
/
math
.
sqrt
(
squeeze
.
shape
[
1
]
*
1.0
)
excitation
=
fluid
.
layers
.
fc
(
input
=
squeeze
,
size
=
num_channels
,
act
=
'sigmoid'
,
param_attr
=
fluid
.
param_attr
.
ParamAttr
(
stdv
=
1.0
/
math
.
sqrt
(
med_ch
*
1.0
)
self
.
excitation
=
Linear
(
med_ch
,
num_filters
,
act
=
"sigmoid"
,
param_attr
=
ParamAttr
(
initializer
=
fluid
.
initializer
.
Uniform
(
-
stdv
,
stdv
),
name
=
name
+
'_exc_weights'
),
name
=
name
+
"_exc_weights"
),
bias_attr
=
ParamAttr
(
name
=
name
+
'_exc_offset'
))
scale
=
fluid
.
layers
.
elementwise_mul
(
x
=
input
,
y
=
excitation
,
axis
=
0
)
return
scale
def
forward
(
self
,
input
):
pool
=
self
.
pool2d_gap
(
input
)
pool
=
fluid
.
layers
.
reshape
(
pool
,
shape
=
[
-
1
,
self
.
_num_channels
])
squeeze
=
self
.
squeeze
(
pool
)
excitation
=
self
.
excitation
(
squeeze
)
excitation
=
fluid
.
layers
.
reshape
(
excitation
,
shape
=
[
-
1
,
self
.
_num_channels
,
1
,
1
])
out
=
input
*
excitation
return
out
class
SE_ResNet_vd
(
fluid
.
dygraph
.
Layer
):
def
__init__
(
self
,
layers
=
50
,
class_dim
=
1000
):
super
(
SE_ResNet_vd
,
self
).
__init__
()
def
SE_ResNet18_vd
():
model
=
SE_ResNet_vd
(
layers
=
18
,
is_3x3
=
True
)
self
.
layers
=
layers
supported_layers
=
[
18
,
34
,
50
,
101
,
152
,
200
]
assert
layers
in
supported_layers
,
\
"supported layers are {} but input layer is {}"
.
format
(
supported_layers
,
layers
)
if
layers
==
18
:
depth
=
[
2
,
2
,
2
,
2
]
elif
layers
==
34
or
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
]
if
layers
>=
50
else
[
64
,
64
,
128
,
256
]
num_filters
=
[
64
,
128
,
256
,
512
]
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
=
[]
if
layers
>=
50
:
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
]
*
4
,
num_filters
=
num_filters
[
block
],
stride
=
2
if
i
==
0
and
block
!=
0
else
1
,
shortcut
=
shortcut
,
if_first
=
block
==
i
==
0
,
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
],
stride
=
2
if
i
==
0
and
block
!=
0
else
1
,
shortcut
=
shortcut
,
if_first
=
block
==
i
==
0
,
name
=
conv_name
))
self
.
block_list
.
append
(
bisic_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
=
"fc6_weights"
),
bias_attr
=
ParamAttr
(
name
=
"fc6_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
SE_ResNet18_vd
(
**
args
):
model
=
SE_ResNet_vd
(
layers
=
18
,
**
args
)
return
model
def
SE_ResNet34_vd
():
model
=
SE_ResNet_vd
(
layers
=
34
,
is_3x3
=
True
)
def
SE_ResNet34_vd
(
**
args
):
model
=
SE_ResNet_vd
(
layers
=
34
,
**
args
)
return
model
def
SE_ResNet50_vd
():
model
=
SE_ResNet_vd
(
layers
=
50
,
is_3x3
=
True
)
def
SE_ResNet50_vd
(
**
args
):
model
=
SE_ResNet_vd
(
layers
=
50
,
**
args
)
return
model
def
SE_ResNet101_vd
():
model
=
SE_ResNet_vd
(
layers
=
101
,
is_3x3
=
True
)
def
SE_ResNet101_vd
(
**
args
):
model
=
SE_ResNet_vd
(
layers
=
101
,
**
args
)
return
model
def
SE_ResNet152_vd
():
model
=
SE_ResNet_vd
(
layers
=
152
,
is_3x3
=
True
)
def
SE_ResNet152_vd
(
**
args
):
model
=
SE_ResNet_vd
(
layers
=
152
,
**
args
)
return
model
def
SE_ResNet200_vd
():
model
=
SE_ResNet_vd
(
layers
=
200
,
is_3x3
=
True
)
def
SE_ResNet200_vd
(
**
args
):
model
=
SE_ResNet_vd
(
layers
=
200
,
**
args
)
return
model
ppcls/modeling/architectures/se_resnext_vd.py
浏览文件 @
7f80e25c
#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");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
Licensed under the Apache License, Version 2.0 (the "License");
#
you may not use this file except in compliance with the License.
#
You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
#
Unless required by applicable law or agreed to in writing, software
#
distributed under the License is distributed on an "AS IS" BASIS,
#
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
See the License for the specific language governing permissions and
#
limitations under the License.
from
__future__
import
absolute_import
from
__future__
import
division
from
__future__
import
print_function
import
math
import
numpy
as
np
import
paddle
import
paddle.fluid
as
fluid
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__
=
[
"SE_ResNeXt_vd"
,
"SE_ResNeXt50_32x4d_vd"
,
"SE_ResNeXt101_32x4d_vd"
,
"SENet154_vd"
]
import
math
__all__
=
[
"SE_ResNeXt50_vd_32x4d"
,
"SE_ResNeXt50_vd_32x4d"
,
"SENet154_vd"
]
class
SE_ResNeXt_vd
():
def
__init__
(
self
,
layers
=
50
):
self
.
layers
=
layers
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
)
if
layers
==
50
:
cardinality
=
32
reduction_ratio
=
16
depth
=
[
3
,
4
,
6
,
3
]
num_filters
=
[
128
,
256
,
512
,
1024
]
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__
()
conv
=
self
.
conv_bn_layer
(
input
=
input
,
num_filters
=
64
,
filter_size
=
3
,
stride
=
2
,
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
)
bn_name
=
name
+
'_bn'
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_channels
,
num_filters
,
stride
,
cardinality
,
reduction_ratio
,
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
=
'conv1_
1'
)
conv
=
self
.
conv_bn_l
ayer
(
input
=
conv
,
num_filters
=
64
,
name
=
'conv'
+
name
+
'_x
1'
)
self
.
conv1
=
ConvBNL
ayer
(
num_channels
=
num_filters
,
num_filters
=
num_filters
,
filter_size
=
3
,
stride
=
1
,
groups
=
cardinality
,
stride
=
stride
,
act
=
'relu'
,
name
=
'conv1_2'
)
conv
=
self
.
conv_bn_layer
(
input
=
conv
,
num_filters
=
128
,
filter_size
=
3
,
name
=
'conv'
+
name
+
'_x2'
)
self
.
conv2
=
ConvBNLayer
(
num_channels
=
num_filters
,
num_filters
=
num_filters
*
2
if
cardinality
==
32
else
num_filters
,
filter_size
=
1
,
act
=
None
,
name
=
'conv'
+
name
+
'_x3'
)
self
.
scale
=
SELayer
(
num_channels
=
num_filters
*
2
if
cardinality
==
32
else
num_filters
,
num_filters
=
num_filters
*
2
if
cardinality
==
32
else
num_filters
,
reduction_ratio
=
reduction_ratio
,
name
=
'fc_'
+
name
)
if
not
shortcut
:
self
.
short
=
ConvBNLayer
(
num_channels
=
num_channels
,
num_filters
=
num_filters
*
2
if
cardinality
==
32
else
num_filters
,
filter_size
=
1
,
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'
)
is_vd_mode
=
False
if
if_first
else
True
,
name
=
'conv'
+
name
+
'_prj'
)
self
.
shortcut
=
shortcut
def
forward
(
self
,
inputs
):
y
=
self
.
conv0
(
inputs
)
conv1
=
self
.
conv1
(
y
)
conv2
=
self
.
conv2
(
conv1
)
scale
=
self
.
scale
(
conv2
)
if
self
.
shortcut
:
short
=
inputs
else
:
short
=
self
.
short
(
inputs
)
y
=
fluid
.
layers
.
elementwise_add
(
x
=
short
,
y
=
scale
)
layer_helper
=
LayerHelper
(
self
.
full_name
(),
act
=
'relu'
)
return
layer_helper
.
append_activation
(
y
)
class
SELayer
(
fluid
.
dygraph
.
Layer
):
def
__init__
(
self
,
num_channels
,
num_filters
,
reduction_ratio
,
name
=
None
):
super
(
SELayer
,
self
).
__init__
()
self
.
pool2d_gap
=
Pool2D
(
pool_type
=
'avg'
,
global_pooling
=
True
)
self
.
_num_channels
=
num_channels
med_ch
=
int
(
num_channels
/
reduction_ratio
)
stdv
=
1.0
/
math
.
sqrt
(
num_channels
*
1.0
)
self
.
squeeze
=
Linear
(
num_channels
,
med_ch
,
act
=
"relu"
,
param_attr
=
ParamAttr
(
initializer
=
fluid
.
initializer
.
Uniform
(
-
stdv
,
stdv
),
name
=
name
+
"_sqz_weights"
),
bias_attr
=
ParamAttr
(
name
=
name
+
'_sqz_offset'
))
stdv
=
1.0
/
math
.
sqrt
(
med_ch
*
1.0
)
self
.
excitation
=
Linear
(
med_ch
,
num_filters
,
act
=
"sigmoid"
,
param_attr
=
ParamAttr
(
initializer
=
fluid
.
initializer
.
Uniform
(
-
stdv
,
stdv
),
name
=
name
+
"_exc_weights"
),
bias_attr
=
ParamAttr
(
name
=
name
+
'_exc_offset'
))
def
forward
(
self
,
input
):
pool
=
self
.
pool2d_gap
(
input
)
pool
=
fluid
.
layers
.
reshape
(
pool
,
shape
=
[
-
1
,
self
.
_num_channels
])
squeeze
=
self
.
squeeze
(
pool
)
excitation
=
self
.
excitation
(
squeeze
)
excitation
=
fluid
.
layers
.
reshape
(
excitation
,
shape
=
[
-
1
,
self
.
_num_channels
,
1
,
1
])
out
=
input
*
excitation
return
out
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
self
.
reduction_ratio
=
16
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
:
cardinality
=
32
reduction_ratio
=
16
depth
=
[
3
,
4
,
23
,
3
]
num_filters
=
[
128
,
256
,
512
,
1024
]
conv
=
self
.
conv_bn_layer
(
input
=
input
,
num_filters
=
64
,
filter_size
=
3
,
stride
=
2
,
act
=
'relu'
,
name
=
'conv1_1'
)
conv
=
self
.
conv_bn_layer
(
input
=
conv
,
num_filters
=
64
,
filter_size
=
3
,
stride
=
1
,
act
=
'relu'
,
name
=
'conv1_2'
)
conv
=
self
.
conv_bn_layer
(
input
=
conv
,
num_filters
=
128
,
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'
)
elif
layers
==
152
:
cardinality
=
64
reduction_ratio
=
16
depth
=
[
3
,
8
,
36
,
3
]
num_filters
=
[
256
,
512
,
1024
,
2048
]
num_channels
=
[
128
,
256
,
512
,
1024
]
num_filters
=
[
128
,
256
,
512
,
1024
]
if
cardinality
==
32
else
[
256
,
512
,
1024
,
2048
]
conv
=
self
.
conv_bn_l
ayer
(
input
=
input
,
self
.
conv1_1
=
ConvBNL
ayer
(
num_channels
=
3
,
num_filters
=
64
,
filter_size
=
3
,
stride
=
2
,
act
=
'relu'
,
name
=
'conv1_1'
)
conv
=
self
.
conv_bn_l
ayer
(
input
=
conv
,
name
=
"conv1_1"
)
self
.
conv1_2
=
ConvBNL
ayer
(
num_channels
=
64
,
num_filters
=
64
,
filter_size
=
3
,
stride
=
1
,
act
=
'relu'
,
name
=
'conv1_2'
)
conv
=
self
.
conv_bn_l
ayer
(
input
=
conv
,
name
=
"conv1_2"
)
self
.
conv1_3
=
ConvBNL
ayer
(
num_channels
=
64
,
num_filters
=
128
,
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'
)
name
=
"conv1_3"
)
self
.
pool2d_max
=
Pool2D
(
pool_size
=
3
,
pool_stride
=
2
,
pool_padding
=
1
,
pool_type
=
'max'
)
self
.
block_list
=
[]
n
=
1
if
layers
==
50
or
layers
==
101
else
3
for
block
in
range
(
len
(
depth
)):
n
+=
1
shortcut
=
False
for
i
in
range
(
depth
[
block
]):
conv
=
self
.
bottleneck_block
(
input
=
conv
,
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
=
cardinality
,
reduction_ratio
=
reduction_ratio
,
cardinality
=
self
.
cardinality
,
reduction_ratio
=
self
.
reduction_ratio
,
shortcut
=
shortcut
,
if_first
=
block
==
0
,
name
=
str
(
n
)
+
'_'
+
str
(
i
+
1
))
pool
=
fluid
.
layers
.
pool2d
(
input
=
conv
,
pool_type
=
'avg'
,
global_pooling
=
True
)
if
layers
==
152
:
pool
=
fluid
.
layers
.
dropout
(
x
=
pool
,
dropout_prob
=
0.2
)
stdv
=
1.0
/
math
.
sqrt
(
pool
.
shape
[
1
]
*
1.0
)
out
=
fluid
.
layers
.
fc
(
input
=
pool
,
size
=
class_dim
,
param_attr
=
ParamAttr
(
initializer
=
fluid
.
initializer
.
Uniform
(
-
stdv
,
stdv
),
name
=
'fc6_weights'
),
bias_attr
=
ParamAttr
(
name
=
'fc6_offset'
))
return
out
def
shortcut
(
self
,
input
,
ch_out
,
stride
,
name
,
if_first
=
False
):
ch_in
=
input
.
shape
[
1
]
if
ch_in
!=
ch_out
or
stride
!=
1
:
filter_size
=
1
if
if_first
:
return
self
.
conv_bn_layer
(
input
,
ch_out
,
filter_size
,
stride
,
name
=
'conv'
+
name
+
'_prj'
)
else
:
return
self
.
conv_bn_layer_new
(
input
,
ch_out
,
filter_size
,
stride
,
name
=
'conv'
+
name
+
'_prj'
)
else
:
return
input
def
bottleneck_block
(
self
,
input
,
num_filters
,
stride
,
cardinality
,
reduction_ratio
,
if_first
,
name
=
None
):
conv0
=
self
.
conv_bn_layer
(
input
=
input
,
num_filters
=
num_filters
,
filter_size
=
1
,
act
=
'relu'
,
name
=
'conv'
+
name
+
'_x1'
)
conv1
=
self
.
conv_bn_layer
(
input
=
conv0
,
num_filters
=
num_filters
,
filter_size
=
3
,
stride
=
stride
,
groups
=
cardinality
,
act
=
'relu'
,
name
=
'conv'
+
name
+
'_x2'
)
if
cardinality
==
64
:
num_filters
=
num_filters
//
2
conv2
=
self
.
conv_bn_layer
(
input
=
conv1
,
num_filters
=
num_filters
*
2
,
filter_size
=
1
,
act
=
None
,
name
=
'conv'
+
name
+
'_x3'
)
scale
=
self
.
squeeze_excitation
(
input
=
conv2
,
num_channels
=
num_filters
*
2
,
reduction_ratio
=
reduction_ratio
,
name
=
'fc'
+
name
)
name
=
str
(
n
)
+
'_'
+
str
(
i
+
1
)))
self
.
block_list
.
append
(
bottleneck_block
)
shortcut
=
True
s
hort
=
self
.
shortcut
(
input
,
num_filters
*
2
,
stride
,
if_first
=
if_first
,
name
=
nam
e
)
s
elf
.
pool2d_avg
=
Pool2D
(
pool_size
=
7
,
pool_type
=
'avg'
,
global_pooling
=
Tru
e
)
return
fluid
.
layers
.
elementwise_add
(
x
=
short
,
y
=
scale
,
act
=
'relu'
)
self
.
pool2d_avg_channels
=
num_channels
[
-
1
]
*
2
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
,
bias_attr
=
False
,
param_attr
=
ParamAttr
(
name
=
name
+
'_weights'
),
)
bn_name
=
name
+
"_bn"
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
)
bn_name
=
name
+
"_bn"
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'
)
stdv
=
1.0
/
math
.
sqrt
(
self
.
pool2d_avg_channels
*
1.0
)
def
squeeze_excitation
(
self
,
input
,
num_channels
,
reduction_ratio
,
name
=
None
):
pool
=
fluid
.
layers
.
pool2d
(
input
=
input
,
pool_type
=
'avg'
,
global_pooling
=
True
)
stdv
=
1.0
/
math
.
sqrt
(
pool
.
shape
[
1
]
*
1.0
)
squeeze
=
fluid
.
layers
.
fc
(
input
=
pool
,
size
=
num_channels
//
reduction_ratio
,
act
=
'relu'
,
param_attr
=
fluid
.
param_attr
.
ParamAttr
(
initializer
=
fluid
.
initializer
.
Uniform
(
-
stdv
,
stdv
),
name
=
name
+
'_sqz_weights'
),
bias_attr
=
ParamAttr
(
name
=
name
+
'_sqz_offset'
))
stdv
=
1.0
/
math
.
sqrt
(
squeeze
.
shape
[
1
]
*
1.0
)
excitation
=
fluid
.
layers
.
fc
(
input
=
squeeze
,
size
=
num_channels
,
act
=
'sigmoid'
,
param_attr
=
fluid
.
param_attr
.
ParamAttr
(
self
.
out
=
Linear
(
self
.
pool2d_avg_channels
,
class_dim
,
param_attr
=
ParamAttr
(
initializer
=
fluid
.
initializer
.
Uniform
(
-
stdv
,
stdv
),
name
=
name
+
'_exc_weights'
),
bias_attr
=
ParamAttr
(
name
=
name
+
'_exc_offset'
))
scale
=
fluid
.
layers
.
elementwise_mul
(
x
=
input
,
y
=
excitation
,
axis
=
0
)
return
scale
name
=
"fc6_weights"
),
bias_attr
=
ParamAttr
(
name
=
"fc6_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
SE_ResNeXt50_vd_32x4d
():
model
=
SE_ResNeXt_vd
(
layers
=
50
)
def
SE_ResNeXt50_vd_32x4d
(
**
args
):
model
=
ResNeXt
(
layers
=
50
,
cardinality
=
32
,
**
args
)
return
model
def
SE_ResNeXt101_vd_32x4d
():
model
=
SE_ResNeXt_vd
(
layers
=
101
)
def
SE_ResNeXt101_vd_32x4d
(
**
args
):
model
=
ResNeXt
(
layers
=
101
,
cardinality
=
32
,
**
args
)
return
model
def
SENet154_vd
():
model
=
SE_ResNeXt_vd
(
layers
=
152
)
def
SENet154_vd
(
**
args
):
model
=
ResNeXt
(
layers
=
152
,
cardinality
=
64
,
**
args
)
return
model
ppcls/modeling/architectures/shufflenet_v2.py
浏览文件 @
7f80e25c
#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");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
Licensed under the Apache License, Version 2.0 (the "License");
#
you may not use this file except in compliance with the License.
#
You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
#
Unless required by applicable law or agreed to in writing, software
#
distributed under the License is distributed on an "AS IS" BASIS,
#
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
See the License for the specific language governing permissions and
#
limitations under the License.
from
__future__
import
absolute_import
from
__future__
import
division
from
__future__
import
print_function
import
math
import
numpy
as
np
import
paddle
import
paddle.fluid
as
fluid
from
paddle.fluid.initializer
import
MSRA
from
paddle.fluid.param_attr
import
ParamAttr
from
paddle.fluid.layer_helper
import
LayerHelper
from
paddle.fluid.dygraph.nn
import
Conv2D
,
Pool2D
,
BatchNorm
,
Linear
,
Dropout
from
paddle.fluid.initializer
import
MSRA
import
math
__all__
=
[
'ShuffleNetV2_x0_25'
,
'ShuffleNetV2_x0_33'
,
'ShuffleNetV2_x0_5'
,
'ShuffleNetV2_x1_0'
,
'ShuffleNetV2_x1_5'
,
'ShuffleNetV2_x2_0'
,
'ShuffleNetV2'
"ShuffleNetV2_x0_25"
,
"ShuffleNetV2_x0_33"
,
"ShuffleNetV2_x0_5"
,
"ShuffleNetV2_x1_0"
,
"ShuffleNetV2_x1_5"
,
"ShuffleNetV2_x2_0"
,
"ShuffleNetV2_swish"
]
class
ShuffleNetV2
():
def
__init__
(
self
,
scale
=
1.0
):
self
.
scale
=
scale
def
net
(
self
,
input
,
class_dim
=
1000
):
scale
=
self
.
scale
stage_repeats
=
[
4
,
8
,
4
]
def
channel_shuffle
(
x
,
groups
):
batchsize
,
num_channels
,
height
,
width
=
x
.
shape
[
0
],
x
.
shape
[
1
],
x
.
shape
[
2
],
x
.
shape
[
3
]
channels_per_group
=
num_channels
//
groups
if
scale
==
0.25
:
stage_out_channels
=
[
-
1
,
24
,
24
,
48
,
96
,
512
]
elif
scale
==
0.33
:
stage_out_channels
=
[
-
1
,
24
,
32
,
64
,
128
,
512
]
elif
scale
==
0.5
:
stage_out_channels
=
[
-
1
,
24
,
48
,
96
,
192
,
1024
]
elif
scale
==
1.0
:
stage_out_channels
=
[
-
1
,
24
,
116
,
232
,
464
,
1024
]
elif
scale
==
1.5
:
stage_out_channels
=
[
-
1
,
24
,
176
,
352
,
704
,
1024
]
elif
scale
==
2.0
:
stage_out_channels
=
[
-
1
,
24
,
224
,
488
,
976
,
2048
]
else
:
raise
NotImplementedError
(
"This scale size:["
+
str
(
scale
)
+
"] is not implemented!"
)
#conv1
# reshape
x
=
fluid
.
layers
.
reshape
(
x
=
x
,
shape
=
[
batchsize
,
groups
,
channels_per_group
,
height
,
width
])
input_channel
=
stage_out_channels
[
1
]
conv1
=
self
.
conv_bn_layer
(
input
=
input
,
filter_size
=
3
,
num_filters
=
input_channel
,
padding
=
1
,
stride
=
2
,
name
=
'stage1_conv'
)
pool1
=
fluid
.
layers
.
pool2d
(
input
=
conv1
,
pool_size
=
3
,
pool_stride
=
2
,
pool_padding
=
1
,
pool_type
=
'max'
)
conv
=
pool1
# bottleneck sequences
for
idxstage
in
range
(
len
(
stage_repeats
)):
numrepeat
=
stage_repeats
[
idxstage
]
output_channel
=
stage_out_channels
[
idxstage
+
2
]
for
i
in
range
(
numrepeat
):
if
i
==
0
:
conv
=
self
.
inverted_residual_unit
(
input
=
conv
,
num_filters
=
output_channel
,
stride
=
2
,
benchmodel
=
2
,
name
=
str
(
idxstage
+
2
)
+
'_'
+
str
(
i
+
1
))
else
:
conv
=
self
.
inverted_residual_unit
(
input
=
conv
,
num_filters
=
output_channel
,
stride
=
1
,
benchmodel
=
1
,
name
=
str
(
idxstage
+
2
)
+
'_'
+
str
(
i
+
1
))
x
=
fluid
.
layers
.
transpose
(
x
=
x
,
perm
=
[
0
,
2
,
1
,
3
,
4
])
# flatten
x
=
fluid
.
layers
.
reshape
(
x
=
x
,
shape
=
[
batchsize
,
num_channels
,
height
,
width
])
return
x
conv_last
=
self
.
conv_bn_layer
(
input
=
conv
,
filter_size
=
1
,
num_filters
=
stage_out_channels
[
-
1
],
padding
=
0
,
stride
=
1
,
name
=
'conv5'
)
pool_last
=
fluid
.
layers
.
pool2d
(
input
=
conv_last
,
pool_size
=
7
,
pool_stride
=
1
,
pool_padding
=
0
,
pool_type
=
'avg'
)
output
=
fluid
.
layers
.
fc
(
input
=
pool_last
,
size
=
class_dim
,
param_attr
=
ParamAttr
(
initializer
=
MSRA
(),
name
=
'fc6_weights'
),
bias_attr
=
ParamAttr
(
name
=
'fc6_offset'
))
return
output
def
conv_bn_layer
(
self
,
input
,
class
ConvBNLayer
(
fluid
.
dygraph
.
Layer
):
def
__init__
(
self
,
num_channels
,
filter_size
,
num_filters
,
stride
,
padding
,
channels
=
None
,
num_groups
=
1
,
use_cudnn
=
True
,
if_act
=
True
,
name
=
None
):
conv
=
fluid
.
layers
.
conv2d
(
input
=
input
,
act
=
'relu'
,
name
=
None
,
use_cudnn
=
True
):
super
(
ConvBNLayer
,
self
).
__init__
()
self
.
_if_act
=
if_act
assert
act
in
[
'relu'
,
'swish'
],
\
"supported act are {} but your act is {}"
.
format
(
[
'relu'
,
'swish'
],
act
)
self
.
_act
=
act
self
.
_conv
=
Conv2D
(
num_channels
=
num_channels
,
num_filters
=
num_filters
,
filter_size
=
filter_size
,
stride
=
stride
,
...
...
@@ -130,178 +77,279 @@ class ShuffleNetV2():
act
=
None
,
use_cudnn
=
use_cudnn
,
param_attr
=
ParamAttr
(
initializer
=
MSRA
(),
name
=
name
+
'_weights'
),
initializer
=
MSRA
(),
name
=
name
+
"_weights"
),
bias_attr
=
False
)
out
=
int
((
input
.
shape
[
2
]
-
1
)
/
float
(
stride
)
+
1
)
bn_name
=
name
+
'_bn'
if
if_act
:
return
fluid
.
layers
.
batch_norm
(
input
=
conv
,
act
=
'relu'
,
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'
)
else
:
return
fluid
.
layers
.
batch_norm
(
input
=
conv
,
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
channel_shuffle
(
self
,
x
,
groups
):
batchsize
,
num_channels
,
height
,
width
=
x
.
shape
[
0
],
x
.
shape
[
1
],
x
.
shape
[
2
],
x
.
shape
[
3
]
channels_per_group
=
num_channels
//
groups
# reshape
x
=
fluid
.
layers
.
reshape
(
x
=
x
,
shape
=
[
batchsize
,
groups
,
channels_per_group
,
height
,
width
])
x
=
fluid
.
layers
.
transpose
(
x
=
x
,
perm
=
[
0
,
2
,
1
,
3
,
4
])
# flatten
x
=
fluid
.
layers
.
reshape
(
x
=
x
,
shape
=
[
batchsize
,
num_channels
,
height
,
width
])
return
x
def
inverted_residual_unit
(
self
,
input
,
self
.
_batch_norm
=
BatchNorm
(
num_filters
,
param_attr
=
ParamAttr
(
name
=
name
+
"_bn_scale"
),
bias_attr
=
ParamAttr
(
name
=
name
+
"_bn_offset"
),
moving_mean_name
=
name
+
"_bn_mean"
,
moving_variance_name
=
name
+
"_bn_variance"
)
def
forward
(
self
,
inputs
,
if_act
=
True
):
y
=
self
.
_conv
(
inputs
)
y
=
self
.
_batch_norm
(
y
)
if
self
.
_if_act
:
y
=
fluid
.
layers
.
relu
(
y
)
if
self
.
_act
==
'relu'
else
fluid
.
layers
.
swish
(
y
)
return
y
class
InvertedResidualUnit
(
fluid
.
dygraph
.
Layer
):
def
__init__
(
self
,
num_channels
,
num_filters
,
stride
,
benchmodel
,
act
=
'relu'
,
name
=
None
):
super
(
InvertedResidualUnit
,
self
).
__init__
()
assert
stride
in
[
1
,
2
],
\
"supported stride are {} but your stride is {}"
.
format
([
1
,
2
],
stride
)
"supported stride are {} but your stride is {}"
.
format
([
1
,
2
],
stride
)
self
.
benchmodel
=
benchmodel
oup_inc
=
num_filters
//
2
inp
=
input
.
shape
[
1
]
inp
=
num_channels
if
benchmodel
==
1
:
x1
,
x2
=
fluid
.
layers
.
split
(
input
,
num_or_sections
=
[
input
.
shape
[
1
]
//
2
,
input
.
shape
[
1
]
//
2
],
dim
=
1
)
conv_pw
=
self
.
conv_bn_layer
(
input
=
x2
,
self
.
_conv_pw
=
ConvBNLayer
(
num_channels
=
num_channels
//
2
,
num_filters
=
oup_inc
,
filter_size
=
1
,
stride
=
1
,
padding
=
0
,
num_groups
=
1
,
if_act
=
True
,
act
=
act
,
name
=
'stage_'
+
name
+
'_conv1'
)
conv_dw
=
self
.
conv_bn_layer
(
input
=
conv_pw
,
self
.
_conv_dw
=
ConvBNLayer
(
num_channels
=
oup_inc
,
num_filters
=
oup_inc
,
filter_size
=
3
,
stride
=
stride
,
padding
=
1
,
num_groups
=
oup_inc
,
if_act
=
False
,
act
=
act
,
use_cudnn
=
False
,
name
=
'stage_'
+
name
+
'_conv2'
)
conv_linear
=
self
.
conv_bn_layer
(
input
=
conv_dw
,
self
.
_conv_linear
=
ConvBNLayer
(
num_channels
=
oup_inc
,
num_filters
=
oup_inc
,
filter_size
=
1
,
stride
=
1
,
padding
=
0
,
num_groups
=
1
,
if_act
=
True
,
act
=
act
,
name
=
'stage_'
+
name
+
'_conv3'
)
out
=
fluid
.
layers
.
concat
([
x1
,
conv_linear
],
axis
=
1
)
else
:
#branch1
conv_dw_1
=
self
.
conv_bn_l
ayer
(
input
=
input
,
#
branch1
self
.
_conv_dw_1
=
ConvBNL
ayer
(
num_channels
=
num_channels
,
num_filters
=
inp
,
filter_size
=
3
,
stride
=
stride
,
padding
=
1
,
num_groups
=
inp
,
if_act
=
False
,
act
=
act
,
use_cudnn
=
False
,
name
=
'stage_'
+
name
+
'_conv4'
)
conv_linear_1
=
self
.
conv_bn_layer
(
input
=
conv_dw_1
,
self
.
_conv_linear_1
=
ConvBNLayer
(
num_channels
=
inp
,
num_filters
=
oup_inc
,
filter_size
=
1
,
stride
=
1
,
padding
=
0
,
num_groups
=
1
,
if_act
=
True
,
act
=
act
,
name
=
'stage_'
+
name
+
'_conv5'
)
#branch2
conv_pw_2
=
self
.
conv_bn_layer
(
input
=
input
,
# branch2
self
.
_conv_pw_2
=
ConvBNLayer
(
num_channels
=
num_channels
,
num_filters
=
oup_inc
,
filter_size
=
1
,
stride
=
1
,
padding
=
0
,
num_groups
=
1
,
if_act
=
True
,
act
=
act
,
name
=
'stage_'
+
name
+
'_conv1'
)
conv_dw_2
=
self
.
conv_bn_layer
(
input
=
conv_pw_2
,
self
.
_conv_dw_2
=
ConvBNLayer
(
num_channels
=
oup_inc
,
num_filters
=
oup_inc
,
filter_size
=
3
,
stride
=
stride
,
padding
=
1
,
num_groups
=
oup_inc
,
if_act
=
False
,
act
=
act
,
use_cudnn
=
False
,
name
=
'stage_'
+
name
+
'_conv2'
)
conv_linear_2
=
self
.
conv_bn_layer
(
input
=
conv_dw_2
,
self
.
_conv_linear_2
=
ConvBNLayer
(
num_channels
=
oup_inc
,
num_filters
=
oup_inc
,
filter_size
=
1
,
stride
=
1
,
padding
=
0
,
num_groups
=
1
,
if_act
=
True
,
act
=
act
,
name
=
'stage_'
+
name
+
'_conv3'
)
out
=
fluid
.
layers
.
concat
([
conv_linear_1
,
conv_linear_2
],
axis
=
1
)
return
self
.
channel_shuffle
(
out
,
2
)
def
forward
(
self
,
inputs
):
if
self
.
benchmodel
==
1
:
x1
,
x2
=
fluid
.
layers
.
split
(
inputs
,
num_or_sections
=
[
inputs
.
shape
[
1
]
//
2
,
inputs
.
shape
[
1
]
//
2
],
dim
=
1
)
x2
=
self
.
_conv_pw
(
x2
)
x2
=
self
.
_conv_dw
(
x2
)
x2
=
self
.
_conv_linear
(
x2
)
out
=
fluid
.
layers
.
concat
([
x1
,
x2
],
axis
=
1
)
else
:
x1
=
self
.
_conv_dw_1
(
inputs
)
x1
=
self
.
_conv_linear_1
(
x1
)
x2
=
self
.
_conv_pw_2
(
inputs
)
x2
=
self
.
_conv_dw_2
(
x2
)
x2
=
self
.
_conv_linear_2
(
x2
)
out
=
fluid
.
layers
.
concat
([
x1
,
x2
],
axis
=
1
)
return
channel_shuffle
(
out
,
2
)
class
ShuffleNet
(
fluid
.
dygraph
.
Layer
):
def
__init__
(
self
,
class_dim
=
1000
,
scale
=
1.0
,
act
=
'relu'
):
super
(
ShuffleNet
,
self
).
__init__
()
self
.
scale
=
scale
self
.
class_dim
=
class_dim
stage_repeats
=
[
4
,
8
,
4
]
if
scale
==
0.25
:
stage_out_channels
=
[
-
1
,
24
,
24
,
48
,
96
,
512
]
elif
scale
==
0.33
:
stage_out_channels
=
[
-
1
,
24
,
32
,
64
,
128
,
512
]
elif
scale
==
0.5
:
stage_out_channels
=
[
-
1
,
24
,
48
,
96
,
192
,
1024
]
elif
scale
==
1.0
:
stage_out_channels
=
[
-
1
,
24
,
116
,
232
,
464
,
1024
]
elif
scale
==
1.5
:
stage_out_channels
=
[
-
1
,
24
,
176
,
352
,
704
,
1024
]
elif
scale
==
2.0
:
stage_out_channels
=
[
-
1
,
24
,
224
,
488
,
976
,
2048
]
else
:
raise
NotImplementedError
(
"This scale size:["
+
str
(
scale
)
+
"] is not implemented!"
)
# 1. conv1
self
.
_conv1
=
ConvBNLayer
(
num_channels
=
3
,
num_filters
=
stage_out_channels
[
1
],
filter_size
=
3
,
stride
=
2
,
padding
=
1
,
if_act
=
True
,
act
=
act
,
name
=
'stage1_conv'
)
self
.
_max_pool
=
Pool2D
(
pool_type
=
'max'
,
pool_size
=
3
,
pool_stride
=
2
,
pool_padding
=
1
)
# 2. bottleneck sequences
self
.
_block_list
=
[]
i
=
1
in_c
=
int
(
32
*
scale
)
for
idxstage
in
range
(
len
(
stage_repeats
)):
numrepeat
=
stage_repeats
[
idxstage
]
output_channel
=
stage_out_channels
[
idxstage
+
2
]
for
i
in
range
(
numrepeat
):
if
i
==
0
:
block
=
self
.
add_sublayer
(
str
(
idxstage
+
2
)
+
'_'
+
str
(
i
+
1
),
InvertedResidualUnit
(
num_channels
=
stage_out_channels
[
idxstage
+
1
],
num_filters
=
output_channel
,
stride
=
2
,
benchmodel
=
2
,
act
=
act
,
name
=
str
(
idxstage
+
2
)
+
'_'
+
str
(
i
+
1
)))
self
.
_block_list
.
append
(
block
)
else
:
block
=
self
.
add_sublayer
(
str
(
idxstage
+
2
)
+
'_'
+
str
(
i
+
1
),
InvertedResidualUnit
(
num_channels
=
output_channel
,
num_filters
=
output_channel
,
stride
=
1
,
benchmodel
=
1
,
act
=
act
,
name
=
str
(
idxstage
+
2
)
+
'_'
+
str
(
i
+
1
)))
self
.
_block_list
.
append
(
block
)
# 3. last_conv
self
.
_last_conv
=
ConvBNLayer
(
num_channels
=
stage_out_channels
[
-
2
],
num_filters
=
stage_out_channels
[
-
1
],
filter_size
=
1
,
stride
=
1
,
padding
=
0
,
if_act
=
True
,
act
=
act
,
name
=
'conv5'
)
# 4. pool
self
.
_pool2d_avg
=
Pool2D
(
pool_type
=
'avg'
,
global_pooling
=
True
)
self
.
_out_c
=
stage_out_channels
[
-
1
]
# 5. fc
self
.
_fc
=
Linear
(
stage_out_channels
[
-
1
],
class_dim
,
param_attr
=
ParamAttr
(
name
=
'fc6_weights'
),
bias_attr
=
ParamAttr
(
name
=
'fc6_offset'
))
def
forward
(
self
,
inputs
):
y
=
self
.
_conv1
(
inputs
)
y
=
self
.
_max_pool
(
y
)
for
inv
in
self
.
_block_list
:
y
=
inv
(
y
)
y
=
self
.
_last_conv
(
y
)
y
=
self
.
_pool2d_avg
(
y
)
y
=
fluid
.
layers
.
reshape
(
y
,
shape
=
[
-
1
,
self
.
_out_c
])
y
=
self
.
_fc
(
y
)
return
y
def
ShuffleNetV2_x0_25
(
**
args
):
model
=
ShuffleNetV2
(
scale
=
0.25
,
**
args
)
return
model
def
ShuffleNetV2_x0_
25
(
):
model
=
ShuffleNet
V2
(
scale
=
0.25
)
def
ShuffleNetV2_x0_
33
(
**
args
):
model
=
ShuffleNet
(
scale
=
0.33
,
**
args
)
return
model
def
ShuffleNetV2_x0_
33
(
):
model
=
ShuffleNet
V2
(
scale
=
0.33
)
def
ShuffleNetV2_x0_
5
(
**
args
):
model
=
ShuffleNet
(
scale
=
0.5
,
**
args
)
return
model
def
ShuffleNetV2
_x0_5
(
):
model
=
ShuffleNet
V2
(
scale
=
0.5
)
def
ShuffleNetV2
(
**
args
):
model
=
ShuffleNet
(
scale
=
1.0
,
**
args
)
return
model
def
ShuffleNetV2_x1_
0
(
):
model
=
ShuffleNet
V2
(
scale
=
1.0
)
def
ShuffleNetV2_x1_
5
(
**
args
):
model
=
ShuffleNet
(
scale
=
1.5
,
**
args
)
return
model
def
ShuffleNetV2_x
1_5
(
):
model
=
ShuffleNet
V2
(
scale
=
1.5
)
def
ShuffleNetV2_x
2_0
(
**
args
):
model
=
ShuffleNet
(
scale
=
2.0
,
**
args
)
return
model
def
ShuffleNetV2_
x2_0
(
):
model
=
ShuffleNet
V2
(
scale
=
2.0
)
def
ShuffleNetV2_
swish
(
**
args
):
model
=
ShuffleNet
(
scale
=
1.0
,
act
=
'swish'
,
**
args
)
return
model
ppcls/modeling/architectures/shufflenet_v2_swish.py
已删除
100644 → 0
浏览文件 @
0e7bea51
#copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve.
#
#Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
from
__future__
import
absolute_import
from
__future__
import
division
from
__future__
import
print_function
import
math
import
paddle.fluid
as
fluid
from
paddle.fluid.initializer
import
MSRA
from
paddle.fluid.param_attr
import
ParamAttr
__all__
=
[
'ShuffleNetV2_x0_5_swish'
,
'ShuffleNetV2_x1_0_swish'
,
'ShuffleNetV2_x1_5_swish'
,
'ShuffleNetV2_x2_0_swish'
,
'ShuffleNetV2_swish'
]
class
ShuffleNetV2_swish
():
def
__init__
(
self
,
scale
=
1.0
):
self
.
scale
=
scale
def
net
(
self
,
input
,
class_dim
=
1000
):
scale
=
self
.
scale
stage_repeats
=
[
4
,
8
,
4
]
if
scale
==
0.5
:
stage_out_channels
=
[
-
1
,
24
,
48
,
96
,
192
,
1024
]
elif
scale
==
1.0
:
stage_out_channels
=
[
-
1
,
24
,
116
,
232
,
464
,
1024
]
elif
scale
==
1.5
:
stage_out_channels
=
[
-
1
,
24
,
176
,
352
,
704
,
1024
]
elif
scale
==
2.0
:
stage_out_channels
=
[
-
1
,
24
,
224
,
488
,
976
,
2048
]
else
:
raise
ValueError
(
"""{} groups is not supported for
1x1 Grouped Convolutions"""
.
format
(
num_groups
))
#conv1
input_channel
=
stage_out_channels
[
1
]
conv1
=
self
.
conv_bn_layer
(
input
=
input
,
filter_size
=
3
,
num_filters
=
input_channel
,
padding
=
1
,
stride
=
2
,
name
=
'stage1_conv'
)
pool1
=
fluid
.
layers
.
pool2d
(
input
=
conv1
,
pool_size
=
3
,
pool_stride
=
2
,
pool_padding
=
1
,
pool_type
=
'max'
)
conv
=
pool1
# bottleneck sequences
for
idxstage
in
range
(
len
(
stage_repeats
)):
numrepeat
=
stage_repeats
[
idxstage
]
output_channel
=
stage_out_channels
[
idxstage
+
2
]
for
i
in
range
(
numrepeat
):
if
i
==
0
:
conv
=
self
.
inverted_residual_unit
(
input
=
conv
,
num_filters
=
output_channel
,
stride
=
2
,
benchmodel
=
2
,
name
=
str
(
idxstage
+
2
)
+
'_'
+
str
(
i
+
1
))
else
:
conv
=
self
.
inverted_residual_unit
(
input
=
conv
,
num_filters
=
output_channel
,
stride
=
1
,
benchmodel
=
1
,
name
=
str
(
idxstage
+
2
)
+
'_'
+
str
(
i
+
1
))
conv_last
=
self
.
conv_bn_layer
(
input
=
conv
,
filter_size
=
1
,
num_filters
=
stage_out_channels
[
-
1
],
padding
=
0
,
stride
=
1
,
name
=
'conv5'
)
pool_last
=
fluid
.
layers
.
pool2d
(
input
=
conv_last
,
pool_size
=
7
,
pool_stride
=
1
,
pool_padding
=
0
,
pool_type
=
'avg'
)
output
=
fluid
.
layers
.
fc
(
input
=
pool_last
,
size
=
class_dim
,
param_attr
=
ParamAttr
(
initializer
=
MSRA
(),
name
=
'fc6_weights'
),
bias_attr
=
ParamAttr
(
name
=
'fc6_offset'
))
return
output
def
conv_bn_layer
(
self
,
input
,
filter_size
,
num_filters
,
stride
,
padding
,
num_groups
=
1
,
use_cudnn
=
True
,
if_act
=
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
)
out
=
int
((
input
.
shape
[
2
]
-
1
)
/
float
(
stride
)
+
1
)
bn_name
=
name
+
'_bn'
if
if_act
:
return
fluid
.
layers
.
batch_norm
(
input
=
conv
,
act
=
'swish'
,
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'
)
else
:
return
fluid
.
layers
.
batch_norm
(
input
=
conv
,
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
channel_shuffle
(
self
,
x
,
groups
):
batchsize
,
num_channels
,
height
,
width
=
x
.
shape
[
0
],
x
.
shape
[
1
],
x
.
shape
[
2
],
x
.
shape
[
3
]
channels_per_group
=
num_channels
//
groups
# reshape
x
=
fluid
.
layers
.
reshape
(
x
=
x
,
shape
=
[
batchsize
,
groups
,
channels_per_group
,
height
,
width
])
x
=
fluid
.
layers
.
transpose
(
x
=
x
,
perm
=
[
0
,
2
,
1
,
3
,
4
])
# flatten
x
=
fluid
.
layers
.
reshape
(
x
=
x
,
shape
=
[
batchsize
,
num_channels
,
height
,
width
])
return
x
def
inverted_residual_unit
(
self
,
input
,
num_filters
,
stride
,
benchmodel
,
name
=
None
):
assert
stride
in
[
1
,
2
],
\
"supported stride are {} but your stride is {}"
.
format
([
1
,
2
],
stride
)
oup_inc
=
num_filters
//
2
inp
=
input
.
shape
[
1
]
if
benchmodel
==
1
:
x1
,
x2
=
fluid
.
layers
.
split
(
input
,
num_or_sections
=
[
input
.
shape
[
1
]
//
2
,
input
.
shape
[
1
]
//
2
],
dim
=
1
)
conv_pw
=
self
.
conv_bn_layer
(
input
=
x2
,
num_filters
=
oup_inc
,
filter_size
=
1
,
stride
=
1
,
padding
=
0
,
num_groups
=
1
,
if_act
=
True
,
name
=
'stage_'
+
name
+
'_conv1'
)
conv_dw
=
self
.
conv_bn_layer
(
input
=
conv_pw
,
num_filters
=
oup_inc
,
filter_size
=
3
,
stride
=
stride
,
padding
=
1
,
num_groups
=
oup_inc
,
if_act
=
False
,
use_cudnn
=
False
,
name
=
'stage_'
+
name
+
'_conv2'
)
conv_linear
=
self
.
conv_bn_layer
(
input
=
conv_dw
,
num_filters
=
oup_inc
,
filter_size
=
1
,
stride
=
1
,
padding
=
0
,
num_groups
=
1
,
if_act
=
True
,
name
=
'stage_'
+
name
+
'_conv3'
)
out
=
fluid
.
layers
.
concat
([
x1
,
conv_linear
],
axis
=
1
)
else
:
#branch1
conv_dw_1
=
self
.
conv_bn_layer
(
input
=
input
,
num_filters
=
inp
,
filter_size
=
3
,
stride
=
stride
,
padding
=
1
,
num_groups
=
inp
,
if_act
=
False
,
use_cudnn
=
False
,
name
=
'stage_'
+
name
+
'_conv4'
)
conv_linear_1
=
self
.
conv_bn_layer
(
input
=
conv_dw_1
,
num_filters
=
oup_inc
,
filter_size
=
1
,
stride
=
1
,
padding
=
0
,
num_groups
=
1
,
if_act
=
True
,
name
=
'stage_'
+
name
+
'_conv5'
)
#branch2
conv_pw_2
=
self
.
conv_bn_layer
(
input
=
input
,
num_filters
=
oup_inc
,
filter_size
=
1
,
stride
=
1
,
padding
=
0
,
num_groups
=
1
,
if_act
=
True
,
name
=
'stage_'
+
name
+
'_conv1'
)
conv_dw_2
=
self
.
conv_bn_layer
(
input
=
conv_pw_2
,
num_filters
=
oup_inc
,
filter_size
=
3
,
stride
=
stride
,
padding
=
1
,
num_groups
=
oup_inc
,
if_act
=
False
,
use_cudnn
=
False
,
name
=
'stage_'
+
name
+
'_conv2'
)
conv_linear_2
=
self
.
conv_bn_layer
(
input
=
conv_dw_2
,
num_filters
=
oup_inc
,
filter_size
=
1
,
stride
=
1
,
padding
=
0
,
num_groups
=
1
,
if_act
=
True
,
name
=
'stage_'
+
name
+
'_conv3'
)
out
=
fluid
.
layers
.
concat
([
conv_linear_1
,
conv_linear_2
],
axis
=
1
)
return
self
.
channel_shuffle
(
out
,
2
)
def
ShuffleNetV2_x0_5_swish
():
model
=
ShuffleNetV2_swish
(
scale
=
0.5
)
return
model
def
ShuffleNetV2_x1_0_swish
():
model
=
ShuffleNetV2_swish
(
scale
=
1.0
)
return
model
def
ShuffleNetV2_x1_5_swish
():
model
=
ShuffleNetV2_swish
(
scale
=
1.5
)
return
model
def
ShuffleNetV2_x2_0_swish
():
model
=
ShuffleNetV2_swish
(
scale
=
2.0
)
return
model
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录