diff --git a/x2paddle/convert.py b/x2paddle/convert.py index 458f9108ac800ad1918a454356215c9e0f63c818..d3503efa62d364cfe38a3f0cce125526fa15f036 100644 --- a/x2paddle/convert.py +++ b/x2paddle/convert.py @@ -178,7 +178,7 @@ def onnx2paddle(model_path, save_dir, params_merge=False): return print("Now translating model from onnx to paddle.") - from x2paddle.op_mapper.onnx_op_mapper import ONNXOpMapper + from x2paddle.op_mapper.onnx2paddle.onnx_op_mapper import ONNXOpMapper from x2paddle.decoder.onnx_decoder import ONNXDecoder from x2paddle.optimizer.onnx_optimizer import ONNXOptimizer model = ONNXDecoder(model_path) @@ -192,12 +192,12 @@ def onnx2paddle(model_path, save_dir, params_merge=False): print("Paddle model and code generated.") -def paddle2onnx(model_path, save_dir, opset): +def paddle2onnx(model_path, save_dir, opset_number): from x2paddle.decoder.paddle_decoder import PaddleDecoder - from x2paddle.op_mapper.paddle_op_mapper import PaddleOpMapper + from x2paddle.op_mapper.paddle2onnx.paddle_op_mapper import PaddleOpMapper model = PaddleDecoder(model_path, '__model__', '__params__') mapper = PaddleOpMapper() - mapper.convert(model.program, save_dir, opset) + mapper.convert(model.program, save_dir, opset_number=opset_number) def main(): diff --git a/x2paddle/op_mapper/onnx_op_mapper.py b/x2paddle/op_mapper/onnx_op_mapper.py deleted file mode 100644 index ea095ca0e0747a4a4f86fe589b50262d3ce7f4c8..0000000000000000000000000000000000000000 --- a/x2paddle/op_mapper/onnx_op_mapper.py +++ /dev/null @@ -1,92 +0,0 @@ -# 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. - -from x2paddle.op_mapper.onnx_opsets.opset9 import OpSet9 -from x2paddle.core.op_mapper import OpMapper -from x2paddle.op_mapper.onnx_opsets.custom_layer import * -from x2paddle.decoder.onnx_decoder import ONNXGraph, ONNXGraphNode, ONNXGraphDataNode - - -class ONNXOpMapper(OpMapper): - def __init__(self, decoder): - super(ONNXOpMapper, self).__init__() - self.support_op_sets = [9, ] - self.default_op_set = 9 - self.graph = decoder.graph - self.opset = self.create_opset(decoder) - if not self.op_checker(): - raise Exception("Model are not supported yet.") - #mapping op - print("Total nodes: {}".format( - sum([ - isinstance(node, ONNXGraphNode) - 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) - op = node.layer_type - if hasattr(self.opset, op): - func = getattr(self.opset, op) - func(node) - elif op in self.opset.default_op_mapping: - self.opset.directly_map(node) - elif op in custom_layers: - self.opset.deal_custom_layer(node) - elif op in self.opset.elementwise_ops: - self.opset.elementwise_map(node) - print("Nodes converted.") - self.weights = self.opset.weights - self.omit_nodes = self.opset.omit_nodes - self.used_custom_layers = self.opset.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.opset, op) and \ - op not in self.opset.default_op_mapping and \ - op not in custom_layers and \ - op not in self.opset.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))) - for op in unsupported_ops: - print(op) - return False - - def create_opset(self, decoder): - run_op_set = self.default_op_set - opset = '' - if decoder.op_set in self.support_op_sets: - opset = 'OpSet' + str(decoder.op_set) - elif decoder.op_set < self.default_op_set: - opset = 'OpSet' + str(self.default_op_set) - else: - for op_set in self.support_op_sets: - if decoder.op_set > op_set: - run_op_set = op_set - else: - break - opset = 'OpSet' + str(run_op_set) - print( - 'Now, onnx2paddle support convert onnx model opset_verison {},' - 'opset_verison of your onnx model is {}, automatically treated as op_set: {}.' - .format(self.support_op_sets, decoder.op_set, run_op_set)) - return eval(opset)(decoder) diff --git a/x2paddle/op_mapper/onnx_opsets/__init__.py b/x2paddle/op_mapper/onnx_opsets/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/x2paddle/op_mapper/onnx_opsets/custom_layer/InstanceNormalization.py b/x2paddle/op_mapper/onnx_opsets/custom_layer/InstanceNormalization.py deleted file mode 100644 index f47273206d3108316e5a3a8a72da5a1f96f8fe9e..0000000000000000000000000000000000000000 --- a/x2paddle/op_mapper/onnx_opsets/custom_layer/InstanceNormalization.py +++ /dev/null @@ -1,56 +0,0 @@ -# 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. - -from .register import register - - -def InstanceNormalization_shape(input_shape): - return input_shape - - -def InstanceNormalization_layer(inputs, name=None): - # TODO(lvmengsi@baidu.com): Check the accuracy when using fluid.layers.layer_norm. - epsilon = 1e-5 - input_ = inputs[0] - mean = fluid.layers.reduce_mean(input_, dim=[2, 3], keep_dim=True) - var = fluid.layers.reduce_mean( - fluid.layers.square(input_ - mean), dim=[2, 3], keep_dim=True) - if name is not None: - scale_name = name + "_scale" - offset_name = name + "_offset" - - scale_param = inputs[1] - offset_param = inputs[2] - scale = fluid.layers.create_parameter( - name=scale_param.name, shape=input_.shape[1:2], dtype="float32") - offset = fluid.layers.create_parameter( - name=offset_param.name, shape=input_.shape[1:2], dtype="float32") - - tmp = fluid.layers.elementwise_mul(x=(input_ - mean), y=scale, axis=1) - tmp = tmp / fluid.layers.sqrt(var + epsilon) - tmp = fluid.layers.elementwise_add(tmp, offset, axis=1) - return tmp - - -def InstanceNormalization_weights(name, data=None): - weights_name = [name + '_scale'] - return weights_name - - -register( - kind='InstanceNormalization', - shape=InstanceNormalization_shape, - layer=InstanceNormalization_layer, - child_func=None, - weights=InstanceNormalization_weights) diff --git a/x2paddle/op_mapper/onnx_opsets/custom_layer/__init__.py b/x2paddle/op_mapper/onnx_opsets/custom_layer/__init__.py deleted file mode 100644 index 3c074350a63e9e24cf1eba441da5a420868b5bb7..0000000000000000000000000000000000000000 --- a/x2paddle/op_mapper/onnx_opsets/custom_layer/__init__.py +++ /dev/null @@ -1,115 +0,0 @@ -# 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. - -from .register import get_registered_layers -#custom layer import begins - -from . import InstanceNormalization -#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 make_custom_child_func(node): - """ get the code which implement the custom layer function - """ - layer_type = node.layer_type - child_func = custom_layers[layer_type]['child_func'] - if child_func is None: - return None, child_func - import inspect - return inspect.getsource(child_func), child_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) diff --git a/x2paddle/op_mapper/onnx_opsets/custom_layer/register.py b/x2paddle/op_mapper/onnx_opsets/custom_layer/register.py deleted file mode 100644 index 37a593648a0b8717eb22cde7f1bc8b85c4990e39..0000000000000000000000000000000000000000 --- a/x2paddle/op_mapper/onnx_opsets/custom_layer/register.py +++ /dev/null @@ -1,55 +0,0 @@ -# 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. -""" this module provides 'register' for registering customized layers -""" - -g_custom_layers = {} - - -def register(kind, shape, layer, child_func, 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, - 'child_func': child_func, - 'weights': weights - } - - -def get_registered_layers(): - return g_custom_layers diff --git a/x2paddle/op_mapper/onnx_opsets/opset9.py b/x2paddle/op_mapper/onnx_opsets/opset9.py deleted file mode 100644 index 5cf058f58ed3c35f54ff26cec469739cded0a23c..0000000000000000000000000000000000000000 --- a/x2paddle/op_mapper/onnx_opsets/opset9.py +++ /dev/null @@ -1,1523 +0,0 @@ -# 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. - -from x2paddle.decoder.onnx_decoder import ONNXGraph, ONNXGraphNode, ONNXGraphDataNode -from x2paddle.core.graph import GraphNode -from x2paddle.core.fluid_code import Layer -from x2paddle.core.fluid_code import FluidCode -from x2paddle.core.util import string -from functools import reduce -import numpy as np -import onnx -import onnx.numpy_helper as numpy_helper -from onnx.mapping import TENSOR_TYPE_TO_NP_TYPE -import logging as _logging -from collections import OrderedDict -import math -import os -import shutil - -_logger = _logging.getLogger(__name__) - - -def _const_weight_or_none(node): - if 'Constant' in node.layer_type: - return node.value - if isinstance(node, ONNXGraphDataNode): - return node.weight - return None - - -def get_same_padding(in_size, kernel_size, stride): - new_size = int(math.ceil(in_size * 1.0 / stride)) - pad_size = (new_size - 1) * stride + kernel_size - in_size - pad0 = int(pad_size / 2) - pad1 = pad_size - pad0 - return [pad0, pad1] - - -def print_mapping_info(func): - def run_mapping(*args, **kwargs): - node = args[1] - try: - res = func(*args, **kwargs) - except: - print("convert failed node:{}, op_type is {}".format( - node.layer_name[9:], node.layer_type)) - raise - else: - #print("convert successfully node:{}, op_type is {}".format( - # node.layer_name[9:], node.layer_type)) - return res - - return run_mapping - - -class OpSet9(): - elementwise_ops = { - 'Add': 'elementwise_add', - 'Div': 'elementwise_div', - 'Sub': 'elementwise_sub', - 'Mul': 'elementwise_mul', - 'Pow': 'elementwise_pow', - } - - default_op_mapping_field_values = OrderedDict() - default_op_mapping_field_values['FLUID_OP'] = '' - default_op_mapping_field_values['FLUID_INPUT_ARGS'] = None - default_op_mapping_field_values['FLUID_OUTPUT_ARGS'] = None - default_op_mapping_field_values['ATTR_MAPPING'] = dict() - default_op_mapping_field_values['DEFAULTS'] = dict() - default_op_mapping_field_values['INPUT_PERM'] = None - default_op_mapping_field_values['OUTPUT_PERM'] = None - default_op_mapping_field_values['FILL_NAME_FIELD'] = True - - default_op_mapping = { - 'Shape': ['shape', ['X'], ['Out']], - 'Clip': [ - 'clip', ['X'], ['Out'], dict(), dict( - min=(np.asarray( - [255, 255, 127, 255], 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']], - 'Ceil': ['ceil', ['X'], ['Out']], - 'ReduceMean': [ - 'reduce_mean', ['X'], ['Out'], dict( - axes='dim', keepdims='keep_dim'), dict(keep_dim=1) - ], - 'ReduceSum': [ - 'reduce_sum', ['X'], ['Out'], dict( - axes='dim', keepdims='keep_dim'), dict(keep_dim=1) - ], - 'ReduceMin': [ - 'reduce_min', ['X'], ['Out'], dict( - axes='dim', keepdims='keep_dim'), dict(keep_dim=1) - ], - #active function - 'Relu': ['relu', ['X'], ['Out']], - 'LeakyRelu': ['leaky_relu', ['X'], ['Out'], dict(), dict(alpha=.01)], - 'Elu': ['elu', ['X'], ['Out'], dict(), dict(alpha=1.)], - 'ThresholdedRelu': [ - 'thresholded_relu', ['X'], ['Out'], dict(alpha='threshold'), - dict(alpha=1.) - ], - 'Tanh': ['tanh', ['X'], ['Out']], - 'Sigmoid': ['sigmoid', ['X'], ['Out']], - 'HardSigmoid': [ - 'hard_sigmoid', ['X'], ['Out'], dict( - alpha='slope', beta='offset'), dict( - slope=.2, offset=.5) - ], - 'Softsign': ['softsign', ['X'], ['Out']], - 'Softplus': ['softplus', ['X'], ['Out']], - 'Exp': ['exp', ['X'], ['Out']], - 'Softmax': ['softmax', ['X'], ['Out'], dict(), dict(axis=1)], - 'Sqrt': ['sqrt', ['X'], ['Out']], - 'Floor': ['floor', ['X'], ['Out']], - 'Abs': ['abs', ['X'], ['Out']], - } - - default_ioa_constraint = { - 'Gather': - [(lambda i, o, a: a.get('axis', 0) == 0, 'only axis = 0 is supported')], - } - - def __init__(self, decoder): - super(OpSet9, self).__init__() - self.graph = decoder.graph - self.input_shapes = [] - self.weights = dict() - self.omit_nodes = list() - self.used_custom_layers = dict() - - @print_mapping_info - def directly_map(self, node, name='', *args, **kwargs): - inputs = node.layer.input - outputs = node.layer.output - op_type = node.layer_type - attrs = node.attr_map - info = self.default_op_mapping[op_type] - info.extend( - list(self.default_op_mapping_field_values.values())[len(info):]) - ( - fluid_op, - fluid_input_args, - fluid_output_args, - attr_mapping, - default_attrs, - input_perm, - output_perm, - fill_name_field, ) = info - - if fluid_op in self.default_ioa_constraint: - for predicate, message in self.default_ioa_constraint[fluid_op]: - assert predicate(inputs, outputs, attrs), message - - mapped_attrs = { - attr_mapping.get(key, key): value - for key, value in attrs.items() - } - if '' in mapped_attrs: - mapped_attrs.pop('') - if '_' in mapped_attrs: - mapped_attrs.pop('_') - fluid_attrs = default_attrs.copy() - fluid_attrs.update(mapped_attrs) - inputs = inputs if input_perm is None else list( - map(lambda i: inputs[i], input_perm)) - val_inps = [] - for idx, ipt in enumerate(inputs): - val_inps.append(self.graph.get_input_node(node, idx=idx, copy=True)) - - val_outs = outputs if output_perm is None else list( - map(lambda i: outputs[i], output_perm)) - attr = fluid_attrs - assert len(val_inps) == 1, 'directly_map error with multi inputs' - if fluid_op not in ['shape', 'erf']: - attr['name'] = string(node.layer_name) - node.fluid_code.add_layer( - fluid_op, inputs=val_inps[0], output=val_outs[0], param_attr=attr) - if fluid_op in ['shape']: - node.fluid_code.add_layer( - 'cast', - inputs=val_outs[0], - output=val_outs[0], - param_attr={'dtype': string('int64')}) - - @print_mapping_info - def deal_custom_layer(self, node): - op = node.layer_type - custom_code, func = make_custom_layer(node) - child_func_code, child_func = make_custom_child_func(node) - params = get_params(node.layer, node.layer_type) - arg_names, kwargs = set_args(func, params) - kwargs['name'] = string(node.layer_name) - node.fluid_code.add_layer( - func.__code__.co_name, - inputs=node.inputs, - output=node, - param_attr=kwargs, - is_custom_layer=True) - if op not in self.used_custom_layers: - self.used_custom_layers[op] = custom_code - if op + '_child_func' not in self.used_custom_layers: - if child_func_code is not None: - self.used_custom_layers[op + - '_child_func'] = child_func_code - - @print_mapping_info - def elementwise_map(self, node): - assert node.layer_type in self.elementwise_ops - op_type = self.elementwise_ops[node.layer_type] - - val_x = self.graph.get_input_node(node, idx=0, copy=True) - val_y = self.graph.get_input_node(node, idx=1, copy=True) - val_y_shape = val_y.out_shapes[0] - val_x_shape = val_x.out_shapes[0] - - if len(val_x_shape) < len(val_y_shape): - val_x, val_y = val_y, val_x - val_y_shape, val_x_shape = val_x_shape, val_y_shape - - str_y_shape = ','.join(str(e) for e in val_y_shape) - str_x_shape = ','.join(str(e) for e in val_x_shape) - slice_idx = 0 - if str_y_shape not in str_x_shape: - for dim in val_y_shape: - if dim == 1: - slice_idx += 1 - else: - break - attr = {"name": string(node.layer_name)} - if slice_idx < len(val_y_shape) and slice_idx > 0: - val_y_reshaped = val_y_shape[slice_idx:] - var_y_reshaped = val_y.layer_name + '_reshaped' - attr_reshaped = { - 'shape': val_y_reshaped, - 'name': string(var_y_reshaped) - } - node.fluid_code.add_layer( - 'reshape', - inputs=val_y, - output=var_y_reshaped, - param_attr=attr_reshaped) - inputs = {'x': val_x, 'y': var_y_reshaped} - node.fluid_code.add_layer( - op_type, inputs=inputs, output=node, param_attr=attr) - else: - inputs = {'x': val_x, 'y': val_y} - node.fluid_code.add_layer( - op_type, inputs=inputs, output=node, param_attr=attr) - - @print_mapping_info - def place_holder(self, node): - self.input_shapes.append(node.out_shapes[0]) - - shape = node.out_shapes[0] - for i, dim_shape in enumerate(shape): - if dim_shape == 0 and i == 0: - shape[i] = 1 - if dim_shape == 0 and i != 0: - assert 'shape of input is not assigned' - attr = { - "dtype": string(node.dtype), - "shape": shape, - "name": string(node.layer_name), - "append_batch_size": 'False' - } - - node.fluid_code.add_layer( - "data", inputs=None, output=node, param_attr=attr) - - @print_mapping_info - def create_parameter(self, node, parameter=None): - if parameter is not None: - node = parameter - dtype = node.dtype - shape = node.out_shapes[0] - if len(node.weight.shape) == 0: - shape = [1] - self.weights[node.layer_name] = node.weight - attr = { - 'dtype': string(dtype), - 'shape': shape, - 'name': string(node.layer_name), - 'default_initializer': 'Constant(0.0)' - } - if dtype == 'bool': - attr['dtype'] = string('int64') - node.fluid_code.add_layer( - "create_parameter", inputs=None, output=node, param_attr=attr) - node.fluid_code.add_layer( - "cast", - inputs=node, - output=node, - param_attr={'dtype': string('bool')}) - elif dtype == 'uint8': - attr['dtype'] = string('float32') - node.fluid_code.add_layer( - "create_parameter", inputs=None, output=node, param_attr=attr) - else: - node.fluid_code.add_layer( - "create_parameter", inputs=None, output=node, param_attr=attr) - - def _pad_if_asymmetric(self, node, pads, val_name): # pads: SSEE - assert len(pads) & 1 == 0 - symmetric = True - ndims = len(pads) // 2 - for idx_dim in range(ndims): - if pads[idx_dim] != pads[ndims + idx_dim]: - symmetric = False - break - if symmetric: - return pads[:ndims], val_name - val_padded = self.Pad(node, op_independent=False) - return [0] * ndims, val_padded - - def _interpolate(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - if node.layer_type == 'Resize': - val_scales = self.graph.get_input_node(node, idx=2, copy=True) - elif node.layer_type == 'Upsample': - val_scales = self.graph.get_input_node(node, idx=1, copy=True) - - attr = {'name': string(node.layer_name)} - mode = node.get_attr('mode', 'nearest') - fluid_op = 'resize_{}'.format(mode) - if 'linear' in mode: - print( - 'Warnning: paddle not support op:resize wiht mode: linear, we use bilinear replace linear' - ) - fluid_op = 'resize_bilinear' - - node.fluid_code.add_layer( - fluid_op, - inputs={'input': val_x, - 'scale': val_scales}, - output=node, - param_attr=attr) - - @print_mapping_info - def RoiAlign(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - val_rois = self.graph.get_input_node(node, idx=1, copy=True) - - pooled_height = node.get_attr('output_height') - pooled_width = node.get_attr('output_width') - spatial_scale = node.get_attr('spatial_scale') - sampling_ratio = node.get_attr('sampling_ratio') - attr = { - 'pooled_height': pooled_height, - 'pooled_width': pooled_width, - 'spatial_scale': spatial_scale, - 'sampling_ratio': sampling_ratio, - } - node.fluid_code.add_layer( - 'roi_align', - inputs={'input': val_x, - 'rois': val_rois}, - output=node, - param_attr=attr) - - @print_mapping_info - def MaxRoiPool(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - val_rois = self.graph.get_input_node(node, idx=1, copy=True) - - spatial_scale = node.get_attr('spatial_scale') - pooled_height, pooled_width = node.get_attr('pooled_shape') - attr = { - 'pooled_height': pooled_height, - 'pooled_width': pooled_width, - 'spatial_scale': spatial_scale, - } - node.fluid_code.add_layer( - 'roi_pool', - inputs={'input': val_x, - 'rois': val_rois}, - output=node, - param_attr=attr) - - @print_mapping_info - def Pad(self, node, op_independent=True): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - pads = node.get_attr('pads') - mode = node.get_attr('mode', 'constant') - value = node.get_attr('value', 0.) - data_shape = val_x.out_shapes[0] - output_shape = node.out_shapes[0] - assume_pad2d = False - attr = {} - if len(pads) == 4: - assume_pad2d |= mode != 'constant' - if data_shape: - assume_pad2d |= data_shape and len(data_shape) == 4 # NCHW - if output_shape: - assume_pad2d |= output_shape and len(output_shape) == 4 # NCHW - if assume_pad2d: - fluid_op = 'pad2d' - attr['data_format'] = string('NCHW') - attr['mode'] = string(mode) - else: - attr = {'pad_value': value} - fluid_op = 'pad' - if len(pads) == 4: - paddings = np.array(pads).reshape( - (-1, 2)).transpose().flatten().tolist() # SSEE -> SESE - elif len(pads) == 8: - paddings = np.array(pads).reshape( - (-1, 4)).transpose().flatten().tolist() # SSEE -> SESE - if sum(paddings[:4]) == 0: - fluid_op = 'pad2d' - paddings = paddings[4:] - attr['mode'] = string(mode) - attr['paddings'] = paddings - if op_independent: - attr['name'] = string(node.layer_name) - node.fluid_code.add_layer( - fluid_op, inputs=val_x, output=node, param_attr=attr) - else: - attr['name'] = string(node.layer_name + '_paded') - node.fluid_code.add_layer( - fluid_op, - inputs=val_x, - output=node.layer_name + '_paded', - param_attr=attr) - return node.layer_name + '_paded' - - @print_mapping_info - def Unsqueeze(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - axes = node.get_attr('axes') - attr = {'axes': axes, 'name': string(node.layer_name)} - if len(val_x.out_shapes[0]) == 0: - if node.layer_name: - node.fluid_code.add_layer( - 'reshape', - inputs=val_x, - output=node, - param_attr={'shape': [1]}) - else: - node.fluid_code.add_layer( - 'unsqueeze', inputs=val_x, output=node, param_attr=attr) - - @print_mapping_info - def Shrink(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - bias = node.get_attr('bias') - lambd = node.get_attr('lambd') - assert bias == 0.0, 'not support bias!=0' - attr = {'threshold': lambd, 'name': node.layer_name} - node.fluid_code.add_layer( - 'hard_shrink', inputs=val_x, output=node, param_attr=attr) - - def Greater(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - val_y = self.graph.get_input_node(node, idx=1, copy=True) - node.fluid_code.add_layer( - 'greater_than', - inputs={'x': val_x, - 'y': val_y}, - output=node, - param_attr=None) - - @print_mapping_info - def Constant(self, node): - val_output = self.graph.get_node(node.layer.output[0], copy=True) - - value = node.get_attr('value') - dtype = np.dtype(value.dtype) - output_dtype = val_output.dtype - if output_dtype: - assert dtype == output_dtype, 'tensor dtype unmatches storage dtype' - - shape = node.get_attr('shape', None) - - if shape is None: - shape = val_output.out_shapes[0] - if shape is None: - shape = list(value.shape) - _logger.warning('in (Constant -> %s): ' - 'attribute "shape" of %s not inferred, ' - 'using value as 1-D tensor may lead to fails', - val_output.layer_name, val_output.layer_name) - - if len(value) == 1: - value = value.tolist() - shape = [1] - value = value[0] - if dtype.name == 'int64': - dtype = 'int32' - attr = {'shape': shape, 'dtype': string(dtype), 'value': value} - node.fluid_code.add_layer( - 'fill_constant', inputs=None, output=node, param_attr=attr) - else: - if dtype.name == 'uint8': - dtype = 'int64' - value = np.reshape(value, shape) - self.weights[node.layer_name] = value - attr = { - 'dtype': string(dtype), - 'shape': shape, - 'name': string(node.layer_name), - 'default_initializer': 'Constant(0.0)' - } - node.fluid_code.add_layer( - "create_parameter", inputs=None, output=node, param_attr=attr) - - @print_mapping_info - def Resize(self, node): - self._interpolate(node) - - @print_mapping_info - def Upsample(self, node): - self._interpolate(node) - - @print_mapping_info - def InstanceNormalization(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - val_scale = self.graph.get_input_node(node, idx=1, copy=True) - val_b = self.graph.get_input_node(node, idx=2, copy=True) - epsilon = node.get_attr('epsilon', 1e-5) - attr = { - 'epsilon': epsilon, - 'param_attr': string(val_scale.layer_name), - 'bias_attr': string(val_b.layer_name) - } - node.fluid_code.add_layer( - "instance_norm", inputs=val_x, output=node, param_attr=attr) - - @print_mapping_info - def Expand(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - val_shape = self.graph.get_input_node(node, idx=1, copy=True) - - if len(val_shape.outputs) == 1: - self.omit_nodes.append(val_shape.layer_name) - - val_y = self.graph.get_node(node.layer.output[0], copy=True) - out_shape = node.out_shapes[0] - val_x_dtype = val_x.dtype - - name_ones = node.layer_name + '_ones' - attr_ones = {'shape': out_shape, 'dtype': string(val_x_dtype)} - node.fluid_code.add_layer( - 'ones', inputs=None, output=name_ones, param_attr=attr_ones) - inputs = {'x': name_ones, 'y': val_x} - attr = {'name': string(node.layer_name)} - node.fluid_code.add_layer( - 'elementwise_mul', - inputs=inputs, - output=node.layer_name, - param_attr=attr) - - @print_mapping_info - def Gather(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - indices = self.graph.get_input_node(node, idx=1, copy=True) - indices_shape = indices.out_shapes[0] - axis = node.get_attr('axis', 0) - #assert len( - # indices_shape) <= 2, "Gather op don't support dim of indice >2 " - if axis == 0 and len(indices_shape) <= 1: - node.fluid_code.add_layer( - 'gather', - inputs={'input': val_x, - 'index': indices}, - output=node, - param_attr=None) - elif axis > 0 and len(indices_shape) <= 1: - perm = list(range(len(val_x.out_shapes[0]))) - perm = [axis] + perm[:axis] + perm[axis + 1:] - attr_trans = {'perm': perm} - name_trans = val_x.layer_name + '_trans' - node.fluid_code.add_layer( - 'transpose', - inputs=val_x, - output=name_trans, - param_attr=attr_trans) - node.fluid_code.add_layer( - 'gather', - inputs={'input': name_trans, - 'index': indices}, - output=node, - param_attr=None) - node.fluid_code.add_layer( - 'transpose', inputs=node, output=node, param_attr=attr_trans) - elif axis == 0 and len(indices_shape) > 1: - if val_x.out_shapes[0] is not None and isinstance( - val_x, ONNXGraphDataNode): - node.fluid_code.add_layer( - 'embedding', - inputs=indices, - output=node, - use_fluid=True, - param_attr={ - 'param_attr': string(val_x.layer_name), - 'size': val_x.out_shapes[0] - }) - else: - from functools import reduce - #indices_shape = [1,7] - reshape_shape = reduce(lambda x, y: x * y, indices_shape) - indices_reshape = indices.layer_name + '_shape' - node.fluid_code.add_layer( - 'reshape', - inputs=indices, - output=indices_reshape, - param_attr={'shape': [reshape_shape, ]}) - - perm = list(range(len(val_x.out_shapes[0]))) - node.fluid_code.add_layer( - 'gather', - inputs={'input': val_x, - 'index': indices_reshape}, - output=node, - param_attr=None) - val_x_shape = val_x.out_shapes[0] - reshaped_shape = [] - for i in perm: - reshaped_shape.append(indices_shape[i]) - for i in val_x_shape[:axis] + val_x_shape[axis + 1:]: - reshaped_shape.append(i) - node.fluid_code.add_layer( - 'reshape', - inputs=node, - output=node, - param_attr={'shape': reshaped_shape}) - elif axis > 0 and len(indices_shape) > 1: - from functools import reduce - reshape_shape = reduce(lambda x, y: x * y, indices_shape) - indices_reshape = indices.layer_name + '_shape' - node.fluid_code.add_layer( - 'reshape', - inputs=indices, - output=indices_reshape, - param_attr={'shape': [reshape_shape, ]}) - - perm = list(range(len(val_x.out_shapes[0]))) - perm = [axis] + perm[:axis] + perm[axis + 1:] - attr_trans = {'perm': perm} - name_trans = val_x.layer_name + '_trans' - node.fluid_code.add_layer( - 'transpose', - inputs=val_x, - output=name_trans, - param_attr=attr_trans) - node.fluid_code.add_layer( - 'gather', - inputs={'input': name_trans, - 'index': indices_reshape}, - output=node, - param_attr=None) - node.fluid_code.add_layer( - 'transpose', inputs=node, output=node, param_attr=attr_trans) - val_x_shape = val_x.out_shapes[0] - reshaped_shape = [] - for i in perm: - reshaped_shape.append(indices_shape[i]) - for i in val_x_shape[:axis] + val_x_shape[axis + 1:]: - reshaped_shape.append(i) - node.fluid_code.add_layer( - 'reshape', - inputs=node, - output=node, - param_attr={'shape': reshaped_shape}) - - @print_mapping_info - def Range(self, node): - val_start = self.graph.get_input_node(node, idx=0, copy=True) - val_limit = self.graph.get_input_node(node, idx=1, copy=True) - val_delta = self.graph.get_input_node(node, idx=2, copy=True) - dtype = val_start.dtype - inputs = {'start': val_start, 'end': val_limit, 'step': val_delta} - node.fluid_code.add_layer( - 'range', - inputs=inputs, - output=node, - param_attr={'dtype': string(dtype)}) - - @print_mapping_info - def Slice(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - starts, ends, axes, steps = None, None, None, None - attr = {} - if len(node.inputs) > 1: - starts = self.graph.get_input_node(node, idx=1, copy=True) - ends = self.graph.get_input_node(node, idx=2, copy=True) - if len(node.inputs) > 3: - axes = self.graph.get_input_node(node, idx=3, copy=True) - axes = _const_weight_or_none(axes) - if len(node.inputs) > 4: - steps = self.graph.get_input_node(node, idx=4, copy=True) - steps = _const_weight_or_none(steps) - if steps is not None: - assert steps == 1, "Only support convert op:Slice, which attribute:steps == 1" - attr = { - "axes": axes, - "starts": starts.layer_name, - "ends": ends.layer_name - } - starts_value = _const_weight_or_none(starts) - ends_value = _const_weight_or_none(ends) - if starts_value is not None and ends_value is not None: - self.omit_nodes.append(starts.layer_name) - self.omit_nodes.append(ends.layer_name) - ends_value = ends_value.copy() - for idx in range(len(ends_value)): - if ends_value[idx] > 2**31 - 1: - ends_value[idx] = 2**31 - 1 - attr = { - "axes": axes, - "starts": starts_value, - "ends": ends_value - } - else: - if starts.dtype != 'int32': - node.fluid_code.add_layer( - 'cast', - inputs=starts, - output=starts, - param_attr={'dtype': string('int32')}) - if ends.dtype != 'int32': - node.fluid_code.add_layer( - 'cast', - inputs=ends, - output=ends, - param_attr={'dtype': string('int32')}) - else: - starts = node.get_attr('starts') - ends = node.get_attr('ends') - axes = node.get_attr('axes') - for idx in range(len(ends)): - if ends[idx] > 2**31 - 1: - ends[idx] = 2**31 - 1 - attr = {"axes": axes, "starts": starts, "ends": ends} - - node.fluid_code.add_layer( - 'slice', inputs=val_x, output=node, param_attr=attr) - - @print_mapping_info - def ConstantOfShape(self, node): - val_shape = self.graph.get_input_node(node, idx=0, copy=True) - val_y = self.graph.get_node(node.layer.output[0], copy=True) - - value = node.get_attr('value') - dtype = value.dtype - value = value.tolist() - assert len(value) == 1, ('given value not Scalar, shape of value > 1, ' - 'this is not supported') - if len(value) == 1: - value = value[0] - if dtype.name == 'int64': - dtype = 'int32' - attr = { - 'shape': val_shape.layer_name, - 'dtype': string(dtype), - 'value': value - } - node.fluid_code.add_layer( - 'fill_constant', inputs=None, output=node, param_attr=attr) - - @print_mapping_info - def Split(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - val_y = self.graph.get_node(node.layer.output[0], copy=True) - - fluid_op = 'split' - split = node.get_attr('split') - axis = node.get_attr('axis', 0) - attr = { - 'num_or_sections': split, - 'dim': axis, - 'name': string(node.layer_name) - } - - node.fluid_code.add_layer( - 'split', inputs=val_x, output=val_y, param_attr=attr) - - @print_mapping_info - def Reshape(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - val_shape = self.graph.get_input_node(node, idx=1, copy=True) - val_reshaped = self.graph.get_node(node.layer.output[0], copy=True) - attr = {} - shape_value = _const_weight_or_none(val_shape) - shape_dims = len(val_shape.out_shapes[0]) - - if shape_value is not None: - node.fluid_code.add_layer( - 'reshape', - inputs={'x': val_x}, - output=node, - param_attr={'shape': shape_value.tolist()}) - elif val_shape.dtype == 'int64': - val_shape_cast = val_shape.layer_name + '_cast' - node.fluid_code.add_layer( - 'cast', - inputs=val_shape, - output=val_shape_cast, - param_attr={'dtype': string('int32')}) - node.fluid_code.add_layer( - 'reshape', - inputs=val_shape_cast, - output=val_shape_cast, - param_attr={'shape': val_shape.out_shapes[0]}) - node.fluid_code.add_layer( - 'reshape', - inputs={'x': val_x, - 'shape': val_shape_cast}, - output=node, - param_attr=attr) - else: - node.fluid_code.add_layer( - 'reshape', - inputs=val_shape, - output=val_shape, - param_attr={'shape': val_shape.out_shapes[0]}) - node.fluid_code.add_layer( - 'reshape', - inputs={'x': val_x, - 'shape': val_shape}, - output=node, - param_attr=attr) - - @print_mapping_info - def Cast(self, node): - val_input = self.graph.get_input_node(node, idx=0, copy=True) - val_output = self.graph.get_node(node.layer.output[0], copy=True) - - dtype = node.get_attr('to') - if not isinstance(dtype, np.dtype): - dtype = TENSOR_TYPE_TO_NP_TYPE[dtype] - - output_dtype = val_output.dtype - if output_dtype: - assert dtype == output_dtype, 'dtype of to unmatches output' - attr = {'dtype': string(dtype)} - node.fluid_code.add_layer( - 'cast', inputs=val_input, output=node, param_attr=attr) - - @print_mapping_info - def AveragePool(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - - auto_pad = node.get_attr('auto_pad', 'NOTSET') - kernel_shape = node.get_attr("kernel_shape") - poolnd = len(kernel_shape) - strides = node.get_attr("strides") - pad_mode = node.get_attr("pads") - ceil_mode = bool(node.get_attr('ceil_mode', 0)) - pads = node.get_attr('pads', [0] * (poolnd * 2)) - fluid_op = 'pool{}d'.format(poolnd) - assert 2 <= poolnd <= 3, 'only pool2d and pool3d is supported' - - paddings, val_x = self._pad_if_asymmetric(node, pads, val_x) - - if auto_pad == "SAME_UPPER" or auto_pad == "SAME_LOWER": - input_shape = val_x.out_shapes[0] - pad_h = get_same_padding(input_shape[2], kernel_shape[0], - strides[0]) - pad_w = get_same_padding(input_shape[3], kernel_shape[1], - strides[1]) - attr = {"paddings": pad_h + pad_w, "pad_value": 0.0} - - attr = { - "pool_size": kernel_shape, - "pool_type": string('avg'), - "pool_stride": strides, - "pool_padding": paddings, - "ceil_mode": ceil_mode, - "exclusive": 'True', - "name": string(node.layer_name) - } - - node.fluid_code.add_layer( - fluid_op, inputs=val_x, output=node, param_attr=attr) - - @print_mapping_info - def Concat(self, node): - inputs = [] - for i in range(len(node.layer.input)): - ipt = self.graph.get_input_node(node, idx=i, copy=True) - if isinstance(ipt, str): - inputs.append(ipt) - else: - inputs.append(ipt.layer_name) - axis = node.get_attr('axis') - attr = {'axis': axis} - node.fluid_code.add_layer( - 'concat', inputs=inputs, output=node, param_attr=attr) - - @print_mapping_info - def Flatten(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - axis = node.get_attr('axis', 1) - attr = {"axis": str(axis), "name": string(node.layer_name)} - node.fluid_code.add_layer( - 'flatten', inputs=val_x, output=node, param_attr=attr) - - @print_mapping_info - def Gemm(self, node): - val_a = self.graph.get_input_node(node, idx=0, copy=True) - val_b = self.graph.get_input_node(node, idx=1, copy=True) - val_c = self.graph.get_input_node(node, idx=2, copy=True) - - alpha = node.get_attr('alpha', 1.) # optional - beta = node.get_attr('beta', 1.) # optional - trans_a = bool(node.get_attr('transA', 0)) # optional - trans_b = bool(node.get_attr('transB', 0)) # optional - val_mm = node.layer_name + '_mm' - matmul_inputs = {"x": val_a, "y": val_b} - attr_matmul = { - "transpose_x": trans_a, - "transpose_y": trans_b, - "alpha": alpha, - "name": string(val_mm) - } - node.fluid_code.add_layer( - 'matmul', - inputs=matmul_inputs, - output=val_mm, - param_attr=attr_matmul) - - if beta != 0: - if beta == 1.: - add_inputs = {"x": val_mm, "y": val_c} - attr = {"name": string(node.layer_name)} - node.fluid_code.add_layer( - "elementwise_add", - inputs=add_inputs, - output=node, - param_attr=attr) - else: - var_beta = node.layer_name + '_beta' - matmul_beta_inputs = {"x": val_c, "y": var_beta} - node.fluid_code.add_layer( - "Constant", - inputs=matmul_beta_inputs, - output=var_beta, - param_attr={'value': beta}) - - add_inputs = {"x": val_mm, "y": var_beta} - attr = {"name": string(node.layer_name)} - node.fluid_code.add_layer( - "elementwise_add", - inputs=add_inputs, - output=node, - param_attr=attr) - - @print_mapping_info - def Sum(self, node): - val_inps = node.layer.input - inputs = { - "x": self.graph.get_input_node( - node, idx=0, copy=True), - "y": self.graph.get_input_node( - node, idx=1, copy=True), - } - node.fluid_code.add_layer("elementwise_add", inputs=inputs, output=node) - - for idx, ipt in enumerate(val_inps[2:]): - y = self.graph.get_input_node(node, idx=idx, copy=True) - inputs = { - "x": node.layer_name, - "y": y, - } - node.fluid_code.add_layer( - "elementwise_add", inputs=inputs, output=node) - - @print_mapping_info - def MatMul(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - val_y = self.graph.get_input_node(node, idx=1, copy=True) - inputs = {"x": val_x, "y": val_y} - attr = {"name": string(node.layer_name)} - node.fluid_code.add_layer( - "matmul", inputs=inputs, output=node, param_attr=attr) - - @print_mapping_info - def BatchNormalization(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - val_scale = self.graph.get_input_node(node, idx=1, copy=True) - val_b = self.graph.get_input_node(node, idx=2, copy=True) - val_mean = self.graph.get_input_node(node, idx=3, copy=True) - val_var = self.graph.get_input_node(node, idx=4, copy=True) - - self.omit_nodes.append(val_scale.layer_name) - self.omit_nodes.append(val_b.layer_name) - self.omit_nodes.append(val_mean.layer_name) - self.omit_nodes.append(val_var.layer_name) - - momentum = node.get_attr('momentum', .9) - epsilon = node.get_attr('epsilon', 1e-5) - - # Attribute: spatial is used in BatchNormalization-1,6,7 - spatial = bool(node.get_attr('spatial')) - attr = { - "momentum": momentum, - "epsilon": epsilon, - "data_layout": string('NCHW'), - "is_test": True, - "param_attr": string(val_scale.layer_name), - "bias_attr": string(val_b.layer_name), - "moving_mean_name": string(val_mean.layer_name), - "moving_variance_name": string(val_var.layer_name), - "use_global_stats": spatial, - "name": string(node.layer_name) - } - node.fluid_code.add_layer( - "batch_norm", inputs=val_x, output=node, param_attr=attr) - - @print_mapping_info - def Transpose(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - perm = node.get_attr('perm') - attr = {'perm': perm, "name": string(node.layer_name)} - node.fluid_code.add_layer( - "transpose", inputs=val_x, output=node, param_attr=attr) - - @print_mapping_info - def Relu(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - attr = {"name": string(node.layer_name)} - node.fluid_code.add_layer( - "relu", inputs=val_x, output=node, param_attr=attr) - - @print_mapping_info - def PRelu(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - val_slope = self.graph.get_input_node(node, idx=1, copy=True) - - mode = 'channel' - shape_slope = val_slope.out_shapes[0] - if len(shape_slope) == 1: - mode = 'all' - elif len(shape_slope) > 2: - mode = 'element' - attr = { - "param_attr": string(val_slope.layer_name), - 'mode': string(mode) - } - node.fluid_code.add_layer( - "prelu", inputs=val_x, output=node, param_attr=attr) - - @print_mapping_info - def Squeeze(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - axes = node.get_attr('axes') - attr = {'axes': axes, "name": string(node.layer_name)} - if len(val_x.out_shapes[0]) == 1: - node.fluid_code.add_layer( - "cast", - inputs=val_x, - output=node, - param_attr={'dtype': string(val_x.dtype)}) - else: - node.fluid_code.add_layer( - "squeeze", inputs=val_x, output=node, param_attr=attr) - - @print_mapping_info - def Equal(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - val_y = self.graph.get_input_node(node, idx=1, copy=True) - node.fluid_code.add_layer( - "equal", - inputs={'x': val_x, - 'y': val_y}, - output=node, - param_attr=None) - - @print_mapping_info - def Where(self, node): - condition = self.graph.get_input_node(node, idx=0, copy=True) - val_x = self.graph.get_input_node(node, idx=1, copy=True) - val_y = self.graph.get_input_node(node, idx=2, copy=True) - - not_condition = condition.layer_name + '_not' - node.fluid_code.add_layer( - "logical_not", - inputs=condition, - output=not_condition, - param_attr=None) - cast_not_condition = not_condition + '_cast' - node.fluid_code.add_layer( - "cast", - inputs=not_condition, - output=cast_not_condition, - param_attr={'dtype': string(val_x.dtype)}) - cast_condition = condition.layer_name + '_cast' - node.fluid_code.add_layer( - "cast", - inputs=condition, - output=cast_condition, - param_attr={'dtype': string(val_x.dtype)}) - mul_val_x = val_x.layer_name + '_mul' - node.fluid_code.add_layer( - "elementwise_mul", - inputs={'x': val_x, - 'y': cast_condition}, - output=mul_val_x, - param_attr=None) - - mul_val_y = val_y.layer_name + '_mul' - node.fluid_code.add_layer( - "elementwise_mul", - inputs={'x': val_y, - 'y': cast_not_condition}, - output=mul_val_y, - param_attr=None) - - node.fluid_code.add_layer( - "elementwise_add", - inputs={'x': mul_val_x, - 'y': mul_val_y}, - output=node, - param_attr=None) - - @print_mapping_info - def NonZero(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - val_x_dim = len(val_x.out_shapes[0]) - print(val_x.layer_name, val_x.out_shapes[0]) - if val_x_dim == 1: - node.fluid_code.add_layer("nonzero", inputs=val_x, output=val_x) - node.fluid_code.add_layer( - "transpose", - inputs=val_x, - output=node, - param_attr={'perm': [1, 0]}) - if val_x_dim > 1: - node.fluid_code.add_layer("nonzero", inputs=val_x, output=val_x) - node.fluid_code.add_layer( - "split", - inputs=val_x, - output=val_x, - param_attr={'num_or_sections': 1, - 'dim': val_x_dim}) - node.fluid_code.add_layer("concat", inputs=val_x, output=node) - - @print_mapping_info - def Identity(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - node.fluid_code.add_layer("assign", inputs=val_x, output=node) - - @print_mapping_info - def Tile(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - val_repeats = self.graph.get_input_node(node, idx=1, copy=True) - repeats = _const_weight_or_none(val_repeats) - - if repeats is None: - repeats = val_repeats.layer_name - elif isinstance(repeats, int): - repeats = [repeats] - - attr = { - 'expand_times': repeats, - "name": string(node.layer_name), - } - node.fluid_code.add_layer( - "expand", inputs=val_x, output=node, param_attr=attr) - - @print_mapping_info - def MaxPool(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - auto_pad = node.get_attr('auto_pad', 'NOTSET') - assert node.get_attr( - "dilations") is None, 'only dilations = 0 is supported' # optional - - kernel_shape = node.get_attr("kernel_shape") - poolnd = len(kernel_shape) - strides = node.get_attr("strides") - pad_mode = node.get_attr("pads") - ceil_mode = bool(node.get_attr('ceil_mode', 0)) # optional - pads = node.get_attr('pads', [0] * (poolnd * 2)) # optional - fluid_op = 'pool{}d'.format(poolnd) - assert 2 <= poolnd <= 3, 'only pool2d and pool3d is supported' - - paddings, val_x = self._pad_if_asymmetric(node, pads, val_x) - - if auto_pad == "SAME_UPPER" or auto_pad == "SAME_LOWER": - input_shape = val_x.out_shapes[0] - pad_h = get_same_padding(input_shape[2], kernel_shape[0], - strides[0]) - pad_w = get_same_padding(input_shape[3], kernel_shape[1], - strides[1]) - attr = {"paddings": pad_h + pad_w, "pad_value": 0.0} - - attr = { - "pool_size": kernel_shape, - "pool_type": string("max"), - "pool_stride": strides, - "pool_padding": paddings, - "ceil_mode": ceil_mode, - "name": string(node.layer_name), - "exclusive": False - } - node.fluid_code.add_layer( - fluid_op, inputs=val_x, output=node, param_attr=attr) - - def _global_pool(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - val_y = self.graph.get_node(node.layer.output[0], copy=True) - fluid_op = 'pool2d' - pool_type = None - if node.layer.op_type == 'GlobalMaxPool': - pool_type = 'max' - elif node.layer.op_type == 'GlobalAveragePool': - pool_type = 'avg' - - attr = { - "pool_type": string(pool_type), - "global_pooling": True, - "name": string(node.layer_name) - } - node.fluid_code.add_layer( - fluid_op, inputs=val_x, output=node, param_attr=attr) - - @print_mapping_info - def GlobalMaxPool(self, node): - self._global_pool(node) - - @print_mapping_info - def GlobalAveragePool(self, node): - self._global_pool(node) - - @print_mapping_info - def Conv(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - val_w = self.graph.get_input_node(node, idx=1, copy=True) - val_y = self.graph.get_node(node.layer.output[0], copy=True) - - self.omit_nodes.append(val_w.layer_name) - - has_bias = len(node.layer.input) == 3 - if has_bias: - val_b = self.graph.get_input_node(node, idx=2, copy=True) - self.omit_nodes.append(val_b.layer_name) - auto_pad = node.get_attr('auto_pad', 'NOTSET') - - kernel_shape = node.get_attr('kernel_shape') - convnd = len(kernel_shape) - assert 2 <= convnd <= 3, 'only conv2d and conv3d is supported' - num_out_channels = val_w.out_shapes[0][0] # OI... - fluid_op = 'conv{}d'.format(convnd) - - num_groups = node.get_attr('group', 1) - strides = node.get_attr('strides', [1] * convnd) # optional - dilations = node.get_attr('dilations', [1] * convnd) # optional - pads = node.get_attr('pads', [0] * (convnd * 2)) # optional - - input_shape = val_x.out_shapes[0] - paddings, val_x = self._pad_if_asymmetric(node, pads, val_x) - - if auto_pad == "SAME_UPPER" or auto_pad == "SAME_LOWER": - pad_h = get_same_padding(input_shape[2], kernel_shape[0], - strides[0]) - pad_w = get_same_padding(input_shape[3], kernel_shape[1], - strides[1]) - attr = {"paddings": pad_h + pad_w, "pad_value": 0.0} - - attr = { - "num_filters": num_out_channels, - "filter_size": kernel_shape, - "stride": strides, - "padding": paddings, - "dilation": dilations, - "groups": num_groups, - 'param_attr': string(val_w.layer_name), - "name": string(node.layer_name) - } - if has_bias: - attr["bias_attr"] = string(val_b.layer_name) - else: - attr["bias_attr"] = False - node.fluid_code.add_layer( - fluid_op, inputs=val_x, output=node, param_attr=attr) - - @print_mapping_info - def ConvTranspose(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - val_w = self.graph.get_input_node(node, idx=1, copy=True) - val_b = None - if len(node.layer.input) > 2: - val_b = self.graph.get_input_node(node, idx=2, copy=True) - self.omit_nodes.append(val_b.layer_name) - self.omit_nodes.append(val_w.layer_name) - - val_y = self.graph.get_node(node.layer.output[0], copy=True) - - auto_pad = node.get_attr('auto_pad', 'NOTSET') - out_padding = node.get_attr('output_padding', [0, 0]) - kernel_shape = node.get_attr('kernel_shape') - assert kernel_shape, 'kernel_shape not inferred' - convnd = len(kernel_shape) - assert 2 <= convnd <= 3, 'only conv2d_transpose and conv3d_transpose supported' - num_out_channels = val_w.out_shapes[0][1] - fluid_op = 'conv{}d_transpose'.format(convnd) - - num_groups = node.get_attr('group', 1) - strides = node.get_attr('strides', [1] * convnd) - dilations = node.get_attr('dilations', [1] * convnd) - output_size = node.get_attr('output_shape', []) - pads = node.get_attr('pads', [0] * (convnd * 2)) - - paddings, var_x = self._pad_if_asymmetric(node, pads, val_x) - - output_size = [0, 0] - - output_size[0] = (val_x.out_shapes[0][2] - 1 - ) * strides[0] - 2 * paddings[0] + dilations[0] * ( - kernel_shape[0] - 1) + 1 + out_padding[0] - output_size[1] = (val_x.out_shapes[0][3] - 1 - ) * strides[1] - 2 * paddings[1] + dilations[1] * ( - kernel_shape[1] - 1) + 1 + out_padding[1] - attr = { - 'num_filters': num_out_channels, - 'output_size': output_size or None, - 'filter_size': kernel_shape, - 'padding': paddings, - 'stride': strides, - 'dilation': dilations, - 'groups': num_groups, - 'param_attr': string(val_w.layer_name), - 'bias_attr': None if val_b is None else string(val_b.layer_name), - 'name': string(node.layer_name), - } - node.fluid_code.add_layer( - fluid_op, inputs=val_x, output=node, param_attr=attr) - - @print_mapping_info - def GRU(self, node): - val_x = self.graph.get_input_node(node, idx=0, copy=True) - val_w = self.graph.get_input_node(node, idx=1, copy=True) - val_r = self.graph.get_input_node(node, idx=2, copy=True) - - val_b = None - val_len = None - val_xh = None - miss_arg_num = 0 - num_ipt = len(node.layer.input) - if num_ipt > 3 and node.layer.input[3] != '': - val_b = self.graph.get_input_node(node, idx=3, copy=True) - else: - miss_arg_num += 1 - if num_ipt > 4 and node.layer.input[4] != '': - val_len = self.graph.get_input_node( - node, idx=4 - miss_arg_num, copy=True) - else: - miss_arg_num += 1 - if num_ipt > 5 and node.layer.input[5] != '': - val_xh = self.graph.get_input_node( - node, idx=5 - miss_arg_num, copy=True) - - x_shape = val_x.out_shapes[0] - - assert x_shape[1] == 1, 'only X with batch_size = 1 supported' - assert node.get_attr('clip', None) is None, 'clipping not supported' - - hidden_size = node.get_attr('hidden_size', None) - if hidden_size is None: - r_shape = val_r.out_shapes[0] - if r_shape: - hidden_size = r_shape[-1] - if hidden_size is None: - w_shape = var_w.out_shapes[0] - if w_shape: - hidden_size = w_shape[-2] // 3 - if hidden_size is None and val_b: - b_shape = val_b.out_shapes[0] - if b_shape: - hidden_size = b_shape[-1] // 6 - if hidden_size is None and val_xh: - xh_shape = val_xh.out_shapes[0] - if xh_shape: - hidden_size = xh_shape[-1] - - direction = node.get_attr('direction', 'forward') - assert direction != 'bidirectional', 'direction = bidirectional not supported' - - activations = node.get_attr('activations', ['Sigmoid', 'Tanh']) - assert len(activations) == 2, 'bidirectional operation not supported' - - assert node.get_attr('linear_before_reset', - 0) == 0, 'only linear_before_reset = 0 supported' - - activations = [s.lower() for s in activations] - gate_activation, candidate_activation = activations - is_reverse = direction == 'reverse' - - var_x0 = node.layer_name + '_x0' - node.fluid_code.add_layer( - 'squeeze', - inputs=val_x, - output=var_x0, - param_attr={'axes': [1], - 'name': string(var_x0)}) - - var_w0 = node.layer_name + '_w0' - node.fluid_code.add_layer( - 'squeeze', - inputs=val_w, - output=var_w0, - param_attr={'axes': [0], - 'name': string(var_w0)}) - - var_fc = node.layer_name + '_fc' - var_mm = (node.layer_name + '_mm') if val_b else var_fc - node.fluid_code.add_layer( - 'matmul', - inputs={'x': var_x0, - 'y': var_w0}, - output=var_mm, - param_attr={ - 'transpose_x': 0, - 'transpose_y': 1, - 'name': string(var_mm) - }) - - var_r0 = node.layer_name + '_r0' - node.fluid_code.add_layer( - 'squeeze', - inputs=val_r, - output=var_r0, - param_attr={'axes': [0], - 'name': string(var_r0)}) - - var_r0t = node.layer_name + '_r0t' - - node.fluid_code.add_layer( - 'transpose', - inputs=var_r0, - output=var_r0t, - param_attr={'perm': [1, 0], - 'name': string(var_r0t)}) - if val_b: - var_bi = node.layer_name + '_bi' - var_bh = node.layer_name + '_bh' - node.fluid_code.add_layer( - 'split', - inputs=val_b, - output=var_bi + ',' + var_bh, - param_attr={ - 'axis': 1, - 'split': [hidden_size * 3, hidden_size * 3], - 'name': string(node.layer_name + '.b/split') - }) - var_bi0 = node.layer_name + '_bi0' - node.fluid_code.add_layer( - 'squeeze', - inputs=var_bi, - output=var_bi0, - param_attr={'axes': [0], - 'name': string(var_bi0)}) - - node.fluid_code.add_layer( - 'elmentwise_add', - inputs=[var_mm, var_bi0], - output=var_fc, - param_attr={ - 'axes': 1, - 'name': string(node.layer_name + '.i/bias') - }) - - if val_xh: - var_xh0 = node.layer_name + '_xh0' - node.fluid_code.add_layer( - 'squeeze', - inputs=val_xh, - output=var_xh0, - param_attr={'axes': [1], - 'name': string(var_xh0)}) - var_y00 = node.layer_name + '_y00' - - attr = { - 'origin_mode': True, - 'h_0': var_xh0 if val_xh else None, - 'is_reverse': is_reverse, - 'gate_activation': string(gate_activation), - 'candidate_activation': string(candidate_activation), - 'param_attr': string(var_r0t), - 'bias_attr': string(var_bh) if val_b else False, - } - node.fluid_code.add_layer( - 'dynamic_gru', - inputs=var_fc + ',' + str(hidden_size), - output=var_y00, - param_attr=attr) - - num_opt = len(node.layer.output) - - if num_opt > 0 and node.layer.output[0] != '': - node.fluid_code.add_layer( - 'unsqueeze', - inputs=var_y00, - output=node.layer.output[0], - param_attr={ - 'axes': [1, 1], - 'name': string(node.layer.output[0]) - }) - if num_opt > 1 and node.layer.output[1] != '': - node.fluid_code.add_layer( - 'unsqueeze', - inputs=var_y00, - output=node.layer.output[1], - param_attr={ - 'axes': [1, 1], - 'name': string(node.layer.output[1]) - }) diff --git a/x2paddle/op_mapper/paddle_custom_layer/__init__.py b/x2paddle/op_mapper/paddle_custom_layer/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/x2paddle/op_mapper/paddle_custom_layer/im2sequence.py b/x2paddle/op_mapper/paddle_custom_layer/im2sequence.py deleted file mode 100644 index aeb4a9ceddb280295aafb2ebcafa3a25f8767d75..0000000000000000000000000000000000000000 --- a/x2paddle/op_mapper/paddle_custom_layer/im2sequence.py +++ /dev/null @@ -1,80 +0,0 @@ -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 diff --git a/x2paddle/op_mapper/paddle_custom_layer/multiclass_nms.py b/x2paddle/op_mapper/paddle_custom_layer/multiclass_nms.py deleted file mode 100644 index 5d30f651bbe2e51a2d328a81ceb8c52391374d60..0000000000000000000000000000000000000000 --- a/x2paddle/op_mapper/paddle_custom_layer/multiclass_nms.py +++ /dev/null @@ -1,416 +0,0 @@ -# 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 diff --git a/x2paddle/op_mapper/paddle_custom_layer/yolo_box.py b/x2paddle/op_mapper/paddle_custom_layer/yolo_box.py deleted file mode 100644 index a1e49e77b32ce1d64c11ca35ac69ed6cb20ee51c..0000000000000000000000000000000000000000 --- a/x2paddle/op_mapper/paddle_custom_layer/yolo_box.py +++ /dev/null @@ -1,822 +0,0 @@ -import onnx -import numpy as np -from onnx import onnx_pb, helper - - -def get_old_name(arg, name_prefix=''): - prefix_index = arg.find(name_prefix) - - if prefix_index != -1: - last_prefix = arg[len(name_prefix):] - else: - last_prefix = arg - idx = last_prefix.find('@') - if idx != -1: - last_prefix = last_prefix[:idx] - return name_prefix + last_prefix - - -def yolo_box(op, block): - 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) - model_name = outputs['Boxes'][0] - input_shape = block.vars[get_old_name(inputs['X'][0])].shape - image_size = inputs['ImgSize'] - input_height = input_shape[2] - input_width = input_shape[3] - - class_num = attrs['class_num'] - anchors = attrs['anchors'] - num_anchors = int(len(anchors)) // 2 - downsample_ratio = attrs['downsample_ratio'] - input_size = input_height * downsample_ratio - conf_thresh = attrs['conf_thresh'] - conf_thresh_mat = np.ones([num_anchors * input_height * - input_width]) * conf_thresh - - node_list = [] - im_outputs = [] - - x_shape = [1, num_anchors, 5 + class_num, input_height, input_width] - name_x_shape = [model_name + "@x_shape"] - node_x_shape = onnx.helper.make_node( - 'Constant', - inputs=[], - outputs=name_x_shape, - value=onnx.helper.make_tensor( - name=name_x_shape[0] + "@const", - data_type=onnx.TensorProto.INT64, - dims=[5], - vals=x_shape)) - node_list.append(node_x_shape) - - outputs_x_reshape = [model_name + "@reshape"] - node_x_reshape = onnx.helper.make_node( - 'Reshape', inputs=inputs['X'] + name_x_shape, outputs=outputs_x_reshape) - node_list.append(node_x_reshape) - - outputs_x_transpose = [model_name + "@x_transpose"] - node_x_transpose = onnx.helper.make_node( - 'Transpose', - inputs=outputs_x_reshape, - outputs=outputs_x_transpose, - perm=[0, 1, 3, 4, 2]) - node_list.append(node_x_transpose) - - range_x = [] - range_y = [] - for i in range(0, input_width): - range_x.append(i) - for j in range(0, input_height): - range_y.append(j) - - name_range_x = [model_name + "@range_x"] - node_range_x = onnx.helper.make_node( - 'Constant', - inputs=[], - outputs=name_range_x, - value=onnx.helper.make_tensor( - name=name_range_x[0] + "@const", - data_type=onnx.TensorProto.FLOAT, - dims=[input_width], - vals=range_x)) - node_list.append(node_range_x) - - name_range_y = [model_name + "@range_y"] - node_range_y = onnx.helper.make_node( - 'Constant', - inputs=[], - outputs=name_range_y, - value=onnx.helper.make_tensor( - name=name_range_y[0] + "@const", - data_type=onnx.TensorProto.FLOAT, - dims=[input_height], - vals=range_y)) - node_list.append(node_range_y) - - range_x_new_shape = [1, input_width] - range_y_new_shape = [input_height, 1] - - name_range_x_new_shape = [model_name + "@range_x_new_shape"] - node_range_x_new_shape = onnx.helper.make_node( - 'Constant', - inputs=[], - outputs=name_range_x_new_shape, - value=onnx.helper.make_tensor( - name=name_range_x_new_shape[0] + "@const", - data_type=onnx.TensorProto.INT64, - dims=[len(range_x_new_shape)], - vals=range_x_new_shape)) - node_list.append(node_range_x_new_shape) - - name_range_y_new_shape = [model_name + "@range_y_new_shape"] - node_range_y_new_shape = onnx.helper.make_node( - 'Constant', - inputs=[], - outputs=name_range_y_new_shape, - value=onnx.helper.make_tensor( - name=name_range_y_new_shape[0] + "@const", - data_type=onnx.TensorProto.INT64, - dims=[len(range_y_new_shape)], - vals=range_y_new_shape)) - node_list.append(node_range_y_new_shape) - - outputs_range_x_reshape = [model_name + "@range_x_reshape"] - node_range_x_reshape = onnx.helper.make_node( - 'Reshape', - inputs=name_range_x + name_range_x_new_shape, - outputs=outputs_range_x_reshape) - node_list.append(node_range_x_reshape) - - outputs_range_y_reshape = [model_name + "@range_y_reshape"] - node_range_y_reshape = onnx.helper.make_node( - 'Reshape', - inputs=name_range_y + name_range_y_new_shape, - outputs=outputs_range_y_reshape) - node_list.append(node_range_y_reshape) - - outputs_grid_x = [model_name + "@grid_x"] - node_grid_x = onnx.helper.make_node( - "Tile", - inputs=outputs_range_x_reshape + name_range_y_new_shape, - outputs=outputs_grid_x) - node_list.append(node_grid_x) - - outputs_grid_y = [model_name + "@grid_y"] - node_grid_y = onnx.helper.make_node( - "Tile", - inputs=outputs_range_y_reshape + name_range_x_new_shape, - outputs=outputs_grid_y) - node_list.append(node_grid_y) - - outputs_box_x = [model_name + "@box_x"] - outputs_box_y = [model_name + "@box_y"] - outputs_box_w = [model_name + "@box_w"] - outputs_box_h = [model_name + "@box_h"] - outputs_conf = [model_name + "@conf"] - outputs_prob = [model_name + "@prob"] - - node_split_input = onnx.helper.make_node( - "Split", - inputs=outputs_x_transpose, - outputs=outputs_box_x + outputs_box_y + outputs_box_w\ - + outputs_box_h + outputs_conf + outputs_prob, - axis=-1, - split=[1, 1, 1, 1, 1, class_num]) - node_list.append(node_split_input) - - outputs_box_x_sigmoid = [model_name + "@box_x_sigmoid"] - outputs_box_y_sigmoid = [model_name + "@box_y_sigmoid"] - - node_box_x_sigmoid = onnx.helper.make_node( - "Sigmoid", inputs=outputs_box_x, outputs=outputs_box_x_sigmoid) - node_list.append(node_box_x_sigmoid) - - node_box_y_sigmoid = onnx.helper.make_node( - "Sigmoid", inputs=outputs_box_y, outputs=outputs_box_y_sigmoid) - node_list.append(node_box_y_sigmoid) - - outputs_box_x_squeeze = [model_name + "@box_x_squeeze"] - outputs_box_y_squeeze = [model_name + "@box_y_squeeze"] - - node_box_x_squeeze = onnx.helper.make_node( - 'Squeeze', - inputs=outputs_box_x_sigmoid, - outputs=outputs_box_x_squeeze, - axes=[4]) - node_list.append(node_box_x_squeeze) - - node_box_y_squeeze = onnx.helper.make_node( - 'Squeeze', - inputs=outputs_box_y_sigmoid, - outputs=outputs_box_y_squeeze, - axes=[4]) - node_list.append(node_box_y_squeeze) - - outputs_box_x_add_grid = [model_name + "@box_x_add_grid"] - outputs_box_y_add_grid = [model_name + "@box_y_add_grid"] - - node_box_x_add_grid = onnx.helper.make_node( - "Add", - inputs=outputs_grid_x + outputs_box_x_squeeze, - outputs=outputs_box_x_add_grid) - node_list.append(node_box_x_add_grid) - - node_box_y_add_grid = onnx.helper.make_node( - "Add", - inputs=outputs_grid_y + outputs_box_y_squeeze, - outputs=outputs_box_y_add_grid) - node_list.append(node_box_y_add_grid) - - name_input_h = [model_name + "@input_h"] - name_input_w = [model_name + "@input_w"] - - node_input_h = onnx.helper.make_node( - 'Constant', - inputs=[], - outputs=name_input_h, - value=onnx.helper.make_tensor( - name=name_input_w[0] + "@const", - data_type=onnx.TensorProto.FLOAT, - dims=(), - vals=[input_height])) - node_list.append(node_input_h) - - node_input_w = onnx.helper.make_node( - 'Constant', - inputs=[], - outputs=name_input_w, - value=onnx.helper.make_tensor( - name=name_input_w[0] + "@const", - data_type=onnx.TensorProto.FLOAT, - dims=(), - vals=[input_width])) - node_list.append(node_input_w) - - outputs_box_x_encode = [model_name + "@box_x_encode"] - outputs_box_y_encode = [model_name + "@box_y_encode"] - - node_box_x_encode = onnx.helper.make_node( - 'Div', - inputs=outputs_box_x_add_grid + name_input_w, - outputs=outputs_box_x_encode) - node_list.append(node_box_x_encode) - - node_box_y_encode = onnx.helper.make_node( - 'Div', - inputs=outputs_box_y_add_grid + name_input_h, - outputs=outputs_box_y_encode) - node_list.append(node_box_y_encode) - - name_anchor_tensor = [model_name + "@anchor_tensor"] - node_anchor_tensor = onnx.helper.make_node( - "Constant", - inputs=[], - outputs=name_anchor_tensor, - value=onnx.helper.make_tensor( - name=name_anchor_tensor[0] + "@const", - data_type=onnx.TensorProto.FLOAT, - dims=[len(anchors)], - vals=anchors)) - node_list.append(node_anchor_tensor) - - anchor_shape = [int(num_anchors), 2] - name_anchor_shape = [model_name + "@anchor_shape"] - node_anchor_shape = onnx.helper.make_node( - "Constant", - inputs=[], - outputs=name_anchor_shape, - value=onnx.helper.make_tensor( - name=name_anchor_shape[0] + "@const", - data_type=onnx.TensorProto.INT64, - dims=[2], - vals=anchor_shape)) - node_list.append(node_anchor_shape) - - outputs_anchor_tensor_reshape = [model_name + "@anchor_tensor_reshape"] - node_anchor_tensor_reshape = onnx.helper.make_node( - "Reshape", - inputs=name_anchor_tensor + name_anchor_shape, - outputs=outputs_anchor_tensor_reshape) - node_list.append(node_anchor_tensor_reshape) - - name_input_size = [model_name + "@input_size"] - node_input_size = onnx.helper.make_node( - "Constant", - inputs=[], - outputs=name_input_size, - value=onnx.helper.make_tensor( - name=name_input_size[0] + "@const", - data_type=onnx.TensorProto.FLOAT, - dims=(), - vals=[input_size])) - node_list.append(node_input_size) - - outputs_anchors_div_input_size = [model_name + "@anchors_div_input_size"] - node_anchors_div_input_size = onnx.helper.make_node( - "Div", - inputs=outputs_anchor_tensor_reshape + name_input_size, - outputs=outputs_anchors_div_input_size) - node_list.append(node_anchors_div_input_size) - - outputs_anchor_w = [model_name + "@anchor_w"] - outputs_anchor_h = [model_name + "@anchor_h"] - - node_anchor_split = onnx.helper.make_node( - 'Split', - inputs=outputs_anchors_div_input_size, - outputs=outputs_anchor_w + outputs_anchor_h, - axis=1, - split=[1, 1]) - node_list.append(node_anchor_split) - - new_anchor_shape = [1, int(num_anchors), 1, 1] - name_new_anchor_shape = [model_name + "@new_anchor_shape"] - node_new_anchor_shape = onnx.helper.make_node( - 'Constant', - inputs=[], - outputs=name_new_anchor_shape, - value=onnx.helper.make_tensor( - name=name_new_anchor_shape[0] + "@const", - data_type=onnx.TensorProto.INT64, - dims=[len(new_anchor_shape)], - vals=new_anchor_shape)) - node_list.append(node_new_anchor_shape) - - outputs_anchor_w_reshape = [model_name + "@anchor_w_reshape"] - outputs_anchor_h_reshape = [model_name + "@anchor_h_reshape"] - - node_anchor_w_reshape = onnx.helper.make_node( - 'Reshape', - inputs=outputs_anchor_w + name_new_anchor_shape, - outputs=outputs_anchor_w_reshape) - node_list.append(node_anchor_w_reshape) - - node_anchor_h_reshape = onnx.helper.make_node( - 'Reshape', - inputs=outputs_anchor_h + name_new_anchor_shape, - outputs=outputs_anchor_h_reshape) - node_list.append(node_anchor_h_reshape) - - outputs_box_w_squeeze = [model_name + "@box_w_squeeze"] - node_box_w_squeeze = onnx.helper.make_node( - 'Squeeze', - inputs=outputs_box_w, - outputs=outputs_box_w_squeeze, - axes=[4]) - node_list.append(node_box_w_squeeze) - - outputs_box_h_squeeze = [model_name + "@box_h_squeeze"] - node_box_h_squeeze = onnx.helper.make_node( - 'Squeeze', - inputs=outputs_box_h, - outputs=outputs_box_h_squeeze, - axes=[4]) - node_list.append(node_box_h_squeeze) - - outputs_box_w_exp = [model_name + "@box_w_exp"] - node_box_w_exp = onnx.helper.make_node( - "Exp", inputs=outputs_box_w_squeeze, outputs=outputs_box_w_exp) - node_list.append(node_box_w_exp) - - outputs_box_h_exp = [model_name + "@box_h_exp"] - node_box_h_exp = onnx.helper.make_node( - "Exp", inputs=outputs_box_h_squeeze, outputs=outputs_box_h_exp) - node_list.append(node_box_h_exp) - - outputs_box_w_encode = [model_name + "box_w_encode"] - outputs_box_h_encode = [model_name + "box_h_encode"] - - node_box_w_encode = onnx.helper.make_node( - 'Mul', - inputs=outputs_box_w_exp + outputs_anchor_w_reshape, - outputs=outputs_box_w_encode) - node_list.append(node_box_w_encode) - - node_box_h_encode = onnx.helper.make_node( - 'Mul', - inputs=outputs_box_h_exp + outputs_anchor_h_reshape, - outputs=outputs_box_h_encode) - node_list.append(node_box_h_encode) - - outputs_conf_sigmoid = [model_name + "@conf_sigmoid"] - node_conf_sigmoid = onnx.helper.make_node( - 'Sigmoid', inputs=outputs_conf, outputs=outputs_conf_sigmoid) - node_list.append(node_conf_sigmoid) - - name_conf_thresh = [model_name + "@conf_thresh"] - node_conf_thresh = onnx.helper.make_node( - 'Constant', - inputs=[], - outputs=name_conf_thresh, - value=onnx.helper.make_tensor( - name=name_conf_thresh[0] + "@const", - data_type=onnx.TensorProto.FLOAT, - dims=[num_anchors * input_height * input_width], - vals=conf_thresh_mat)) - node_list.append(node_conf_thresh) - - conf_shape = [1, int(num_anchors), input_height, input_width, 1] - name_conf_shape = [model_name + "@conf_shape"] - node_conf_shape = onnx.helper.make_node( - 'Constant', - inputs=[], - outputs=name_conf_shape, - value=onnx.helper.make_tensor( - name=name_conf_shape[0] + "@const", - data_type=onnx.TensorProto.INT64, - dims=[len(conf_shape)], - vals=conf_shape)) - node_list.append(node_conf_shape) - - outputs_conf_thresh_reshape = [model_name + "@conf_thresh_reshape"] - node_conf_thresh_reshape = onnx.helper.make_node( - 'Reshape', - inputs=name_conf_thresh + name_conf_shape, - outputs=outputs_conf_thresh_reshape) - node_list.append(node_conf_thresh_reshape) - - outputs_conf_sub = [model_name + "@conf_sub"] - node_conf_sub = onnx.helper.make_node( - 'Sub', - inputs=outputs_conf_sigmoid + outputs_conf_thresh_reshape, - outputs=outputs_conf_sub) - node_list.append(node_conf_sub) - - outputs_conf_clip = [model_name + "@conf_clip"] - node_conf_clip = onnx.helper.make_node( - 'Clip', inputs=outputs_conf_sub, outputs=outputs_conf_clip) - node_list.append(node_conf_clip) - - zeros = [0] - name_zeros = [model_name + "@zeros"] - node_zeros = onnx.helper.make_node( - 'Constant', - inputs=[], - outputs=name_zeros, - value=onnx.helper.make_tensor( - name=name_zeros[0] + "@const", - data_type=onnx.TensorProto.FLOAT, - dims=(), - vals=zeros)) - node_list.append(node_zeros) - - outputs_conf_clip_bool = [model_name + "@conf_clip_bool"] - node_conf_clip_bool = onnx.helper.make_node( - 'Greater', - inputs=outputs_conf_clip + name_zeros, - outputs=outputs_conf_clip_bool) - node_list.append(node_conf_clip_bool) - - outputs_conf_clip_cast = [model_name + "@conf_clip_cast"] - node_conf_clip_cast = onnx.helper.make_node( - 'Cast', - inputs=outputs_conf_clip_bool, - outputs=outputs_conf_clip_cast, - to=1) - node_list.append(node_conf_clip_cast) - - outputs_conf_set_zero = [model_name + "@conf_set_zero"] - node_conf_set_zero = onnx.helper.make_node( - 'Mul', - inputs=outputs_conf_sigmoid + outputs_conf_clip_cast, - outputs=outputs_conf_set_zero) - node_list.append(node_conf_set_zero) - - outputs_prob_sigmoid = [model_name + "@prob_sigmoid"] - node_prob_sigmoid = onnx.helper.make_node( - 'Sigmoid', inputs=outputs_prob, outputs=outputs_prob_sigmoid) - node_list.append(node_prob_sigmoid) - - new_shape = [1, int(num_anchors), input_height, input_width, 1] - name_new_shape = [model_name + "@new_shape"] - node_new_shape = onnx.helper.make_node( - 'Constant', - inputs=[], - outputs=name_new_shape, - value=onnx.helper.make_tensor( - name=name_new_shape[0] + "@const", - data_type=onnx.TensorProto.INT64, - dims=[len(new_shape)], - vals=new_shape)) - node_list.append(node_new_shape) - - outputs_conf_new_shape = [model_name + "@_conf_new_shape"] - node_conf_new_shape = onnx.helper.make_node( - 'Reshape', - inputs=outputs_conf_set_zero + name_new_shape, - outputs=outputs_conf_new_shape) - node_list.append(node_conf_new_shape) - - outputs_score = [model_name + "@score"] - node_score = onnx.helper.make_node( - 'Mul', - inputs=outputs_prob_sigmoid + outputs_conf_new_shape, - outputs=outputs_score) - node_list.append(node_score) - - outputs_conf_bool = [model_name + "@conf_bool"] - node_conf_bool = onnx.helper.make_node( - 'Greater', - inputs=outputs_conf_new_shape + name_zeros, - outputs=outputs_conf_bool) - node_list.append(node_conf_bool) - - outputs_box_x_new_shape = [model_name + "@box_x_new_shape"] - node_box_x_new_shape = onnx.helper.make_node( - 'Reshape', - inputs=outputs_box_x_encode + name_new_shape, - outputs=outputs_box_x_new_shape) - node_list.append(node_box_x_new_shape) - - outputs_box_y_new_shape = [model_name + "@box_y_new_shape"] - node_box_y_new_shape = onnx.helper.make_node( - 'Reshape', - inputs=outputs_box_y_encode + name_new_shape, - outputs=outputs_box_y_new_shape) - node_list.append(node_box_y_new_shape) - - outputs_box_w_new_shape = [model_name + "@box_w_new_shape"] - node_box_w_new_shape = onnx.helper.make_node( - 'Reshape', - inputs=outputs_box_w_encode + name_new_shape, - outputs=outputs_box_w_new_shape) - node_list.append(node_box_w_new_shape) - - outputs_box_h_new_shape = [model_name + "@box_h_new_shape"] - node_box_h_new_shape = onnx.helper.make_node( - 'Reshape', - inputs=outputs_box_h_encode + name_new_shape, - outputs=outputs_box_h_new_shape) - node_list.append(node_box_h_new_shape) - - outputs_pred_box = [model_name + "@pred_box"] - node_pred_box = onnx.helper.make_node( - 'Concat', - inputs=outputs_box_x_new_shape + outputs_box_y_new_shape + \ - outputs_box_w_new_shape + outputs_box_h_new_shape, - outputs=outputs_pred_box, - axis=4) - node_list.append(node_pred_box) - - outputs_conf_cast = [model_name + "conf_cast"] - node_conf_cast = onnx.helper.make_node( - 'Cast', inputs=outputs_conf_bool, outputs=outputs_conf_cast, to=1) - node_list.append(node_conf_cast) - - outputs_pred_box_mul_conf = [model_name + "@pred_box_mul_conf"] - node_pred_box_mul_conf = onnx.helper.make_node( - 'Mul', - inputs=outputs_pred_box + outputs_conf_cast, - outputs=outputs_pred_box_mul_conf) - node_list.append(node_pred_box_mul_conf) - - box_shape = [1, int(num_anchors) * input_height * input_width, 4] - name_box_shape = [model_name + "@box_shape"] - node_box_shape = onnx.helper.make_node( - 'Constant', - inputs=[], - outputs=name_box_shape, - value=onnx.helper.make_tensor( - name=name_box_shape[0] + "@const", - data_type=onnx.TensorProto.INT64, - dims=[len(box_shape)], - vals=box_shape)) - node_list.append(node_box_shape) - - outputs_pred_box_new_shape = [model_name + "@pred_box_new_shape"] - node_pred_box_new_shape = onnx.helper.make_node( - 'Reshape', - inputs=outputs_pred_box_mul_conf + name_box_shape, - outputs=outputs_pred_box_new_shape) - node_list.append(node_pred_box_new_shape) - - outputs_pred_box_x = [model_name + "@_pred_box_x"] - outputs_pred_box_y = [model_name + "@_pred_box_y"] - outputs_pred_box_w = [model_name + "@_pred_box_w"] - outputs_pred_box_h = [model_name + "@_pred_box_h"] - - node_pred_box_split = onnx.helper.make_node( - 'Split', - inputs=outputs_pred_box_new_shape, - outputs=outputs_pred_box_x + outputs_pred_box_y + outputs_pred_box_w + - outputs_pred_box_h, - axis=2) - node_list.append(node_pred_box_split) - - name_number_two = [model_name + "@number_two"] - node_number_two = onnx.helper.make_node( - "Constant", - inputs=[], - outputs=name_number_two, - value=onnx.helper.make_tensor( - name=name_number_two[0] + "@const", - data_type=onnx.TensorProto.FLOAT, - dims=(), - vals=[2])) - node_list.append(node_number_two) - - outputs_half_w = [model_name + "@half_w"] - node_half_w = onnx.helper.make_node( - "Div", - inputs=outputs_pred_box_w + name_number_two, - outputs=outputs_half_w) - node_list.append(node_half_w) - - outputs_half_h = [model_name + "@half_h"] - node_half_h = onnx.helper.make_node( - "Div", - inputs=outputs_pred_box_h + name_number_two, - outputs=outputs_half_h) - node_list.append(node_half_h) - - outputs_pred_box_x1 = [model_name + "@pred_box_x1"] - node_pred_box_x1 = onnx.helper.make_node( - 'Sub', - inputs=outputs_pred_box_x + outputs_half_w, - outputs=outputs_pred_box_x1) - node_list.append(node_pred_box_x1) - - outputs_pred_box_y1 = [model_name + "@pred_box_y1"] - node_pred_box_y1 = onnx.helper.make_node( - 'Sub', - inputs=outputs_pred_box_y + outputs_half_h, - outputs=outputs_pred_box_y1) - node_list.append(node_pred_box_y1) - - outputs_pred_box_x2 = [model_name + "@pred_box_x2"] - node_pred_box_x2 = onnx.helper.make_node( - 'Add', - inputs=outputs_pred_box_x + outputs_half_w, - outputs=outputs_pred_box_x2) - node_list.append(node_pred_box_x2) - - outputs_pred_box_y2 = [model_name + "@pred_box_y2"] - node_pred_box_y2 = onnx.helper.make_node( - 'Add', - inputs=outputs_pred_box_y + outputs_half_h, - outputs=outputs_pred_box_y2) - node_list.append(node_pred_box_y2) - - outputs_sqeeze_image_size = [model_name + "@sqeeze_image_size"] - node_sqeeze_image_size = onnx.helper.make_node( - "Squeeze", - axes=[0], - inputs=image_size, - outputs=outputs_sqeeze_image_size) - node_list.append(node_sqeeze_image_size) - - output_img_height = [model_name + "@img_height"] - output_img_width = [model_name + "@img_width"] - node_image_size_split = onnx.helper.make_node( - "Split", - inputs=outputs_sqeeze_image_size, - outputs=output_img_height + output_img_width, - axis=-1, - split=[1, 1]) - node_list.append(node_image_size_split) - - output_img_width_cast = [model_name + "@img_width_cast"] - node_img_width_cast = onnx.helper.make_node( - 'Cast', inputs=output_img_width, outputs=output_img_width_cast, to=1) - node_list.append(node_img_width_cast) - - output_img_height_cast = [model_name + "@img_height_cast"] - node_img_height_cast = onnx.helper.make_node( - 'Cast', inputs=output_img_height, outputs=output_img_height_cast, to=1) - node_list.append(node_img_height_cast) - - outputs_pred_box_x1_decode = [model_name + "@pred_box_x1_decode"] - outputs_pred_box_y1_decode = [model_name + "@pred_box_y1_decode"] - outputs_pred_box_x2_decode = [model_name + "@pred_box_x2_decode"] - outputs_pred_box_y2_decode = [model_name + "@pred_box_y2_decode"] - - node_pred_box_x1_decode = onnx.helper.make_node( - 'Mul', - inputs=outputs_pred_box_x1 + output_img_width_cast, - outputs=outputs_pred_box_x1_decode) - node_list.append(node_pred_box_x1_decode) - - node_pred_box_y1_decode = onnx.helper.make_node( - 'Mul', - inputs=outputs_pred_box_y1 + output_img_height_cast, - outputs=outputs_pred_box_y1_decode) - node_list.append(node_pred_box_y1_decode) - - node_pred_box_x2_decode = onnx.helper.make_node( - 'Mul', - inputs=outputs_pred_box_x2 + output_img_width_cast, - outputs=outputs_pred_box_x2_decode) - node_list.append(node_pred_box_x2_decode) - - node_pred_box_y2_decode = onnx.helper.make_node( - 'Mul', - inputs=outputs_pred_box_y2 + output_img_height_cast, - outputs=outputs_pred_box_y2_decode) - node_list.append(node_pred_box_y2_decode) - - name_number_one = [model_name + "@one"] - node_number_one = onnx.helper.make_node( - 'Constant', - inputs=[], - outputs=name_number_one, - value=onnx.helper.make_tensor( - name=name_number_one[0] + "@const", - data_type=onnx.TensorProto.FLOAT, - dims=(), - vals=[1])) - node_list.append(node_number_one) - - output_new_img_height = [model_name + "@new_img_height"] - node_new_img_height = onnx.helper.make_node( - 'Sub', - inputs=output_img_height_cast + name_number_one, - outputs=output_new_img_height) - node_list.append(node_new_img_height) - - output_new_img_width = [model_name + "@new_img_width"] - node_new_img_width = onnx.helper.make_node( - 'Sub', - inputs=output_img_width_cast + name_number_one, - outputs=output_new_img_width) - node_list.append(node_new_img_width) - - outputs_pred_box_x2_sub_w = [model_name + "@pred_box_x2_sub_w"] - node_pred_box_x2_sub_w = onnx.helper.make_node( - 'Sub', - inputs=outputs_pred_box_x2_decode + output_new_img_width, - outputs=outputs_pred_box_x2_sub_w) - node_list.append(node_pred_box_x2_sub_w) - - outputs_pred_box_y2_sub_h = [model_name + "@pred_box_y2_sub_h"] - node_pred_box_y2_sub_h = onnx.helper.make_node( - 'Sub', - inputs=outputs_pred_box_y2_decode + output_new_img_height, - outputs=outputs_pred_box_y2_sub_h) - node_list.append(node_pred_box_y2_sub_h) - - outputs_pred_box_x1_clip = [model_name + "@pred_box_x1_clip"] - outputs_pred_box_y1_clip = [model_name + "@pred_box_y1_clip"] - outputs_pred_box_x2_clip = [model_name + "@pred_box_x2_clip"] - outputs_pred_box_y2_clip = [model_name + "@pred_box_y2_clip"] - - node_pred_box_x1_clip = onnx.helper.make_node( - 'Clip', - inputs=outputs_pred_box_x1_decode, - outputs=outputs_pred_box_x1_clip, - min=0.0, - max=float(np.inf)) - node_list.append(node_pred_box_x1_clip) - - node_pred_box_y1_clip = onnx.helper.make_node( - 'Clip', - inputs=outputs_pred_box_y1_decode, - outputs=outputs_pred_box_y1_clip, - min=0.0, - max=float(np.inf)) - node_list.append(node_pred_box_y1_clip) - - node_pred_box_x2_clip = onnx.helper.make_node( - 'Clip', - inputs=outputs_pred_box_x2_sub_w, - outputs=outputs_pred_box_x2_clip, - min=0.0, - max=float(np.inf)) - node_list.append(node_pred_box_x2_clip) - - node_pred_box_y2_clip = onnx.helper.make_node( - 'Clip', - inputs=outputs_pred_box_y2_sub_h, - outputs=outputs_pred_box_y2_clip, - min=0.0, - max=float(np.inf)) - node_list.append(node_pred_box_y2_clip) - - outputs_pred_box_x2_res = [model_name + "@box_x2_res"] - node_pred_box_x2_res = onnx.helper.make_node( - 'Sub', - inputs=outputs_pred_box_x2_decode + outputs_pred_box_x2_clip, - outputs=outputs_pred_box_x2_res) - node_list.append(node_pred_box_x2_res) - - outputs_pred_box_y2_res = [model_name + "@box_y2_res"] - node_pred_box_y2_res = onnx.helper.make_node( - 'Sub', - inputs=outputs_pred_box_y2_decode + outputs_pred_box_y2_clip, - outputs=outputs_pred_box_y2_res) - node_list.append(node_pred_box_y2_res) - - node_pred_box_result = onnx.helper.make_node( - 'Concat', - inputs=outputs_pred_box_x1_clip + outputs_pred_box_y1_clip + - outputs_pred_box_x2_res + outputs_pred_box_y2_res, - outputs=outputs['Boxes'], - axis=-1) - node_list.append(node_pred_box_result) - - score_shape = [1, input_height * input_width * int(num_anchors), class_num] - name_score_shape = [model_name + "@score_shape"] - node_score_shape = onnx.helper.make_node( - "Constant", - inputs=[], - outputs=name_score_shape, - value=onnx.helper.make_tensor( - name=name_score_shape[0] + "@const", - data_type=onnx.TensorProto.INT64, - dims=[len(score_shape)], - vals=score_shape)) - node_list.append(node_score_shape) - - node_score_new_shape = onnx.helper.make_node( - 'Reshape', - inputs=outputs_score + name_score_shape, - outputs=outputs['Scores']) - node_list.append(node_score_new_shape) - return node_list diff --git a/x2paddle/op_mapper/paddle_op_mapper.py b/x2paddle/op_mapper/paddle_op_mapper.py deleted file mode 100644 index dafbfe60f9ff3d96ef276f74da51d13212b3893f..0000000000000000000000000000000000000000 --- a/x2paddle/op_mapper/paddle_op_mapper.py +++ /dev/null @@ -1,850 +0,0 @@ -# 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 x2paddle -import os -import numpy as np -import paddle.fluid.core as core -import paddle.fluid as fluid -import onnx -from onnx import helper, onnx_pb - - -class PaddleOpMapper(object): - def __init__(self): - self.paddle_onnx_dtype_map = { - core.VarDesc.VarType.FP32: onnx_pb.TensorProto.FLOAT, - core.VarDesc.VarType.FP64: onnx_pb.TensorProto.DOUBLE, - core.VarDesc.VarType.INT32: onnx_pb.TensorProto.INT32, - core.VarDesc.VarType.INT16: onnx_pb.TensorProto.INT16, - core.VarDesc.VarType.INT16: onnx_pb.TensorProto.UINT16, - core.VarDesc.VarType.INT64: onnx_pb.TensorProto.INT64, - core.VarDesc.VarType.BOOL: onnx_pb.TensorProto.BOOL - } - - self.name_counter = dict() - - def convert(self, program, save_dir, opset=10): - weight_nodes = self.convert_weights(program) - op_nodes = list() - input_nodes = list() - output_nodes = list() - unsupported_ops = set() - - print("Translating PaddlePaddle to ONNX...\n") - for block in program.blocks: - for i, op in enumerate(block.ops): - sys.stdout.write( - "\rTotal:{}, Current:{} : {} ".format( - len(block.ops), i + 1, op.type)) - sys.stdout.flush() - if not hasattr(self, op.type): - unsupported_ops.add(op.type) - continue - if len(unsupported_ops) > 0: - continue - node = getattr(self, op.type)(op, block) - if op.type == 'feed': - input_nodes.append(node) - elif op.type == 'fetch': - output_nodes.append(node) - else: - if isinstance(node, list): - op_nodes = op_nodes + node - else: - op_nodes.append(node) - - if len(unsupported_ops) > 0: - print("\nThere's {} ops are not supported yet".format( - len(unsupported_ops))) - for op in unsupported_ops: - print("=========== {} ===========".format(op)) - return - - graph = helper.make_graph( - nodes=weight_nodes + op_nodes, - name='onnx_model_from_paddle', - initializer=[], - inputs=input_nodes, - outputs=output_nodes) - opset_imports = [helper.make_opsetid("", opset)] - model = helper.make_model( - graph, producer_name='X2Paddle', opset_imports=opset_imports) - onnx.checker.check_model(model) - - if not os.path.isdir(save_dir): - os.makedirs(save_dir) - with open(os.path.join(save_dir, 'x2paddle_model.onnx'), 'wb') as f: - f.write(model.SerializeToString()) - print("\nTranslated model saved in {}".format( - os.path.join(save_dir, 'x2paddle_model.onnx'))) - - def get_name(self, op_name, var_name): - name = 'p2o.{}.{}'.format(op_name, var_name) - if name not in self.name_counter: - self.name_counter[name] = 0 - else: - self.name_counter[name] += 1 - return name + '.{}'.format(self.name_counter[name]) - - def convert_weights(self, program): - var_names = program.global_block().vars - nodes = list() - for name in var_names: - var = program.global_block().var(name) - if name.endswith('feed') or name.endswith('fetch'): - continue - if not var.persistable: - continue - weight = np.array(fluid.global_scope().find_var(name).get_tensor()) - tensor = helper.make_tensor( - name=name, - dims=var.shape, - data_type=self.paddle_onnx_dtype_map[var.dtype], - vals=weight.flatten().tolist()) - node = helper.make_node( - 'Constant', inputs=[], outputs=[name], value=tensor) - nodes.append(node) - return nodes - - def make_constant_node(self, name, dtype, value=None): - if isinstance(value, list): - dims = (len(value), ) - elif value is None: - dims = () - value = [] - else: - dims = () - value = [value] - tensor = helper.make_tensor( - name=name, data_type=dtype, dims=dims, vals=value) - node = helper.make_node( - 'Constant', inputs=[], outputs=[name], value=tensor) - return node - - def conv2d(self, op, block): - kernel_shape = block.var(op.input('Filter')[0]).shape - node = helper.make_node( - 'Conv', - inputs=op.input('Input') + op.input('Filter'), - outputs=op.output('Output'), - dilations=op.attr('dilations'), - kernel_shape=kernel_shape[-2:], - strides=op.attr('strides'), - group=op.attr('groups'), - pads=op.attr('paddings') + op.attr('paddings')) - return node - - def conv2d_transpose(self, op, block): - kernel_shape = block.var(op.input('Filter')[0]).shape - node = helper.make_node( - 'ConvTranspose', - inputs=op.input('Input') + op.input('Filter'), - outputs=op.output('Output'), - dilations=op.attr('dilations'), - kernel_shape=kernel_shape[-2:], - strides=op.attr('strides'), - group=1, - pads=op.attr('paddings') + op.attr('paddings')) - return node - - def relu(self, op, block): - node = helper.make_node( - 'Relu', inputs=op.input('X'), outputs=op.output('Out')) - return node - - def sigmoid(self, op, block): - node = helper.make_node( - 'Sigmoid', inputs=op.input('X'), outputs=op.output('Out')) - return node - - def exp(self, op, block): - node = helper.make_node( - 'Exp', inputs=op.input('X'), outputs=op.output('Out')) - return node - - def leaky_relu(self, op, block): - node = helper.make_node( - 'LeakyRelu', - inputs=op.input('X'), - outputs=op.output('Out'), - alpha=op.attr('alpha')) - return node - - def swish(self, op, block): - """ - The activation swish, y = x / (1 + exp(-beta * x)) - """ - beta = op.attr('beta') - beta_name = self.get_name(op.type, 'beta') - beta_node = onnx.helper.make_node( - 'Constant', - name=beta_name, - inputs=[], - outputs=[beta_name], - value=onnx.helper.make_tensor( - name=beta_name, - data_type=onnx.TensorProto.FLOAT, - dims=(), - vals=[beta])) - - beta_x_name = self.get_name(op.type, 'beta_x') - beta_x_node = onnx.helper.make_node( - 'Mul', - name=beta_x_name, - inputs=[op.input('X')[0], beta_name], - outputs=[beta_x_name]) - sigmoid_name = self.get_name(op.type, 'sigmoid') - sigmoid_node = onnx.helper.make_node( - 'Sigmoid', - name=sigmoid_name, - inputs=[beta_x_name], - outputs=[sigmoid_name]) - swish_node = onnx.helper.make_node( - 'Mul', - inputs=[op.input('X')[0], sigmoid_name], - outputs=op.output('Out')) - return [beta_node, beta_x_node, sigmoid_node, swish_node] - - def elementwise_add(self, op, block): - axis = op.attr('axis') - x_shape = block.var(op.input('X')[0]).shape - y_shape = block.var(op.input('Y')[0]).shape - if len(y_shape) == 1 and axis == 1: - shape_name = self.get_name(op.type, 'shape') - shape_value = [1] * len(x_shape) - shape_value[axis] = y_shape[0] - shape_node = self.make_constant_node( - shape_name, onnx_pb.TensorProto.INT64, shape_value) - temp_value = self.get_name(op.type, 'temp') - y_node = helper.make_node( - 'Reshape', - inputs=[op.input('Y')[0], shape_name], - outputs=[temp_value]) - node = helper.make_node( - 'Add', - inputs=[op.input('X')[0], temp_value], - outputs=op.output('Out')) - return [shape_node, y_node, node] - elif len(x_shape) == len(y_shape): - node = helper.make_node( - 'Add', - inputs=[op.input('X')[0], op.input('Y')[0]], - outputs=op.output('Out')) - return node - else: - raise Excpetion("Unexpected situation happend in elementwise_add") - - def elementwise_sub(self, op, block): - axis = op.attr('axis') - x_shape = block.var(op.input('X')[0]).shape - y_shape = block.var(op.input('Y')[0]).shape - if len(y_shape) == 1 and axis == 1: - shape_name = self.get_name(op.type, 'shape') - shape_value = [1] * len(x_shape) - shape_value[axis] = y_shape[0] - shape_node = self.make_constant_node( - shape_name, onnx_pb.TensorProto.INT64, shape_value) - temp_value = self.get_name(op.type, 'temp') - y_node = helper.make_node( - 'Reshape', - inputs=[op.input('Y')[0], shape_name], - outputs=[temp_value]) - node = helper.make_node( - 'Sub', - inputs=[op.input('X')[0], temp_value], - outputs=op.output('Out')) - return [shape_node, y_node, node] - elif len(x_shape) == len(y_shape): - node = helper.make_node( - 'Sub', - inputs=[op.input('X')[0], op.input('Y')[0]], - outputs=op.output('Out')) - return node - else: - raise Excpetion("Unexpected situation happend in elementwise_sub") - - def pool2d(self, op, block): - pool_type = { - 'max': ('MaxPool', 'GlobalMaxPool'), - 'avg': ('AveragePool', 'GlobalAveragePool') - } - if op.attr('global_pooling'): - node = helper.make_node( - pool_type[op.attr('pooling_type')][1], - inputs=op.input('X'), - outputs=op.output('Out'), ) - else: - input_shape = block.var(op.input('X')[0]).shape - k_size = op.attr('ksize') - paddings = op.attr('paddings') - if input_shape[2] > 0 and input_shape[2] + paddings[0] < k_size[0]: - k_size[0] = input_shape[2] + paddings[0] - if input_shape[3] > 0 and input_shape[3] + paddings[1] < k_size[1]: - k_size[1] = input_shape[3] + paddings[1] - node = helper.make_node( - pool_type[op.attr('pooling_type')][0], - inputs=op.input('X'), - outputs=op.output('Out'), - kernel_shape=k_size, - strides=op.attr('strides'), - pads=op.attr('paddings') + op.attr('paddings')) - return node - - def softmax(self, op, block): - axis = op.attr('axis') - shape = block.var(op.output('Out')[0]).shape - if axis < 0: - axis += len(shape) - if axis == len(shape) - 1: - node = helper.make_node( - 'Softmax', - inputs=op.input('X'), - outputs=op.output('Out'), - axis=op.attr('axis')) - return node - else: - perm = [i for i in range(len(shape))] - perm[-1] = axis - perm[axis] = len(shape) - 1 - transpose_name0 = self.get_name(op.type, 'transpose') - transpose_node0 = helper.make_node( - 'Transpose', - inputs=op.input('X'), - outputs=[transpose_name0], - perm=perm) - softmax_name = self.get_name(op.type, 'softmax') - softmax_node = helper.make_node( - 'Softmax', - inputs=[transpose_name0], - outputs=[softmax_name], - axis=-1) - transpose_name1 = self.get_name(op.type, 'transpose') - transpose_node1 = helper.make_node( - 'Transpose', - inputs=[softmax_name], - outputs=op.output('Out'), - perm=perm) - return [transpose_node0, softmax_node, transpose_node1] - - def scale(self, op, block): - scale = op.attr('scale') - bias = op.attr('bias') - if math.fabs(scale - 1.0) < 1e-06 and math.fabs(bias - 0.0) < 1e-06: - name = op.output('Out')[0] - var = block.var(name) - dtype = self.paddle_onnx_dtype_map[var.dtype] - node = helper.make_node( - 'Cast', - inputs=op.input('X'), - outputs=op.output('Out'), - to=dtype) - #node = helper.make_node( - # 'Identity', inputs=op.input('X'), outputs=op.output('Out')) - return node - else: - scale_name = self.get_name(op.type, 'scale') - bias_name = self.get_name(op.type, 'bias') - scale_node = self.make_constant_node( - scale_name, onnx_pb.TensorProto.FLOAT, scale) - bias_node = self.make_constant_node(bias_name, - onnx_pb.TensorProto.FLOAT, bias) - temp_tensor_name = self.get_name(op.type, 'temporary') - if op.attr('bias_after_scale'): - node1 = helper.make_node( - 'Mul', - inputs=[scale_name, op.input('X')[0]], - outputs=[temp_tensor_name]) - node2 = helper.make_node( - 'Add', - inputs=[bias_name, temp_tensor_name], - outputs=op.output('Out')) - else: - node1 = helper.make_node( - 'Add', - inputs=[bias_name, op.input('X')[0]], - outputs=temp_tensor_name) - node2 = helper.make_node( - 'Mul', - inputs=[scale_name, temp_tensor_name], - outputs=[op.output('Out')]) - return [scale_node, bias_node, node1, node2] - - def mul(self, op, block): - x_shape = block.var(op.input('X')[0]).shape - y_shape = block.var(op.input('Y')[0]).shape - out_shape = list(block.var(op.output('Out')[0]).shape) - x_num_col_dims = op.attr('x_num_col_dims') - y_num_col_dims = op.attr('y_num_col_dims') - flatten_x_name = 'flatten_{}'.format(op.input('X')[0]) - flatten_y_name = 'flatten_{}'.format(op.input('Y')[0]) - shape_name = 'temp_shape_{}'.format(op.output('Out')[0]) - temp_out_name = 'temp_{}'.format(op.output('Out')[0]) - flatten_x = helper.make_node( - 'Flatten', - inputs=op.input('X'), - outputs=[flatten_x_name], - axis=x_num_col_dims) - flatten_y = helper.make_node( - 'Flatten', - inputs=op.input('Y'), - outputs=[flatten_y_name], - axis=y_num_col_dims) - shape_node = self.make_constant_node( - shape_name, onnx_pb.TensorProto.INT64, out_shape) - node = helper.make_node( - 'MatMul', - inputs=[flatten_x_name, flatten_y_name], - outputs=[temp_out_name]) - reshape_out = helper.make_node( - 'Reshape', - inputs=[temp_out_name, shape_name], - outputs=op.output('Out')) - return [flatten_x, flatten_y, shape_node, node, reshape_out] - - def batch_norm(self, op, block): - kwargs = { - 'epsilon': op.attr('epsilon'), - 'momentum': op.attr('momentum') - } - inputs = op.input('X') + op.input('Scale') + op.input( - 'Bias') + op.input('Mean') + op.input('Variance') - node = helper.make_node( - 'BatchNormalization', - inputs=inputs, - outputs=op.output('Y'), - **kwargs) - return node - - def concat(self, op, block): - node = helper.make_node( - 'Concat', - inputs=op.input('X'), - outputs=op.output('Out'), - axis=op.attr('axis')) - return node - - def depthwise_conv2d(self, op, block): - return self.conv2d(op, block) - - def relu6(self, op, block): - min_name = self.get_name(op.type, 'min') - max_name = self.get_name(op.type, 'max') - min_node = self.make_constant_node(min_name, onnx_pb.TensorProto.FLOAT, - 0) - max_node = self.make_constant_node(max_name, onnx_pb.TensorProto.FLOAT, - op.attr('threshold')) - node = helper.make_node( - 'Clip', - inputs=[op.input('X')[0], min_name, max_name], - outputs=op.output('Out'), ) - return [min_node, max_node, node] - - def shape(self, op, block): - node = helper.make_node( - 'Shape', inputs=op.input('Input'), outputs=op.output('Out')) - return node - - def split(self, op, block): - sections = op.attr('sections') - if len(sections) > 0: - node = helper.make_node( - 'Split', - inputs=op.input('X'), - outputs=op.output('Out'), - axis=op.attr('axis'), - split=sections) - else: - node = helper.make_node( - 'Split', - inputs=op.input('X'), - outputs=op.output('Out'), - axis=op.attr('axis')) - return node - - def slice(self, op, block): - axes = op.attr('axes') - starts = op.attr('starts') - ends = op.attr('ends') - axes_name = self.get_name(op.type, 'axes') - starts_name = self.get_name(op.type, 'starts') - ends_name = self.get_name(op.type, 'ends') - - axes_node = self.make_constant_node(axes_name, - onnx_pb.TensorProto.INT64, axes) - starts_node = self.make_constant_node(starts_name, - onnx_pb.TensorProto.INT64, starts) - ends_node = self.make_constant_node(ends_name, - onnx_pb.TensorProto.INT64, ends) - node = helper.make_node( - "Slice", - inputs=[op.input('Input')[0], starts_name, ends_name, axes_name], - outputs=op.output('Out'), ) - return [starts_node, ends_node, axes_node, node] - - def fill_constant(self, op, block): - value = op.attr('value') - dtype = op.attr('dtype') - shape = op.attr('shape') - value = np.ones(shape) * value - if dtype == 2: - value = value.astype('int32') - node = helper.make_node( - 'Constant', - inputs=[], - outputs=op.output('Out'), - value=helper.make_tensor( - name=op.output('Out')[0], - data_type=self.paddle_onnx_dtype_map[dtype], - dims=shape, - vals=value.tolist())) - return node - - def transpose2(self, op, block): - node = helper.make_node( - 'Transpose', - inputs=op.input('X'), - outputs=op.output('Out'), - perm=op.attr('axis')) - return node - - def reshape2(self, op, block): - input_names = op.input_names - if len(op.input('ShapeTensor')) > 1: - cast_shape_nodes = list() - cast_shape_names = list() - for i in range(len(op.input('ShapeTensor'))): - dim = op.input('ShapeTensor')[i] - temp_name = self.get_name(op.type, 'shape.cast') - node = helper.make_node( - 'Cast', - inputs=[dim], - outputs=[temp_name], - to=onnx_pb.TensorProto.INT64) - cast_shape_nodes.append(node) - cast_shape_names.append(temp_name) - - temp_name = self.get_name(op.type, 'shape.concat') - shape_node = helper.make_node( - 'Concat', inputs=cast_shape_names, outputs=[temp_name], axis=-1) - node = helper.make_node( - 'Reshape', - inputs=[op.input('X')[0], temp_name], - outputs=op.output('Out')) - return cast_shape_nodes + [shape_node, node] - else: - temp_name = self.get_name(op.type, 'shape.cast') - cast_shape_node = helper.make_node( - 'Cast', - inputs=op.input('ShapeTensor'), - outputs=[temp_name], - to=onnx_pb.TensorProto.INT64) - node = helper.make_node( - 'Reshape', - inputs=[op.input('X')[0], temp_name], - outputs=op.output('Out')) - return [cast_shape_node, node] - - def dropout(self, op, block): - dropout_mode = op.attr('dropout_implementation') - dropout_prob = op.attr('dropout_prob') - if dropout_mode == 'upscale_in_train': - node = helper.make_node( - 'Identity', inputs=op.input('X'), outputs=op.output('Out')) - return node - elif dropout_mode == 'downgrade_in_infer': - scale_name = self.get_name(op.type, 'scale') - scale_node = self.make_constant_node( - scale_name, onnx_pb.TensorProto.FLOAT, 1 - dropout_prob) - node = helper.make_node( - "Mul", - inputs=[op.input('X')[0], scale_name], - outputs=op.output('Out')) - return [scale_node, node] - else: - raise Exception("Unexpected situation happend") - - def reduce_mean(self, op, block): - node = helper.make_node( - 'ReduceMean', - inputs=op.input('X'), - outputs=op.output('Out'), - axes=op.attr('dim'), - keepdims=op.attr('keep_dim')) - return node - - def bilinear_interp(self, op, block): - input_names = op.input_names - input_shape = block.vars[op.input('X')[0]].shape - if ('OutSize' in input_names and len(op.input('OutSize')) > 0) or ( - 'SizeTensor' in input_names and - len(op.input('SizeTensor')) > 0): - node_list = list() - shape_name0 = self.get_name(op.type, 'shape') - shape_node0 = helper.make_node( - 'Shape', inputs=op.input('X'), outputs=[shape_name0]) - starts_name = self.get_name(op.type, 'slice.starts') - starts_node = self.make_constant_node( - starts_name, onnx_pb.TensorProto.INT64, [0]) - ends_name = self.get_name(op.type, 'slice.ends') - ends_node = self.make_constant_node(ends_name, - onnx_pb.TensorProto.INT64, [2]) - shape_name1 = self.get_name(op.type, 'shape') - shape_node1 = helper.make_node( - 'Slice', - inputs=[shape_name0, starts_name, ends_name], - outputs=[shape_name1]) - node_list.extend([shape_node0, starts_node, ends_node, shape_node1]) - if 'OutSize' in input_names and len(op.input('OutSize')) > 0: - cast_shape_name = self.get_name(op.type, "shape.cast") - cast_shape_node = helper.make_node( - 'Cast', - inputs=op.input('OutSize'), - outputs=[cast_shape_name], - to=onnx_pb.TensorProto.INT64) - node_list.append(cast_shape_node) - else: - concat_shape_name = self.get_name( - op.type, op.output('Out')[0] + "shape.concat") - concat_shape_node = helper.make_node( - "Concat", - inputs=op.input('SizeTensor'), - outputs=[concat_shape_name], - axis=0) - cast_shape_name = self.get_name(op.type, "shape.cast") - cast_shape_node = helper.make_node( - 'Cast', - inputs=[concat_shape_name], - outputs=[cast_shape_name], - to=onnx_pb.TensorProto.INT64) - node_list.extend([concat_shape_node, cast_shape_node]) - shape_name2 = self.get_name(op.type, "shape.concat") - shape_node2 = helper.make_node( - 'Concat', - inputs=[shape_name1, cast_shape_name], - outputs=[shape_name2], - axis=0) - node_list.append(shape_node2) - cast_shape_name2 = self.get_name(op.type, "shape.cast") - cast_shape_node2 = helper.make_node( - 'Cast', - inputs=[shape_name2], - outputs=[cast_shape_name2], - to=onnx_pb.TensorProto.FLOAT) - node_list.append(cast_shape_node2) - cast_shape_name0 = self.get_name(op.type, "shape.cast") - cast_shape_node0 = helper.make_node( - 'Cast', - inputs=[shape_name0], - outputs=[cast_shape_name0], - to=onnx_pb.TensorProto.FLOAT) - node_list.append(cast_shape_node0) - outputs_h_w_scales = op.output('Out')[0] + "@out_hw_scales" - node_h_w_scales = helper.make_node( - 'Div', - inputs=[cast_shape_name2, cast_shape_name0], - outputs=[outputs_h_w_scales]) - node_list.append(node_h_w_scales) - result_node = helper.make_node( - 'Resize', - inputs=[op.input('X')[0], outputs_h_w_scales], - outputs=op.output('Out'), - mode='linear') - node_list.extend([result_node]) - return node_list - elif 'Scale' in input_names and len(op.input('Scale')) > 0: - node = helper.make_node( - 'Resize', - inputs=[op.input('X')[0], op.input('Scale')[0]], - outputs=op.output('Out'), - mode='linear') - else: - out_shape = [op.attr('out_h'), op.attr('out_w')] - scale = op.attr('scale') - if out_shape.count(-1) > 0: - scale_name = self.get_name(op.type, 'scale') - scale_node = self.make_constant_node(scale_name, - onnx_pb.TensorProto.FLOAT, - [1, 1, scale, scale]) - node = helper.make_node( - 'Resize', - inputs=[op.input('X')[0], scale_name], - outputs=op.output('Out'), - mode='linear') - return [scale_node, node] - else: - raise Exception("Unexpected situation happend") - return node - - def nearest_interp(self, op, block): - input_names = op.input_names - if 'OutSize' in input_names and len(op.input('OutSize')) > 0: - node = helper.make_node( - 'Resize', - inputs=[op.input('X')[0], op.input('OutSize')[0]], - outputs=op.output('Out'), - mode='nearest') - elif 'Scale' in input_names and len(op.input('Scale')) > 0: - node = helper.make_node( - 'Resize', - inputs=[op.input('X')[0], op.input('Scale')[0]], - outputs=op.output('Out'), - mode='nearest') - else: - out_shape = [op.attr('out_h'), op.attr('out_w')] - scale = op.attr('scale') - if out_shape.count(-1) > 0: - scale_name = self.get_name(op.type, 'scale') - scale_node = self.make_constant_node(scale_name, - onnx_pb.TensorProto.FLOAT, - [1, 1, scale, scale]) - node = helper.make_node( - 'Resize', - inputs=[op.input('X')[0], scale_name], - outputs=op.output('Out'), - mode='nearest') - return [scale_node, node] - else: - raise Exception("Unexpected situation happend") - return node - - def hard_sigmoid(self, op, block): - slope = op.attr('slope') - offset = op.attr('offset') - node = helper.make_node( - 'HardSigmoid', - inputs=op.input('X'), - outputs=op.output('Out'), - alpha=slope, - beta=offset) - return node - - def hard_swish(self, op, block): - min_name = self.get_name(op.type, 'min') - max_name = self.get_name(op.type, 'max') - scale_name = self.get_name(op.type, 'scale') - offset_name = self.get_name(op.type, 'offset') - min_node = self.make_constant_node(min_name, onnx_pb.TensorProto.FLOAT, - 0) - max_node = self.make_constant_node(max_name, onnx_pb.TensorProto.FLOAT, - op.attr('threshold')) - scale_node = self.make_constant_node(scale_name, - onnx_pb.TensorProto.FLOAT, - op.attr('scale')) - offset_node = self.make_constant_node(offset_name, - onnx_pb.TensorProto.FLOAT, - op.attr('offset')) - - name0 = self.get_name(op.type, 'add') - node0 = helper.make_node( - 'Add', inputs=[op.input('X')[0], offset_name], outputs=[name0]) - name1 = self.get_name(op.type, 'relu') - node1 = helper.make_node( - 'Clip', - inputs=[name0, min_name, max_name], - outputs=[name1], ) - name2 = self.get_name(op.type, 'mul') - node2 = helper.make_node( - 'Mul', inputs=[op.input('X')[0], name1], outputs=[name2]) - node3 = helper.make_node( - 'Div', inputs=[name2, scale_name], outputs=op.output('Out')) - return [ - min_node, max_node, scale_node, offset_node, node0, node1, node2, - node3 - ] - - def elementwise_mul(self, op, block): - axis = op.attr('axis') - x_shape = block.var(op.input('X')[0]).shape - y_shape = block.var(op.input('Y')[0]).shape - if len(y_shape) == 1 and axis == 1: - shape_name = self.get_name(op.type, 'shape') - shape_value = [1] * len(x_shape) - shape_value[axis] = y_shape[0] - shape_node = self.make_constant_node( - shape_name, onnx_pb.TensorProto.INT64, shape_value) - temp_value = self.get_name(op.type, 'temp') - y_node = helper.make_node( - 'Reshape', - inputs=[op.input('Y')[0], shape_name], - outputs=[temp_value]) - node = helper.make_node( - 'Mul', - inputs=[op.input('X')[0], temp_value], - outputs=op.output('Out')) - return [shape_node, y_node, node] - elif len(x_shape) == len(y_shape): - node = helper.make_node( - 'Mul', - inputs=[op.input('X')[0], op.input('Y')[0]], - outputs=op.output('Out')) - return node - else: - raise Excpetion("Unexpected situation happend in elementwise_add") - return node - - def feed(self, op, block): - name = op.output('Out')[0] - var = block.var(name) - tensor_info = helper.make_tensor_value_info( - name=name, - shape=var.shape, - elem_type=self.paddle_onnx_dtype_map[var.dtype]) - return tensor_info - - def fetch(self, op, block): - name = op.input('X')[0] - var = block.var(name) - tensor_info = helper.make_tensor_value_info( - name=name, - shape=var.shape, - elem_type=self.paddle_onnx_dtype_map[var.dtype]) - return tensor_info - - def unsqueeze2(self, op, block): - node = helper.make_node( - 'Unsqueeze', - inputs=op.input('X'), - outputs=op.output('Out'), - axes=op.attr('axes')) - return node - - def arg_max(self, op, block): - node = helper.make_node( - 'ArgMax', - inputs=op.input('X'), - outputs=op.output('Out'), - axis=op.attr('axis'), - keepdims=0) - return node - - def reciprocal(self, op, block): - inputs = op.input(op.input_names[0]) - outputs = op.output(op.output_names[0]) - node = helper.make_node('Reciprocal', inputs=inputs, outputs=outputs) - return node - - def im2sequence(self, op, block): - from .paddle_custom_layer.im2sequence import im2sequence - return im2sequence(op, block) - - def yolo_box(self, op, block): - from .paddle_custom_layer.yolo_box import yolo_box - return yolo_box(op, block) - - def multiclass_nms(self, op, block): - from .paddle_custom_layer.multiclass_nms import multiclass_nms - return multiclass_nms(op, block)