Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
PaddlePaddle
X2Paddle
提交
a1af51d3
X
X2Paddle
项目概览
PaddlePaddle
/
X2Paddle
大约 1 年 前同步成功
通知
328
Star
698
Fork
167
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
26
列表
看板
标记
里程碑
合并请求
4
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
X
X2Paddle
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
26
Issue
26
列表
看板
标记
里程碑
合并请求
4
合并请求
4
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
未验证
提交
a1af51d3
编写于
12月 14, 2020
作者:
S
SunAhong1993
提交者:
GitHub
12月 14, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #15 from PaddlePaddle/develop
Merge
上级
e19d3442
e6bb7357
变更
19
隐藏空白更改
内联
并排
Showing
19 changed file
with
1091 addition
and
1725 deletion
+1091
-1725
docs/user_guides/add_caffe_custom_layer.md
docs/user_guides/add_caffe_custom_layer.md
+0
-44
x2paddle/core/program.py
x2paddle/core/program.py
+8
-1
x2paddle/op_mapper/dygraph/caffe2paddle/caffe_op_mapper.py
x2paddle/op_mapper/dygraph/caffe2paddle/caffe_op_mapper.py
+1
-5
x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer/__init__.py
...mapper/static/caffe2paddle/caffe_custom_layer/__init__.py
+20
-100
x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer/axpy.py
.../op_mapper/static/caffe2paddle/caffe_custom_layer/axpy.py
+0
-29
x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer/convolutiondepthwise.py
...c/caffe2paddle/caffe_custom_layer/convolutiondepthwise.py
+0
-150
x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer/detectionoutput.py
...static/caffe2paddle/caffe_custom_layer/detectionoutput.py
+47
-59
x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer/normalize.py
...apper/static/caffe2paddle/caffe_custom_layer/normalize.py
+24
-37
x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer/permute.py
..._mapper/static/caffe2paddle/caffe_custom_layer/permute.py
+0
-30
x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer/priorbox.py
...mapper/static/caffe2paddle/caffe_custom_layer/priorbox.py
+44
-60
x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer/register.py
...mapper/static/caffe2paddle/caffe_custom_layer/register.py
+0
-41
x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer/relu6.py
...op_mapper/static/caffe2paddle/caffe_custom_layer/relu6.py
+0
-21
x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer/roipooling.py
...pper/static/caffe2paddle/caffe_custom_layer/roipooling.py
+31
-41
x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer/select.py
...p_mapper/static/caffe2paddle/caffe_custom_layer/select.py
+29
-51
x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer/shufflechannel.py
.../static/caffe2paddle/caffe_custom_layer/shufflechannel.py
+0
-24
x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer/upsample.py
...mapper/static/caffe2paddle/caffe_custom_layer/upsample.py
+0
-66
x2paddle/op_mapper/static/caffe2paddle/caffe_op_mapper.py
x2paddle/op_mapper/static/caffe2paddle/caffe_op_mapper.py
+793
-547
x2paddle/op_mapper/static/caffe2paddle/caffe_shape.py
x2paddle/op_mapper/static/caffe2paddle/caffe_shape.py
+0
-364
x2paddle/optimizer/fusion/static/bn_scale_fuser.py
x2paddle/optimizer/fusion/static/bn_scale_fuser.py
+94
-55
未找到文件。
docs/user_guides/add_caffe_custom_layer.md
浏览文件 @
a1af51d3
...
...
@@ -38,50 +38,6 @@ bash ./toos/compile.sh /home/root/caffe/src/caffe/proto
```
***步骤三 添加自定义Layer的实现代码**
*
**静态图方式:**
-
进入./x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer,创建.py文件,例如mylayer.py
-
仿照./x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer中的其他文件,在mylayer.py中主要需要实现3个函数,下面以roipooling.py为例分析代码:
1.
`def roipooling_shape(input_shape, pooled_w=None, pooled_h=None)`
参数:
1.
input_shape(list):其中每个元素代表该层每个输入数据的shape,为必须传入的参数
2.
pooled_w(int):代表ROI Pooling的kernel的宽,其命名与.prototxt中roi_pooling_param中的key一致
3.
pooled_h(int):代表ROI Pooling的kernel的高,其命名与.prototxt中roi_pooling_param中的key一致
功能:计算出进行ROI Pooling后的shape
返回:一个list,其中每个元素代表每个输出数据的shape,由于ROI Pooling的输出数据只有一个,所以其list长度为1
2.
`def roipooling_layer(inputs, input_shape=None, name=None, pooled_w=None, pooled_h=None, spatial_scale=None)`
参数:
1. inputs(list):其中每个元素代表该层每个输入数据,为必须传入的参数
2. input_shape(list):其中每个元素代表该层每个输入数据的shape,为必须传入的参数
3. name(str):ROI Pooling层的名字,为必须传入的参数
4. pooled_w(int):代表ROI Pooling的kernel的宽,其命名与.prototxt中roi_pooling_param中的key一致
5. pooled_h(int):代表ROI Pooling的kernel的高,其命名与.prototxt中roi_pooling_param中的key一致
6. spatial_scale(float):用于将ROI坐标从输入比例转换为池化时使用的比例,其命名与.prototxt中roi_pooling_param中的key一致
功能:运用PaddlePaddle完成组网来实现`roipooling_layer`的功能
返回:一个Variable,为组网后的结果
3.
`def roipooling_weights(name, data=None)`
参数:
1. name(str):ROI Pooling层的名字,为必须传入的参数
2. data(list):由Caffe模型.caffemodel获得的关于roipooling的参数,roipooling的参数为None
功能:为每个参数(例如kernel、bias等)命名;同时,若Caffe中该层参数与PaddlePaddle中参数的格式不一致,则变换操作也在该函数中实现。
返回:一个list,包含每个参数的名字。
-
在roipooling.py中注册
`roipooling`
,主要运用下述代码实现:
```
register(kind='ROIPooling', shape=roipooling_shape, layer=roipooling_layer, weights=roipooling_weights)
# kind为在model.prototxt中roipooling的type
```
-
在./x2paddle/op_mapper/caffe_custom_layer/
\_\_
init
\_\_
.py中引入该层的使用
```
from . import roipooling
```
**动态图方式:**
> 【注意】若Caffe自定义layer与Paddle的op一一对应,使用方式一,否则使用方式二。
-
方式一:
...
...
x2paddle/core/program.py
浏览文件 @
a1af51d3
...
...
@@ -309,12 +309,19 @@ class PaddleGraph(object):
if
not
osp
.
exists
(
code_dir
):
os
.
makedirs
(
code_dir
)
f
=
open
(
osp
.
join
(
code_dir
,
'x2paddle_model.py'
),
'w'
)
if
self
.
source_type
==
"caffe"
:
custom_import
=
"from x2paddle.op_mapper.static.caffe2paddle "
+
\
"import caffe_custom_layer as x2paddle_nn"
else
:
custom_import
=
""
write_code
(
f
,
[
"from paddle.fluid.initializer import Constant"
,
"from paddle.fluid.param_attr import ParamAttr"
,
"import paddle.fluid as fluid"
,
custom_import
,
"import paddle"
,
"import math"
,
""
,
],
...
...
@@ -347,7 +354,7 @@ class PaddleGraph(object):
line
+=
"{}, "
.
format
(
output
)
line
=
line
.
strip
(
", "
)
if
layer
.
kernel
.
startswith
(
"custom_layer"
):
line
+=
"
= {}("
.
format
(
layer
.
kernel
.
split
(
":"
)[
-
1
].
lower
()
+
"_layer"
)
line
+=
"
= x2paddle_nn.{}("
.
format
(
layer
.
kernel
.
split
(
":"
)[
-
1
]
)
else
:
line
+=
" = {}("
.
format
(
layer
.
kernel
)
for
k
,
v
in
layer
.
inputs
.
items
():
...
...
x2paddle/op_mapper/dygraph/caffe2paddle/caffe_op_mapper.py
浏览文件 @
a1af51d3
...
...
@@ -1092,11 +1092,7 @@ class CaffeOpMapper(OpMapper):
**
layer_attrs
)
def
ReLU6
(
self
,
node
):
if
"relu6"
in
self
.
nn_name2id
:
self
.
nn_name2id
[
"relu6"
]
+=
1
else
:
self
.
nn_name2id
[
"relu6"
]
=
0
relu6_name
=
"relu6"
+
str
(
self
.
nn_name2id
[
"relu6"
])
relu6_name
=
name_generator
(
"relu6"
,
self
.
nn_name2id
)
output_name
=
node
.
layer_name
layer_outputs
=
[
relu6_name
,
output_name
]
assert
len
(
...
...
x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer/__init__.py
浏览文件 @
a1af51d3
from
.register
import
get_registered_layers
#custom layer import begins
from
.
import
roipooling
from
.
import
priorbox
from
.
import
permute
from
.
import
detectionoutput
from
.
import
normalize
from
.
import
select
from
.
import
shufflechannel
from
.
import
convolutiondepthwise
from
.
import
axpy
from
.
import
upsample
from
.
import
relu6
#custom layer import ends
custom_layers
=
get_registered_layers
()
def
set_args
(
f
,
params
):
""" set args for function 'f' using the parameters in node.layer.param
Args:
f (function): a python function object
params (object): a object contains attributes needed by f's arguments
Returns:
arg_names (list): a list of argument names
kwargs (dict): a dict contains needed arguments
"""
argc
=
f
.
__code__
.
co_argcount
arg_list
=
f
.
__code__
.
co_varnames
[
0
:
argc
]
kwargs
=
{}
for
arg_name
in
arg_list
:
if
hasattr
(
params
,
arg_name
)
and
params
is
not
None
:
kwargs
[
arg_name
]
=
getattr
(
params
,
arg_name
)
return
arg_list
,
kwargs
def
has_layer
(
layer_type
):
""" test whether this layer exists in custom layer
"""
return
layer_type
in
custom_layers
def
get_params
(
layer
,
layer_type
):
import
re
if
layer_type
.
lower
()
==
"deconvolution"
or
layer_type
.
lower
(
)
==
"convolutiondepthwise"
:
param_name
=
'_'
.
join
((
'convolution'
,
'param'
))
elif
layer_type
.
lower
()
==
"normalize"
:
param_name
=
'_'
.
join
((
'norm'
,
'param'
))
elif
len
(
layer_type
)
-
len
(
re
.
sub
(
"[A-Z]"
,
""
,
layer_type
))
>=
2
:
s
=
''
tmp_name
=
''
for
i
,
ch
in
enumerate
(
layer_type
):
if
i
==
0
:
s
+=
ch
.
lower
()
continue
elif
ch
.
isupper
()
and
layer_type
[
i
-
1
].
islower
():
tmp_name
+=
(
s
+
'_'
)
s
=
''
s
+=
ch
.
lower
()
tmp_name
+=
s
param_name
=
'_'
.
join
((
tmp_name
,
'param'
))
else
:
param_name
=
'_'
.
join
((
layer_type
.
lower
(),
'param'
))
return
getattr
(
layer
,
param_name
,
None
)
def
compute_output_shape
(
node
):
""" compute the output shape of custom layer
"""
layer_type
=
node
.
layer_type
assert
layer_type
in
custom_layers
,
"layer[%s] not exist in custom layers"
%
(
layer_type
)
shape_func
=
custom_layers
[
layer_type
][
'shape'
]
layer
=
node
.
layer
params
=
get_params
(
layer
,
layer_type
)
arg_names
,
kwargs
=
set_args
(
shape_func
,
params
)
input_shape
=
node
.
input_shape
return
shape_func
(
input_shape
,
**
kwargs
)
def
make_custom_layer
(
node
):
""" get the code which implement the custom layer function
"""
layer_type
=
node
.
layer_type
assert
layer_type
in
custom_layers
,
"layer[%s] not exist in custom layers"
%
(
layer_type
)
layer_func
=
custom_layers
[
layer_type
][
'layer'
]
import
inspect
return
inspect
.
getsource
(
layer_func
),
layer_func
def
deal_weights
(
node
,
data
=
None
):
""" deal the weights of the custom layer
"""
layer_type
=
node
.
layer_type
weights_func
=
custom_layers
[
layer_type
][
'weights'
]
name
=
node
.
layer_name
return
weights_func
(
name
,
data
)
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from
.detectionoutput
import
detectionoutput
from
.normalize
import
normalize
from
.priorbox
import
priorbox
from
.roipooling
import
roipooling
from
.select
import
select
\ No newline at end of file
x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer/axpy.py
已删除
100644 → 0
浏览文件 @
e19d3442
from
.register
import
register
from
x2paddle.core.util
import
*
def
axpy_shape
(
input_shapes
):
assert
len
(
input_shapes
)
==
3
,
"not valid input shape for axpy layer"
assert
len
(
input_shapes
[
0
])
==
len
(
input_shapes
[
1
]),
'should have same dims'
output_shape
=
input_shapes
[
1
]
assert
(
input_shapes
[
2
]
==
output_shape
),
\
"shape not consistent for axpy[%s <--> %s]"
\
%
(
str
(
output_shape
),
str
(
input_shapes
[
2
]))
return
[
output_shape
]
def
axpy_layer
(
inputs
,
input_shape
=
None
,
name
=
None
):
alpha
=
inputs
[
0
]
x
=
inputs
[
1
]
y
=
inputs
[
2
]
out
=
fluid
.
layers
.
elementwise_mul
(
x
,
alpha
,
axis
=
0
)
out
=
fluid
.
layers
.
elementwise_add
(
out
,
y
,
name
=
name
)
return
out
def
axpy_weights
(
name
,
data
=
None
):
weights_name
=
[]
return
weights_name
register
(
kind
=
'Axpy'
,
shape
=
axpy_shape
,
layer
=
axpy_layer
,
weights
=
axpy_weights
)
x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer/convolutiondepthwise.py
已删除
100644 → 0
浏览文件 @
e19d3442
from
.register
import
register
from
x2paddle.core.util
import
*
import
numbers
def
convolutiondepthwise_shape
(
input_shape
,
num_output
=
None
,
pad
=
None
,
kernel_size
=
None
,
stride
=
None
,
dilation
=
None
,
pad_h
=
None
,
pad_w
=
None
,
kernel_h
=
None
,
kernel_w
=
None
,
stride_h
=
None
,
stride_w
=
None
):
[
k_h
,
k_w
]
=
[
1
,
1
]
if
isinstance
(
kernel_size
,
numbers
.
Number
):
[
k_h
,
k_w
]
=
[
kernel_size
]
*
2
elif
len
(
kernel_size
)
>
0
:
k_h
=
kernel_h
if
kernel_h
>
0
else
kernel_size
[
0
]
k_w
=
kernel_w
if
kernel_w
>
0
else
kernel_size
[
len
(
kernel_size
)
-
1
]
elif
kernel_h
>
0
or
kernel_w
>
0
:
k_h
=
kernel_h
k_w
=
kernel_w
[
s_h
,
s_w
]
=
[
1
,
1
]
if
isinstance
(
stride
,
numbers
.
Number
):
[
s_h
,
s_w
]
=
[
stride
]
*
2
elif
len
(
stride
)
>
0
:
s_h
=
stride_h
if
stride_h
>
0
else
stride
[
0
]
s_w
=
stride_w
if
stride_w
>
0
else
stride
[
len
(
stride
)
-
1
]
elif
stride_h
>
0
or
stride_w
>
0
:
s_h
=
stride_h
s_w
=
stride_w
[
p_h
,
p_w
]
=
[
0
,
0
]
if
isinstance
(
pad
,
numbers
.
Number
):
[
p_h
,
p_w
]
=
[
pad
]
*
2
elif
len
(
pad
)
>
0
:
p_h
=
pad_h
if
pad_h
>
0
else
pad
[
0
]
p_w
=
pad_w
if
pad_w
>
0
else
pad
[
len
(
pad
)
-
1
]
elif
pad_h
>
0
or
pad_w
>
0
:
p_h
=
pad_h
p_w
=
pad_w
dila_len
=
len
(
dilation
)
dila_h
=
1
dila_w
=
1
if
dila_len
==
2
:
dila_h
=
dilation
[
0
]
dila_w
=
dilation
[
1
]
elif
dila_len
==
1
:
dila_h
=
dila_w
=
dilation
[
0
]
else
:
assert
dila_len
==
0
,
"invalid length[%s] of dilation in convolution"
%
(
dila_len
)
i_w
=
input_shape
[
0
][
2
]
i_h
=
input_shape
[
0
][
3
]
o_h
=
(
i_h
+
2
*
p_h
-
(
dila_h
*
(
k_h
-
1
)
+
1
))
/
float
(
s_h
)
+
1
o_w
=
(
i_w
+
2
*
p_w
-
(
dila_w
*
(
k_w
-
1
)
+
1
))
/
float
(
s_w
)
+
1
import
math
o_h
=
int
(
math
.
floor
(
o_h
))
o_w
=
int
(
math
.
floor
(
o_w
))
c
=
num_output
if
num_output
is
not
None
else
input_shape
[
0
][
1
]
return
[[
input_shape
[
0
][
0
],
c
,
o_h
,
o_w
]]
def
convolutiondepthwise_layer
(
inputs
,
num_output
=
None
,
pad
=
None
,
kernel_size
=
None
,
stride
=
None
,
dilation
=
None
,
pad_h
=
None
,
pad_w
=
None
,
kernel_h
=
None
,
kernel_w
=
None
,
stride_h
=
None
,
stride_w
=
None
,
input_shape
=
None
,
name
=
None
):
import
numbers
[
k_h
,
k_w
]
=
[
1
,
1
]
if
isinstance
(
kernel_size
,
numbers
.
Number
):
[
k_h
,
k_w
]
=
[
kernel_size
]
*
2
elif
len
(
kernel_size
)
>
0
:
k_h
=
kernel_h
if
kernel_h
>
0
else
kernel_size
[
0
]
k_w
=
kernel_w
if
kernel_w
>
0
else
kernel_size
[
len
(
kernel_size
)
-
1
]
elif
kernel_h
>
0
or
kernel_w
>
0
:
k_h
=
kernel_h
k_w
=
kernel_w
[
s_h
,
s_w
]
=
[
1
,
1
]
if
isinstance
(
stride
,
numbers
.
Number
):
[
s_h
,
s_w
]
=
[
stride
]
*
2
elif
len
(
stride
)
>
0
:
s_h
=
stride_h
if
stride_h
>
0
else
stride
[
0
]
s_w
=
stride_w
if
stride_w
>
0
else
stride
[
len
(
stride
)
-
1
]
elif
stride_h
>
0
or
stride_w
>
0
:
s_h
=
stride_h
s_w
=
stride_w
[
p_h
,
p_w
]
=
[
0
,
0
]
if
isinstance
(
pad
,
numbers
.
Number
):
[
p_h
,
p_w
]
=
[
pad
]
*
2
elif
len
(
pad
)
>
0
:
p_h
=
pad_h
if
pad_h
>
0
else
pad
[
0
]
p_w
=
pad_w
if
pad_w
>
0
else
pad
[
len
(
pad
)
-
1
]
elif
pad_h
>
0
or
pad_w
>
0
:
p_h
=
pad_h
p_w
=
pad_w
input
=
inputs
[
0
]
dila_len
=
len
(
dilation
)
dila_h
=
1
dila_w
=
1
if
dila_len
==
2
:
dila_h
=
dilation
[
0
]
dila_w
=
dilation
[
1
]
elif
dila_len
==
1
:
dila_h
=
dila_w
=
dilation
[
0
]
else
:
assert
dila_len
==
0
,
"invalid length[%s] of dilation in convolution"
%
(
dila_len
)
c_in
=
input_shape
[
0
][
1
]
c_out
=
num_output
if
num_output
is
not
None
else
input_shape
[
0
][
1
]
group
=
int
(
c_in
/
(
c_in
/
c_out
))
if
c_in
>
c_out
else
int
(
c_in
/
(
c_out
/
c_in
))
out
=
fluid
.
layers
.
conv2d
(
input
,
dilation
=
[
dila_h
,
dila_w
],
filter_size
=
[
k_h
,
k_w
],
stride
=
[
s_h
,
s_w
],
padding
=
[
p_h
,
p_w
],
groups
=
group
,
num_filters
=
c_out
,
param_attr
=
name
+
'_weights'
,
bias_attr
=
name
+
'_bias'
,
name
=
name
)
return
out
def
convolutiondepthwise_weights
(
name
,
data
=
None
):
weights_name
=
[]
weights_name
.
append
(
name
+
'_weights'
)
weights_name
.
append
(
name
+
'_bias'
)
return
weights_name
register
(
kind
=
'ConvolutionDepthwise'
,
shape
=
convolutiondepthwise_shape
,
layer
=
convolutiondepthwise_layer
,
weights
=
convolutiondepthwise_weights
)
x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer/detectionoutput.py
浏览文件 @
a1af51d3
from
.register
import
register
from
x2paddle.core.util
import
*
def
detectionoutput_shape
(
input_shape
):
return
[[
-
1
,
6
]]
def
detectionoutput_layer
(
inputs
,
nms_param
=
None
,
background_label_id
=
0
,
share_location
=
True
,
keep_top_k
=
100
,
confidence_threshold
=
0.1
,
input_shape
=
None
,
name
=
None
):
if
nms_param
is
None
:
nms_param
=
{
"nms_threshold"
:
0.3
,
"top_k"
:
10
,
"eta"
:
1.0
}
mbox_conf_flatten
=
inputs
[
1
]
mbox_priorbox
=
inputs
[
2
]
mbox_priorbox_list
=
fluid
.
layers
.
split
(
mbox_priorbox
,
2
,
dim
=
1
)
pb
=
mbox_priorbox_list
[
0
]
pbv
=
mbox_priorbox_list
[
1
]
pb
=
fluid
.
layers
.
reshape
(
x
=
pb
,
shape
=
[
-
1
,
4
])
pbv
=
fluid
.
layers
.
reshape
(
x
=
pbv
,
shape
=
[
-
1
,
4
])
mbox_loc
=
inputs
[
0
]
mbox_loc
=
fluid
.
layers
.
reshape
(
x
=
mbox_loc
,
shape
=
[
-
1
,
pb
.
shape
[
0
],
4
])
mbox_conf_flatten
=
fluid
.
layers
.
reshape
(
x
=
mbox_conf_flatten
,
shape
=
[
0
,
pb
.
shape
[
0
],
-
1
])
default
=
{
"nms_threshold"
:
0.3
,
"top_k"
:
10
,
"eta"
:
1.0
}
fields
=
[
'eta'
,
'top_k'
,
'nms_threshold'
]
for
f
in
default
.
keys
():
if
f
not
in
nms_param
:
nms_param
[
f
]
=
default
[
f
]
out
=
fluid
.
layers
.
detection_output
(
scores
=
mbox_conf_flatten
,
loc
=
mbox_loc
,
prior_box
=
pb
,
prior_box_var
=
pbv
,
background_label
=
background_label_id
,
nms_threshold
=
nms_param
[
"nms_threshold"
],
nms_top_k
=
nms_param
[
"top_k"
],
keep_top_k
=
keep_top_k
,
score_threshold
=
confidence_threshold
,
nms_eta
=
nms_param
[
"eta"
])
return
out
def
detectionoutput_weights
(
name
,
data
=
None
):
weights_name
=
[]
return
weights_name
register
(
kind
=
'DetectionOutput'
,
shape
=
detectionoutput_shape
,
layer
=
detectionoutput_layer
,
weights
=
detectionoutput_weights
)
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import
paddle
import
paddle.fluid
as
fluid
def
detectionoutput
(
x0
,
x1
,
x2
,
nms_threshold
,
nms_top_k
,
keep_top_k
,
nms_eta
,
score_threshold
,
background_label
):
detection_output_layer_attrs
=
{
"background_label"
:
background_label
,
"nms_threshold"
:
nms_threshold
,
"nms_top_k"
:
nms_top_k
,
"keep_top_k"
:
keep_top_k
,
"score_threshold"
:
score_threshold
,
"nms_eta"
:
nms_eta
}
priorbox_list
=
paddle
.
split
(
x2
,
num_or_sections
=
2
,
axis
=
1
)
pb
=
priorbox_list
[
0
]
pbv
=
priorbox_list
[
1
]
pb
=
paddle
.
reshape
(
x
=
pb
,
shape
=
[
-
1
,
4
])
pbv
=
paddle
.
reshape
(
x
=
pbv
,
shape
=
[
-
1
,
4
])
pb_dim
=
fluid
.
layers
.
shape
(
pb
)[
0
]
loc
=
paddle
.
reshape
(
x0
,
shape
=
[
-
1
,
pb_dim
,
4
])
conf_flatten
=
paddle
.
reshape
(
x1
,
shape
=
[
0
,
pb_dim
,
-
1
])
out
=
fluid
.
layers
.
detection_output
(
loc
=
loc
,
scores
=
conf_flatten
,
prior_box
=
pb
,
prior_box_var
=
pbv
,
**
detection_output_layer_attrs
)
return
out
\ No newline at end of file
x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer/normalize.py
浏览文件 @
a1af51d3
from
.register
import
register
from
x2paddle.core.util
import
*
def
normalize_shape
(
input_shape
):
return
input_shape
def
normalize_layer
(
inputs
,
across_spatial
=
None
,
channel_shared
=
None
,
input_shape
=
None
,
name
=
None
):
assert
across_spatial
==
False
,
"Only support across_spatial == False for Normalize"
input
=
inputs
[
0
]
l2_norm
=
fluid
.
layers
.
l2_normalize
(
input
,
axis
=
1
,
name
=
name
+
'_l2'
)
scale_param
=
fluid
.
layers
.
create_parameter
(
shape
=
[
1
]
if
channel_shared
else
[
1
,
1
,
1
,
input_shape
[
0
][
1
]],
dtype
=
input
.
dtype
,
attr
=
fluid
.
ParamAttr
(
name
=
name
+
'_scale'
))
scale_param
=
fluid
.
layers
.
reshape
(
x
=
scale_param
,
\
shape
=
[
1
]
if
channel_shared
else
[
input_shape
[
0
][
1
]])
out
=
fluid
.
layers
.
elementwise_mul
(
x
=
l2_norm
,
y
=
scale_param
,
axis
=-
1
if
channel_shared
else
1
)
return
out
def
normalize_weights
(
name
,
data
=
None
):
weights_name
=
[
name
+
'_scale'
]
return
weights_name
register
(
kind
=
'Normalize'
,
shape
=
normalize_shape
,
layer
=
normalize_layer
,
weights
=
normalize_weights
)
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import
paddle
import
paddle.fluid
as
fluid
def
normalize
(
x
,
axis
,
param_name
,
param_shape
,
param_dtype
):
l2
=
fluid
.
layers
.
prior_box
(
x
=
x
,
p
=
2
,
axis
=
1
)
param
=
paddle
.
static
.
nn
.
create_parameter
(
shape
=
param_shape
,
dtype
=
string
(
param_dtype
),
name
=
string
(
param_name
))
out
=
paddle
.
multiply
(
x
=
l2
,
y
=
param
,
axis
=
axis
)
return
out
\ No newline at end of file
x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer/permute.py
已删除
100644 → 0
浏览文件 @
e19d3442
from
.register
import
register
from
x2paddle.core.util
import
*
def
permute_shape
(
input_shape
,
order
=
None
):
inshape
=
input_shape
[
0
]
output_shape
=
[]
for
ii
in
order
:
assert
ii
<
len
(
inshape
),
"invalid order for permute[%s]"
%
(
name
)
output_shape
.
append
(
inshape
[
ii
])
return
[
output_shape
]
def
permute_layer
(
inputs
,
order
=
None
,
input_shape
=
None
,
name
=
None
):
input
=
inputs
[
0
]
order
=
list
(
order
)
out
=
fluid
.
layers
.
transpose
(
input
,
perm
=
order
,
name
=
name
)
return
out
def
permute_weights
(
name
,
data
=
None
):
weights_name
=
[]
return
weights_name
register
(
kind
=
'Permute'
,
shape
=
permute_shape
,
layer
=
permute_layer
,
weights
=
permute_weights
)
x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer/priorbox.py
浏览文件 @
a1af51d3
from
.register
import
register
from
x2paddle.core.util
import
*
def
priorbox_shape
(
input_shape
,
max_size
=
None
,
aspect_ratio
=
None
):
fc_shape
=
input_shape
[
0
]
N
=
1
if
not
max_size
==
None
:
N
+=
1
if
not
aspect_ratio
==
None
:
N
+=
2
*
len
(
aspect_ratio
)
N_bbx
=
fc_shape
[
2
]
*
fc_shape
[
3
]
*
N
output_shape
=
[
1
,
2
,
4
*
N_bbx
]
return
[
output_shape
]
def
priorbox_layer
(
inputs
,
step
=
0.0
,
offset
=
0.5
,
min_size
=
None
,
max_size
=
[],
aspect_ratio
=
[
1.0
],
flip
=
False
,
clip
=
False
,
variance
=
[
0.1
,
0.1
,
0.2
,
0.2
],
input_shape
=
None
,
name
=
None
):
input
=
inputs
[
0
]
image
=
inputs
[
1
]
steps
=
tuple
(
step
)
if
type
(
step
)
is
list
or
type
(
step
)
is
tuple
else
(
step
,
step
)
box
,
variance_
=
fluid
.
layers
.
prior_box
(
input
,
image
,
min_sizes
=
min_size
,
max_sizes
=
max_size
,
aspect_ratios
=
aspect_ratio
,
variance
=
variance
,
flip
=
flip
,
clip
=
clip
,
steps
=
steps
,
offset
=
offset
,
name
=
name
,
min_max_aspect_ratios_order
=
True
)
box
=
fluid
.
layers
.
reshape
(
box
,
[
1
,
1
,
-
1
])
variance_
=
fluid
.
layers
.
reshape
(
variance_
,
[
1
,
1
,
-
1
])
out
=
fluid
.
layers
.
concat
([
box
,
variance_
],
axis
=
1
)
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import
paddle
import
paddle.fluid
as
fluid
def
priorbox
(
x0
,
x1
,
min_sizes
,
max_sizes
,
aspect_ratios
,
variance
,
flip
,
clip
,
steps
,
offset
,
min_max_aspect_ratios_order
):
priorbox_layer_attrs
=
{
"min_sizes"
:
min_sizes
,
"max_sizes"
:
max_sizes
,
"aspect_ratios"
:
aspect_ratios
,
"variance"
:
variance
,
"flip"
:
flip
,
"clip"
:
clip
,
"steps"
:
steps
,
"offset"
:
offset
,
"min_max_aspect_ratios_order"
:
min_max_aspect_ratios_order
}
box
,
var
=
fluid
.
layers
.
prior_box
(
input
=
x0
,
image
=
x1
,
**
priorbox_layer_attrs
)
box
=
paddle
.
reshape
(
x
=
box
,
shape
=
[
1
,
1
,
-
1
])
var
=
paddle
.
reshape
(
x
=
var
,
shape
=
[
1
,
1
,
-
1
])
out
=
paddle
.
concat
(
x
=
[
box
,
var
],
axis
=
1
)
return
out
def
priorbox_weights
(
name
,
data
=
None
):
weights_name
=
[]
return
weights_name
register
(
kind
=
'PriorBox'
,
shape
=
priorbox_shape
,
layer
=
priorbox_layer
,
weights
=
priorbox_weights
)
x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer/register.py
已删除
100644 → 0
浏览文件 @
e19d3442
""" this module provides 'register' for registering customized layers
"""
g_custom_layers
=
{}
def
register
(
kind
,
shape
,
layer
,
weights
):
""" register a custom layer or a list of custom layers
Args:
@kind (str or list): type name of the layer
@shape (function): a function to generate the shape of layer's output
@layer (function): a function to generate the paddle code of layer
@weights (function): a function to deal with weights data
Returns:
None
"""
assert
type
(
shape
).
__name__
==
'function'
,
'shape should be a function'
assert
type
(
layer
).
__name__
==
'function'
,
'layer should be a function'
if
type
(
kind
)
is
str
:
kind
=
[
kind
]
else
:
assert
type
(
kind
)
is
list
,
'invalid param "kind" for register, not a list or str'
for
k
in
kind
:
assert
type
(
k
)
is
str
,
'invalid param "kind" for register, not a list of str'
assert
k
not
in
g_custom_layers
,
'this type[%s] has already been registered'
%
(
k
)
g_custom_layers
[
k
]
=
{
'shape'
:
shape
,
'layer'
:
layer
,
'weights'
:
weights
}
def
get_registered_layers
():
return
g_custom_layers
x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer/relu6.py
已删除
100644 → 0
浏览文件 @
e19d3442
from
.register
import
register
from
x2paddle.core.util
import
*
def
relu6_shape
(
input_shape
):
return
input_shape
def
relu6_layer
(
inputs
,
input_shape
=
None
,
name
=
None
):
input
=
inputs
[
0
]
out
=
fluid
.
layers
.
relu6
(
x
=
input
)
return
out
def
relu6_weights
(
name
,
data
=
None
):
weights_name
=
[]
return
weights_name
register
(
kind
=
'ReLU6'
,
shape
=
relu6_shape
,
layer
=
relu6_layer
,
weights
=
relu6_weights
)
x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer/roipooling.py
浏览文件 @
a1af51d3
from
.register
import
register
from
x2paddle.core.util
import
*
def
roipooling_shape
(
input_shape
,
pooled_w
=
None
,
pooled_h
=
None
):
base_fea_shape
=
input_shapes
[
0
]
rois_shape
=
input_shapes
[
1
]
output_shape
=
base_fea_shape
output_shape
[
0
]
=
rois_shape
[
0
]
output_shape
[
2
]
=
pooled_h
output_shape
[
3
]
=
pooled_w
return
[
output_shape
]
def
roipooling_layer
(
inputs
,
pooled_w
=
None
,
pooled_h
=
None
,
spatial_scale
=
None
,
input_shape
=
None
,
name
=
None
):
input
=
inputs
[
0
]
roi
=
inputs
[
1
]
roi
=
fluid
.
layers
.
slice
(
roi
,
axes
=
[
1
],
starts
=
[
1
],
ends
=
[
5
])
out
=
fluid
.
layers
.
roi_pool
(
input
,
roi
,
pooled_height
=
pooled_h
,
pooled_width
=
pooled_w
,
spatial_scale
=
spatial_scale
)
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import
paddle
import
paddle.fluid
as
fluid
def
roipooling
(
x0
,
x1
,
pooled_height
,
pooled_width
,
spatial_scale
):
roipooling_layer_attrs
=
{
"pooled_height"
:
pooled_height
,
"pooled_width"
:
pooled_width
,
"spatial_scale"
:
spatial_scale
}
slice_x1
=
paddle
.
slice
(
input
=
x1
,
axes
=
[
1
],
starts
=
[
1
],
ends
=
[
5
])
out
=
fluid
.
layers
.
roi_pool
(
input
=
x0
,
rois
=
slice_x1
,
**
roipooling_layer_attrs
)
return
out
def
roipooling_weights
(
name
,
data
=
None
):
weights_name
=
[]
return
weights_name
register
(
kind
=
'ROIPooling'
,
shape
=
roipooling_shape
,
layer
=
roipooling_layer
,
weights
=
roipooling_weights
)
x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer/select.py
浏览文件 @
a1af51d3
from
.register
import
register
from
x2paddle.core.util
import
*
def
select_shape
(
input_shape
,
axis
=
None
,
slice_point
=
None
):
inshape
=
input_shape
[
0
]
slice_point
=
slice_point
start
=
slice_point
[
0
]
if
len
(
slice_point
)
==
2
:
end
=
slice_point
[
1
]
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import
paddle
import
paddle.fluid
as
fluid
def
select
(
x
,
input_shape
,
point
,
axis
):
start
=
point
[
0
]
if
len
(
point
)
==
2
:
end
=
point
[
1
]
else
:
end
=
input_shape
[
axis
]
assert
end
>
start
,
"invalid slice_point with [start:%d, end:%d]"
%
(
start
,
end
)
output_shape
=
input_shape
output_shape
[
axis
]
=
end
-
start
return
[
output_shape
]
def
select_layer
(
inputs
,
axis
=
None
,
slice_point
=
None
,
input_shape
=
None
,
name
=
None
):
input
=
inputs
[
0
]
maxint32
=
2147483647
slice_point
=
[
0
]
+
slice_point
slice_point
.
append
(
maxint32
)
i
=
0
out
=
[]
for
i
in
range
(
len
(
slice_point
)):
out
.
append
(
fluid
.
layers
.
slice
(
input
,
axes
=
[
axis
],
starts
=
[
slice_point
[
i
]],
ends
=
[
slice_point
[
i
+
1
]],
name
=
name
+
'_'
+
str
(
i
)))
if
i
==
len
(
slice_point
)
-
2
:
break
return
out
def
select_weights
(
name
,
data
=
None
):
weights_name
=
[]
return
weights_name
register
(
kind
=
'Select'
,
shape
=
select_shape
,
layer
=
select_layer
,
weights
=
select_weights
)
out
=
paddle
.
slice
(
x
=
x
,
start
=
start
,
end
=
end
,
axes
=
[
axis
])
return
out
\ No newline at end of file
x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer/shufflechannel.py
已删除
100644 → 0
浏览文件 @
e19d3442
from
.register
import
register
from
x2paddle.core.util
import
*
def
shufflechannel_shape
(
input_shape
):
return
input_shape
def
shufflechannel_layer
(
inputs
,
group
=
None
,
input_shape
=
None
,
name
=
None
):
input
=
inputs
[
0
]
out
=
fluid
.
layers
.
shuffle_channel
(
x
=
input
,
group
=
group
)
return
out
def
shufflechannel_weights
(
name
,
data
=
None
):
weights_name
=
[]
return
weights_name
register
(
kind
=
'ShuffleChannel'
,
shape
=
shufflechannel_shape
,
layer
=
shufflechannel_layer
,
weights
=
shufflechannel_weights
)
x2paddle/op_mapper/static/caffe2paddle/caffe_custom_layer/upsample.py
已删除
100644 → 0
浏览文件 @
e19d3442
# -*- coding: utf-8 -*-
################################################################################
#
# Copyright (c) 2020 Baidu.com, Inc. All Rights Reserved
#
################################################################################
"""
Author: Drift
Email: wutuobang@baidu.com
Date: 2020/04/22 18:45
"""
from
.register
import
register
from
x2paddle.core.util
import
*
def
upsample_shape
(
input_shapes
,
scale
):
"""
:param input_shapes:
:param scale:
:return:
"""
assert
len
(
input_shapes
)
==
1
,
"not valid input shape for upsample layer"
assert
type
(
scale
)
is
int
input_shape
=
input_shapes
[
0
]
new_h
=
scale
*
input_shape
[
2
]
new_w
=
scale
*
input_shape
[
3
]
output_shape
=
[
input_shape
[
0
],
input_shape
[
1
],
new_h
,
new_w
]
return
[
output_shape
]
def
upsample_layer
(
inputs
,
scale
,
input_shape
=
None
,
name
=
None
):
"""
:param inputs:
:param scale:
:param input_shape:
:param name:
:return:
"""
x
=
inputs
[
0
]
out
=
fluid
.
layers
.
resize_nearest
(
x
,
align_corners
=
False
,
scale
=
scale
,
name
=
name
)
return
out
def
upsample_weights
(
name
,
data
=
None
):
"""
:param name:
:param data:
:return:
"""
weights_name
=
[]
return
weights_name
register
(
kind
=
'Upsample'
,
shape
=
upsample_shape
,
layer
=
upsample_layer
,
weights
=
upsample_weights
)
x2paddle/op_mapper/static/caffe2paddle/caffe_op_mapper.py
浏览文件 @
a1af51d3
...
...
@@ -15,183 +15,167 @@
import
numbers
import
copy
import
numpy
as
np
from
x2paddle.decoder.caffe_decoder
import
CaffeGraph
from
x2paddle.decoder.caffe_decoder
import
CaffeGraph
,
CaffeGraphNode
from
x2paddle.core.op_mapper
import
OpMapper
from
x2paddle.core.util
import
*
from
x2paddle.op_mapper.static.caffe2paddle
import
caffe_shape
from
x2paddle.op_mapper.static.caffe2paddle.caffe_custom_layer
import
*
from
x2paddle.core.program
import
PaddleGraph
def
_adjust_parameters
(
node
):
data
=
node
.
data
# When using the protobuf-backend, each parameter initially has four dimensions.
# In certain cases (like FC layers), we want to eliminate the singleton dimensions.
# This implementation takes care of the common cases. However, it does leave the
# potential for future issues.
# The Caffe-backend does not suffer from this problem.
data
=
list
(
data
)
squeeze_indices
=
[
1
]
# Squeeze biases.
if
node
.
layer_type
==
'InnerProduct'
:
squeeze_indices
.
append
(
0
)
# Squeeze FC.
for
idx
in
squeeze_indices
:
if
idx
>=
len
(
data
):
continue
d
=
data
[
idx
]
assert
len
(
d
.
shape
)
==
4
,
'invalid shape[%s] from caffe when adjust_parameters'
%
(
str
(
d
.
shape
))
shape_old
=
d
.
shape
sq_axis
=
None
if
idx
==
0
:
sq_axis
=
(
0
,
1
)
elif
idx
==
1
:
sq_axis
=
(
0
,
1
,
2
)
else
:
continue
data
[
idx
]
=
np
.
squeeze
(
d
,
axis
=
sq_axis
)
shape_new
=
data
[
idx
].
shape
return
data
def
_get_kernel_parameters
(
kind
,
params
):
assert
kind
in
[
"Convolution"
,
"Pooling"
,
"Deconvolution"
,
"ConvolutionDepthwise"
]
[
k_h
,
k_w
]
=
[
1
,
1
]
if
isinstance
(
params
.
kernel_size
,
numbers
.
Number
):
[
k_h
,
k_w
]
=
[
params
.
kernel_size
]
*
2
elif
len
(
params
.
kernel_size
)
>
0
:
k_h
=
params
.
kernel_h
if
params
.
kernel_h
>
0
else
params
.
kernel_size
[
0
]
k_w
=
params
.
kernel_w
if
params
.
kernel_w
>
0
else
params
.
kernel_size
[
len
(
params
.
kernel_size
)
-
1
]
elif
params
.
kernel_h
>
0
or
params
.
kernel_w
>
0
:
k_h
=
params
.
kernel_h
k_w
=
params
.
kernel_w
[
s_h
,
s_w
]
=
[
1
,
1
]
if
isinstance
(
params
.
stride
,
numbers
.
Number
):
[
s_h
,
s_w
]
=
[
params
.
stride
]
*
2
elif
len
(
params
.
stride
)
>
0
:
s_h
=
params
.
stride_h
if
params
.
stride_h
>
0
else
params
.
stride
[
0
]
s_w
=
params
.
stride_w
if
params
.
stride_w
>
0
else
params
.
stride
[
len
(
params
.
stride
)
-
1
]
elif
params
.
stride_h
>
0
or
params
.
stride_w
>
0
:
s_h
=
params
.
stride_h
s_w
=
params
.
stride_w
[
p_h
,
p_w
]
=
[
0
,
0
]
if
isinstance
(
params
.
pad
,
numbers
.
Number
):
[
p_h
,
p_w
]
=
[
params
.
pad
]
*
2
elif
len
(
params
.
pad
)
>
0
:
p_h
=
params
.
pad_h
if
params
.
pad_h
>
0
else
params
.
pad
[
0
]
p_w
=
params
.
pad_w
if
params
.
pad_w
>
0
else
params
.
pad
[
len
(
params
.
pad
)
-
1
]
elif
params
.
pad_h
>
0
or
params
.
pad_w
>
0
:
p_h
=
params
.
pad_h
p_w
=
params
.
pad_w
dila_h
=
dila_w
=
1
group
=
1
c_o
=
1
if
kind
in
[
"Convolution"
,
"Deconvolution"
,
"ConvolutionDepthwise"
]:
if
kind
in
[
"Convolution"
,
"Deconvolution"
]:
c_o
=
params
.
num_output
dila_len
=
len
(
params
.
dilation
)
if
dila_len
==
2
:
dila_h
=
params
.
dilation
[
0
]
dila_w
=
params
.
dilation
[
1
]
elif
dila_len
==
1
:
dila_h
=
dila_w
=
params
.
dilation
[
0
]
else
:
assert
dila_len
==
0
,
"invalid length[%s] of dilation in convolution"
%
(
dila_len
)
if
kind
in
[
'Convolution'
,
'Deconvolution'
]:
group
=
params
.
group
kernel
=
[
k_h
,
k_w
]
stride
=
[
s_h
,
s_w
]
pad
=
[
p_h
,
p_w
]
dilation
=
[
dila_h
,
dila_w
]
return
c_o
,
kernel
,
stride
,
pad
,
dilation
,
group
class
CaffeOpMapper
(
OpMapper
):
directly_map_ops
=
{
'AbsVal'
:
'paddle.abs'
,
'Sigmoid'
:
'
fluid.layers
.sigmoid'
,
'Sigmoid'
:
'
paddle.nn.functional
.sigmoid'
,
'TanH'
:
'paddle.tanh'
,
}
def
__init__
(
self
,
decoder
):
super
(
CaffeOpMapper
,
self
).
__init__
()
self
.
graph
=
decoder
.
caffe_graph
self
.
weight
s
=
dict
()
self
.
param
s
=
dict
()
resolver
=
decoder
.
resolver
self
.
used_custom_layers
=
{}
self
.
paddle_graph
=
PaddleGraph
(
parent_layer
=
None
,
graph_type
=
"static"
,
source_type
=
"caffe"
)
self
.
paddle_graph
.
inputs
=
self
.
graph
.
input_nodes
self
.
paddle_graph
.
outputs
=
self
.
graph
.
output_nodes
print
(
"Total nodes: {}"
.
format
(
len
(
self
.
graph
.
topo_sort
)))
print
(
"Total nodes: {}"
.
format
(
sum
([
isinstance
(
node
,
CaffeGraphNode
)
for
name
,
node
in
self
.
graph
.
node_map
.
items
()
])))
print
(
"Nodes converting ..."
)
for
node_name
in
self
.
graph
.
topo_sort
:
node
=
self
.
graph
.
get_node
(
node_name
)
if
node
.
layer_type
==
'DepthwiseConvolution'
:
node
.
layer_type
=
'ConvolutionDepthwise'
op
=
node
.
layer_type
if
hasattr
(
self
,
op
):
self
.
set_node_shape
(
node
)
func
=
getattr
(
self
,
op
)
func
(
node
)
elif
op
in
custom_layers
:
self
.
set_node_shape
(
node
,
is_fluid_op
=
False
)
self
.
deal_custom_layer
(
node
)
elif
op
in
self
.
directly_map_ops
:
self
.
set_node_shape
(
node
)
self
.
directly_map
(
node
)
else
:
raise
Exception
(
"The op {} in model is not supported yet."
.
format
(
op
))
self
.
paddle_graph
.
set_parameters
(
self
.
weights
)
print
(
"
\n
Nodes converted."
)
self
.
paddle_graph
.
set_parameters
(
self
.
params
)
self
.
paddle_graph
.
set_custom
(
self
.
used_custom_layers
)
def
op_checker
(
self
):
unsupported_ops
=
set
()
for
node_name
in
self
.
graph
.
topo_sort
:
node
=
self
.
graph
.
get_node
(
node_name
)
op
=
node
.
layer_type
if
not
hasattr
(
self
,
op
)
and
op
not
in
custom_layers
:
if
not
hasattr
(
self
,
op
)
and
\
op
not
in
self
.
directly_map_ops
and
\
op
not
in
self
.
elementwise_ops
:
unsupported_ops
.
add
(
op
)
if
len
(
unsupported_ops
)
==
0
:
return
True
else
:
print
(
"There are {} ops not supported yet, list as below"
.
format
(
len
(
unsupported_ops
)))
if
len
(
unsupported_ops
)
>
0
:
print
(
"
\n
========= {} OPs are not supported yet ==========="
.
format
(
len
(
unsupported_ops
)))
for
op
in
unsupported_ops
:
print
(
op
)
print
(
"========== {} ============"
.
format
(
op
)
)
return
False
def
set_node_shape
(
self
,
node
,
is_fluid_op
=
True
):
inputs
=
node
.
inputs
input_shape
=
[]
for
i
,
nm
in
enumerate
(
inputs
):
last_node
=
self
.
graph
.
get_node
(
nm
)
tmp
=
node
.
layer
.
bottom
[
i
]
idx
=
list
(
last_node
.
layer
.
top
).
index
(
tmp
)
input_shape
.
append
(
last_node
.
output_shape
[
idx
])
node
.
input_shape
=
input_shape
func_name
=
'shape_'
+
node
.
layer_type
.
lower
()
if
is_fluid_op
:
node
.
output_shape
=
getattr
(
caffe_shape
,
func_name
)(
node
.
layer
,
input_shape
)
else
:
node
.
output_shape
=
compute_output_shape
(
node
)
def
adjust_parameters
(
self
,
node
):
data
=
node
.
data
# When using the protobuf-backend, each parameter initially has four dimensions.
# In certain cases (like FC layers), we want to eliminate the singleton dimensions.
# This implementation takes care of the common cases. However, it does leave the
# potential for future issues.
# The Caffe-backend does not suffer from this problem.
data
=
list
(
data
)
squeeze_indices
=
[
1
]
# Squeeze biases.
if
node
.
layer_type
==
'InnerProduct'
:
squeeze_indices
.
append
(
0
)
# Squeeze FC.
for
idx
in
squeeze_indices
:
if
idx
>=
len
(
data
):
continue
d
=
data
[
idx
]
assert
len
(
d
.
shape
)
==
4
,
'invalid shape[%s] from caffe when adjust_parameters'
%
(
str
(
d
.
shape
))
shape_old
=
d
.
shape
sq_axis
=
None
if
idx
==
0
:
sq_axis
=
(
0
,
1
)
elif
idx
==
1
:
sq_axis
=
(
0
,
1
,
2
)
else
:
continue
data
[
idx
]
=
np
.
squeeze
(
d
,
axis
=
sq_axis
)
shape_new
=
data
[
idx
].
shape
return
data
def
get_kernel_parameters
(
self
,
kind
,
params
):
assert
kind
in
[
'Convolution'
,
'Pooling'
,
'Deconvolution'
]
[
k_h
,
k_w
]
=
[
1
,
1
]
if
isinstance
(
params
.
kernel_size
,
numbers
.
Number
):
[
k_h
,
k_w
]
=
[
params
.
kernel_size
]
*
2
elif
len
(
params
.
kernel_size
)
>
0
:
k_h
=
params
.
kernel_h
if
params
.
kernel_h
>
0
else
params
.
kernel_size
[
0
]
k_w
=
params
.
kernel_w
if
params
.
kernel_w
>
0
else
params
.
kernel_size
[
len
(
params
.
kernel_size
)
-
1
]
elif
params
.
kernel_h
>
0
or
params
.
kernel_w
>
0
:
k_h
=
params
.
kernel_h
k_w
=
params
.
kernel_w
[
s_h
,
s_w
]
=
[
1
,
1
]
if
isinstance
(
params
.
stride
,
numbers
.
Number
):
[
s_h
,
s_w
]
=
[
params
.
stride
]
*
2
elif
len
(
params
.
stride
)
>
0
:
s_h
=
params
.
stride_h
if
params
.
stride_h
>
0
else
params
.
stride
[
0
]
s_w
=
params
.
stride_w
if
params
.
stride_w
>
0
else
params
.
stride
[
len
(
params
.
stride
)
-
1
]
elif
params
.
stride_h
>
0
or
params
.
stride_w
>
0
:
s_h
=
params
.
stride_h
s_w
=
params
.
stride_w
[
p_h
,
p_w
]
=
[
0
,
0
]
if
isinstance
(
params
.
pad
,
numbers
.
Number
):
[
p_h
,
p_w
]
=
[
params
.
pad
]
*
2
elif
len
(
params
.
pad
)
>
0
:
p_h
=
params
.
pad_h
if
params
.
pad_h
>
0
else
params
.
pad
[
0
]
p_w
=
params
.
pad_w
if
params
.
pad_w
>
0
else
params
.
pad
[
len
(
params
.
pad
)
-
1
]
elif
params
.
pad_h
>
0
or
params
.
pad_w
>
0
:
p_h
=
params
.
pad_h
p_w
=
params
.
pad_w
dila_h
=
dila_w
=
1
group
=
1
c_o
=
1
if
kind
in
[
'Convolution'
,
'Deconvolution'
]:
c_o
=
params
.
num_output
dila_len
=
len
(
params
.
dilation
)
if
dila_len
==
2
:
dila_h
=
params
.
dilation
[
0
]
dila_w
=
params
.
dilation
[
1
]
elif
dila_len
==
1
:
dila_h
=
dila_w
=
params
.
dilation
[
0
]
else
:
assert
dila_len
==
0
,
"invalid length[%s] of dilation in convolution"
%
(
dila_len
)
if
kind
in
[
'Convolution'
,
'Deconvolution'
]:
group
=
params
.
group
kernel
=
[
k_h
,
k_w
]
stride
=
[
s_h
,
s_w
]
pad
=
[
p_h
,
p_w
]
dilation
=
[
dila_h
,
dila_w
]
return
c_o
,
kernel
,
stride
,
pad
,
dilation
,
group
def
get_input_name
(
self
,
node
):
if
hasattr
(
node
,
"index"
):
return
"{}_{}"
.
format
(
node
.
layer_name
,
node
.
index
)
else
:
return
node
.
layer_name
def
directly_map
(
self
,
node
):
assert
node
.
layer_type
in
self
.
directly_map_ops
op_info
=
self
.
directly_map_ops
[
node
.
layer_type
]
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
self
.
paddle_graph
.
add_layer
(
kernel
=
op_info
,
inputs
=
{
"x"
:
input
.
name
},
outputs
=
[
node
.
name
])
def
Input
(
self
,
node
):
shape
=
list
(
node
.
layer
.
input_param
.
shape
[
0
].
dim
)[
1
:]
...
...
@@ -199,128 +183,236 @@ class CaffeOpMapper(OpMapper):
layer_attrs
=
{
"dtype"
:
string
(
dtype
),
"shape"
:
[
-
1
]
+
shape
,
"name"
:
string
(
node
.
layer_
name
)
"name"
:
string
(
node
.
name
)
}
self
.
paddle_graph
.
add_layer
(
kernel
=
"
fluid
.data"
,
kernel
=
"
paddle.static
.data"
,
inputs
=
{},
outputs
=
[
node
.
layer_
name
],
outputs
=
[
node
.
name
],
**
layer_attrs
)
def
Convolution
(
self
,
node
):
data
=
node
.
data
params
=
node
.
layer
.
convolution_param
channel
,
kernel
,
stride
,
pad
,
dilation
,
group
=
self
.
get_kernel_parameters
(
channel
,
kernel
,
stride
,
pad
,
dilation
,
group
=
_
get_kernel_parameters
(
node
.
layer_type
,
params
)
if
data
is
None
:
data
=
[]
print
(
"The parameter of {} (type is {}) is not set. So we set the parameters as 0"
.
format
(
node
.
layer_
name
,
node
.
layer_type
))
input_c
=
node
.
in
put_shape
[
0
][
1
]
.
format
(
node
.
name
,
node
.
layer_type
))
input_c
=
node
.
in
_shapes
[
0
][
1
]
output_c
=
channel
data
.
append
(
np
.
zeros
([
output_c
,
input_c
,
kernel
[
0
],
kernel
[
1
]]).
astype
(
'float32'
))
data
.
append
(
np
.
zeros
([
output_c
,
]).
astype
(
'float32'
))
else
:
data
=
self
.
adjust_parameters
(
node
)
self
.
weights
[
node
.
layer_name
+
'_weights'
]
=
data
[
0
]
data
=
_adjust_parameters
(
node
)
kernel_weight_name
=
node
.
name
+
'_weights'
self
.
params
[
kernel_weight_name
]
=
data
[
0
]
self
.
paddle_graph
.
add_layer
(
kernel
=
"paddle.static.create_parameter"
,
inputs
=
{},
outputs
=
[
kernel_weight_name
],
shape
=
self
.
params
[
kernel_weight_name
].
shape
,
dtype
=
string
(
str
(
self
.
params
[
kernel_weight_name
].
dtype
)),
name
=
string
(
kernel_weight_name
))
if
len
(
data
)
==
2
:
self
.
weights
[
node
.
layer_name
+
'_bias'
]
=
data
[
1
]
kernel_bias_name
=
node
.
name
+
'_bias'
self
.
params
[
kernel_bias_name
]
=
data
[
1
]
self
.
paddle_graph
.
add_layer
(
kernel
=
"paddle.static.create_parameter"
,
inputs
=
{},
outputs
=
[
kernel_bias_name
],
shape
=
self
.
params
[
kernel_bias_name
].
shape
,
dtype
=
string
(
str
(
self
.
params
[
kernel_bias_name
].
dtype
)),
name
=
string
(
kernel_bias_name
))
assert
len
(
node
.
inputs
)
==
1
,
'The count of Convolution node
\'
s input is not 1.'
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
layer_attrs
=
{
'filter_size'
:
kernel
,
'num_filters'
:
channel
,
'stride'
:
stride
,
'padding'
:
pad
,
'dilation'
:
dilation
,
'groups'
:
group
,
'name'
:
string
(
node
.
layer_name
),
'param_attr'
:
string
(
node
.
layer_name
+
'_weights'
),
'bias_attr'
:
False
if
len
(
data
)
==
1
else
string
(
node
.
layer_name
+
'_bias'
),
}
layer_inputs
=
{
"x"
:
input
.
name
,
"weight"
:
kernel_weight_name
}
layer_attrs
=
{
'stride'
:
stride
,
'padding'
:
pad
,
'dilation'
:
dilation
,
'groups'
:
group
}
if
len
(
data
)
==
2
:
layer_inputs
[
"bias"
]
=
kernel_bias_name
else
:
layer_attrs
[
"bias"
]
=
None
self
.
paddle_graph
.
add_layer
(
kernel
=
"
fluid.layers
.conv2d"
,
inputs
=
{
"input"
:
self
.
get_input_name
(
input
)}
,
outputs
=
[
node
.
layer_
name
],
**
layer_attrs
)
kernel
=
"
paddle.nn.functional
.conv2d"
,
inputs
=
layer_inputs
,
outputs
=
[
node
.
name
],
**
layer_attrs
)
def
Deconvolution
(
self
,
node
):
data
=
node
.
data
params
=
node
.
layer
.
convolution_param
channel
,
kernel
,
stride
,
pad
,
dilation
,
group
=
self
.
get_kernel_parameters
(
channel
,
kernel
,
stride
,
pad
,
dilation
,
group
=
_
get_kernel_parameters
(
node
.
layer_type
,
params
)
if
data
is
None
:
data
=
[]
print
(
'The parameter of {} (type is {}) is not set. So we set the parameters as 0'
.
format
(
node
.
layer_
name
,
node
.
layer_type
))
input_c
=
node
.
in
put_shape
[
0
][
1
]
.
format
(
node
.
name
,
node
.
layer_type
))
input_c
=
node
.
in
_shapes
[
0
][
1
]
output_c
=
channel
data
.
append
(
np
.
zeros
([
output_c
,
input_c
,
kernel
[
0
],
kernel
[
1
]]).
astype
(
'float32'
))
data
.
append
(
np
.
zeros
([
output_c
,
]).
astype
(
'float32'
))
else
:
data
=
self
.
adjust_parameters
(
node
)
self
.
weights
[
node
.
layer_name
+
'_weights'
]
=
data
[
0
]
data
=
_adjust_parameters
(
node
)
kernel_weight_name
=
node
.
name
+
'_weights'
self
.
params
[
kernel_weight_name
]
=
data
[
0
]
self
.
paddle_graph
.
add_layer
(
kernel
=
"paddle.static.create_parameter"
,
inputs
=
{},
outputs
=
[
kernel_weight_name
],
shape
=
self
.
params
[
kernel_weight_name
].
shape
,
dtype
=
string
(
str
(
self
.
params
[
kernel_weight_name
].
dtype
)),
name
=
string
(
kernel_weight_name
))
if
len
(
data
)
==
2
:
self
.
weights
[
node
.
layer_name
+
'_bias'
]
=
data
[
1
]
kernel_bias_name
=
node
.
name
+
'_bias'
self
.
params
[
kernel_bias_name
]
=
data
[
1
]
self
.
paddle_graph
.
add_layer
(
kernel
=
"paddle.static.create_parameter"
,
inputs
=
{},
outputs
=
[
kernel_bias_name
],
shape
=
self
.
params
[
kernel_bias_name
].
shape
,
dtype
=
string
(
str
(
self
.
params
[
kernel_bias_name
].
dtype
)),
name
=
string
(
kernel_bias_name
))
assert
len
(
node
.
inputs
)
==
1
,
'The count of Deconvolution node
\'
s input is not 1.'
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
layer_attrs
=
{
'output_size'
:
None
,
'filter_size'
:
kernel
,
'num_filters'
:
channel
,
'stride'
:
stride
,
'padding'
:
pad
,
'dilation'
:
dilation
,
'groups'
:
group
,
'name'
:
string
(
node
.
layer_name
),
'param_attr'
:
string
(
node
.
layer_name
+
'_weights'
),
'bias_attr'
:
False
if
len
(
data
)
==
1
else
string
(
node
.
layer_name
+
'_bias'
)
}
layer_inputs
=
{
"x"
:
input
.
name
,
"weight"
:
kernel_weight_name
}
layer_attrs
=
{
'stride'
:
stride
,
'padding'
:
pad
,
'dilation'
:
dilation
,
'groups'
:
group
}
if
len
(
data
)
==
2
:
layer_inputs
[
"bias"
]
=
kernel_bias_name
else
:
layer_attrs
[
"bias"
]
=
None
self
.
paddle_graph
.
add_layer
(
kernel
=
"
fluid.layers
.conv2d_transpose"
,
inputs
=
{
"input"
:
self
.
get_input_name
(
input
)}
,
outputs
=
[
node
.
layer_
name
],
kernel
=
"
paddle.nn.functional
.conv2d_transpose"
,
inputs
=
layer_inputs
,
outputs
=
[
node
.
name
],
**
layer_attrs
)
def
DepthwiseConvolution
(
self
,
node
):
node
.
layer_type
=
"ConvolutionDepthwise"
self
.
ConvolutionDepthwise
(
node
)
def
ConvolutionDepthwise
(
self
,
node
):
data
=
node
.
data
params
=
node
.
layer
.
convolution_param
out_channel
,
kernel
,
stride
,
pad
,
dilation
,
group
=
_get_kernel_parameters
(
node
.
layer_type
,
params
)
out_channel
=
params
.
num_output
if
params
.
num_output
is
not
None
else
node
.
in_shapes
[
0
][
1
]
in_channel
=
node
.
in_shapes
[
0
][
1
]
group
=
int
(
in_channel
/
(
in_channel
/
out_channel
))
if
in_channel
>
out_channel
else
int
(
in_channel
/
(
out_channel
/
in_channel
))
if
data
is
None
:
data
=
[]
print
(
"The parameter of {} (type is {}) is not set. So we set the parameters as 0"
.
format
(
node
.
layer_name
,
node
.
layer_type
))
data
.
append
(
np
.
zeros
([
out_channel
,
node
.
in_shapes
[
0
][
1
],
kernel
[
0
],
kernel
[
1
]]).
astype
(
'float32'
))
data
.
append
(
np
.
zeros
([
out_channel
,
]).
astype
(
'float32'
))
else
:
data
=
_adjust_parameters
(
node
)
kernel_weight_name
=
node
.
name
+
'_weights'
self
.
params
[
kernel_weight_name
]
=
data
[
0
]
self
.
paddle_graph
.
add_layer
(
kernel
=
"paddle.static.create_parameter"
,
inputs
=
{},
outputs
=
[
kernel_weight_name
],
shape
=
self
.
params
[
kernel_weight_name
].
shape
,
dtype
=
string
(
str
(
self
.
params
[
kernel_weight_name
].
dtype
)),
name
=
string
(
kernel_weight_name
))
if
len
(
data
)
==
2
:
kernel_bias_name
=
node
.
name
+
'_bias'
self
.
params
[
kernel_bias_name
]
=
data
[
1
]
self
.
paddle_graph
.
add_layer
(
kernel
=
"paddle.static.create_parameter"
,
inputs
=
{},
outputs
=
[
kernel_bias_name
],
shape
=
self
.
params
[
kernel_bias_name
].
shape
,
dtype
=
string
(
str
(
self
.
params
[
kernel_bias_name
].
dtype
)),
name
=
string
(
kernel_bias_name
))
assert
len
(
node
.
inputs
)
==
1
,
"The count of Deconvolution node
\'
s input is not 1."
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
layer_inputs
=
{
"x"
:
input
.
name
,
"weight"
:
kernel_weight_name
}
layer_attrs
=
{
'stride'
:
stride
,
'padding'
:
pad
,
'dilation'
:
dilation
,
'groups'
:
group
}
if
len
(
data
)
==
2
:
layer_inputs
[
"bias"
]
=
kernel_bias_name
else
:
layer_attrs
[
"bias"
]
=
None
self
.
paddle_graph
.
add_layer
(
kernel
=
"paddle.nn.functional.conv2d"
,
inputs
=
layer_inputs
,
outputs
=
[
node
.
name
],
**
layer_attrs
)
def
Pooling
(
self
,
node
):
params
=
node
.
layer
.
pooling_param
ceil_mode
=
getattr
(
params
,
'ceil_mode'
,
True
)
global_pool
=
getattr
(
params
,
'global_pooling'
,
False
)
kernel_default
=
[
1
,
1
]
channel
,
kernel
,
stride
,
pad
,
dilation
,
group
=
self
.
get_kernel_parameters
(
channel
,
kernel
,
stride
,
pad
,
dilation
,
group
=
_
get_kernel_parameters
(
node
.
layer_type
,
params
)
if
params
.
pool
==
0
:
pool_type
=
'max'
else
:
pool_type
=
'avg'
assert
len
(
node
.
inputs
)
==
1
,
'The count of Pooling node
\'
s input is not 1.'
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
layer_attrs
=
{
'pool_size'
:
kernel
,
'pool_stride'
:
stride
,
'pool_padding'
:
pad
,
'ceil_mode'
:
ceil_mode
,
'pool_type'
:
string
(
pool_type
),
'exclusive'
:
False
,
'global_pooling'
:
global_pool
,
'name'
:
string
(
node
.
layer_name
)
}
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers.pool2d"
,
inputs
=
{
"input"
:
self
.
get_input_name
(
input
)},
outputs
=
[
node
.
layer_name
],
**
layer_attrs
)
if
global_pool
:
if
kernel
[
0
]
==
0
:
kernel
=
[
1
,
1
]
if
params
.
pool
==
0
:
self
.
paddle_graph
.
add_layer
(
"paddle.nn.functional.adaptive_max_pool2d"
,
inputs
=
{
"x"
:
input
.
name
},
outputs
=
layer_outputs
,
output_size
=
kernel
)
else
:
self
.
paddle_graph
.
add_layer
(
"paddle.nn.functional.adaptive_avg_pool2d"
,
inputs
=
{
"x"
:
input
.
name
},
outputs
=
[
node
.
name
],
output_size
=
kernel
)
else
:
if
params
.
pool
==
0
:
self
.
paddle_graph
.
add_layer
(
kernel
=
"paddle.nn.functional.max_pool2d"
,
inputs
=
{
"x"
:
input
.
name
},
outputs
=
[
node
.
name
],
kernel_size
=
kernel
,
stride
=
stride
,
padding
=
pad
,
ceil_mode
=
ceil_mode
)
else
:
# TODO(syf): The op has diff.
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers.pool2d"
,
inputs
=
{
"input"
:
input
.
name
},
outputs
=
[
node
.
name
],
pool_size
=
kernel
,
pool_type
=
string
(
"avg"
),
pool_stride
=
stride
,
pool_padding
=
pad
,
ceil_mode
=
ceil_mode
,
exclusive
=
False
,
global_pooling
=
False
)
def
LRN
(
self
,
node
):
assert
len
(
node
.
inputs
)
==
1
,
'The count of LRN node
\'
s input is not 1.'
...
...
@@ -338,12 +430,12 @@ class CaffeOpMapper(OpMapper):
'k'
:
params
.
k
,
'alpha'
:
alpha
,
'beta'
:
params
.
beta
,
'name'
:
string
(
node
.
layer_
name
)
'name'
:
string
(
node
.
name
)
}
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers.lrn"
,
inputs
=
{
"input"
:
self
.
get_input_name
(
input
)
},
outputs
=
[
node
.
layer_
name
],
inputs
=
{
"input"
:
input
.
name
},
outputs
=
[
node
.
name
],
**
layer_attrs
)
def
InnerProduct
(
self
,
node
):
...
...
@@ -353,7 +445,7 @@ class CaffeOpMapper(OpMapper):
print
(
'The parameter of {} (type is {}) is not set. So we set the parameters as 0.'
.
format
(
node
.
layer_name
,
node
.
layer_type
))
input_c
=
node
.
in
put_shape
[
0
][
1
]
input_c
=
node
.
in
_shapes
[
0
][
1
]
output_c
=
params
.
num_output
data
=
[]
data
.
append
(
...
...
@@ -362,7 +454,7 @@ class CaffeOpMapper(OpMapper):
data
.
append
(
np
.
zeros
([
output_c
]).
astype
(
'float32'
).
astype
(
'float32'
))
else
:
data
=
self
.
adjust_parameters
(
node
)
data
=
_
adjust_parameters
(
node
)
# Reshape the parameters to Paddle's ordering
transpose_order
=
(
1
,
0
)
w
=
data
[
0
]
...
...
@@ -372,28 +464,55 @@ class CaffeOpMapper(OpMapper):
w
=
w
.
transpose
(
transpose_order
)
data
[
0
]
=
w
self
.
weights
[
node
.
layer_name
+
'_weights'
]
=
data
[
0
]
kernel_weight_name
=
node
.
name
+
'_weights'
self
.
params
[
kernel_weight_name
]
=
data
[
0
]
self
.
paddle_graph
.
add_layer
(
kernel
=
"paddle.static.create_parameter"
,
inputs
=
{},
outputs
=
[
kernel_weight_name
],
shape
=
self
.
params
[
kernel_weight_name
].
shape
,
dtype
=
string
(
str
(
self
.
params
[
kernel_weight_name
].
dtype
)),
name
=
string
(
kernel_weight_name
))
if
len
(
data
)
==
2
:
self
.
weights
[
node
.
layer_name
+
'_bias'
]
=
data
[
1
]
kernel_bias_name
=
node
.
name
+
'_bias'
self
.
params
[
kernel_bias_name
]
=
data
[
1
]
self
.
paddle_graph
.
add_layer
(
kernel
=
"paddle.static.create_parameter"
,
inputs
=
{},
outputs
=
[
kernel_bias_name
],
shape
=
self
.
params
[
kernel_bias_name
].
shape
,
dtype
=
string
(
str
(
self
.
params
[
kernel_bias_name
].
dtype
)),
name
=
string
(
kernel_bias_name
))
assert
len
(
node
.
inputs
)
==
1
,
'The count of InnerProduct node
\'
s input is not 1.'
#params = node.layer.inner_product_param
assert
params
.
axis
==
1
assert
params
.
bias_term
==
True
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
layer_attrs
=
{
'size'
:
params
.
num_output
,
'name'
:
string
(
node
.
layer_name
),
'act'
:
None
,
'param_attr'
:
string
(
node
.
layer_name
+
'_weights'
),
'bias_attr'
:
False
if
len
(
data
)
==
1
else
string
(
node
.
layer_name
+
'_bias'
)
}
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers.fc"
,
inputs
=
{
"input"
:
self
.
get_input_name
(
input
)},
outputs
=
[
node
.
layer_name
],
**
layer_attrs
)
layer_inputs
=
{
"x"
:
input
.
name
,
"weight"
:
kernel_weight_name
}
layer_attrs
=
dict
()
if
len
(
data
)
==
2
:
layer_inputs
[
"bias"
]
=
kernel_bias_name
else
:
layer_attrs
[
"bias"
]
=
None
if
node
.
in_shapes
[
0
][
-
1
]
!=
data
[
0
].
shape
[
0
]:
self
.
paddle_graph
.
add_layer
(
"paddle.reshape"
,
inputs
=
{
"x"
:
input
.
name
},
outputs
=
[
input
.
name
],
shape
=
[
-
1
,
data
[
0
].
shape
[
0
]])
self
.
paddle_graph
.
add_layer
(
kernel
=
"paddle.nn.functional.linear"
,
inputs
=
layer_inputs
,
outputs
=
[
node
.
name
],
**
layer_attrs
)
else
:
self
.
paddle_graph
.
add_layer
(
kernel
=
"paddle.nn.functional.linear"
,
inputs
=
layer_inputs
,
outputs
=
[
node
.
name
],
**
layer_attrs
)
def
Softmax
(
self
,
node
):
assert
len
(
...
...
@@ -401,19 +520,19 @@ class CaffeOpMapper(OpMapper):
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
params
=
node
.
layer
.
softmax_param
axis
=
params
.
axis
shape
=
node
.
in
put_shape
[
0
]
shape
=
node
.
in
_shapes
[
0
]
dims
=
len
(
shape
)
axis
=
axis
+
dims
if
axis
<
0
else
axis
layer_attrs
=
{
'axis'
:
axis
,
'name'
:
string
(
node
.
layer_name
+
'_softmax'
)}
self
.
paddle_graph
.
add_layer
(
kernel
=
"paddle.nn.functional.softmax"
,
inputs
=
{
"x"
:
self
.
get_input_name
(
input
)
},
inputs
=
{
"x"
:
input
.
name
},
outputs
=
[
node
.
layer_name
],
**
layer_attrs
)
def
Slice
(
self
,
node
):
assert
len
(
node
.
inputs
)
==
1
,
'The count of Slice node
\'
s input is not 1.'
node
.
inputs
)
==
1
,
"The count of Slice node
\'
s input is not 1."
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
top_len
=
len
(
node
.
layer
.
top
)
params
=
node
.
layer
.
slice_param
...
...
@@ -421,20 +540,19 @@ class CaffeOpMapper(OpMapper):
slice_dim
=
params
.
slice_dim
if
slice_dim
!=
1
and
axis
==
1
:
axis
=
slice_dim
output_shape
=
node
.
out
put_shape
output_shape
=
node
.
out
_shapes
sections_list
=
list
()
outputs_list
=
list
()
for
i
,
s
in
enumerate
(
output_shape
):
sections_list
.
append
(
s
[
axis
])
outputs_list
.
append
(
"{}_{}"
.
format
(
node
.
layer_name
,
i
))
outputs_list
.
append
(
"{}_
p
{}"
.
format
(
node
.
layer_name
,
i
))
layer_attrs
=
{
'num_or_sections'
:
sections_list
,
'dim'
:
axis
,
'name'
:
string
(
node
.
layer_name
)
'axis'
:
axis
,
}
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers
.split"
,
inputs
=
{
"
input"
:
self
.
get_input_name
(
input
)
},
"paddle
.split"
,
inputs
=
{
"
x"
:
input
.
name
},
outputs
=
outputs_list
,
**
layer_attrs
)
...
...
@@ -445,18 +563,19 @@ class CaffeOpMapper(OpMapper):
inputs_list
=
[]
for
i
in
range
(
len
(
node
.
inputs
)):
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
i
,
copy
=
True
)
inputs_list
.
append
(
self
.
get_input_name
(
input
)
)
inputs_list
.
append
(
input
.
name
)
params
=
node
.
layer
.
concat_param
axis
=
params
.
axis
layer_attrs
=
{
'axis'
:
axis
,
'name'
:
string
(
node
.
layer_
name
)}
layer_attrs
=
{
'axis'
:
axis
,
'name'
:
string
(
node
.
name
)}
self
.
paddle_graph
.
add_layer
(
kernel
=
"paddle.concat"
,
inputs
=
{
"x"
:
inputs_list
},
outputs
=
[
node
.
layer_
name
],
outputs
=
[
node
.
name
],
**
layer_attrs
)
def
ReLU
(
self
,
node
):
"""
:param node:
:return:
"""
...
...
@@ -468,15 +587,15 @@ class CaffeOpMapper(OpMapper):
if
params
.
HasField
(
'negative_slope'
)
and
params
.
negative_slope
!=
0
:
negative_slope
=
float
(
params
.
negative_slope
)
self
.
paddle_graph
.
add_layer
(
kernel
=
"
fluid.layers
.leaky_relu"
,
inputs
=
{
"x"
:
self
.
get_input_name
(
input
)
},
outputs
=
[
node
.
layer_
name
],
alpha
=
negative_slope
)
kernel
=
"
paddle.nn.functional
.leaky_relu"
,
inputs
=
{
"x"
:
input
.
name
},
outputs
=
[
node
.
name
],
negative_slope
=
negative_slope
)
else
:
self
.
paddle_graph
.
add_layer
(
kernel
=
"
fluid.layers
.relu"
,
inputs
=
{
"x"
:
self
.
get_input_name
(
input
)
},
outputs
=
[
node
.
layer_
name
])
kernel
=
"
paddle.nn.functional
.relu"
,
inputs
=
{
"x"
:
input
.
name
},
outputs
=
[
node
.
name
])
def
PReLU
(
self
,
node
):
assert
len
(
...
...
@@ -484,122 +603,83 @@ class CaffeOpMapper(OpMapper):
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
params
=
node
.
layer
.
prelu_param
mode_bool
=
params
.
channel_shared
output_shape
=
node
.
out_shapes
[
0
]
if
mode_bool
:
mode
=
'all'
num_parameters
=
1
else
:
mode
=
'channel'
num_parameters
=
output_shape
[
1
]
data
=
node
.
data
assert
data
is
not
None
,
'The parameter of {} (type is {}) is not set. You need to use python package of caffe to set the default value.'
.
format
(
node
.
layer_name
,
node
.
layer_type
)
self
.
weights
[
node
.
layer_name
+
'_weights'
]
=
data
[
0
]
layer_attrs
=
{
'mode'
:
string
(
mode
),
'param_attr'
:
string
(
node
.
layer_name
+
'_weights'
),
'name'
:
string
(
node
.
layer_name
)
}
node
.
name
,
node
.
layer_type
)
kernel_weight_name
=
node
.
name
+
'_weights'
self
.
params
[
kernel_weight_name
]
=
np
.
squeeze
(
data
[
0
])
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers.prelu"
,
inputs
=
{
"x"
:
self
.
get_input_name
(
input
)},
outputs
=
[
node
.
layer_name
],
**
layer_attrs
)
def
Accuracy
(
self
,
node
):
assert
len
(
node
.
inputs
)
==
2
,
'The count of Accuracy node
\'
s input is not 2.'
inputs_dict
=
dict
()
for
i
,
shape
in
enumerate
(
node
.
input_shape
):
if
shape
[
1
]
==
1
:
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
i
,
copy
=
True
)
inputs_dict
[
"label"
]
=
self
.
get_input_name
(
input
)
else
:
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
i
,
copy
=
True
)
inputs_dict
[
"input"
]
=
self
.
get_input_name
(
input
)
params
=
node
.
layer
.
accuracy_param
top_k
=
params
.
top_k
axis
=
params
.
axis
ignore_label
=
params
.
ignore_label
assert
axis
==
1
,
'PaddlePaddle can not support the situation when the axis is not 1.'
assert
not
ignore_label
>=
0
,
'PaddlePaddle can not support the situation when the model has ignore label.'
kernel
=
"paddle.static.create_parameter"
,
inputs
=
{},
outputs
=
[
kernel_weight_name
],
shape
=
[
num_parameters
],
dtype
=
string
(
str
(
self
.
params
[
kernel_weight_name
].
dtype
)),
name
=
string
(
kernel_weight_name
))
self
.
paddle_graph
.
add_layer
(
kernel
=
"
fluid.layers.accuracy
"
,
inputs
=
inputs_dict
,
outputs
=
[
node
.
layer_name
]
,
k
=
top_k
)
kernel
=
"
paddle.nn.functional.prelu
"
,
inputs
=
{
"x"
:
input
.
name
,
"weight"
:
kernel_weight_name
}
,
outputs
=
[
node
.
name
]
)
def
Eltwise
(
self
,
node
):
assert
len
(
node
.
inputs
)
==
2
,
'The count of TanH node
\'
s input is not 2.'
node
.
inputs
)
==
2
,
"The count of Eltwise node
\'
s input is not 2."
params
=
node
.
layer
.
eltwise_param
mode
=
params
.
operation
inputs
=
[]
input0
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
inputs
.
append
(
input0
)
input1
=
self
.
graph
.
get_input_node
(
node
,
idx
=
1
,
copy
=
True
)
inputs
.
append
(
input1
)
input0_name
=
input0
.
name
input1_name
=
input1
.
name
if
mode
==
0
:
inputs_dict
=
{}
inputs_dict
[
'x'
]
=
self
.
get_input_name
(
inputs
[
0
])
inputs_dict
[
'y'
]
=
self
.
get_input_name
(
inputs
[
1
])
inputs_dict
[
'x'
]
=
input0_name
inputs_dict
[
'y'
]
=
input1_name
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers.elementwise_mul
"
,
"paddle.multiply
"
,
inputs
=
inputs_dict
,
outputs
=
[
node
.
layer_
name
])
outputs
=
[
node
.
name
])
elif
mode
==
1
:
if
hasattr
(
params
,
'coeff'
)
and
len
(
params
.
coeff
)
==
2
:
coeff
=
params
.
coeff
input1_name
=
self
.
get_input_name
(
inputs
[
0
])
layer_attrs
=
{
'shape'
:
[
1
],
'value'
:
coeff
[
0
],
'dtype'
:
'{}.dtype'
.
format
(
input1_name
)
}
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers.fill_constant"
,
inputs
=
{},
outputs
=
[
"{}_const1"
.
format
(
node
.
layer_name
)],
**
layer_attrs
)
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers.elementwise_mul"
,
inputs
=
{
"x"
:
input1_name
,
"y"
:
"{}_const1"
.
format
(
node
.
layer_name
)},
outputs
=
[
"{}_mul1"
.
format
(
node
.
layer_name
)])
input2_name
=
self
.
get_input_name
(
inputs
[
1
])
layer_attrs
=
{
'shape'
:
[
1
],
'value'
:
coeff
[
1
],
'dtype'
:
'{}.dtype'
.
format
(
input2_name
)
}
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers.fill_constant
"
,
inputs
=
{},
outputs
=
[
"{}_const2"
.
format
(
node
.
layer_name
)
],
**
layer_attrs
)
"paddle.scale
"
,
inputs
=
{
"x"
:
input0_name
},
outputs
=
[
node
.
name
+
'_mul0'
],
scale
=
coeff
[
0
]
)
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers.elementwise_mul"
,
inputs
=
{
"x"
:
input2_name
,
"y"
:
"{}_const2"
.
format
(
node
.
layer_name
)},
outputs
=
[
"{}_mul2"
.
format
(
node
.
layer_name
)])
"paddle.scale"
,
inputs
=
{
"x"
:
input1_name
},
outputs
=
[
node
.
name
+
'_mul1'
],
scale
=
coeff
[
2
])
inputs_dict
=
{}
inputs_dict
[
'x'
]
=
node
.
name
+
'_mul0'
inputs_dict
[
'y'
]
=
node
.
name
+
'_mul1'
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers.elementwise_add"
,
inputs
=
{
"x"
:
"{}_mul1"
.
format
(
node
.
layer_name
),
"y"
:
"{}_mul2"
.
format
(
node
.
layer_name
)},
outputs
=
[
node
.
layer_name
])
"paddle.add"
,
inputs
=
inputs_dict
,
outputs
=
[
node
.
name
])
else
:
inputs_dict
=
{}
inputs_dict
[
'x'
]
=
self
.
get_input_name
(
inputs
[
0
])
inputs_dict
[
'y'
]
=
self
.
get_input_name
(
inputs
[
1
])
inputs_dict
[
'x'
]
=
input0_name
inputs_dict
[
'y'
]
=
input1_name
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers.elementwise_
add"
,
"paddle.
add"
,
inputs
=
inputs_dict
,
outputs
=
[
node
.
layer_
name
])
outputs
=
[
node
.
name
])
else
:
inputs_dict
=
{}
inputs_dict
[
'x'
]
=
self
.
get_input_name
(
inputs
[
0
])
inputs_dict
[
'y'
]
=
self
.
get_input_name
(
inputs
[
1
])
inputs_dict
[
'x'
]
=
input0_name
inputs_dict
[
'y'
]
=
input1_name
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers.elementwise_
max"
,
inputs
=
inputs_dict
,
outputs
=
[
node
.
layer_
name
])
"paddle.
max"
,
inputs
=
inputs_dict
,
outputs
=
[
node
.
name
])
def
BatchNorm
(
self
,
node
):
assert
len
(
...
...
@@ -610,11 +690,15 @@ class CaffeOpMapper(OpMapper):
eps
=
params
.
eps
else
:
eps
=
1e-5
if
hasattr
(
params
,
'moving_average_fraction'
):
momentum
=
params
.
moving_average_fraction
else
:
momentum
=
0.9
if
node
.
data
is
None
or
len
(
node
.
data
)
!=
3
:
print
(
'The parameter of {} (type is {}) is not set. So we set the parameters as 0'
.
format
(
node
.
layer_name
,
node
.
layer_type
))
input_c
=
node
.
in
put_shape
[
0
][
1
]
input_c
=
node
.
in
_shapes
[
0
][
1
]
mean
=
np
.
zeros
([
input_c
,
]).
astype
(
'float32'
)
variance
=
np
.
zeros
([
input_c
,
]).
astype
(
'float32'
)
scale
=
0
...
...
@@ -626,235 +710,241 @@ class CaffeOpMapper(OpMapper):
scaling_factor
=
1.0
/
scale
if
scale
!=
0
else
0
mean
*=
scaling_factor
variance
*=
scaling_factor
self
.
weights
[
node
.
layer_name
+
'_mean'
]
=
mean
self
.
weights
[
node
.
layer_name
+
'_variance'
]
=
variance
weight_name
=
node
.
name
+
'_weight'
self
.
paddle_graph
.
add_layer
(
kernel
=
"paddle.ones"
,
inputs
=
{},
outputs
=
[
weight_name
],
shape
=
mean
.
shape
,
dtype
=
string
(
"float32"
))
bias_name
=
node
.
name
+
'_bias'
self
.
paddle_graph
.
add_layer
(
kernel
=
"paddle.zeros"
,
inputs
=
{},
outputs
=
[
bias_name
],
shape
=
mean
.
shape
,
dtype
=
string
(
"float32"
))
mean_name
=
node
.
name
+
'_mean'
self
.
params
[
mean_name
]
=
mean
self
.
paddle_graph
.
add_layer
(
kernel
=
"paddle.static.create_parameter"
,
inputs
=
{},
outputs
=
[
mean_name
],
shape
=
self
.
params
[
mean_name
].
shape
,
dtype
=
string
(
str
(
self
.
params
[
mean_name
].
dtype
)),
name
=
string
(
mean_name
))
variance_name
=
node
.
name
+
'_variance'
self
.
params
[
variance_name
]
=
variance
self
.
paddle_graph
.
add_layer
(
kernel
=
"paddle.static.create_parameter"
,
inputs
=
{},
outputs
=
[
variance_name
],
shape
=
self
.
params
[
variance_name
].
shape
,
dtype
=
string
(
str
(
self
.
params
[
variance_name
].
dtype
)),
name
=
string
(
variance_name
))
layer_attrs
=
{
'is_test'
:
True
,
'param_attr'
:
None
,
'bias_attr'
:
None
,
'moving_mean_name'
:
string
(
node
.
layer_name
+
'_mean'
),
'moving_variance_name'
:
string
(
node
.
layer_name
+
'_variance'
),
'epsilon'
:
eps
,
'
name'
:
string
(
node
.
layer_name
)
'
momentum'
:
momentum
}
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers.batch_norm"
,
inputs
=
{
"input"
:
self
.
get_input_name
(
input
)},
outputs
=
[
node
.
layer_name
],
kernel
=
"paddle.nn.functional.batch_norm"
,
inputs
=
{
"x"
:
input
.
name
,
"weight"
:
weight_name
,
"bias"
:
bias_name
,
"running_mean"
:
mean_name
,
"running_var"
:
variance_name
,},
outputs
=
[
node
.
name
],
**
layer_attrs
)
def
Scale
(
self
,
node
):
if
node
.
data
is
None
:
print
(
'The parameter of {} (type is {}) is not set. So we set the parameters as 0'
.
format
(
node
.
layer_name
,
node
.
layer_type
))
input_c
=
node
.
input_shape
[
0
][
1
]
self
.
weights
[
node
.
layer_name
+
'_scale'
]
=
np
.
zeros
([
input_c
,
]).
astype
(
'float32'
)
self
.
weights
[
node
.
layer_name
+
'_offset'
]
=
np
.
zeros
([
input_c
,
]).
astype
(
'float32'
)
"The parameter of {} (type is {}) is not set. So we set the parameters as 0"
.
format
(
node
.
name
,
node
.
layer_type
))
self
.
params
[
node
.
name
+
"_cparam1"
]
=
np
.
zeros
([
node
.
in_shapes
[
0
][
1
],
]).
astype
(
"float32"
)
self
.
params
[
node
.
name
+
"_cparam2"
]
=
np
.
zeros
([
node
.
in_shapes
[
0
][
1
],
]).
astype
(
"float32"
)
else
:
self
.
weights
[
node
.
layer_name
+
'_scale'
]
=
np
.
squeeze
(
node
.
data
[
0
]).
astype
(
'float32'
)
self
.
weights
[
node
.
layer_name
+
'_offset'
]
=
np
.
squeeze
(
node
.
data
[
1
]).
astype
(
'float32'
)
self
.
params
[
node
.
name
+
"_cparam1"
]
=
np
.
squeeze
(
node
.
data
[
0
]).
astype
(
"float32"
)
self
.
params
[
node
.
name
+
"_cparam2"
]
=
np
.
squeeze
(
node
.
data
[
1
]).
astype
(
"float32"
)
params
=
node
.
layer
.
scale_param
axis
=
params
.
axis
num_axes
=
params
.
num_axes
inputs
=
[]
if
len
(
node
.
inputs
)
==
2
:
# for two tensor, here resets axis to 1. Maybe there is a bug for unkown case.
axis
=
1
bias_shape
=
node
.
input_shape
[
0
][
axis
:
axis
+
num_axes
]
input0
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
input1
=
self
.
graph
.
get_input_node
(
node
,
idx
=
1
,
copy
=
True
)
input0_name
=
input0
.
name
input1_name
=
input1
.
name
inputs_dict
=
{}
inputs_dict
[
'x'
]
=
self
.
get_input_name
(
input0
)
inputs_dict
[
'y'
]
=
self
.
get_input_name
(
input1
)
inputs_dict
[
'x'
]
=
input0_name
inputs_dict
[
'y'
]
=
input1_name
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers.elementwise_mul
"
,
"paddle.multiply
"
,
inputs
=
inputs_dict
,
outputs
=
[
"{}_mul"
.
format
(
node
.
layer_name
)
],
axis
=
axis
)
outputs
=
[
node
.
name
+
"_mul"
],
axis
=
1
)
else
:
bias_shape
=
node
.
input_shape
[
0
][
axis
:
axis
+
num_axes
]
input0
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
input0_name
=
self
.
get_input_name
(
input0
)
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.ParamAtt
r"
,
"paddle.static.create_paramete
r"
,
inputs
=
{},
outputs
=
[
"{}_scale"
.
format
(
node
.
layer_name
)],
name
=
string
(
"{}_scale"
.
format
(
node
.
layer_name
)))
layer_attrs
=
{
'dtype'
:
'{}.dtype'
.
format
(
input0_name
),
'shape'
:
bias_shape
,
'name'
:
string
(
node
.
layer_name
+
'_cparam1'
),
'is_bias'
:
True
,
'default_initializer'
:
'Constant(value=1.0)'
}
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers.create_parameter"
,
inputs
=
{
"attr"
:
node
.
layer_name
+
'_scale'
,},
outputs
=
[
"{}_cparam1"
.
format
(
node
.
layer_name
)],
**
layer_attrs
)
outputs
=
[
node
.
name
+
"_cparam1"
],
shape
=
self
.
params
[
node
.
name
+
"_cparam1"
].
shape
,
dtype
=
string
(
str
(
self
.
params
[
node
.
name
+
"_cparam1"
].
dtype
)),
name
=
string
(
node
.
name
+
"_cparam1"
))
input0
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
input0_name
=
input0
.
name
inputs_dict
=
{}
inputs_dict
[
'x'
]
=
self
.
get_input_name
(
input0
)
inputs_dict
[
'y'
]
=
"{}_cparam1"
.
format
(
node
.
layer_name
)
inputs_dict
[
'x'
]
=
input0_name
inputs_dict
[
'y'
]
=
node
.
name
+
"_cparam1"
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers.elementwise_mul
"
,
"paddle.multiply
"
,
inputs
=
inputs_dict
,
outputs
=
[
"{}_mul"
.
format
(
node
.
layer_name
)
],
outputs
=
[
node
.
name
+
"_mul"
],
axis
=
axis
)
scale_shape
=
bias_shape
input0_name
=
self
.
get_input_name
(
input0
)
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.ParamAtt
r"
,
"paddle.static.create_paramete
r"
,
inputs
=
{},
outputs
=
[
"{}_offset"
.
format
(
node
.
layer_name
)],
name
=
string
(
"{}_offset"
.
format
(
node
.
layer_name
)))
layer_attrs
=
{
'dtype'
:
'{}.dtype'
.
format
(
input0_name
),
'shape'
:
scale_shape
,
'name'
:
string
(
node
.
layer_name
+
'_cparam2'
),
'is_bias'
:
True
,
'default_initializer'
:
'Constant(value=1.0)'
}
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers.create_parameter"
,
inputs
=
{
"attr"
:
node
.
layer_name
+
'_offset'
},
outputs
=
[
"{}_cparam2"
.
format
(
node
.
layer_name
)],
**
layer_attrs
)
outputs
=
[
node
.
name
+
"_cparam2"
],
shape
=
self
.
params
[
node
.
name
+
"_cparam2"
].
shape
,
dtype
=
string
(
str
(
self
.
params
[
node
.
name
+
"_cparam2"
].
dtype
)),
name
=
string
(
node
.
name
+
"_cparam2"
))
inputs_dict
=
{}
inputs_dict
[
'x'
]
=
"{}_mul"
.
format
(
node
.
layer_name
)
inputs_dict
[
'y'
]
=
"{}_cparam2"
.
format
(
node
.
layer_name
)
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers.elementwise_add"
,
inputs
=
inputs_dict
,
outputs
=
[
node
.
layer_name
],
axis
=
axis
)
inputs_dict
[
'x'
]
=
node
.
name
+
"_mul"
inputs_dict
[
'y'
]
=
node
.
name
+
"_cparam2"
output_shape
=
node
.
out_shapes
[
0
]
if
axis
==
-
1
:
self
.
paddle_graph
.
add_layer
(
"paddle.add"
,
inputs
=
inputs_dict
,
outputs
=
[
node
.
name
])
else
:
if
axis
<
0
:
axis
=
axis
+
len
(
output_shape
)
param2_shape
=
self
.
params
[
node
.
name
+
"_cparam2"
].
shape
param2_shape_len
=
len
(
param2_shape
)
diff_len
=
len
(
output_shape
)
-
axis
-
param2_shape_len
new_shape
=
list
(
param2_shape
)
+
[
1
]
*
diff_len
self
.
paddle_graph
.
add_layer
(
"paddle.reshape"
,
inputs
=
{
"x"
:
node
.
name
+
"_cparam2"
},
outputs
=
[
node
.
name
+
"_cparam2"
],
shape
=
new_shape
)
self
.
paddle_graph
.
add_layer
(
"paddle.add"
,
inputs
=
inputs_dict
,
outputs
=
[
node
.
name
])
def
Reshape
(
self
,
node
):
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
top_count
=
len
(
input
.
layer
.
top
)
is_inplace
=
False
if
top_count
==
1
else
True
output_shape
=
node
.
output_shape
[
0
]
layer_attrs
=
{
'shape'
:
output_shape
,
'inplace'
:
is_inplace
,
'act'
:
None
,
'name'
:
string
(
node
.
layer_name
)
}
output_shape
=
node
.
out_shapes
[
0
]
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers
.reshape"
,
inputs
=
{
"x"
:
self
.
get_input_name
(
input
)
},
outputs
=
[
node
.
layer_
name
],
**
layer_attrs
)
"paddle
.reshape"
,
inputs
=
{
"x"
:
input
.
name
},
outputs
=
[
node
.
name
],
shape
=
output_shape
)
def
ArgMax
(
self
,
node
):
assert
len
(
node
.
inputs
)
==
1
and
len
(
node
.
outputs
)
==
1
,
'The count of ArgMax node
\'
s input and output is not 1.'
)
==
1
,
"The count of ArgMax node
\'
s input and output is not 1."
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
in
put_shape
=
node
.
input_shape
[
0
]
in
_shapes
=
node
.
in_shapes
[
0
]
params
=
node
.
layer
.
argmax_param
out_max_val
=
params
.
out_max_val
if
hasattr
(
params
,
out_max_val
)
else
False
top_k
=
params
.
top_k
if
hasattr
(
params
,
top_k
)
else
1
axis
=
parmas
.
axis
if
hasattr
(
params
,
axis
)
else
-
1
if
axis
<
0
:
axis
+=
len
(
in
put_shape
)
axis
+=
len
(
in
_shapes
)
if
out_max_val
is
True
:
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers.topk"
,
inputs
=
{
"input"
:
self
.
get_input_name
(
input
)},
outputs
=
[
"{}_topk_var"
.
format
(
node
.
layer_name
),
"{}_index_var"
.
format
(
node
.
layer_name
)],
"paddle.topk"
,
inputs
=
{
"x"
:
input
.
name
},
outputs
=
[
node
.
name
+
"_topk_var"
,
node
.
name
+
"_index_var"
],
k
=
top_k
)
self
.
paddle_graph
.
add_layer
(
kernel
=
"paddle.cast"
,
inputs
=
{
"x"
:
"{}_topk_var"
.
format
(
node
.
layer_name
)
},
outputs
=
[
"{}_topk_var"
.
format
(
node
.
layer_name
)
],
dtype
=
"{}_topk_var.dtype"
.
format
(
node
.
layer_
name
))
"paddle.cast"
,
inputs
=
{
"x"
:
node
.
name
+
"_index_var"
},
outputs
=
[
node
.
name
+
"_index_var"
],
dtype
=
"{}_topk_var.dtype"
.
format
(
node
.
name
))
self
.
paddle_graph
.
add_layer
(
kernel
=
"paddle.concat"
,
inputs
=
{
"x"
:
"[{}_topk_var, {}_index_var]"
.
format
(
node
.
layer_name
,
node
.
layer_name
)},
outputs
=
[
node
.
layer_name
],
"paddle.concat"
,
inputs
=
{
"x"
:
[
node
.
name
+
"_topk_var"
,
node
.
name
+
"_index_var"
]},
outputs
=
[
node
.
name
],
axis
=
axis
)
else
:
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers
.topk"
,
inputs
=
{
"
input"
:
self
.
get_input_name
(
input
)
},
outputs
=
[
"_"
,
node
.
layer_
name
],
"paddle
.topk"
,
inputs
=
{
"
x"
:
input
.
name
},
outputs
=
[
"_"
,
node
.
name
],
k
=
top_k
)
def
Crop
(
self
,
node
):
assert
len
(
node
.
inputs
)
==
2
,
'The count of Crop node
\'
s input is not 2.'
node
.
inputs
)
==
2
,
"The count of Crop node
\'
s input is not 2."
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
example
=
self
.
graph
.
get_input_node
(
node
,
idx
=
1
,
copy
=
True
)
params
=
node
.
layer
.
crop_param
axis
=
params
.
axis
in
put_shape
=
node
.
input_shape
[
0
]
in
_shapes
=
node
.
in_shapes
[
0
]
if
axis
<
0
:
axis
+=
len
(
in
put_shape
)
offset_real
=
[
0
]
*
len
(
in
put_shape
)
axis
+=
len
(
in
_shapes
)
offset_real
=
[
0
]
*
len
(
in
_shapes
)
if
hasattr
(
params
,
"offset"
)
and
len
(
params
.
offset
)
>
0
:
offset
=
list
(
params
.
offset
)
assert
(
len
(
in
put_shape
)
-
axis
assert
(
len
(
in
_shapes
)
-
axis
)
==
len
(
offset
),
"invalid offset[%s] in crop layer"
%
(
str
(
offset
))
offset_real
=
[
0
]
*
axis
+
offset
layer_attrs
=
{
"offsets"
:
list
(
offset_real
),
"shape"
:
node
.
input_shape
[
1
]}
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers.crop_tensor"
,
inputs
=
{
"x"
:
self
.
get_input_name
(
input
)},
outputs
=
[
node
.
layer_name
],
**
layer_attrs
)
"paddle.crop"
,
inputs
=
{
"x"
:
input
.
name
},
outputs
=
[
node
.
name
],
shape
=
node
.
in_shapes
[
1
],
offsets
=
list
(
offset_real
))
def
Flatten
(
self
,
node
):
assert
len
(
node
.
inputs
)
==
1
,
'The count of DetectionOutput node
\'
s input is not 1.'
inputs
)
==
1
,
"The count of DetectionOutput node
\'
s input is not 1."
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers
.reshape"
,
inputs
=
{
"x"
:
self
.
get_input_name
(
input
)
},
outputs
=
[
node
.
layer_
name
],
shape
=
node
.
output_shape
[
0
])
"paddle
.reshape"
,
inputs
=
{
"x"
:
input
.
name
},
outputs
=
[
node
.
name
],
shape
=
node
.
out_shapes
[
0
])
def
Power
(
self
,
node
):
assert
len
(
node
.
inputs
)
==
1
,
'The count of Permute node
\'
s input is not 1.'
node
.
inputs
)
==
1
,
"The count of Permute node
\'
s input is not 1."
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
params
=
node
.
layer
.
power_param
power
=
params
.
power
scale
=
params
.
scale
shift
=
params
.
shift
layer_attrs
=
{
'scale'
:
scale
,
'bias'
:
shift
,
'bias_after_scale'
:
True
,
'name'
:
string
(
node
.
layer_name
+
'_scale'
)
'scale'
:
params
.
scale
,
'bias'
:
params
.
shift
,
'bias_after_scale'
:
True
}
self
.
paddle_graph
.
add_layer
(
kernel
=
"paddle.scale"
,
inputs
=
{
"x"
:
self
.
get_input_name
(
input
)
},
outputs
=
[
node
.
layer_
name
],
"paddle.scale"
,
inputs
=
{
"x"
:
input
.
name
},
outputs
=
[
node
.
name
],
**
layer_attrs
)
self
.
paddle_graph
.
add_layer
(
kernel
=
"paddle.pow"
,
inputs
=
{
"x"
:
node
.
layer_
name
},
outputs
=
[
node
.
layer_
name
],
factor
=
power
)
"paddle.pow"
,
inputs
=
{
"x"
:
node
.
name
},
outputs
=
[
node
.
name
],
exponent
=
params
.
power
)
def
Reduction
(
self
,
node
):
assert
len
(
node
.
inputs
)
==
1
,
'The count of Reduction node
\'
s input is not 1.'
node
.
inputs
)
==
1
,
"The count of Reduction node
\'
s input is not 1."
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
params
=
node
.
layer
.
reduction_param
operation
=
params
.
operation
...
...
@@ -862,86 +952,104 @@ class CaffeOpMapper(OpMapper):
coeff
=
params
.
coeff
assert
operation
>=
1
and
operation
<=
4
,
"reduction reduction [%s] error"
%
(
operation
)
input_len
=
len
(
node
.
in
put_shape
[
0
])
input_len
=
len
(
node
.
in
_shapes
[
0
])
if
axis
<
0
:
axis
+=
input_len
+
1
dim
=
list
(
range
(
input_len
))
if
operation
==
1
:
## operation = SUM
# operation = SUM
if
operation
==
1
:
layer_attrs
=
{
'dim'
:
dim
[
axis
:],
'keep_dim'
:
False
,
'name'
:
string
(
node
.
layer_name
)
"dim"
:
dim
[
axis
:],
"keep_dim"
:
False
,
}
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers.reduce_
sum"
,
inputs
=
{
"input"
:
self
.
get_input_name
(
input
)
},
outputs
=
[
node
.
layer_
name
],
"paddle.
sum"
,
inputs
=
{
"input"
:
input
.
name
},
outputs
=
[
node
.
name
],
**
layer_attrs
)
elif
operation
==
2
:
## operation = ASUM
# operation = ASUM
elif
operation
==
2
:
self
.
paddle_graph
.
add_layer
(
kernel
=
"paddle.abs"
,
inputs
=
{
"x"
:
self
.
get_input_name
(
input
)
},
outputs
=
[
node
.
layer_
name
])
"paddle.abs"
,
inputs
=
{
"x"
:
input
.
name
},
outputs
=
[
node
.
name
])
layer_attrs
=
{
'dim'
:
dim
[
axis
:],
'keep_dim'
:
False
,
'name'
:
string
(
node
.
layer_name
)
"dim"
:
dim
[
axis
:],
"keep_dim"
:
False
,
}
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers.reduce_
sum"
,
inputs
=
{
"input"
:
node
.
layer_
name
},
outputs
=
[
node
.
layer_
name
],
"paddle.
sum"
,
inputs
=
{
"input"
:
node
.
name
},
outputs
=
[
node
.
name
],
**
layer_attrs
)
elif
operation
==
3
:
## operation = SUMSQ
# operation = SUMSQ
elif
operation
==
3
:
self
.
paddle_graph
.
add_layer
(
kernel
=
"paddle.pow"
,
inputs
=
{
"x"
:
self
.
get_input_name
(
input
)
},
outputs
=
[
node
.
layer_
name
],
factor
=
2.0
)
"paddle.pow"
,
inputs
=
{
"x"
:
input
.
name
},
outputs
=
[
node
.
name
],
exponent
=
2.0
)
layer_attrs
=
{
'dim'
:
dim
[
axis
:],
'keep_dim'
:
False
,
'name'
:
string
(
node
.
layer_name
)
"dim"
:
dim
[
axis
:],
"keep_dim"
:
False
,
}
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers.reduce_
sum"
,
inputs
=
{
"input"
:
node
.
layer_
name
},
outputs
=
[
node
.
layer_
name
],
"paddle.
sum"
,
inputs
=
{
"input"
:
node
.
name
},
outputs
=
[
node
.
name
],
**
layer_attrs
)
else
:
## operation = MEAN
# operation = MEAN
else
:
layer_attrs
=
{
'dim'
:
dim
[
axis
:],
'keep_dim'
:
False
,
'name'
:
string
(
node
.
layer_name
)
"dim"
:
dim
[
axis
:],
"keep_dim"
:
False
,
}
self
.
paddle_graph
.
add_layer
(
kernel
=
"fluid.layers.reduce_
mean"
,
inputs
=
{
"input"
:
node
.
layer_
name
},
outputs
=
[
node
.
layer_
name
],
"paddle.
mean"
,
inputs
=
{
"input"
:
input
.
name
},
outputs
=
[
node
.
name
],
**
layer_attrs
)
self
.
paddle_graph
.
add_layer
(
kernel
=
"paddle.scale"
,
inputs
=
{
"x"
:
node
.
layer_
name
},
outputs
=
[
node
.
layer_
name
],
"paddle.scale"
,
inputs
=
{
"x"
:
node
.
name
},
outputs
=
[
node
.
name
],
scale
=
coeff
)
def
deal_custom_layer
(
self
,
node
):
op
=
node
.
layer_type
custom_code
,
func
=
make_custom_layer
(
node
)
params
=
get_params
(
node
.
layer
,
node
.
layer_type
)
arg_names
,
kwargs
=
set_args
(
func
,
params
)
kwargs
[
'name'
]
=
string
(
node
.
layer_name
)
kwargs
[
'input_shape'
]
=
node
.
input_shape
data
=
node
.
data
if
data
is
not
None
:
data
=
self
.
adjust_parameters
(
node
)
weights_name
=
deal_weights
(
node
)
for
i
in
range
(
len
(
data
)):
self
.
weights
[
weights_name
[
i
]]
=
data
[
i
]
inputs_list
=
[]
def
Axpy
(
self
,
node
):
assert
len
(
node
.
inputs
)
==
1
and
len
(
node
.
outputs
)
==
1
,
"The count of Axpy node
\'
s input and output is not 1."
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
params
=
node
.
layer
.
axpy_param
input0
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
input1
=
self
.
graph
.
get_input_node
(
node
,
idx
=
1
,
copy
=
True
)
input2
=
self
.
graph
.
get_input_node
(
node
,
idx
=
2
,
copy
=
True
)
input0_name
=
input0
.
name
input1_name
=
input1
.
name
input2_name
=
input2
.
name
inputs_dict
=
{}
inputs_dict
[
'x'
]
=
input1_name
inputs_dict
[
'y'
]
=
input0_name
self
.
paddle_graph
.
add_layer
(
"paddle.multiply"
,
inputs
=
inputs_dict
,
outputs
=
[
node
.
name
+
"_mul"
],
axis
=
0
)
inputs_dict
=
{}
inputs_dict
[
'x'
]
=
node
.
name
+
"_mul"
inputs_dict
[
'y'
]
=
input2_name
self
.
paddle_graph
.
add_layer
(
"paddle.add"
,
inputs
=
inputs_dict
,
outputs
=
[
node
.
name
+
"_mul"
])
def
DetectionOutput
(
self
,
node
):
assert
len
(
node
.
inputs
)
==
3
,
"The count of DetectionOutput node
\'
s input is not 3."
inputs_dict
=
dict
()
for
i
in
range
(
len
(
node
.
inputs
)):
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
i
,
copy
=
True
)
if
i
==
1
and
op
==
'DetectionOutput'
:
if
i
==
1
:
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
i
,
copy
=
True
)
while
input
is
not
None
\
and
input
.
layer_type
!=
'Softmax'
\
...
...
@@ -949,27 +1057,165 @@ class CaffeOpMapper(OpMapper):
input
=
self
.
graph
.
get_input_node
(
input
,
idx
=
0
,
copy
=
True
)
assert
input
is
not
None
,
'This kind of DetectionOutput is not supported!'
input
=
self
.
graph
.
get_input_node
(
input
,
idx
=
0
,
copy
=
True
)
inputs_list
.
append
(
self
.
get_input_name
(
input
))
kwargs_tmp
=
copy
.
deepcopy
(
kwargs
)
for
k
,
v
in
kwargs_tmp
.
items
():
if
str
(
type
(
v
))
==
"<class 'caffe_pb2.NonMaximumSuppressionParameter'>"
:
kwargs
[
k
]
=
dict
()
kwargs
[
k
][
"nms_threshold"
]
=
v
.
nms_threshold
kwargs
[
k
][
"top_k"
]
=
v
.
top_k
kwargs
[
k
][
"eta"
]
=
v
.
eta
self
.
paddle_graph
.
add_layer
(
kernel
=
"custom_layer:{}"
.
format
(
op
),
inputs
=
{
"inputs"
:
inputs_list
},
outputs
=
[
node
.
layer_name
],
**
kwargs
)
if
op
not
in
self
.
used_custom_layers
:
self
.
used_custom_layers
[
op
]
=
custom_code
inputs_dict
[
"x{}"
.
format
(
i
)]
=
input
.
name
params
=
node
.
layer
.
detection_output_param
nms_param
=
params
.
nms_param
nms_param_dict
=
dict
()
nms_param_dict
[
"nms_threshold"
]
=
nms_param
.
nms_threshold
nms_param_dict
[
"top_k"
]
=
nms_param
.
top_k
nms_param_dict
[
"eta"
]
=
nms_param
.
eta
if
nms_param
is
None
:
nms_param_dict
=
{
"nms_threshold"
:
0.3
,
"top_k"
:
10
,
"eta"
:
1.0
}
default
=
{
"nms_threshold"
:
0.3
,
"top_k"
:
10
,
"eta"
:
1.0
}
fields
=
[
"eta"
,
"top_k"
,
"nms_threshold"
]
for
f
in
default
.
keys
():
if
f
not
in
nms_param_dict
:
nms_param_dict
[
f
]
=
default
[
f
]
layer_attrs
=
{
"background_label"
:
params
.
background_label_id
,
"nms_threshold"
:
nms_param_dict
[
"nms_threshold"
],
"nms_top_k"
:
nms_param_dict
[
"top_k"
],
"keep_top_k"
:
params
.
keep_top_k
,
"score_threshold"
:
params
.
confidence_threshold
,
"nms_eta"
:
nms_param_dict
[
"eta"
]}
self
.
paddle_graph
.
add_layer
(
kernel
=
"custom_layer:detectionoutput"
,
inputs
=
inputs_dict
,
outputs
=
[
node
.
name
],
**
layer_attrs
)
def
directly_map
(
self
,
node
):
assert
node
.
layer_type
in
self
.
directly_map_ops
op_info
=
self
.
directly_map_ops
[
node
.
layer_type
]
def
Normalize
(
self
,
node
):
assert
len
(
node
.
inputs
)
==
1
,
"The count of Normalize node
\'
s input is not 1."
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
params
=
node
.
layer
.
norm_param
scale_name
=
node
.
name
+
"_scale"
if
node
.
data
is
None
or
len
(
node
.
data
)
!=
1
:
print
(
"The parameter of {} (type is {}) is not set. So we set the parameters as 0"
.
format
(
scale_name
,
node
.
layer_type
))
self
.
parmas
[
scale_name
]
=
\
np
.
zeros
([
1
]
if
params
.
channel_shared
else
[
1
,
1
,
1
,
node
.
in_shapes
[
0
][
1
]]).
astype
(
"float32"
)
else
:
self
.
parmas
[
scale_name
]
=
_adjust_parameters
(
node
)[
0
]
layer_attrs
=
{
"axis"
:
-
1
if
params
.
channel_shared
else
1
,
"param_name"
:
scale_name
,
"param_shape"
:
self
.
parmas
[
scale_name
].
shape
,
"param_dtype"
:
str
(
self
.
parmas
[
scale_name
].
dtype
)}
self
.
pd_pdgraph
.
add_layer
(
"custom_layer:normalize"
,
inputs
=
{
"x"
:
input
.
name
},
outputs
=
[
node
.
name
],
**
layer_attrs
)
def
Permute
(
self
,
node
):
assert
len
(
node
.
inputs
)
==
1
,
"The count of Permute node
\'
s input is not 1."
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
params
=
node
.
layer
.
permute_param
order
=
list
(
params
.
order
)
self
.
paddle_graph
.
add_layer
(
kernel
=
op_info
,
inputs
=
{
"x"
:
self
.
get_input_name
(
input
)},
outputs
=
[
node
.
layer_name
])
\ No newline at end of file
"paddle.transpose"
,
inputs
=
{
"x"
:
input
.
name
},
outputs
=
[
node
.
name
],
perm
=
order
)
def
PriorBox
(
self
,
node
):
assert
len
(
node
.
inputs
)
==
2
,
"The count of PriorBox node
\'
s input is not 2."
input0
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
input1
=
self
.
graph
.
get_input_node
(
node
,
idx
=
1
,
copy
=
True
)
inputs_dict
=
{}
inputs_dict
[
"x0"
]
=
input0
.
name
inputs_dict
[
"x1"
]
=
input1
.
name
params
=
node
.
layer
.
prior_box_param
steps
=
tuple
(
params
.
step
)
if
type
(
params
.
step
)
\
is
list
or
type
(
params
.
step
)
is
tuple
\
else
(
params
.
step
,
params
.
step
)
layer_attrs
=
{
"min_sizes"
:
params
.
min_size
,
"max_sizes"
:
params
.
max_size
,
"aspect_ratios"
:
params
.
aspect_ratio
,
"variance"
:
params
.
variance
,
"flip"
:
params
.
flip
,
"clip"
:
params
.
clip
,
"steps"
:
steps
,
"offset"
:
params
.
offset
,
"min_max_aspect_ratios_order"
:
True
}
self
.
paddle_graph
.
add_layer
(
"custom_layer:priorbox"
,
inputs
=
inputs_dict
,
outputs
=
[
node
.
name
],
**
layer_attrs
)
def
ReLU6
(
self
,
node
):
assert
len
(
node
.
inputs
)
==
1
,
"The count of RelU6 node
\'
s input is not 1."
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
self
.
paddle_graph
.
add_layer
(
"paddle.nn.functional.relu6"
,
inputs
=
{
"x"
:
input
.
name
},
outputs
=
[
node
.
name
])
def
ROIPooling
(
self
,
node
):
assert
len
(
node
.
inputs
)
==
2
,
"The count of ROIPooling node
\'
s input is not 2."
input0
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
input1
=
self
.
graph
.
get_input_node
(
node
,
idx
=
1
,
copy
=
True
)
inputs_dict
=
{}
inputs_dict
[
"x0"
]
=
input0
.
name
inputs_dict
[
"x1"
]
=
input1
.
name
params
=
node
.
layer
.
roi_pooling_param
layer_attrs
=
{
"pooled_height"
:
params
.
pooled_h
,
"pooled_width"
:
params
.
pooled_w
,
"spatial_scale"
:
params
.
spatial_scale
}
self
.
paddle_graph
.
add_layer
(
"custom_layer:ROIPooling"
,
inputs
=
inputs_dict
,
outputs
=
[
node
.
name
],
**
layer_attrs
)
def
ShuffleChannel
(
self
,
node
):
assert
len
(
node
.
inputs
)
==
1
,
"The count of ShuffleChannel node
\'
s input is not 1."
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
params
=
node
.
layer
.
shuffle_channel_param
self
.
paddle_graph
.
add_layer
(
"fluid.layers.shuffle_channel"
,
inputs
=
{
"x"
:
input
.
name
},
outputs
=
[
node
.
layer_name
],
group
=
params
.
group
)
def
Upsample
(
self
,
node
):
assert
len
(
node
.
inputs
)
==
1
,
"The count of Upsample node
\'
s input is not 1."
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
params
=
node
.
layer
.
upsample_param
layer_attrs
=
{
"align_corners"
:
False
,
"scale_factor"
:
params
.
scale
,
"mode"
:
"nearest"
}
self
.
paddle_graph
.
add_layer
(
"paddle.nn.functioanl.interpolate"
,
inputs
=
{
"input"
:
input
.
name
},
outputs
=
[
node
.
layer_name
],
**
layer_attrs
)
def
Select
(
self
,
node
):
assert
len
(
node
.
inputs
)
==
1
,
"The count of Select node
\'
s input is not 1."
input
=
self
.
graph
.
get_input_node
(
node
,
idx
=
0
,
copy
=
True
)
in_shapes
=
node
.
in_shapes
[
0
]
params
=
node
.
layer
.
select_param
layer_attrs
=
{
"in_shapes"
:
in_shapes
,
"point"
:
params
.
slice_point
,
"axis"
:
params
.
axis
}
self
.
paddle_graph
.
add_layer
(
"custom_layer:select"
,
inputs
=
{
"x"
:
input
.
name
},
outputs
=
[
node
.
name
],
**
layer_attrs
)
x2paddle/op_mapper/static/caffe2paddle/caffe_shape.py
已删除
100644 → 0
浏览文件 @
e19d3442
# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import
math
import
numbers
from
functools
import
reduce
def
get_kernel_parameters
(
params
):
[
k_h
,
k_w
]
=
[
1
,
1
]
if
isinstance
(
params
.
kernel_size
,
numbers
.
Number
):
[
k_h
,
k_w
]
=
[
params
.
kernel_size
]
*
2
elif
len
(
params
.
kernel_size
)
>
0
:
k_h
=
params
.
kernel_h
if
params
.
kernel_h
>
0
else
params
.
kernel_size
[
0
]
k_w
=
params
.
kernel_w
if
params
.
kernel_w
>
0
else
params
.
kernel_size
[
len
(
params
.
kernel_size
)
-
1
]
elif
params
.
kernel_h
>
0
or
params
.
kernel_w
>
0
:
k_h
=
params
.
kernel_h
k_w
=
params
.
kernel_w
[
s_h
,
s_w
]
=
[
1
,
1
]
if
isinstance
(
params
.
stride
,
numbers
.
Number
):
[
s_h
,
s_w
]
=
[
params
.
stride
]
*
2
elif
len
(
params
.
stride
)
>
0
:
s_h
=
params
.
stride_h
if
params
.
stride_h
>
0
else
params
.
stride
[
0
]
s_w
=
params
.
stride_w
if
params
.
stride_w
>
0
else
params
.
stride
[
len
(
params
.
stride
)
-
1
]
elif
params
.
stride_h
>
0
or
params
.
stride_w
>
0
:
s_h
=
params
.
stride_h
s_w
=
params
.
stride_w
[
p_h
,
p_w
]
=
[
0
,
0
]
if
isinstance
(
params
.
pad
,
numbers
.
Number
):
[
p_h
,
p_w
]
=
[
params
.
pad
]
*
2
elif
len
(
params
.
pad
)
>
0
:
p_h
=
params
.
pad_h
if
params
.
pad_h
>
0
else
params
.
pad
[
0
]
p_w
=
params
.
pad_w
if
params
.
pad_w
>
0
else
params
.
pad
[
len
(
params
.
pad
)
-
1
]
elif
params
.
pad_h
>
0
or
params
.
pad_w
>
0
:
p_h
=
params
.
pad_h
p_w
=
params
.
pad_w
dila_h
=
dila_w
=
1
if
hasattr
(
params
,
'dilation'
):
dila_len
=
len
(
params
.
dilation
)
if
dila_len
==
2
:
dila_h
=
params
.
dilation
[
0
]
dila_w
=
params
.
dilation
[
1
]
elif
dila_len
==
1
:
dila_h
=
dila_w
=
params
.
dilation
[
0
]
else
:
assert
dila_len
==
0
,
"invalid length[%s] of dilation in convolution"
%
(
dila_len
)
return
dila_h
,
dila_w
,
p_h
,
p_w
,
k_h
,
k_w
,
s_h
,
s_w
def
get_strided_kernel_output_shape
(
params
,
input_shape
,
round_func
):
i_h
=
input_shape
[
2
]
i_w
=
input_shape
[
3
]
dila_h
,
dila_w
,
pad_h
,
pad_w
,
kernel_h
,
kernel_w
,
stride_h
,
stride_w
=
get_kernel_parameters
(
params
)
o_h
=
(
i_h
+
2
*
pad_h
-
(
dila_h
*
(
kernel_h
-
1
)
+
1
))
/
float
(
stride_h
)
+
1
o_w
=
(
i_w
+
2
*
pad_w
-
(
dila_w
*
(
kernel_w
-
1
)
+
1
))
/
float
(
stride_w
)
+
1
o_h
=
int
(
round_func
(
o_h
))
o_w
=
int
(
round_func
(
o_w
))
has_c_o
=
hasattr
(
params
,
'num_output'
)
c
=
params
.
num_output
if
has_c_o
else
input_shape
[
1
]
return
[[
input_shape
[
0
],
c
,
o_h
,
o_w
]]
def
shape_convolution
(
layer
,
input_shape
):
params
=
layer
.
convolution_param
return
get_strided_kernel_output_shape
(
params
,
input_shape
[
0
],
math
.
floor
)
def
shape_deconvolution
(
layer
,
input_shape
):
h_i
=
input_shape
[
0
][
2
]
w_i
=
input_shape
[
0
][
3
]
params
=
layer
.
convolution_param
dila_h
,
dila_w
,
pad_h
,
pad_w
,
kernel_h
,
kernel_w
,
stride_h
,
stride_w
=
get_kernel_parameters
(
params
)
h_o
=
(
h_i
-
1
)
*
stride_h
-
2
*
pad_h
+
dila_h
*
(
kernel_h
-
1
)
+
1
w_o
=
(
w_i
-
1
)
*
stride_w
-
2
*
pad_w
+
dila_w
*
(
kernel_w
-
1
)
+
1
has_c_o
=
hasattr
(
params
,
'num_output'
)
c
=
params
.
num_output
if
has_c_o
else
input_shape
.
channels
return
[[
input_shape
[
0
][
0
],
c
,
h_o
,
w_o
]]
def
shape_pooling
(
layer
,
input_shape
):
params
=
layer
.
pooling_param
global_pool
=
getattr
(
params
,
'global_pooling'
,
False
)
if
global_pool
:
return
[[
input_shape
[
0
][
0
],
input_shape
[
0
][
1
],
1
,
1
]]
ceil_mode
=
getattr
(
params
,
'ceil_mode'
,
True
)
if
ceil_mode
is
True
:
method
=
math
.
ceil
else
:
method
=
math
.
floor
return
get_strided_kernel_output_shape
(
params
,
input_shape
[
0
],
method
)
def
shape_innerproduct
(
layer
,
input_shape
):
params
=
layer
.
inner_product_param
return
[[
input_shape
[
0
][
0
],
params
.
num_output
]]
def
shape_lrn
(
layer
,
input_shape
):
return
input_shape
def
shape_relu
(
layer
,
input_shape
):
return
input_shape
def
shape_softmax
(
layer
,
input_shape
):
return
input_shape
def
shape_input
(
layer
,
input_shape
):
return
[
list
(
layer
.
input_param
.
shape
[
0
].
dim
)]
def
shape_memorydata
(
layer
,
input_shape
):
params
=
layer
.
memory_data_param
shape
=
[]
shape
.
append
(
int
(
params
.
batch_size
))
shape
.
append
(
int
(
params
.
channels
))
shape
.
append
(
int
(
params
.
height
))
shape
.
append
(
int
(
params
.
width
))
return
[
shape
]
def
shape_concat
(
layer
,
input_shape
):
params
=
layer
.
concat_param
axis
=
params
.
axis
output_shape
=
None
for
shape
in
input_shape
:
if
output_shape
is
None
:
output_shape
=
[]
for
i
in
range
(
len
(
shape
)):
output_shape
.
append
(
shape
[
i
])
else
:
output_shape
[
axis
]
+=
shape
[
axis
]
return
[
output_shape
]
def
shape_slice
(
layer
,
input_shape
):
inshape
=
input_shape
[
0
]
top_len
=
len
(
layer
.
top
)
params
=
layer
.
slice_param
axis
=
params
.
axis
slice_dim
=
params
.
slice_dim
if
slice_dim
!=
1
and
axis
==
1
:
axis
=
slice_dim
points
=
list
(
params
.
slice_point
)
count
=
inshape
[
axis
]
if
len
(
points
)
==
0
:
assert
count
%
top_len
==
0
,
"the parameter of Slice is wrong"
part
=
count
/
top_len
t
=
part
while
t
<
count
:
points
.
append
(
int
(
t
))
t
+=
part
points
=
[
0
]
+
points
+
[
count
]
output_shape
=
[]
for
i
in
range
(
len
(
points
)):
shape
=
[]
for
ii
in
range
(
len
(
inshape
)):
shape
.
append
(
inshape
[
ii
])
size
=
points
[
i
+
1
]
-
points
[
i
]
shape
[
axis
]
=
size
output_shape
.
append
(
shape
)
if
i
==
len
(
points
)
-
2
:
break
return
output_shape
def
shape_prelu
(
layer
,
input_shape
):
return
input_shape
def
shape_sigmoid
(
layer
,
input_shape
):
return
input_shape
def
shape_absval
(
layer
,
input_shape
):
return
input_shape
def
shape_accuracy
(
layer
,
input_shape
):
return
[[
1
]]
def
shape_tanh
(
layer
,
input_shape
):
return
input_shape
def
shape_eltwise
(
layer
,
input_shape
):
return
[
input_shape
[
0
]]
def
shape_batchnorm
(
layer
,
input_shape
):
return
input_shape
def
shape_scale
(
layer
,
input_shape
):
return
input_shape
def
shape_reshape
(
layer
,
input_shape
):
def
count
(
num_list
):
return
reduce
(
lambda
a
,
b
:
a
*
b
,
num_list
)
inshape
=
input_shape
[
0
]
params
=
layer
.
reshape_param
axis
=
params
.
axis
if
hasattr
(
params
,
'axis'
)
else
0
num_axes
=
params
.
num_axes
if
hasattr
(
params
,
'num_axes'
)
else
-
1
if
inshape
[
0
]
==
-
1
:
inshape
[
0
]
=
1
input_count
=
count
(
inshape
)
input_num_axes
=
len
(
inshape
)
input_start_axis
=
axis
start_axis
=
input_start_axis
if
input_start_axis
>=
0
\
else
input_num_axes
+
input_start_axis
+
1
assert
start_axis
>=
0
,
"[Reshape]axis %d out of range"
%
(
input_start_axis
)
assert
start_axis
<=
input_num_axes
,
"[Reshape]axis %d out of range for %d-D input data"
\
%
(
input_start_axis
,
input_num_axes
)
assert
num_axes
>=
-
1
,
"[Reshape]num_axes must be >= 0, or -1 for all"
end_axis
=
input_num_axes
if
num_axes
==
-
1
else
start_axis
+
num_axes
assert
end_axis
<=
input_num_axes
,
"end_axis[%d] = axis[%d] + num_axes[%d] is out of range"
\
%
(
end_axis
,
start_axis
,
num_axes
)
num_axes_replaced
=
end_axis
-
start_axis
num_axes_retained
=
input_num_axes
-
num_axes_replaced
num_new_axes
=
len
(
list
(
params
.
shape
.
dim
))
outshape
=
[]
for
i
in
range
(
start_axis
):
outshape
.
append
(
inshape
[
i
])
for
i
in
range
(
num_new_axes
):
outshape
.
append
(
params
.
shape
.
dim
[
i
])
for
i
in
range
(
end_axis
,
input_num_axes
):
outshape
.
append
(
inshape
[
i
])
assert
len
(
outshape
)
==
num_axes_retained
+
num_new_axes
,
\
"[Reshape]invalid dims of output shape[%s]"
%
(
str
(
outshape
))
inferred_axis
=
-
1
copy_axes
=
[]
constant_count
=
1
for
i
in
range
(
num_new_axes
):
top_dim
=
params
.
shape
.
dim
[
i
]
if
top_dim
==
0
:
copy_axes
.
append
(
i
)
copy_axis_index
=
start_axis
+
i
outshape
[
copy_axis_index
]
=
inshape
[
copy_axis_index
]
elif
top_dim
==
-
1
:
assert
inferred_axis
==
-
1
,
"[Reshape]new shape contains multiple -1 dims"
inferred_axis
=
i
else
:
constant_count
*=
top_dim
if
inferred_axis
>=
0
:
explicit_count
=
constant_count
l
=
inshape
[
0
:
start_axis
]
if
len
(
l
)
>
0
:
explicit_count
*=
count
(
l
)
l
=
inshape
[
end_axis
:]
if
len
(
l
)
>
0
:
explicit_count
*=
count
(
l
)
for
i
in
range
(
len
(
copy_axes
)):
explicit_count
*=
outshape
[
start_axis
+
copy_axes
[
i
]]
assert
input_count
%
explicit_count
==
0
,
"[Reshape]botom count[%d] "
\
"must be divisible by product of the specified dimensions[%d] "
\
%
(
input_count
,
explicit_count
)
outshape
[
start_axis
+
inferred_axis
]
=
int
(
input_count
/
explicit_count
)
output_count
=
count
(
outshape
)
assert
output_count
==
input_count
,
"[Reshape]output count[%d] must match input count[%d]"
%
(
output_count
,
input_count
)
outshape
[
0
]
=
-
1
return
[
outshape
]
def
shape_argmax
(
layer
,
input_shape
):
inshape
=
input_shape
[
0
]
params
=
layer
.
argmax_param
out_max_val
=
params
.
out_max_val
if
hasattr
(
params
,
out_max_val
)
else
False
top_k
=
params
.
top_k
if
hasattr
(
params
,
top_k
)
else
1
axis
=
parmas
.
axis
if
hasattr
(
params
,
axis
)
else
-
1
if
axis
<
0
:
axis
+=
len
(
inshape
)
assert
(
axis
+
1
==
len
(
inshape
)
),
'only can be applied on the last dimension[axis:%d, %s] now,'
\
'make sure you have set axis param in xxx.prototxt file'
\
%
(
axis
,
str
(
inshape
))
outshape
=
inshape
outshape
[
-
1
]
=
top_k
if
out_max_val
is
True
:
outshape
[
-
1
]
*=
2
return
[
outshape
]
def
shape_crop
(
layer
,
input_shape
):
assert
len
(
input_shape
)
==
2
,
"the number of crop's inputs must be 2"
return
[
input_shape
[
1
]]
def
shape_flatten
(
layer
,
input_shape
):
assert
len
(
input_shape
)
==
1
,
"the number of flatten's inputs must be 1"
inshape
=
input_shape
[
0
]
params
=
layer
.
flatten_param
start_axis
=
params
.
axis
end_axis
=
params
.
end_axis
if
start_axis
<
0
:
start_axis
+=
len
(
inshape
)
if
end_axis
<
0
:
end_axis
+=
len
(
inshape
)
+
1
assert
start_axis
<=
end_axis
,
'invalid axis[%d] or end_axis[%d] params'
\
%
(
start_axis
,
end_axis
)
output_shape
=
inshape
[
0
:
start_axis
]
if
len
(
inshape
[
start_axis
:
end_axis
])
!=
0
:
flat_sz
=
reduce
(
lambda
a
,
b
:
a
*
b
,
inshape
[
start_axis
:
end_axis
])
output_shape
+=
[
flat_sz
]
output_shape
+=
inshape
[
end_axis
:
len
(
inshape
)]
output_shape
[
0
]
=
-
1
return
[
output_shape
]
def
shape_power
(
layer
,
input_shape
):
return
input_shape
def
shape_reduction
(
layer
,
input_shape
):
params
=
layer
.
reduction_param
axis
=
params
.
axis
if
axis
<
0
:
axis
+=
len
(
input_shape
[
0
])
+
1
assert
axis
<=
len
(
input_shape
[
0
]),
'invalid axis[%d] error'
%
(
axis
)
return
[
input_shape
[
0
:
axis
]]
x2paddle/optimizer/fusion/static/bn_scale_fuser.py
浏览文件 @
a1af51d3
...
...
@@ -20,87 +20,126 @@ from x2paddle.core.util import *
class
Static_BNScaleFuser
(
FuseBase
):
def
__init__
(
self
):
super
(
Static_BNScaleFuser
,
self
).
__init__
(
graph_type
=
"dygraph"
)
super
(
Static_BNScaleFuser
,
self
).
__init__
(
graph_type
=
"static"
)
patterns
=
list
()
def
build_pattern
(
self
):
""" 描述需要替换的batchnorm2d图结构。
batchnorm2d层模式python实现代码示例:
conv5_bn = fluid.layers.batch_norm(input=conv5, is_test=True, param_attr=None, bias_attr=None, moving_mean_name='conv5_bn_mean', moving_variance_name='conv5_bn_variance', epsilon=9.999999747378752e-06, name='conv5_bn')
conv5_scale_scale = fluid.ParamAttr(name='conv5_scale_scale')
conv5_scale_cparam1 = fluid.layers.create_parameter(attr=conv5_scale_scale, dtype=conv5_bn.dtype, shape=[256], name='conv5_scale_cparam1', is_bias=True, default_initializer=Constant(value=1.0))
conv5_scale_mul = fluid.layers.elementwise_mul(x=conv5_bn, y=conv5_scale_cparam1, axis=1)
conv5_scale_offset = fluid.ParamAttr(name='conv5_scale_offset')
conv5_scale_cparam2 = fluid.layers.create_parameter(attr=conv5_scale_offset, dtype=conv5_bn.dtype, shape=[256], name='conv5_scale_cparam2', is_bias=True, default_initializer=Constant(value=1.0))
conv5_scale = fluid.layers.elementwise_add(x=conv5_scale_mul, y=conv5_scale_cparam2, axis=1)
模式一:
conv1_bn = paddle.nn.functional.batch_norm(x=conv1, weight=conv1_bn_weight, bias=conv1_bn_bias, running_mean=conv1_bn_mean, running_var=conv1_bn_variance, epsilon=9.999999747378752e-06, momentum=0.9990000128746033)
conv1_scale_cparam1 = paddle.static.create_parameter(shape=(32,), dtype='float32', name='conv1_scale_cparam1')
conv1_scale_mul = paddle.multiply(x=conv1_bn, y=conv1_scale_cparam1, axis=1)
conv1_scale_cparam2 = paddle.static.create_parameter(shape=(32,), dtype='float32', name='conv1_scale_cparam2')
conv1_scale_cparam2 = paddle.reshape(x=conv1_scale_cparam2, shape=[32, 1, 1])
conv1_scale = paddle.add(x=conv1_scale_mul, y=conv1_scale_cparam2)
模式二:
conv1_bn = paddle.nn.functional.batch_norm(x=conv1, weight=conv1_bn_weight, bias=conv1_bn_bias, running_mean=conv1_bn_mean, running_var=conv1_bn_variance, epsilon=9.999999747378752e-06, momentum=0.9990000128746033)
conv1_scale_cparam1 = paddle.static.create_parameter(shape=(32,), dtype='float32', name='conv1_scale_cparam1')
conv1_scale_mul = paddle.multiply(x=conv1_bn, y=conv1_scale_cparam1, axis=1)
conv1_scale_cparam2 = paddle.static.create_parameter(shape=(32,), dtype='float32', name='conv1_scale_cparam2')
conv1_scale = paddle.add(x=conv1_scale_mul, y=conv1_scale_cparam2)
"""
def
gen_name
(
id
):
return
"x"
+
str
(
id
)
self
.
pattern
.
add_layer
(
"fluid.layers.batch_norm"
,
inputs
=
{
"input"
:
"bn-input-0"
},
pattern
=
PaddleGraph
(
graph_type
=
"dygraph"
)
pattern
.
add_layer
(
"paddle.nn.functional.batch_norm"
,
inputs
=
{
"input"
:
"bn-input-0"
,
"weight"
:
"bn-input-1"
,
"bias"
:
"bn-input-2"
,
"running_mean"
:
"bn-input-3"
,
"running_var"
:
"bn-input-4"
,},
outputs
=
[
gen_name
(
0
)])
self
.
pattern
.
add_layer
(
"
fluid.ParamAtt
r"
,
pattern
.
add_layer
(
"
paddle.static.create_paramete
r"
,
inputs
=
{},
outputs
=
[
gen_name
(
1
)])
self
.
pattern
.
add_layer
(
"fluid.layers.create_parameter"
,
inputs
=
{
"attr"
:
gen_name
(
1
)},
outputs
=
[
gen_name
(
2
)])
inputs_dict
=
{}
inputs_dict
[
'x'
]
=
gen_name
(
0
)
inputs_dict
[
'y'
]
=
gen_name
(
2
)
self
.
pattern
.
add_layer
(
"
fluid.layers.elementwise_mul
"
,
inputs_dict
[
'y'
]
=
gen_name
(
1
)
pattern
.
add_layer
(
"
paddle.multiply
"
,
inputs
=
inputs_dict
,
outputs
=
[
gen_name
(
3
)])
self
.
pattern
.
add_layer
(
"
fluid.ParamAtt
r"
,
outputs
=
[
gen_name
(
2
)])
pattern
.
add_layer
(
"
paddle.static.create_paramete
r"
,
inputs
=
{},
outputs
=
[
gen_name
(
3
)])
pattern
.
add_layer
(
"paddle.reshape"
,
inputs
=
{
"x"
:
gen_name
(
3
)},
outputs
=
[
gen_name
(
4
)])
self
.
pattern
.
add_layer
(
"fluid.layers.create_parameter"
,
inputs
=
{
"attr"
:
gen_name
(
4
)},
inputs_dict
=
{}
inputs_dict
[
'x'
]
=
gen_name
(
2
)
inputs_dict
[
'y'
]
=
gen_name
(
4
)
pattern
.
add_layer
(
"paddle.add"
,
inputs
=
inputs_dict
,
outputs
=
[
gen_name
(
5
)])
pattern
.
build
(
inputs
=
{
"input-0"
:
"bn-input-0"
,
"input-1"
:
"bn-input-1"
,
"input-2"
:
"bn-input-2"
,
"input-3"
:
"bn-input-3"
,
"input-4"
:
"bn-input-4"
})
self
.
patterns
.
append
(
pattern
)
pattern
=
PaddleGraph
(
graph_type
=
"dygraph"
)
pattern
.
add_layer
(
"paddle.nn.functional.batch_norm"
,
inputs
=
{
"input"
:
"bn-input-0"
,
"weight"
:
"bn-input-1"
,
"bias"
:
"bn-input-2"
,
"running_mean"
:
"bn-input-3"
,
"running_var"
:
"bn-input-4"
,},
outputs
=
[
gen_name
(
0
)])
pattern
.
add_layer
(
"paddle.static.create_parameter"
,
inputs
=
{},
outputs
=
[
gen_name
(
1
)])
inputs_dict
=
{}
inputs_dict
[
'x'
]
=
gen_name
(
3
)
inputs_dict
[
'y'
]
=
gen_name
(
5
)
self
.
pattern
.
add_layer
(
"
fluid.layers.elementwise_add
"
,
inputs_dict
[
'x'
]
=
gen_name
(
0
)
inputs_dict
[
'y'
]
=
gen_name
(
1
)
pattern
.
add_layer
(
"
paddle.multiply
"
,
inputs
=
inputs_dict
,
outputs
=
[
gen_name
(
6
)])
self
.
pattern
.
build
(
inputs
=
{
"input-0"
:
"bn-input-0"
})
outputs
=
[
gen_name
(
2
)])
pattern
.
add_layer
(
"paddle.static.create_parameter"
,
inputs
=
{},
outputs
=
[
gen_name
(
3
)])
inputs_dict
=
{}
inputs_dict
[
'x'
]
=
gen_name
(
2
)
inputs_dict
[
'y'
]
=
gen_name
(
3
)
pattern
.
add_layer
(
"paddle.add"
,
inputs
=
inputs_dict
,
outputs
=
[
gen_name
(
4
)])
pattern
.
build
(
inputs
=
{
"input-0"
:
"bn-input-0"
,
"input-1"
:
"bn-input-1"
,
"input-2"
:
"bn-input-2"
,
"input-3"
:
"bn-input-3"
,
"input-4"
:
"bn-input-4"
})
self
.
patterns
.
append
(
pattern
)
def
insert_new_layer
(
self
,
graph
,
parameters
,
matches
):
new_layer
=
self
.
gen_new_layer
(
parameters
,
matches
)
new_layer_id
=
list
(
matches
.
keys
())[
0
]
new_layer_id
=
list
(
matches
.
keys
())[
-
1
]
graph
.
layers
[
new_layer_id
]
=
new_layer
matches
.
pop
(
list
(
matches
.
keys
())[
1
])
matches
.
pop
(
list
(
matches
.
keys
())[
2
])
matches
.
pop
(
new_layer_id
)
def
gen_new_layer
(
self
,
parameters
,
matches
):
layers_id
=
list
(
matches
.
keys
())
layer
=
matches
[
layers_id
[
0
]]
layer_inputs
=
layer
.
inputs
layer_name
=
layer
.
outputs
[
0
]
layer_attrs
=
layer
.
attrs
layer_attrs
[
"param_attr"
]
=
string
(
"{}_scale"
.
format
(
layer_name
))
layer_attrs
[
"bias_attr"
]
=
string
(
"{}_offset"
.
format
(
layer_name
))
layer
=
matches
[
layers_id
[
-
1
]]
layer_outputs
=
layer
.
outputs
bn_layer
=
matches
[
layers_id
[
0
]]
layer
=
matches
[
layers_id
[
1
]]
layer_name
=
layer
.
outputs
[
0
]
scale_numpy
=
parameters
.
pop
(
layer_name
)
parameters
[
layer_attrs
[
"param_attr"
][
1
:
-
1
]]
=
scale_numpy
layer
=
matches
[
layers_id
[
4
]]
layer_name
=
layer
.
outputs
[
0
]
scale_numpy
=
parameters
.
pop
(
layer_name
)
parameters
[
layer_attrs
[
"bias_attr"
][
1
:
-
1
]]
=
scale_numpy
new_layer
=
PaddleLayer
(
layers_id
[
0
],
"fluid.layers.batch_norm"
,
inputs
=
layer_inputs
,
outputs
=
layer_outputs
,
**
layer_attrs
)
return
new_layer
\ No newline at end of file
bn_layer
.
inputs
[
"weight"
]
=
layer
.
outputs
[
0
]
layer
=
matches
[
layers_id
[
3
]]
bn_layer
.
inputs
[
"bias"
]
=
layer
.
outputs
[
0
]
bn_layer
.
id
=
layers_id
[
-
1
]
layer
=
matches
[
layers_id
[
-
1
]]
bn_layer
.
outputs
=
layer
.
outputs
return
bn_layer
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录