未验证 提交 619b1833 编写于 作者: S SunAhong1993 提交者: GitHub

Merge pull request #2 from PaddlePaddle/develop

oo
- repo: local - repo: https://github.com/PaddlePaddle/mirrors-yapf.git
sha: 0d79c0c469bab64f7229c9aca2b1186ef47f0e37
hooks: hooks:
- id: yapf - id: yapf
name: yapf
entry: yapf
language: system
args: [-i, --style .style.yapf]
files: \.py$ files: \.py$
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
sha: a11d9314b22d8f8c7556443875b731ef05965464 sha: a11d9314b22d8f8c7556443875b731ef05965464
hooks: hooks:
...@@ -18,6 +14,7 @@ ...@@ -18,6 +14,7 @@
- id: check-symlinks - id: check-symlinks
- id: check-added-large-files - id: check-added-large-files
- repo: local - repo: local
hooks: hooks:
- id: copyright_checker - id: copyright_checker
name: copyright_checker name: copyright_checker
......
language: python language: python
python: python:
- '2.7'
- '3.5' - '3.5'
- '3.6'
script: script:
- if [[ $TRAVIS_PYTHON_VERSION != 2.7 ]]; then /bin/bash ./tools/check_code_style.sh; fi - if [[ $TRAVIS_PYTHON_VERSION != 2.7 ]]; then /bin/bash ./tools/check_code_style.sh; fi
......
...@@ -44,10 +44,15 @@ x2paddle --framework=caffe --prototxt=deploy.prototxt --weight=deploy.caffemodel ...@@ -44,10 +44,15 @@ x2paddle --framework=caffe --prototxt=deploy.prototxt --weight=deploy.caffemodel
``` ```
x2paddle --framework=onnx --model=onnx_model.onnx --save_dir=pd_model x2paddle --framework=onnx --model=onnx_model.onnx --save_dir=pd_model
``` ```
### Paddle2ONNX
```
# 注意:paddle_infer_model_dir下需包含__model__和__params__两个文件
x2paddle --framework=paddle2onnx --model=paddle_infer_model_dir --save_dir=onnx_model
```
### 参数选项 ### 参数选项
| 参数 | | | 参数 | |
|----------|--------------| |----------|--------------|
|--framework | 源模型类型 (tensorflow、caffe、onnx) | |--framework | 源模型类型 (tensorflow、caffe、onnx、paddle2onnx) |
|--prototxt | 当framework为caffe时,该参数指定caffe模型的proto文件路径 | |--prototxt | 当framework为caffe时,该参数指定caffe模型的proto文件路径 |
|--weight | 当framework为caffe时,该参数指定caffe模型的参数文件路径 | |--weight | 当framework为caffe时,该参数指定caffe模型的参数文件路径 |
|--save_dir | 指定转换后的模型保存目录路径 | |--save_dir | 指定转换后的模型保存目录路径 |
......
...@@ -11,8 +11,7 @@ setuptools.setup( ...@@ -11,8 +11,7 @@ setuptools.setup(
version=x2paddle.__version__, version=x2paddle.__version__,
author="dltp-sz", author="dltp-sz",
author_email="dltp-sz@baidu.com", author_email="dltp-sz@baidu.com",
description= description="a toolkit for converting trained model to PaddlePaddle from other deep learning frameworks.",
"a toolkit for converting trained model to PaddlePaddle from other deep learning frameworks.",
long_description=long_description, long_description=long_description,
long_description_content_type="text/plain", long_description_content_type="text/plain",
url="https://github.com/PaddlePaddle/x2paddle", url="https://github.com/PaddlePaddle/x2paddle",
...@@ -23,6 +22,4 @@ setuptools.setup( ...@@ -23,6 +22,4 @@ setuptools.setup(
"Operating System :: OS Independent", "Operating System :: OS Independent",
], ],
license='Apache 2.0', license='Apache 2.0',
entry_points={'console_scripts': [ entry_points={'console_scripts': ['x2paddle=x2paddle.convert:main', ]})
'x2paddle=x2paddle.convert:main',
]})
...@@ -5,12 +5,14 @@ model_dir = sys.argv[1] ...@@ -5,12 +5,14 @@ model_dir = sys.argv[1]
new_model_dir = sys.argv[2] new_model_dir = sys.argv[2]
exe = fluid.Executor(fluid.CPUPlace()) exe = fluid.Executor(fluid.CPUPlace())
[inference_program, feed_target_names, [inference_program, feed_target_names,
fetch_targets] = fluid.io.load_inference_model(dirname=model_dir, executor=exe) fetch_targets] = fluid.io.load_inference_model(
dirname=model_dir, executor=exe)
print(feed_target_names) print(feed_target_names)
fluid.io.save_inference_model(dirname=new_model_dir, fluid.io.save_inference_model(
feeded_var_names=feed_target_names, dirname=new_model_dir,
target_vars=fetch_targets, feeded_var_names=feed_target_names,
executor=exe, target_vars=fetch_targets,
main_program=inference_program, executor=exe,
params_filename="__params__") main_program=inference_program,
params_filename="__params__")
__version__ = "0.7.1" __version__ = "0.7.4"
# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
# #
# Licensed under the Apache License, Version 2.0 (the "License" # Licensed under the Apache License, Version 2.0 (the "License"
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
...@@ -19,32 +19,37 @@ import sys ...@@ -19,32 +19,37 @@ import sys
def arg_parser(): def arg_parser():
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument("--model", parser.add_argument(
"-m", "--model",
type=_text_type, "-m",
default=None, type=_text_type,
help="define model file path for tensorflow or onnx") default=None,
parser.add_argument("--prototxt", help="define model file path for tensorflow or onnx")
"-p", parser.add_argument(
type=_text_type, "--prototxt",
default=None, "-p",
help="prototxt file of caffe model") type=_text_type,
parser.add_argument("--weight", default=None,
"-w", help="prototxt file of caffe model")
type=_text_type, parser.add_argument(
default=None, "--weight",
help="weight file of caffe model") "-w",
parser.add_argument("--save_dir", type=_text_type,
"-s", default=None,
type=_text_type, help="weight file of caffe model")
default=None, parser.add_argument(
help="path to save translated model") "--save_dir",
"-s",
type=_text_type,
default=None,
help="path to save translated model")
parser.add_argument( parser.add_argument(
"--framework", "--framework",
"-f", "-f",
type=_text_type, type=_text_type,
default=None, default=None,
help="define which deeplearning framework(tensorflow/caffe/onnx)") help="define which deeplearning framework(tensorflow/caffe/onnx/paddle2onnx)"
)
parser.add_argument( parser.add_argument(
"--caffe_proto", "--caffe_proto",
"-c", "-c",
...@@ -52,27 +57,30 @@ def arg_parser(): ...@@ -52,27 +57,30 @@ def arg_parser():
default=None, default=None,
help="optional: the .py file compiled by caffe proto file of caffe model" help="optional: the .py file compiled by caffe proto file of caffe model"
) )
parser.add_argument("--version", parser.add_argument(
"-v", "--version",
action="store_true", "-v",
default=False, action="store_true",
help="get version of x2paddle") default=False,
help="get version of x2paddle")
parser.add_argument( parser.add_argument(
"--without_data_format_optimization", "--without_data_format_optimization",
"-wo", "-wo",
action="store_true", action="store_true",
default=False, default=False,
help="tf model conversion without data format optimization") help="tf model conversion without data format optimization")
parser.add_argument("--define_input_shape", parser.add_argument(
"-d", "--define_input_shape",
action="store_true", "-d",
default=False, action="store_true",
help="define input shape for tf model") default=False,
parser.add_argument("--params_merge", help="define input shape for tf model")
"-pm", parser.add_argument(
action="store_true", "--params_merge",
default=False, "-pm",
help="define whether merge the params") action="store_true",
default=False,
help="define whether merge the params")
return parser return parser
...@@ -117,7 +125,6 @@ def tf2paddle(model_path, ...@@ -117,7 +125,6 @@ def tf2paddle(model_path,
optimizer.merge_bias() optimizer.merge_bias()
optimizer.optimize_sub_graph() optimizer.optimize_sub_graph()
# optimizer.merge_batch_norm() # optimizer.merge_batch_norm()
# optimizer.merge_prelu() # optimizer.merge_prelu()
else: else:
...@@ -177,6 +184,14 @@ def onnx2paddle(model_path, save_dir, params_merge=False): ...@@ -177,6 +184,14 @@ def onnx2paddle(model_path, save_dir, params_merge=False):
mapper.save_inference_model(save_dir, params_merge) mapper.save_inference_model(save_dir, params_merge)
def paddle2onnx(model_path, save_dir):
from x2paddle.decoder.paddle_decoder import PaddleDecoder
from x2paddle.op_mapper.paddle_op_mapper import PaddleOpMapper
model = PaddleDecoder(model_path, '__model__', '__params__')
mapper = PaddleOpMapper()
mapper.convert(model.program, save_dir)
def main(): def main():
if len(sys.argv) < 2: if len(sys.argv) < 2:
print("Use \"x2paddle -h\" to print the help information") print("Use \"x2paddle -h\" to print the help information")
...@@ -249,8 +264,14 @@ def main(): ...@@ -249,8 +264,14 @@ def main():
if args.params_merge: if args.params_merge:
params_merge = True params_merge = True
onnx2paddle(args.model, args.save_dir, params_merge) onnx2paddle(args.model, args.save_dir, params_merge)
elif args.framework == "paddle2onnx":
assert args.model is not None, "--model should be defined while translating paddle model to onnx"
paddle2onnx(args.model, args.save_dir)
else: else:
raise Exception("--framework only support tensorflow/caffe/onnx now") raise Exception(
"--framework only support tensorflow/caffe/onnx/paddle2onnx now")
if __name__ == "__main__": if __name__ == "__main__":
......
...@@ -46,8 +46,9 @@ class Layer(object): ...@@ -46,8 +46,9 @@ class Layer(object):
for input in self.inputs: for input in self.inputs:
if isinstance(input, GraphNode): if isinstance(input, GraphNode):
if hasattr(input, "index"): if hasattr(input, "index"):
in_list += (input.layer_name + in_list += (
"[{}]".format(input.index) + ", ") input.layer_name + "[{}]".format(input.index) + ", "
)
else: else:
in_list += (input.layer_name + ", ") in_list += (input.layer_name + ", ")
elif isinstance(input, six.string_types): elif isinstance(input, six.string_types):
...@@ -71,8 +72,8 @@ class Layer(object): ...@@ -71,8 +72,8 @@ class Layer(object):
layer_code = layer_code + key + "={}, ".format(input) layer_code = layer_code + key + "={}, ".format(input)
elif isinstance(self.inputs, GraphNode): elif isinstance(self.inputs, GraphNode):
if hasattr(self.inputs, "index"): if hasattr(self.inputs, "index"):
layer_code += (self.inputs.layer_name + layer_code += (
"[{}]".format(self.inputs.index)) self.inputs.layer_name + "[{}]".format(self.inputs.index))
else: else:
layer_code += (self.inputs.layer_name) layer_code += (self.inputs.layer_name)
if self.op != "=": if self.op != "=":
...@@ -88,6 +89,8 @@ class Layer(object): ...@@ -88,6 +89,8 @@ class Layer(object):
for key, value in param_attr.items(): for key, value in param_attr.items():
if '\n' in str(value): if '\n' in str(value):
value = string(str(value).replace('\n', ',')) value = string(str(value).replace('\n', ','))
if str(key) == 'attr':
value = 'ParamAttr(' + str(value) + ')'
layer_code = layer_code + key + "={}, ".format(value) layer_code = layer_code + key + "={}, ".format(value)
layer_code = layer_code.strip(", ") layer_code = layer_code.strip(", ")
......
...@@ -64,10 +64,8 @@ def run_net(param_dir="./"): ...@@ -64,10 +64,8 @@ def run_net(param_dir="./"):
b = os.path.exists(os.path.join(param_dir, var.name)) b = os.path.exists(os.path.join(param_dir, var.name))
return b return b
fluid.io.load_vars(exe, fluid.io.load_vars(
param_dir, exe, param_dir, fluid.default_main_program(), predicate=if_exist)
fluid.default_main_program(),
predicate=if_exist)
class OpMapper(object): class OpMapper(object):
...@@ -98,8 +96,8 @@ class OpMapper(object): ...@@ -98,8 +96,8 @@ class OpMapper(object):
def add_codes(self, codes, indent=0): def add_codes(self, codes, indent=0):
if isinstance(codes, list): if isinstance(codes, list):
for code in codes: for code in codes:
self.paddle_codes += (self.tab * indent + code.strip('\n') + self.paddle_codes += (
'\n') self.tab * indent + code.strip('\n') + '\n')
elif isinstance(codes, str): elif isinstance(codes, str):
self.paddle_codes += (self.tab * indent + codes.strip('\n') + '\n') self.paddle_codes += (self.tab * indent + codes.strip('\n') + '\n')
else: else:
...@@ -135,24 +133,25 @@ class OpMapper(object): ...@@ -135,24 +133,25 @@ class OpMapper(object):
os.path.join(os.path.join(py_code_dir, var.name))) os.path.join(os.path.join(py_code_dir, var.name)))
return b return b
fluid.io.load_vars(exe, fluid.io.load_vars(
py_code_dir, exe,
fluid.default_main_program(), py_code_dir,
predicate=if_exist) fluid.default_main_program(),
predicate=if_exist)
if params_merge: if params_merge:
fluid.io.save_inference_model(dirname=os.path.join( fluid.io.save_inference_model(
save_dir, "inference_model"), dirname=os.path.join(save_dir, "inference_model"),
feeded_var_names=input_names, feeded_var_names=input_names,
target_vars=outputs, target_vars=outputs,
executor=exe, executor=exe,
params_filename="__params__") params_filename="__params__")
else: else:
fluid.io.save_inference_model(dirname=os.path.join( fluid.io.save_inference_model(
save_dir, "inference_model"), dirname=os.path.join(save_dir, "inference_model"),
feeded_var_names=input_names, feeded_var_names=input_names,
target_vars=outputs, target_vars=outputs,
executor=exe, executor=exe,
params_filename=None) params_filename=None)
except: except:
raise Exception( raise Exception(
"Paddle code was saved in {}/model.py, but seems there's wrong exist, please check model.py manually." "Paddle code was saved in {}/model.py, but seems there's wrong exist, please check model.py manually."
......
...@@ -49,13 +49,11 @@ class CaffeResolver(object): ...@@ -49,13 +49,11 @@ class CaffeResolver(object):
class CaffeGraphNode(GraphNode): class CaffeGraphNode(GraphNode):
def __init__(self, layer, type_str, layer_name=None): def __init__(self, layer, type_str, layer_name=None):
if layer_name is None: if layer_name is None:
super(CaffeGraphNode, super(CaffeGraphNode, self).__init__(
self).__init__(layer, layer, layer.name.replace('/', '_').replace('-', '_'))
layer.name.replace('/', '_').replace('-', '_'))
else: else:
super(CaffeGraphNode, super(CaffeGraphNode, self).__init__(
self).__init__(layer, layer, layer_name.replace('/', '_').replace('-', '_'))
layer_name.replace('/', '_').replace('-', '_'))
self.layer_type = type_str self.layer_type = type_str
self.fluid_code = FluidCode() self.fluid_code = FluidCode()
self.data = None self.data = None
...@@ -268,8 +266,8 @@ class CaffeDecoder(object): ...@@ -268,8 +266,8 @@ class CaffeDecoder(object):
c_i = blob.channels c_i = blob.channels
h = blob.height h = blob.height
w = blob.width w = blob.width
data = np.asarray(list(blob.data), data = np.asarray(
dtype=np.float32).reshape(c_o, c_i, h, w) list(blob.data), dtype=np.float32).reshape(c_o, c_i, h, w)
transformed.append(data) transformed.append(data)
return transformed return transformed
此差异已折叠。
...@@ -71,9 +71,8 @@ class ONNXGraphNode(GraphNode): ...@@ -71,9 +71,8 @@ class ONNXGraphNode(GraphNode):
if attr.type == onnx.AttributeProto.TENSOR: if attr.type == onnx.AttributeProto.TENSOR:
dtype = np.dtype(TENSOR_TYPE_TO_NP_TYPE[attr.t.data_type]) dtype = np.dtype(TENSOR_TYPE_TO_NP_TYPE[attr.t.data_type])
data = attr.t.raw_data data = attr.t.raw_data
value = np.frombuffer(data, value = np.frombuffer(
dtype=dtype, data, dtype=dtype, count=(len(data) // dtype.itemsize))
count=(len(data) // dtype.itemsize))
elif attr.type == onnx.AttributeProto.STRING: elif attr.type == onnx.AttributeProto.STRING:
value = attr.s value = attr.s
value = value.decode() if isinstance(value, bytes) else value value = value.decode() if isinstance(value, bytes) else value
...@@ -205,9 +204,8 @@ class ONNXGraph(Graph): ...@@ -205,9 +204,8 @@ class ONNXGraph(Graph):
self.node_map[name].weight = weight self.node_map[name].weight = weight
self.node_map[name].embeded_as = [] self.node_map[name].embeded_as = []
else: else:
self.node_map[name] = ONNXGraphDataNode(initializer, self.node_map[name] = ONNXGraphDataNode(
layer_name=name, initializer, layer_name=name, is_global_input=False)
is_global_input=False)
self.node_map[name].weight = weight self.node_map[name].weight = weight
self.node_map[name].embeded_as = [] self.node_map[name].embeded_as = []
...@@ -494,8 +492,8 @@ class ONNXDecoder(object): ...@@ -494,8 +492,8 @@ class ONNXDecoder(object):
sess = rt.InferenceSession(model_path) sess = rt.InferenceSession(model_path)
for ipt in sess.get_inputs(): for ipt in sess.get_inputs():
datatype = datatype_map[ipt.type] datatype = datatype_map[ipt.type]
input_dict[ipt.name] = np.random.random( input_dict[ipt.name] = np.random.random(ipt.shape).astype(
ipt.shape).astype(datatype) datatype)
res = sess.run(None, input_feed=input_dict) res = sess.run(None, input_feed=input_dict)
except: except:
......
# 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 paddle.fluid as fluid
class PaddleDecoder(object):
def __init__(self,
model_dir,
model_filename='__model__',
params_filename=None):
exe = fluid.Executor(fluid.CPUPlace())
[self.program, feed, fetchs] = fluid.io.load_inference_model(
model_dir,
exe,
model_filename=model_filename,
params_filename=params_filename)
...@@ -120,13 +120,13 @@ class TFGraph(Graph): ...@@ -120,13 +120,13 @@ class TFGraph(Graph):
def build(self): def build(self):
for layer in self.model.node: for layer in self.model.node:
self.node_map[layer.name.replace('/', '_').replace( self.node_map[layer.name.replace('/', '_').replace(
'-', '_')] = TFGraphNode(layer, data_format=self.tf_data_format) '-', '_')] = TFGraphNode(
layer, data_format=self.tf_data_format)
for layer_name, node in self.node_map.items(): for layer_name, node in self.node_map.items():
for in_node in node.layer.input: for in_node in node.layer.input:
in_node = in_node.replace('/', in_node = in_node.replace('/', '_').replace('-', '_').replace(
'_').replace('-', '^', '')
'_').replace('^', '')
if in_node not in self.node_map: if in_node not in self.node_map:
if in_node.strip().split(':')[0] in self.node_map: if in_node.strip().split(':')[0] in self.node_map:
self.connect(in_node.strip().split(':')[0], layer_name) self.connect(in_node.strip().split(':')[0], layer_name)
...@@ -390,10 +390,10 @@ class TFDecoder(object): ...@@ -390,10 +390,10 @@ class TFDecoder(object):
shape=shape, shape=shape,
name="x2paddle_{}".format(layer.name)) name="x2paddle_{}".format(layer.name))
except: except:
x2paddle_input = tf.placeholder(dtype=dtype, x2paddle_input = tf.placeholder(
shape=shape, dtype=dtype,
name="x2paddle_{}".format( shape=shape,
layer.name)) name="x2paddle_{}".format(layer.name))
input_map["{}:0".format(layer.name)] = x2paddle_input input_map["{}:0".format(layer.name)] = x2paddle_input
if shape.count(None) > 0: if shape.count(None) > 0:
......
...@@ -122,16 +122,17 @@ def convolutiondepthwise_layer(inputs, ...@@ -122,16 +122,17 @@ def convolutiondepthwise_layer(inputs,
c_out = num_output if num_output is not None else 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 / group = int(c_in / (c_in / c_out)) if c_in > c_out else int(c_in /
(c_out / c_in)) (c_out / c_in))
out = fluid.layers.conv2d(input, out = fluid.layers.conv2d(
dilation=[dila_h, dila_w], input,
filter_size=[k_h, k_w], dilation=[dila_h, dila_w],
stride=[s_h, s_w], filter_size=[k_h, k_w],
padding=[p_h, p_w], stride=[s_h, s_w],
groups=group, padding=[p_h, p_w],
num_filters=c_out, groups=group,
param_attr=name + '_weights', num_filters=c_out,
bias_attr=name + '_bias', param_attr=name + '_weights',
name=name) bias_attr=name + '_bias',
name=name)
return out return out
...@@ -142,7 +143,8 @@ def convolutiondepthwise_weights(name, data=None): ...@@ -142,7 +143,8 @@ def convolutiondepthwise_weights(name, data=None):
return weights_name return weights_name
register(kind='ConvolutionDepthwise', register(
shape=convolutiondepthwise_shape, kind='ConvolutionDepthwise',
layer=convolutiondepthwise_layer, shape=convolutiondepthwise_shape,
weights=convolutiondepthwise_weights) layer=convolutiondepthwise_layer,
weights=convolutiondepthwise_weights)
...@@ -37,8 +37,8 @@ def detectionoutput_layer(inputs, ...@@ -37,8 +37,8 @@ def detectionoutput_layer(inputs,
pbv = fluid.layers.reshape(x=pbv, shape=[-1, 4]) pbv = fluid.layers.reshape(x=pbv, shape=[-1, 4])
mbox_loc = inputs[0] mbox_loc = inputs[0]
mbox_loc = fluid.layers.reshape(x=mbox_loc, shape=[-1, pb.shape[0], 4]) mbox_loc = fluid.layers.reshape(x=mbox_loc, shape=[-1, pb.shape[0], 4])
mbox_conf_flatten = fluid.layers.reshape(x=mbox_conf_flatten, mbox_conf_flatten = fluid.layers.reshape(
shape=[0, pb.shape[0], -1]) x=mbox_conf_flatten, shape=[0, pb.shape[0], -1])
default = {"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'] fields = ['eta', 'top_k', 'nms_threshold']
...@@ -64,7 +64,8 @@ def detectionoutput_weights(name, data=None): ...@@ -64,7 +64,8 @@ def detectionoutput_weights(name, data=None):
return weights_name return weights_name
register(kind='DetectionOutput', register(
shape=detectionoutput_shape, kind='DetectionOutput',
layer=detectionoutput_layer, shape=detectionoutput_shape,
weights=detectionoutput_weights) layer=detectionoutput_layer,
weights=detectionoutput_weights)
...@@ -20,9 +20,8 @@ def normalize_layer(inputs, ...@@ -20,9 +20,8 @@ def normalize_layer(inputs,
attr=name + '_scale') attr=name + '_scale')
scale_param = fluid.layers.reshape(x=scale_param, \ scale_param = fluid.layers.reshape(x=scale_param, \
shape=[1] if channel_shared else [input_shape[0][1]]) shape=[1] if channel_shared else [input_shape[0][1]])
out = fluid.layers.elementwise_mul(x=l2_norm, out = fluid.layers.elementwise_mul(
y=scale_param, x=l2_norm, y=scale_param, axis=-1 if channel_shared else 1)
axis=-1 if channel_shared else 1)
return out return out
...@@ -31,7 +30,8 @@ def normalize_weights(name, data=None): ...@@ -31,7 +30,8 @@ def normalize_weights(name, data=None):
return weights_name return weights_name
register(kind='Normalize', register(
shape=normalize_shape, kind='Normalize',
layer=normalize_layer, shape=normalize_shape,
weights=normalize_weights) layer=normalize_layer,
weights=normalize_weights)
...@@ -23,7 +23,8 @@ def permute_weights(name, data=None): ...@@ -23,7 +23,8 @@ def permute_weights(name, data=None):
return weights_name return weights_name
register(kind='Permute', register(
shape=permute_shape, kind='Permute',
layer=permute_layer, shape=permute_shape,
weights=permute_weights) layer=permute_layer,
weights=permute_weights)
...@@ -30,18 +30,19 @@ def priorbox_layer(inputs, ...@@ -30,18 +30,19 @@ def priorbox_layer(inputs,
steps = tuple(step) if type(step) is list or type(step) is tuple else (step, steps = tuple(step) if type(step) is list or type(step) is tuple else (step,
step) step)
box, variance_ = fluid.layers.prior_box(input, box, variance_ = fluid.layers.prior_box(
image, input,
min_sizes=min_size, image,
max_sizes=max_size, min_sizes=min_size,
aspect_ratios=aspect_ratio, max_sizes=max_size,
variance=variance, aspect_ratios=aspect_ratio,
flip=flip, variance=variance,
clip=clip, flip=flip,
steps=steps, clip=clip,
offset=offset, steps=steps,
name=name, offset=offset,
min_max_aspect_ratios_order=True) name=name,
min_max_aspect_ratios_order=True)
box = fluid.layers.reshape(box, [1, 1, -1]) box = fluid.layers.reshape(box, [1, 1, -1])
variance_ = fluid.layers.reshape(variance_, [1, 1, -1]) variance_ = fluid.layers.reshape(variance_, [1, 1, -1])
out = fluid.layers.concat([box, variance_], axis=1) out = fluid.layers.concat([box, variance_], axis=1)
...@@ -53,7 +54,8 @@ def priorbox_weights(name, data=None): ...@@ -53,7 +54,8 @@ def priorbox_weights(name, data=None):
return weights_name return weights_name
register(kind='PriorBox', register(
shape=priorbox_shape, kind='PriorBox',
layer=priorbox_layer, shape=priorbox_shape,
weights=priorbox_weights) layer=priorbox_layer,
weights=priorbox_weights)
...@@ -23,8 +23,7 @@ def register(kind, shape, layer, weights): ...@@ -23,8 +23,7 @@ def register(kind, shape, layer, weights):
kind = [kind] kind = [kind]
else: else:
assert type( assert type(
kind kind) is list, 'invalid param "kind" for register, not a list or str'
) is list, 'invalid param "kind" for register, not a list or str'
for k in kind: for k in kind:
assert type( assert type(
......
...@@ -21,11 +21,12 @@ def roipooling_layer(inputs, ...@@ -21,11 +21,12 @@ def roipooling_layer(inputs,
input = inputs[0] input = inputs[0]
roi = inputs[1] roi = inputs[1]
roi = fluid.layers.slice(roi, axes=[1], starts=[1], ends=[5]) roi = fluid.layers.slice(roi, axes=[1], starts=[1], ends=[5])
out = fluid.layers.roi_pool(input, out = fluid.layers.roi_pool(
roi, input,
pooled_height=pooled_h, roi,
pooled_width=pooled_w, pooled_height=pooled_h,
spatial_scale=spatial_scale) pooled_width=pooled_w,
spatial_scale=spatial_scale)
return out return out
...@@ -34,7 +35,8 @@ def roipooling_weights(name, data=None): ...@@ -34,7 +35,8 @@ def roipooling_weights(name, data=None):
return weights_name return weights_name
register(kind='ROIPooling', register(
shape=roipooling_shape, kind='ROIPooling',
layer=roipooling_layer, shape=roipooling_shape,
weights=roipooling_weights) layer=roipooling_layer,
weights=roipooling_weights)
...@@ -30,11 +30,12 @@ def select_layer(inputs, ...@@ -30,11 +30,12 @@ def select_layer(inputs,
out = [] out = []
for i in range(len(slice_point)): for i in range(len(slice_point)):
out.append( out.append(
fluid.layers.slice(input, fluid.layers.slice(
axes=[axis], input,
starts=[slice_point[i]], axes=[axis],
ends=[slice_point[i + 1]], starts=[slice_point[i]],
name=name + '_' + str(i))) ends=[slice_point[i + 1]],
name=name + '_' + str(i)))
if i == len(slice_point) - 2: if i == len(slice_point) - 2:
break break
return out return out
...@@ -45,7 +46,8 @@ def select_weights(name, data=None): ...@@ -45,7 +46,8 @@ def select_weights(name, data=None):
return weights_name return weights_name
register(kind='Select', register(
shape=select_shape, kind='Select',
layer=select_layer, shape=select_shape,
weights=select_weights) layer=select_layer,
weights=select_weights)
...@@ -17,7 +17,8 @@ def shufflechannel_weights(name, data=None): ...@@ -17,7 +17,8 @@ def shufflechannel_weights(name, data=None):
return weights_name return weights_name
register(kind='ShuffleChannel', register(
shape=shufflechannel_shape, kind='ShuffleChannel',
layer=shufflechannel_layer, shape=shufflechannel_shape,
weights=shufflechannel_weights) layer=shufflechannel_layer,
weights=shufflechannel_weights)
...@@ -33,8 +33,8 @@ def get_kernel_parameters(params): ...@@ -33,8 +33,8 @@ def get_kernel_parameters(params):
[s_h, s_w] = [params.stride] * 2 [s_h, s_w] = [params.stride] * 2
elif len(params.stride) > 0: elif len(params.stride) > 0:
s_h = params.stride_h if params.stride_h > 0 else 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[ s_w = params.stride_w if params.stride_w > 0 else params.stride[len(
len(params.stride) - 1] params.stride) - 1]
elif params.stride_h > 0 or params.stride_w > 0: elif params.stride_h > 0 or params.stride_w > 0:
s_h = params.stride_h s_h = params.stride_h
s_w = params.stride_w s_w = params.stride_w
......
...@@ -24,21 +24,18 @@ def InstanceNormalization_layer(inputs, name=None): ...@@ -24,21 +24,18 @@ def InstanceNormalization_layer(inputs, name=None):
epsilon = 1e-5 epsilon = 1e-5
input_ = inputs[0] input_ = inputs[0]
mean = fluid.layers.reduce_mean(input_, dim=[2, 3], keep_dim=True) mean = fluid.layers.reduce_mean(input_, dim=[2, 3], keep_dim=True)
var = fluid.layers.reduce_mean(fluid.layers.square(input_ - mean), var = fluid.layers.reduce_mean(
dim=[2, 3], fluid.layers.square(input_ - mean), dim=[2, 3], keep_dim=True)
keep_dim=True)
if name is not None: if name is not None:
scale_name = name + "_scale" scale_name = name + "_scale"
offset_name = name + "_offset" offset_name = name + "_offset"
scale_param = inputs[1] scale_param = inputs[1]
offset_param = inputs[2] offset_param = inputs[2]
scale = fluid.layers.create_parameter(name=scale_param.name, scale = fluid.layers.create_parameter(
shape=input_.shape[1:2], name=scale_param.name, shape=input_.shape[1:2], dtype="float32")
dtype="float32") offset = fluid.layers.create_parameter(
offset = fluid.layers.create_parameter(name=offset_param.name, name=offset_param.name, shape=input_.shape[1:2], dtype="float32")
shape=input_.shape[1:2],
dtype="float32")
tmp = fluid.layers.elementwise_mul(x=(input_ - mean), y=scale, axis=1) tmp = fluid.layers.elementwise_mul(x=(input_ - mean), y=scale, axis=1)
tmp = tmp / fluid.layers.sqrt(var + epsilon) tmp = tmp / fluid.layers.sqrt(var + epsilon)
...@@ -51,8 +48,9 @@ def InstanceNormalization_weights(name, data=None): ...@@ -51,8 +48,9 @@ def InstanceNormalization_weights(name, data=None):
return weights_name return weights_name
register(kind='InstanceNormalization', register(
shape=InstanceNormalization_shape, kind='InstanceNormalization',
layer=InstanceNormalization_layer, shape=InstanceNormalization_shape,
child_func=None, layer=InstanceNormalization_layer,
weights=InstanceNormalization_weights) child_func=None,
weights=InstanceNormalization_weights)
...@@ -36,8 +36,7 @@ def register(kind, shape, layer, child_func, weights): ...@@ -36,8 +36,7 @@ def register(kind, shape, layer, child_func, weights):
kind = [kind] kind = [kind]
else: else:
assert type( assert type(
kind kind) is list, 'invalid param "kind" for register, not a list or str'
) is list, 'invalid param "kind" for register, not a list or str'
for k in kind: for k in kind:
assert type( assert type(
......
...@@ -28,61 +28,55 @@ default_op_mapping_field_values['FILL_NAME_FIELD'] = True ...@@ -28,61 +28,55 @@ default_op_mapping_field_values['FILL_NAME_FIELD'] = True
default_op_mapping = { default_op_mapping = {
'Shape': ['shape', ['X'], ['Out']], 'Shape': ['shape', ['X'], ['Out']],
'Clip': [ 'Clip': [
'clip', ['X'], ['Out'], 'clip', ['X'], ['Out'], dict(), dict(
dict(), min=(_np.asarray(
dict( [255, 255, 127, 255], dtype=_np.uint8).view(_np.float32)[0]),
min=(_np.asarray([255, 255, 127, 255], max=(_np.asarray(
dtype=_np.uint8).view(_np.float32)[0]), [255, 255, 127, 127], dtype=_np.uint8).view(_np.float32)[0]), )
max=(_np.asarray([255, 255, 127, 127],
dtype=_np.uint8).view(_np.float32)[0]),
)
], ],
'Erf': ['erf', ['X'], ['Out']], 'Erf': ['erf', ['X'], ['Out']],
'Ceil': ['ceil', ['X'], ['Out']], 'Ceil': ['ceil', ['X'], ['Out']],
'ReduceMean': [ 'ReduceMean': [
'reduce_mean', ['X'], ['Out'], 'reduce_mean', ['X'], ['Out'], dict(
dict(axes='dim', keepdims='keep_dim'), axes='dim', keepdims='keep_dim'), dict(keep_dim=1)
dict(keep_dim=1)
], ],
'ReduceSum': [ 'ReduceSum': [
'reduce_sum', ['X'], ['Out'], 'reduce_sum', ['X'], ['Out'], dict(
dict(axes='dim', keepdims='keep_dim'), axes='dim', keepdims='keep_dim'), dict(keep_dim=1)
dict(keep_dim=1)
], ],
'ReduceMin': [ 'ReduceMin': [
'reduce_min', ['X'], ['Out'], 'reduce_min', ['X'], ['Out'], dict(
dict(axes='dim', keepdims='keep_dim'), axes='dim', keepdims='keep_dim'), dict(keep_dim=1)
dict(keep_dim=1) ],
'ReduceMax': [
'reduce_max', ['X'], ['Out'], dict(
axes='dim', keepdims='keep_dim'), dict(keep_dim=1)
], ],
#active function #active function
'Relu': ['relu', ['X'], ['Out']], 'Relu': ['relu', ['X'], ['Out']],
'LeakyRelu': ['leaky_relu', ['X'], ['Out'], 'LeakyRelu': ['leaky_relu', ['X'], ['Out'], dict(), dict(alpha=.01)],
dict(), dict(alpha=.01)], 'Elu': ['elu', ['X'], ['Out'], dict(), dict(alpha=1.)],
'Elu': ['elu', ['X'], ['Out'],
dict(), dict(alpha=1.)],
'ThresholdedRelu': [ 'ThresholdedRelu': [
'thresholded_relu', ['X'], ['Out'], 'thresholded_relu', ['X'], ['Out'], dict(alpha='threshold'),
dict(alpha='threshold'),
dict(alpha=1.) dict(alpha=1.)
], ],
'Tanh': ['tanh', ['X'], ['Out']], 'Tanh': ['tanh', ['X'], ['Out']],
'Sigmoid': ['sigmoid', ['X'], ['Out']], 'Sigmoid': ['sigmoid', ['X'], ['Out']],
'HardSigmoid': [ 'HardSigmoid': [
'hard_sigmoid', ['X'], ['Out'], 'hard_sigmoid', ['X'], ['Out'], dict(
dict(alpha='slope', beta='offset'), alpha='slope', beta='offset'), dict(
dict(slope=.2, offset=.5) slope=.2, offset=.5)
], ],
'Softsign': ['softsign', ['X'], ['Out']], 'Softsign': ['softsign', ['X'], ['Out']],
'Softplus': ['softplus', ['X'], ['Out']], 'Softplus': ['softplus', ['X'], ['Out']],
'Exp': ['exp', ['X'], ['Out']], 'Exp': ['exp', ['X'], ['Out']],
'Softmax': ['softmax', ['X'], ['Out'], 'Softmax': ['softmax', ['X'], ['Out'], dict(), dict(axis=1)],
dict(), dict(axis=1)],
'Sqrt': ['sqrt', ['X'], ['Out']], 'Sqrt': ['sqrt', ['X'], ['Out']],
'Floor': ['floor', ['X'], ['Out']], 'Floor': ['floor', ['X'], ['Out']],
'Abs': ['abs', ['X'], ['Out']], 'Abs': ['abs', ['X'], ['Out']],
} }
default_ioa_constraint = { default_ioa_constraint = {
'Gather': 'Gather': [(lambda i, o, a: a.get('axis', 0) == 0,
[(lambda i, o, a: a.get('axis', 0) == 0, 'only axis = 0 is supported')], 'only axis = 0 is supported')],
} }
import onnx
import numpy as np
from onnx import onnx_pb, helper
im2seq_counter = 0
def im2sequence(op, block):
global im2sequence_counter
n, c, h, w = block.var(op.input('X')[0]).shape
assert h > 0 and w > 0, "Only supported fixed input shape for im2sequence operator."
stride_h, stride_w = op.attr('strides')
paddings = op.attr('paddings')
assert op.attr(
'out_stride'
) != 1, "Only out_stride==1 is supported for im2sequence operator."
h = h + paddings[0] + paddings[1]
w = w + paddings[1] + paddings[2]
kernel_h, kernel_w = op.attr('kernels')
out_h = 1 + (h - kernel_h + stride_h - 1) // stride_h
out_w = 1 + (w - kernel_w + stride_w - 1) // stride_w
h_steps = list()
for i in range(out_h):
h_steps.append([i * stride_h, i * stride_h + kernel_h])
w_steps = list()
for i in range(out_w):
w_steps.append([i * stride_w, i * stride_w + kernel_w])
nodes = list()
slice_blocks = list()
for i in range(out_h):
for j in range(out_w):
starts_name = "im2sequence.starts.{}.{}.{}".format(im2seq_counter,
i, j)
starts_tensor = helper.make_tensor(
name=starts_name,
data_type=onnx_pb.TensorProto.INT64,
dims=[4],
vals=[0, 0, h_steps[i][0], w_steps[j][0]])
ends_name = "im2sequence.ends.{}.{}.{}".format(im2seq_counter, i, j)
ends_tensor = helper.make_tensor(
name=ends_name,
data_type=onnx_pb.TensorProto.INT64,
dims=[4],
vals=[999999, 999999, h_steps[i][1], w_steps[j][1]])
starts_node = helper.make_node(
'Constant',
inputs=[],
outputs=[starts_name],
value=starts_tensor)
ends_node = helper.make_node(
'Constant', inputs=[], outputs=[ends_name], value=ends_tensor)
nodes.extend([starts_node, ends_node])
slice_block_name = "im2sequence.slice.{}.{}.{}".format(
im2seq_counter, i, j)
slice_block_node = helper.make_node(
'Slice',
inputs=[op.input('X')[0], starts_name, ends_name],
outputs=[slice_block_name])
flatten_block_name = "im2sequence.flatten.{}.{}.{}".format(
im2seq_counter, i, j)
flatten_block_node = helper.make_node(
"Flatten",
inputs=[slice_block_name],
outputs=[flatten_block_name],
axis=0)
nodes.extend([slice_block_node, flatten_block_node])
slice_blocks.append(flatten_block_name)
concat_block_name = "im2sequence.concat_block.{}".format(im2seq_counter)
# concat_block_node = helper.make_node("Concat", inputs=slice_blocks, outputs=[concat_block_name], axis=0)
concat_block_node = helper.make_node(
"Concat", inputs=slice_blocks, outputs=op.output('Out'), axis=0)
nodes.append(concat_block_node)
print("\n\n==========Importance Notice===========")
print(
"Since im2sequence operator is used in your paddlepaddle model, the translated onnx model only support input data with batch_size=1."
)
print("======================================\n")
return nodes
# 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 sys
import os
import numpy as np
import paddle.fluid.core as core
import paddle.fluid as fluid
import onnx
import warnings
from onnx import helper, onnx_pb
def multiclass_nms(op, block):
"""
Convert the paddle multiclass_nms to onnx op.
This op is get the select boxes from origin boxes.
"""
inputs = dict()
outputs = dict()
attrs = dict()
for name in op.input_names:
inputs[name] = op.input(name)
for name in op.output_names:
outputs[name] = op.output(name)
for name in op.attr_names:
attrs[name] = op.attr(name)
result_name = outputs['Out'][0]
background = attrs['background_label']
normalized = attrs['normalized']
if normalized == False:
warnings.warn(
'The parameter normalized of multiclass_nms OP of Paddle is False, which has diff with ONNX. \
Please set normalized=True in multiclass_nms of Paddle')
#convert the paddle attribute to onnx tensor
name_score_threshold = [outputs['Out'][0] + "@score_threshold"]
name_iou_threshold = [outputs['Out'][0] + "@iou_threshold"]
name_keep_top_k = [outputs['Out'][0] + '@keep_top_k']
name_keep_top_k_2D = [outputs['Out'][0] + '@keep_top_k_1D']
node_score_threshold = onnx.helper.make_node(
'Constant',
inputs=[],
outputs=name_score_threshold,
value=onnx.helper.make_tensor(
name=name_score_threshold[0] + "@const",
data_type=onnx.TensorProto.FLOAT,
dims=(),
vals=[float(attrs['score_threshold'])]))
node_iou_threshold = onnx.helper.make_node(
'Constant',
inputs=[],
outputs=name_iou_threshold,
value=onnx.helper.make_tensor(
name=name_iou_threshold[0] + "@const",
data_type=onnx.TensorProto.FLOAT,
dims=(),
vals=[float(attrs['nms_threshold'])]))
node_keep_top_k = onnx.helper.make_node(
'Constant',
inputs=[],
outputs=name_keep_top_k,
value=onnx.helper.make_tensor(
name=name_keep_top_k[0] + "@const",
data_type=onnx.TensorProto.INT64,
dims=(),
vals=[np.int64(attrs['keep_top_k'])]))
node_keep_top_k_2D = onnx.helper.make_node(
'Constant',
inputs=[],
outputs=name_keep_top_k_2D,
value=onnx.helper.make_tensor(
name=name_keep_top_k_2D[0] + "@const",
data_type=onnx.TensorProto.INT64,
dims=[1, 1],
vals=[np.int64(attrs['keep_top_k'])]))
# the paddle data format is x1,y1,x2,y2
kwargs = {'center_point_box': 0}
name_select_nms = [outputs['Out'][0] + "@select_index"]
node_select_nms= onnx.helper.make_node(
'NonMaxSuppression',
inputs=inputs['BBoxes'] + inputs['Scores'] + name_keep_top_k +\
name_iou_threshold + name_score_threshold,
outputs=name_select_nms)
# step 1 nodes select the nms class
node_list = [
node_score_threshold, node_iou_threshold, node_keep_top_k,
node_keep_top_k_2D, node_select_nms
]
# create some const value to use
name_const_value = [result_name+"@const_0",
result_name+"@const_1",\
result_name+"@const_2",\
result_name+"@const_-1"]
value_const_value = [0, 1, 2, -1]
for name, value in zip(name_const_value, value_const_value):
node = onnx.helper.make_node(
'Constant',
inputs=[],
outputs=[name],
value=onnx.helper.make_tensor(
name=name + "@const",
data_type=onnx.TensorProto.INT64,
dims=[1],
vals=[value]))
node_list.append(node)
# Ine this code block, we will deocde the raw score data, reshape N * C * M to 1 * N*C*M
# and the same time, decode the select indices to 1 * D, gather the select_indices
outputs_gather_1 = [result_name + "@gather_1"]
node_gather_1 = onnx.helper.make_node(
'Gather',
inputs=name_select_nms + [result_name + "@const_1"],
outputs=outputs_gather_1,
axis=1)
node_list.append(node_gather_1)
outputs_squeeze_gather_1 = [result_name + "@sequeeze_gather_1"]
node_squeeze_gather_1 = onnx.helper.make_node(
'Squeeze',
inputs=outputs_gather_1,
outputs=outputs_squeeze_gather_1,
axes=[1])
node_list.append(node_squeeze_gather_1)
outputs_gather_2 = [result_name + "@gather_2"]
node_gather_2 = onnx.helper.make_node(
'Gather',
inputs=name_select_nms + [result_name + "@const_2"],
outputs=outputs_gather_2,
axis=1)
node_list.append(node_gather_2)
#slice the class is not 0
if background == 0:
outputs_nonzero = [result_name + "@nonzero"]
node_nonzero = onnx.helper.make_node(
'NonZero', inputs=outputs_squeeze_gather_1, outputs=outputs_nonzero)
node_list.append(node_nonzero)
else:
name_thresh = [result_name + "@thresh"]
node_thresh = onnx.helper.make_node(
'Constant',
inputs=[],
outputs=name_thresh,
value=onnx.helper.make_tensor(
name=name_thresh[0] + "@const",
data_type=onnx.TensorProto.INT32,
dims=[1],
vals=[-1]))
node_list.append(node_thresh)
outputs_cast = [result_name + "@cast"]
node_cast = onnx.helper.make_node(
'Cast', inputs=outputs_squeeze_gather_1, outputs=outputs_cast, to=6)
node_list.append(node_cast)
outputs_greater = [result_name + "@greater"]
node_greater = onnx.helper.make_node(
'Greater',
inputs=outputs_cast + name_thresh,
outputs=outputs_greater)
node_list.append(node_greater)
outputs_nonzero = [result_name + "@nonzero"]
node_nonzero = onnx.helper.make_node(
'NonZero', inputs=outputs_greater, outputs=outputs_nonzero)
node_list.append(node_nonzero)
outputs_gather_1_nonzero = [result_name + "@gather_1_nonzero"]
node_gather_1_nonzero = onnx.helper.make_node(
'Gather',
inputs=outputs_gather_1 + outputs_nonzero,
outputs=outputs_gather_1_nonzero,
axis=0)
node_list.append(node_gather_1_nonzero)
outputs_gather_2_nonzero = [result_name + "@gather_2_nonzero"]
node_gather_2_nonzero = onnx.helper.make_node(
'Gather',
inputs=outputs_gather_2 + outputs_nonzero,
outputs=outputs_gather_2_nonzero,
axis=0)
node_list.append(node_gather_2_nonzero)
# reshape scores N * C * M to (N*C*M) * 1
outputs_reshape_scores_rank1 = [result_name + "@reshape_scores_rank1"]
node_reshape_scores_rank1 = onnx.helper.make_node(
"Reshape",
inputs=inputs['Scores'] + [result_name + "@const_-1"],
outputs=outputs_reshape_scores_rank1)
node_list.append(node_reshape_scores_rank1)
# get the shape of scores
outputs_shape_scores = [result_name + "@shape_scores"]
node_shape_scores = onnx.helper.make_node(
'Shape', inputs=inputs['Scores'], outputs=outputs_shape_scores)
node_list.append(node_shape_scores)
# gather the index: 2 shape of scores
outputs_gather_scores_dim1 = [result_name + "@gather_scores_dim1"]
node_gather_scores_dim1 = onnx.helper.make_node(
'Gather',
inputs=outputs_shape_scores + [result_name + "@const_2"],
outputs=outputs_gather_scores_dim1,
axis=0)
node_list.append(node_gather_scores_dim1)
# mul class * M
outputs_mul_classnum_boxnum = [result_name + "@mul_classnum_boxnum"]
node_mul_classnum_boxnum = onnx.helper.make_node(
'Mul',
inputs=outputs_gather_1_nonzero + outputs_gather_scores_dim1,
outputs=outputs_mul_classnum_boxnum)
node_list.append(node_mul_classnum_boxnum)
# add class * M * index
outputs_add_class_M_index = [result_name + "@add_class_M_index"]
node_add_class_M_index = onnx.helper.make_node(
'Add',
inputs=outputs_mul_classnum_boxnum + outputs_gather_2_nonzero,
outputs=outputs_add_class_M_index)
node_list.append(node_add_class_M_index)
# Squeeze the indices to 1 dim
outputs_squeeze_select_index = [result_name + "@squeeze_select_index"]
node_squeeze_select_index = onnx.helper.make_node(
'Squeeze',
inputs=outputs_add_class_M_index,
outputs=outputs_squeeze_select_index,
axes=[0, 2])
node_list.append(node_squeeze_select_index)
# gather the data from flatten scores
outputs_gather_select_scores = [result_name + "@gather_select_scores"]
node_gather_select_scores = onnx.helper.make_node('Gather',
inputs=outputs_reshape_scores_rank1 + \
outputs_squeeze_select_index,
outputs=outputs_gather_select_scores,
axis=0)
node_list.append(node_gather_select_scores)
# get nums to input TopK
outputs_shape_select_num = [result_name + "@shape_select_num"]
node_shape_select_num = onnx.helper.make_node(
'Shape',
inputs=outputs_gather_select_scores,
outputs=outputs_shape_select_num)
node_list.append(node_shape_select_num)
outputs_gather_select_num = [result_name + "@gather_select_num"]
node_gather_select_num = onnx.helper.make_node(
'Gather',
inputs=outputs_shape_select_num + [result_name + "@const_0"],
outputs=outputs_gather_select_num,
axis=0)
node_list.append(node_gather_select_num)
outputs_unsqueeze_select_num = [result_name + "@unsqueeze_select_num"]
node_unsqueeze_select_num = onnx.helper.make_node(
'Unsqueeze',
inputs=outputs_gather_select_num,
outputs=outputs_unsqueeze_select_num,
axes=[0])
node_list.append(node_unsqueeze_select_num)
outputs_concat_topK_select_num = [result_name + "@conat_topK_select_num"]
node_conat_topK_select_num = onnx.helper.make_node(
'Concat',
inputs=outputs_unsqueeze_select_num + name_keep_top_k_2D,
outputs=outputs_concat_topK_select_num,
axis=0)
node_list.append(node_conat_topK_select_num)
outputs_cast_concat_topK_select_num = [
result_name + "@concat_topK_select_num"
]
node_outputs_cast_concat_topK_select_num = onnx.helper.make_node(
'Cast',
inputs=outputs_concat_topK_select_num,
outputs=outputs_cast_concat_topK_select_num,
to=6)
node_list.append(node_outputs_cast_concat_topK_select_num)
# get min(topK, num_select)
outputs_compare_topk_num_select = [result_name + "@compare_topk_num_select"]
node_compare_topk_num_select = onnx.helper.make_node(
'ReduceMin',
inputs=outputs_cast_concat_topK_select_num,
outputs=outputs_compare_topk_num_select,
keepdims=0)
node_list.append(node_compare_topk_num_select)
# unsqueeze the indices to 1D tensor
outputs_unsqueeze_topk_select_indices = [
result_name + "@unsqueeze_topk_select_indices"
]
node_unsqueeze_topk_select_indices = onnx.helper.make_node(
'Unsqueeze',
inputs=outputs_compare_topk_num_select,
outputs=outputs_unsqueeze_topk_select_indices,
axes=[0])
node_list.append(node_unsqueeze_topk_select_indices)
# cast the indices to INT64
outputs_cast_topk_indices = [result_name + "@cast_topk_indices"]
node_cast_topk_indices = onnx.helper.make_node(
'Cast',
inputs=outputs_unsqueeze_topk_select_indices,
outputs=outputs_cast_topk_indices,
to=7)
node_list.append(node_cast_topk_indices)
# select topk scores indices
outputs_topk_select_topk_indices = [result_name + "@topk_select_topk_values",\
result_name + "@topk_select_topk_indices"]
node_topk_select_topk_indices = onnx.helper.make_node(
'TopK',
inputs=outputs_gather_select_scores + outputs_cast_topk_indices,
outputs=outputs_topk_select_topk_indices)
node_list.append(node_topk_select_topk_indices)
# gather topk label, scores, boxes
outputs_gather_topk_scores = [result_name + "@gather_topk_scores"]
node_gather_topk_scores = onnx.helper.make_node(
'Gather',
inputs=outputs_gather_select_scores +
[outputs_topk_select_topk_indices[1]],
outputs=outputs_gather_topk_scores,
axis=0)
node_list.append(node_gather_topk_scores)
outputs_gather_topk_class = [result_name + "@gather_topk_class"]
node_gather_topk_class = onnx.helper.make_node(
'Gather',
inputs=outputs_gather_1_nonzero +
[outputs_topk_select_topk_indices[1]],
outputs=outputs_gather_topk_class,
axis=1)
node_list.append(node_gather_topk_class)
# gather the boxes need to gather the boxes id, then get boxes
outputs_gather_topk_boxes_id = [result_name + "@gather_topk_boxes_id"]
node_gather_topk_boxes_id = onnx.helper.make_node(
'Gather',
inputs=outputs_gather_2_nonzero +
[outputs_topk_select_topk_indices[1]],
outputs=outputs_gather_topk_boxes_id,
axis=1)
node_list.append(node_gather_topk_boxes_id)
# squeeze the gather_topk_boxes_id to 1 dim
outputs_squeeze_topk_boxes_id = [result_name + "@squeeze_topk_boxes_id"]
node_squeeze_topk_boxes_id = onnx.helper.make_node(
'Squeeze',
inputs=outputs_gather_topk_boxes_id,
outputs=outputs_squeeze_topk_boxes_id,
axes=[0, 2])
node_list.append(node_squeeze_topk_boxes_id)
outputs_gather_select_boxes = [result_name + "@gather_select_boxes"]
node_gather_select_boxes = onnx.helper.make_node(
'Gather',
inputs=inputs['BBoxes'] + outputs_squeeze_topk_boxes_id,
outputs=outputs_gather_select_boxes,
axis=1)
node_list.append(node_gather_select_boxes)
# concat the final result
# before concat need to cast the class to float
outputs_cast_topk_class = [result_name + "@cast_topk_class"]
node_cast_topk_class = onnx.helper.make_node(
'Cast',
inputs=outputs_gather_topk_class,
outputs=outputs_cast_topk_class,
to=1)
node_list.append(node_cast_topk_class)
outputs_unsqueeze_topk_scores = [result_name + "@unsqueeze_topk_scores"]
node_unsqueeze_topk_scores = onnx.helper.make_node(
'Unsqueeze',
inputs=outputs_gather_topk_scores,
outputs=outputs_unsqueeze_topk_scores,
axes=[0, 2])
node_list.append(node_unsqueeze_topk_scores)
inputs_concat_final_results = outputs_cast_topk_class + outputs_unsqueeze_topk_scores +\
outputs_gather_select_boxes
outputs_concat_final_results = outputs['Out']
node_concat_final_results = onnx.helper.make_node(
'Concat',
inputs=inputs_concat_final_results,
outputs=outputs_concat_final_results,
axis=2)
node_list.append(node_concat_final_results)
return node_list
此差异已折叠。
此差异已折叠。
此差异已折叠。
...@@ -41,10 +41,11 @@ class CaffeOptimizer(object): ...@@ -41,10 +41,11 @@ class CaffeOptimizer(object):
if is_delete_node: if is_delete_node:
parent_node.fluid_code.clear() parent_node.fluid_code.clear()
node.fluid_code.clear() node.fluid_code.clear()
node.fluid_code.add_layer("batch_norm", node.fluid_code.add_layer(
inputs=input, "batch_norm",
output=node, inputs=input,
param_attr=parent_param_attr) output=node,
param_attr=parent_param_attr)
def merge_op_activation(self): def merge_op_activation(self):
for node_name in self.graph.topo_sort: for node_name in self.graph.topo_sort:
...@@ -62,7 +63,8 @@ class CaffeOptimizer(object): ...@@ -62,7 +63,8 @@ class CaffeOptimizer(object):
if is_delete_node: if is_delete_node:
parent_node.fluid_code.clear() parent_node.fluid_code.clear()
node.fluid_code.clear() node.fluid_code.clear()
node.fluid_code.add_layer(op, node.fluid_code.add_layer(
inputs=input, op,
output=node, inputs=input,
param_attr=parent_param_attr) output=node,
param_attr=parent_param_attr)
...@@ -554,10 +554,11 @@ class TFOptimizer(object): ...@@ -554,10 +554,11 @@ class TFOptimizer(object):
node.fluid_code.layers[0].param_attr["shape"] = shape node.fluid_code.layers[0].param_attr["shape"] = shape
node.fluid_code.layers[0].output = "nhwc_" + name node.fluid_code.layers[0].output = "nhwc_" + name
attr = {"perm": [0, 2, 3, 1]} attr = {"perm": [0, 2, 3, 1]}
node.fluid_code.add_layer("transpose", node.fluid_code.add_layer(
inputs="nhwc_" + name, "transpose",
output=node, inputs="nhwc_" + name,
param_attr=attr) output=node,
param_attr=attr)
self.graph.input_nodes[i] = "nhwc_" + name self.graph.input_nodes[i] = "nhwc_" + name
for i, name in enumerate(self.graph.output_nodes): for i, name in enumerate(self.graph.output_nodes):
node = self.graph.get_node(name) node = self.graph.get_node(name)
...@@ -767,8 +768,8 @@ class TFOptimizer(object): ...@@ -767,8 +768,8 @@ class TFOptimizer(object):
is_prelu = False is_prelu = False
continue continue
if len(in_nodes0[0].outputs) != 1 or len( if len(in_nodes0[0].outputs) != 1 or len(in_nodes0[1]
in_nodes0[1].outputs) != 1: .outputs) != 1:
is_prelu = False is_prelu = False
continue continue
...@@ -777,8 +778,8 @@ class TFOptimizer(object): ...@@ -777,8 +778,8 @@ class TFOptimizer(object):
self.graph.get_node(in_name) self.graph.get_node(in_name)
for in_name in in_nodes0[1].inputs for in_name in in_nodes0[1].inputs
] ]
if in_nodes2[1].layer_type != "Const" or numpy.fabs( if in_nodes2[1].layer_type != "Const" or numpy.fabs(in_nodes2[
in_nodes2[1].value - 0.5) > 1e-06: 1].value - 0.5) > 1e-06:
is_prelu = False is_prelu = False
continue continue
if in_nodes2[0].layer_type != "Mul": if in_nodes2[0].layer_type != "Mul":
...@@ -787,8 +788,8 @@ class TFOptimizer(object): ...@@ -787,8 +788,8 @@ class TFOptimizer(object):
if exist_act(in_nodes2[0]): if exist_act(in_nodes2[0]):
is_prelu = False is_prelu = False
continue continue
if len(in_nodes2[1].outputs) != 1 or len( if len(in_nodes2[1].outputs) != 1 or len(in_nodes2[0]
in_nodes2[0].outputs) != 1: .outputs) != 1:
is_prelu = False is_prelu = False
continue continue
...@@ -803,8 +804,8 @@ class TFOptimizer(object): ...@@ -803,8 +804,8 @@ class TFOptimizer(object):
if exist_act(in_nodes3[1]): if exist_act(in_nodes3[1]):
is_prelu = False is_prelu = False
continue continue
if len(in_nodes3[0].outputs) != 1 or len( if len(in_nodes3[0].outputs) != 1 or len(in_nodes3[1]
in_nodes3[1].outputs) != 1: .outputs) != 1:
is_prelu = False is_prelu = False
continue continue
...@@ -856,12 +857,12 @@ class TFOptimizer(object): ...@@ -856,12 +857,12 @@ class TFOptimizer(object):
mode = "element" mode = "element"
elif len(in_nodes3[0].value.shape) == 0: elif len(in_nodes3[0].value.shape) == 0:
mode = "all" mode = "all"
elif len(in_nodes3[0].value.shape elif len(in_nodes3[0].value.shape) == 1 and in_nodes3[
) == 1 and in_nodes3[0].value.shape[0] == 1: 0].value.shape[0] == 1:
mode = "all" mode = "all"
elif len(in_shape) == 4 and len( elif len(in_shape) == 4 and len(in_nodes3[
in_nodes3[0].value.shape 0].value.shape) == 1 and in_nodes3[0].value.shape[
) == 1 and in_nodes3[0].value.shape[0] == in_shape[-1]: 0] == in_shape[-1]:
mode = "channel" mode = "channel"
weight = self.op_mapper.weights[in_nodes3[0].layer_name] weight = self.op_mapper.weights[in_nodes3[0].layer_name]
weight = numpy.expand_dims(weight, 0) weight = numpy.expand_dims(weight, 0)
...@@ -916,14 +917,15 @@ class TFOptimizer(object): ...@@ -916,14 +917,15 @@ class TFOptimizer(object):
self.graph.get_node(in_name) for in_name in node.inputs self.graph.get_node(in_name) for in_name in node.inputs
] ]
if in_nodes0[0].layer_type != "Mul" or in_nodes0[ if in_nodes0[0].layer_type != "Mul" or in_nodes0[
1].layer_type != "Const" or in_nodes0[1].value.size != 1: 1].layer_type != "Const" or in_nodes0[
1].value.size != 1:
is_scale = False is_scale = False
continue continue
if exist_act(in_nodes0[0]): if exist_act(in_nodes0[0]):
is_scale = False is_scale = False
continue continue
if len(in_nodes0[0].outputs) != 1 or len( if len(in_nodes0[0].outputs) != 1 or len(in_nodes0[1]
in_nodes0[1].outputs) != 1: .outputs) != 1:
is_scale = False is_scale = False
continue continue
...@@ -939,8 +941,8 @@ class TFOptimizer(object): ...@@ -939,8 +941,8 @@ class TFOptimizer(object):
if exist_act(in_nodes1[1]): if exist_act(in_nodes1[1]):
is_scale = False is_scale = False
continue continue
if len(in_nodes1[0].outputs) != 1 or len( if len(in_nodes1[0].outputs) != 1 or len(in_nodes1[1]
in_nodes1[1].outputs) != 1: .outputs) != 1:
is_scale = False is_scale = False
continue continue
...@@ -962,8 +964,8 @@ class TFOptimizer(object): ...@@ -962,8 +964,8 @@ class TFOptimizer(object):
scale = 1.0 / in_nodes2[1].value * in_nodes1[0].value scale = 1.0 / in_nodes2[1].value * in_nodes1[0].value
act = None act = None
if node.fluid_code.layers[0].param_attr is not None: if node.fluid_code.layers[0].param_attr is not None:
act = node.fluid_code.layers[0].param_attr.get( act = node.fluid_code.layers[0].param_attr.get("act",
"act", None) None)
node.fluid_code.clear() node.fluid_code.clear()
attr = { attr = {
...@@ -972,10 +974,8 @@ class TFOptimizer(object): ...@@ -972,10 +974,8 @@ class TFOptimizer(object):
"bias_after_scale": True, "bias_after_scale": True,
"act": act "act": act
} }
node.fluid_code.add_layer("scale", node.fluid_code.add_layer(
inputs=in_node, "scale", inputs=in_node, output=node, param_attr=attr)
output=node,
param_attr=attr)
del self.graph.node_map[in_nodes0[0].layer_name] del self.graph.node_map[in_nodes0[0].layer_name]
del self.graph.node_map[in_nodes0[1].layer_name] del self.graph.node_map[in_nodes0[1].layer_name]
...@@ -1004,17 +1004,17 @@ class TFOptimizer(object): ...@@ -1004,17 +1004,17 @@ class TFOptimizer(object):
if exist_act(in_nodes0[0]): if exist_act(in_nodes0[0]):
is_affine_channel = False is_affine_channel = False
continue continue
if len(in_nodes0[0].outputs) != 1 or len( if len(in_nodes0[0].outputs) != 1 or len(in_nodes0[1]
in_nodes0[1].outputs) != 1: .outputs) != 1:
is_affine_channel = False is_affine_channel = False
continue continue
in_nodes1 = [ in_nodes1 = [
self.graph.get_node(in_name) self.graph.get_node(in_name)
for in_name in in_nodes0[0].inputs for in_name in in_nodes0[0].inputs
] ]
if len(in_nodes1[0].out_shapes[0] if len(in_nodes1[0].out_shapes[0]) != 4 or in_nodes1[
) != 4 or in_nodes1[1].layer_type != "Const" or len( 1].layer_type != "Const" or len(in_nodes1[1]
in_nodes1[1].value.shape) != 3: .value.shape) != 3:
is_affine_channel = False is_affine_channel = False
continue continue
if len(in_nodes1[1].outputs) != 1: if len(in_nodes1[1].outputs) != 1:
...@@ -1037,8 +1037,8 @@ class TFOptimizer(object): ...@@ -1037,8 +1037,8 @@ class TFOptimizer(object):
node.layer_type = "AffineChannel" node.layer_type = "AffineChannel"
node.inputs = [in_node.layer_name] node.inputs = [in_node.layer_name]
scale = 1.0 / in_nodes0[1].value.flatten() scale = 1.0 / in_nodes0[1].value.flatten()
bias = in_nodes1[1].value.flatten( bias = in_nodes1[1].value.flatten() / in_nodes0[
) / in_nodes0[1].value.flatten() 1].value.flatten()
if not bias_add: if not bias_add:
bias *= -1.0 bias *= -1.0
self.op_mapper.weights[node.layer_name + "_scale"] = scale self.op_mapper.weights[node.layer_name + "_scale"] = scale
...@@ -1046,8 +1046,8 @@ class TFOptimizer(object): ...@@ -1046,8 +1046,8 @@ class TFOptimizer(object):
act = None act = None
if node.fluid_code.layers[0].param_attr is not None: if node.fluid_code.layers[0].param_attr is not None:
act = node.fluid_code.layers[0].param_attr.get( act = node.fluid_code.layers[0].param_attr.get("act",
"act", None) None)
node.fluid_code.clear() node.fluid_code.clear()
attr = { attr = {
...@@ -1055,29 +1055,32 @@ class TFOptimizer(object): ...@@ -1055,29 +1055,32 @@ class TFOptimizer(object):
"shape": [channel], "shape": [channel],
"name": string(node.layer_name + "_scale") "name": string(node.layer_name + "_scale")
} }
node.fluid_code.add_layer("create_parameter", node.fluid_code.add_layer(
inputs=None, "create_parameter",
output=node.layer_name + "_scale", inputs=None,
param_attr=attr) output=node.layer_name + "_scale",
param_attr=attr)
attr = { attr = {
"dtype": string(scale.dtype), "dtype": string(scale.dtype),
"shape": [channel], "shape": [channel],
"name": string(node.layer_name + "_bias") "name": string(node.layer_name + "_bias")
} }
node.fluid_code.add_layer("create_parameter", node.fluid_code.add_layer(
inputs=None, "create_parameter",
output=node.layer_name + "_bias", inputs=None,
param_attr=attr) output=node.layer_name + "_bias",
param_attr=attr)
inputs = { inputs = {
"x": in_node, "x": in_node,
"scale": node.layer_name + "_scale", "scale": node.layer_name + "_scale",
"bias": node.layer_name + "_bias" "bias": node.layer_name + "_bias"
} }
attr = {"act": act} attr = {"act": act}
node.fluid_code.add_layer("affine_channel", node.fluid_code.add_layer(
inputs=inputs, "affine_channel",
output=node, inputs=inputs,
param_attr=attr) output=node,
param_attr=attr)
del self.graph.node_map[in_nodes0[0].layer_name] del self.graph.node_map[in_nodes0[0].layer_name]
del self.graph.node_map[in_nodes0[1].layer_name] del self.graph.node_map[in_nodes0[1].layer_name]
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
| ShuffleNet | [code](https://github.com/TropComplique/shufflenet-v2-tensorflow) |-| | ShuffleNet | [code](https://github.com/TropComplique/shufflenet-v2-tensorflow) |-|
| mNASNet | [code](https://github.com/tensorflow/tpu/tree/master/models/official/mnasnet) |-| | mNASNet | [code](https://github.com/tensorflow/tpu/tree/master/models/official/mnasnet) |-|
| EfficientNet | [code](https://github.com/tensorflow/tpu/tree/master/models/official/efficientnet) |-| | EfficientNet | [code](https://github.com/tensorflow/tpu/tree/master/models/official/efficientnet) |-|
| Inception_V3 | [code](https://github.com/tensorflow/models/blob/master/research/slim/nets/inception_v3.py) |-|
| Inception_V4 | [code](https://github.com/tensorflow/models/blob/master/research/slim/nets/inception_v4.py) |-| | Inception_V4 | [code](https://github.com/tensorflow/models/blob/master/research/slim/nets/inception_v4.py) |-|
| Inception_ResNet_V2 | [code](https://github.com/tensorflow/models/blob/master/research/slim/nets/inception_resnet_v2.py) |-| | Inception_ResNet_V2 | [code](https://github.com/tensorflow/models/blob/master/research/slim/nets/inception_resnet_v2.py) |-|
| VGG16 | [code](https://github.com/tensorflow/models/tree/master/research/slim/nets) |-| | VGG16 | [code](https://github.com/tensorflow/models/tree/master/research/slim/nets) |-|
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册