opset.py 60.0 KB
Newer Older
1
# Copyright (c) 2019  PaddlePaddle Authors. All Rights Reserved.
C
update  
channingss 已提交
2 3 4 5 6 7 8 9 10 11 12 13 14
#
# 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.

C
Channingss 已提交
15
from x2paddle.decoder.onnx_decoder import ONNXGraph, ONNXGraphNode, ONNXGraphDataNode
C
update  
channingss 已提交
16 17 18
from x2paddle.core.graph import GraphNode
from x2paddle.core.fluid_code import Layer
from x2paddle.core.fluid_code import FluidCode
C
channingss 已提交
19
from x2paddle.core.util import string
C
Channingss 已提交
20
from x2paddle.op_mapper.onnx2paddle.opset9.custom_layer import *
C
Channingss 已提交
21
from functools import reduce
C
update  
channingss 已提交
22
import numpy as np
C
channingss 已提交
23
import onnx
C
channingss 已提交
24
import onnx.numpy_helper as numpy_helper
C
channingss 已提交
25
from onnx.mapping import TENSOR_TYPE_TO_NP_TYPE
C
update  
channingss 已提交
26
import logging as _logging
27
from collections import OrderedDict
C
channingss 已提交
28
import math
C
channingss 已提交
29 30
import os
import shutil
31

C
update  
channingss 已提交
32 33 34
_logger = _logging.getLogger(__name__)


C
Channingss 已提交
35
def _const_weight_or_none(node, necessary=False):
C
channings 已提交
36
    if 'Constant' in node.layer_type:
C
channingss 已提交
37
        return node.value
C
update  
channingss 已提交
38 39
    if isinstance(node, ONNXGraphDataNode):
        return node.weight
C
Channingss 已提交
40 41 42
    if necessary:
        assert '{} should be an initializer or Constant operator.'.format(
            node.layer_name)
C
update  
channingss 已提交
43 44 45
    return None


C
Channingss 已提交
46 47 48 49 50 51
def _is_static_shape(shape):
    negtive_dims = 0
    error_dims = 0
    for dim in shape:
        if dim < 0:
            negtive_dims += 1
C
update  
Channingss 已提交
52
        if dim < -1:
C
Channingss 已提交
53 54 55 56 57 58 59
            error_dims += 1
    if negtive_dims > 1:
        return False
    if error_dims > 0:
        return False
    return True

60

C
Channingss 已提交
61
def _get_same_padding(in_size, kernel_size, stride):
C
channingss 已提交
62 63 64 65 66 67 68
    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]


69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
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


C
Channingss 已提交
86
class OpSet9():
87 88 89 90 91
    elementwise_ops = {
        'Add': 'elementwise_add',
        'Div': 'elementwise_div',
        'Sub': 'elementwise_sub',
        'Mul': 'elementwise_mul',
R
root 已提交
92 93
        'Pow': 'elementwise_pow',
    }
94

95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
    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']],
        '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)
        ],
C
Channingss 已提交
121 122 123 124
        'ReduceMax': [
            'reduce_max', ['X'], ['Out'], dict(
                axes='dim', keepdims='keep_dim'), dict(keep_dim=1)
        ],
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
        #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']],
    }

C
Channingss 已提交
149
    default_ioa_constraint = {}
150 151

    def __init__(self, decoder):
C
Channingss 已提交
152
        super(OpSet9, self).__init__()
153
        self.graph = decoder.graph
C
update  
channingss 已提交
154 155 156
        self.input_shapes = []
        self.weights = dict()
        self.omit_nodes = list()
C
channingss 已提交
157
        self.used_custom_layers = dict()
R
root 已提交
158

159
    @print_mapping_info
C
channingss 已提交
160
    def directly_map(self, node, name='', *args, **kwargs):
C
update  
channingss 已提交
161 162 163 164
        inputs = node.layer.input
        outputs = node.layer.output
        op_type = node.layer_type
        attrs = node.attr_map
165 166 167
        info = self.default_op_mapping[op_type]
        info.extend(
            list(self.default_op_mapping_field_values.values())[len(info):])
C
update  
channingss 已提交
168 169 170 171 172 173 174 175
        (
            fluid_op,
            fluid_input_args,
            fluid_output_args,
            attr_mapping,
            default_attrs,
            input_perm,
            output_perm,
176
            fill_name_field, ) = info
C
update  
channingss 已提交
177

178 179
        if fluid_op in self.default_ioa_constraint:
            for predicate, message in self.default_ioa_constraint[fluid_op]:
C
update  
channingss 已提交
180 181 182 183 184 185 186 187 188 189 190 191
                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)
C
channingss 已提交
192
        inputs = inputs if input_perm is None else list(
C
update  
channingss 已提交
193
            map(lambda i: inputs[i], input_perm))
C
channingss 已提交
194 195 196 197
        val_inps = []
        for idx, ipt in enumerate(inputs):
            val_inps.append(self.graph.get_input_node(node, idx=idx, copy=True))

C
update  
channingss 已提交
198 199 200
        val_outs = outputs if output_perm is None else list(
            map(lambda i: outputs[i], output_perm))
        attr = fluid_attrs
C
channingss 已提交
201
        assert len(val_inps) == 1, 'directly_map error with multi inputs'
202
        if fluid_op not in ['shape', 'erf']:
C
update  
channingss 已提交
203
            attr['name'] = string(node.layer_name)
204 205 206 207 208 209 210 211 212 213
        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
C
channingss 已提交
214 215 216
    def deal_custom_layer(self, node):
        op = node.layer_type
        custom_code, func = make_custom_layer(node)
C
channingss 已提交
217
        child_func_code, child_func = make_custom_child_func(node)
C
channingss 已提交
218 219 220
        params = get_params(node.layer, node.layer_type)
        arg_names, kwargs = set_args(func, params)
        kwargs['name'] = string(node.layer_name)
221 222 223 224 225 226
        node.fluid_code.add_layer(
            func.__code__.co_name,
            inputs=node.inputs,
            output=node,
            param_attr=kwargs,
            is_custom_layer=True)
C
channingss 已提交
227 228
        if op not in self.used_custom_layers:
            self.used_custom_layers[op] = custom_code
C
channingss 已提交
229
            if op + '_child_func' not in self.used_custom_layers:
C
channingss 已提交
230 231 232
                if child_func_code is not None:
                    self.used_custom_layers[op +
                                            '_child_func'] = child_func_code
R
root 已提交
233

234
    @print_mapping_info
235 236 237
    def elementwise_map(self, node):
        assert node.layer_type in self.elementwise_ops
        op_type = self.elementwise_ops[node.layer_type]
R
root 已提交
238

239 240
        val_x = self.graph.get_input_node(node, idx=0, copy=True)
        val_y = self.graph.get_input_node(node, idx=1, copy=True)
241 242 243
        inputs = {'x': val_x, 'y': val_y}
        node.fluid_code.add_layer(
            op_type, inputs=inputs, output=node, param_attr=None)
C
channingss 已提交
244

245
    @print_mapping_info
C
update  
channingss 已提交
246
    def place_holder(self, node):
C
channingss 已提交
247
        self.input_shapes.append(node.out_shapes[0])
R
root 已提交
248

C
channings 已提交
249 250
        shape = node.out_shapes[0]
        for i, dim_shape in enumerate(shape):
R
root 已提交
251 252 253
            if dim_shape == 0 and i == 0:
                shape[i] = 1
            if dim_shape == 0 and i != 0:
C
channings 已提交
254
                assert 'shape of input is not assigned'
C
update  
channingss 已提交
255 256
        attr = {
            "dtype": string(node.dtype),
C
channings 已提交
257
            "shape": shape,
C
update  
channingss 已提交
258 259 260 261
            "name": string(node.layer_name),
            "append_batch_size": 'False'
        }

262 263
        node.fluid_code.add_layer(
            "data", inputs=None, output=node, param_attr=attr)
C
update  
channingss 已提交
264

265
    @print_mapping_info
C
update  
channingss 已提交
266 267 268 269
    def create_parameter(self, node, parameter=None):
        if parameter is not None:
            node = parameter
        dtype = node.dtype
C
channingss 已提交
270
        shape = node.out_shapes[0]
C
channingss 已提交
271 272
        if len(node.weight.shape) == 0:
            shape = [1]
C
update  
channingss 已提交
273 274 275 276 277 278 279
        self.weights[node.layer_name] = node.weight
        attr = {
            'dtype': string(dtype),
            'shape': shape,
            'name': string(node.layer_name),
            'default_initializer': 'Constant(0.0)'
        }
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
        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)
C
update  
channingss 已提交
296 297 298 299 300 301 302 303 304 305 306 307 308 309

    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

C
channingss 已提交
310
    def _interpolate(self, node):
C
channingss 已提交
311
        val_x = self.graph.get_input_node(node, idx=0, copy=True)
C
Channingss 已提交
312
        inputs = {'input': val_x}
313
        if node.layer_type == 'Resize':
C
Channingss 已提交
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
            if len(node.layer.input) == 2:
                # opset 10
                val_scales = self.graph.get_input_node(node, idx=1, copy=True)
                inputs['scale'] = val_scales
            elif len(node.layer.input) == 3:
                # opset 11
                val_scales = self.graph.get_input_node(node, idx=2, copy=True)
                inputs['scale'] = val_scales
            elif len(node.layer.input) == 4:
                # opset 11
                val_sizes = self.graph.get_input_node(node, idx=3, copy=True)
                var_nc, var_hw = val_sizes.layer_name + '_nc', val_sizes.layer_name + '_hw'
                node.fluid_code.add_layer(
                    'split',
                    inputs=val_sizes,
                    output=var_nc + ',' + var_hw,
                    param_attr={
                        'dim': 0,
                        'num_or_sections': [2, 2],
                    })
                node.fluid_code.add_layer(
                    "cast",
                    inputs=var_hw,
                    output=var_hw,
                    param_attr={'dtype': string('int32')})
                inputs['out_shape'] = var_hw
340 341
        elif node.layer_type == 'Upsample':
            val_scales = self.graph.get_input_node(node, idx=1, copy=True)
C
Channingss 已提交
342
            inputs['scale'] = val_scales
R
root 已提交
343 344

        attr = {'name': string(node.layer_name)}
C
channingss 已提交
345 346
        mode = node.get_attr('mode', 'nearest')
        fluid_op = 'resize_{}'.format(mode)
347
        if 'linear' in mode:
R
root 已提交
348 349 350
            print(
                'Warnning: paddle not support op:resize wiht mode: linear, we use bilinear replace linear'
            )
351
            fluid_op = 'resize_bilinear'
352
        attr['align_corners'] = False
353
        node.fluid_code.add_layer(
C
Channingss 已提交
354
            fluid_op, inputs=inputs, output=node, param_attr=attr)
R
root 已提交
355

356
    @print_mapping_info
C
channings 已提交
357 358 359
    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)
R
root 已提交
360 361 362

        pooled_height = node.get_attr('output_height')
        pooled_width = node.get_attr('output_width')
C
channings 已提交
363 364 365
        spatial_scale = node.get_attr('spatial_scale')
        sampling_ratio = node.get_attr('sampling_ratio')
        attr = {
R
root 已提交
366 367 368 369 370
            'pooled_height': pooled_height,
            'pooled_width': pooled_width,
            'spatial_scale': spatial_scale,
            'sampling_ratio': sampling_ratio,
        }
371 372 373 374 375 376 377 378
        node.fluid_code.add_layer(
            'roi_align',
            inputs={'input': val_x,
                    'rois': val_rois},
            output=node,
            param_attr=attr)

    @print_mapping_info
C
channings 已提交
379 380 381
    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)
R
root 已提交
382

C
channings 已提交
383 384 385
        spatial_scale = node.get_attr('spatial_scale')
        pooled_height, pooled_width = node.get_attr('pooled_shape')
        attr = {
R
root 已提交
386 387 388 389
            'pooled_height': pooled_height,
            'pooled_width': pooled_width,
            'spatial_scale': spatial_scale,
        }
390 391 392 393 394 395 396 397
        node.fluid_code.add_layer(
            'roi_pool',
            inputs={'input': val_x,
                    'rois': val_rois},
            output=node,
            param_attr=attr)

    @print_mapping_info
C
update  
channingss 已提交
398
    def Pad(self, node, op_independent=True):
C
channingss 已提交
399
        val_x = self.graph.get_input_node(node, idx=0, copy=True)
C
update  
channingss 已提交
400 401 402
        pads = node.get_attr('pads')
        mode = node.get_attr('mode', 'constant')
        value = node.get_attr('value', 0.)
C
channingss 已提交
403 404
        data_shape = val_x.out_shapes[0]
        output_shape = node.out_shapes[0]
C
update  
channingss 已提交
405 406
        assume_pad2d = False
        attr = {}
C
channings 已提交
407
        paddings = []
C
update  
channingss 已提交
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
        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
C
channingss 已提交
427 428 429 430
            if sum(paddings[:4]) == 0:
                fluid_op = 'pad2d'
                paddings = paddings[4:]
                attr['mode'] = string(mode)
C
update  
channingss 已提交
431 432 433
        attr['paddings'] = paddings
        if op_independent:
            attr['name'] = string(node.layer_name)
434 435
            node.fluid_code.add_layer(
                fluid_op, inputs=val_x, output=node, param_attr=attr)
C
update  
channingss 已提交
436 437
        else:
            attr['name'] = string(node.layer_name + '_paded')
438 439 440 441 442
            node.fluid_code.add_layer(
                fluid_op,
                inputs=val_x,
                output=node.layer_name + '_paded',
                param_attr=attr)
C
update  
channingss 已提交
443 444
            return node.layer_name + '_paded'

445
    @print_mapping_info
C
update  
channingss 已提交
446
    def Unsqueeze(self, node):
C
channingss 已提交
447
        val_x = self.graph.get_input_node(node, idx=0, copy=True)
C
update  
channingss 已提交
448
        axes = node.get_attr('axes')
449
        attr = {'axes': axes, 'name': string(node.layer_name)}
R
root 已提交
450
        if len(val_x.out_shapes[0]) == 0:
451 452 453 454 455 456
            if node.layer_name:
                node.fluid_code.add_layer(
                    'reshape',
                    inputs=val_x,
                    output=node,
                    param_attr={'shape': [1]})
457
        else:
C
update  
Channingss 已提交
458 459 460 461 462 463 464 465 466 467 468 469 470 471 472
            if str(val_x.dtype) == 'bool':
                val_x_cast = val_x.layer_name + '_cast'
                node.fluid_code.add_layer(
                    'cast',
                    inputs=val_x,
                    output=val_x_cast,
                    param_attr={'dtype': string('int64')})
                node.fluid_code.add_layer(
                    'unsqueeze',
                    inputs=val_x_cast,
                    output=node,
                    param_attr=attr)
            else:
                node.fluid_code.add_layer(
                    'unsqueeze', inputs=val_x, output=node, param_attr=attr)
473

474
    @print_mapping_info
C
channingss 已提交
475
    def Shrink(self, node):
C
channingss 已提交
476
        val_x = self.graph.get_input_node(node, idx=0, copy=True)
C
channingss 已提交
477 478 479 480
        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}
481 482
        node.fluid_code.add_layer(
            'hard_shrink', inputs=val_x, output=node, param_attr=attr)
C
channingss 已提交
483

484
    @print_mapping_info
C
update  
channingss 已提交
485 486 487 488 489 490 491 492
    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'
R
root 已提交
493

C
update  
channingss 已提交
494
        shape = node.get_attr('shape', None)
R
root 已提交
495

C
update  
channingss 已提交
496
        if shape is None:
C
channingss 已提交
497
            shape = val_output.out_shapes[0]
C
update  
channingss 已提交
498 499
        if shape is None:
            shape = list(value.shape)
500 501 502 503
            _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)
504
        if len(value) == 1:
C
channingss 已提交
505
            value = value.tolist()
C
update  
channingss 已提交
506 507 508 509 510
            shape = [1]
            value = value[0]
            if dtype.name == 'int64':
                dtype = 'int32'
            attr = {'shape': shape, 'dtype': string(dtype), 'value': value}
511 512
            node.fluid_code.add_layer(
                'fill_constant', inputs=None, output=node, param_attr=attr)
C
channingss 已提交
513
        else:
514 515
            if dtype.name == 'uint8':
                dtype = 'int64'
C
channingss 已提交
516 517 518 519 520 521 522 523
            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)'
            }
524 525
            node.fluid_code.add_layer(
                "create_parameter", inputs=None, output=node, param_attr=attr)
C
update  
channingss 已提交
526

527
    @print_mapping_info
C
update  
channingss 已提交
528
    def Resize(self, node):
529 530
        self._interpolate(node)

531
    @print_mapping_info
532 533 534
    def Upsample(self, node):
        self._interpolate(node)

535 536 537 538 539 540 541 542 543 544 545 546 547 548 549
    @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
550
    def Expand(self, node):
C
channingss 已提交
551
        val_x = self.graph.get_input_node(node, idx=0, copy=True)
552
        val_shape = self.graph.get_input_node(node, idx=1, copy=True)
R
root 已提交
553
        if len(val_shape.outputs) == 1:
554 555
            self.omit_nodes.append(val_shape.layer_name)
        val_x_dtype = val_x.dtype
R
root 已提交
556
        name_ones = node.layer_name + '_ones'
C
Channingss 已提交
557 558 559 560 561
        attr_ones = {
            'shape': val_shape.layer_name,
            'dtype': string(val_x_dtype),
            'value': 1
        }
562
        node.fluid_code.add_layer(
C
Channingss 已提交
563 564 565 566
            'fill_constant',
            inputs=None,
            output=name_ones,
            param_attr=attr_ones)
R
root 已提交
567
        inputs = {'x': name_ones, 'y': val_x}
568 569 570 571
        node.fluid_code.add_layer(
            'elementwise_mul',
            inputs=inputs,
            output=node.layer_name,
C
Channingss 已提交
572
            param_attr=None)
C
update  
channingss 已提交
573

574
    @print_mapping_info
C
channingss 已提交
575 576 577 578
    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]
C
Channingss 已提交
579
        axis = node.get_attr('axis', 0)
580 581
        #assert len(
        #    indices_shape) <= 2, "Gather op don't support dim of indice >2 "
R
root 已提交
582
        if axis == 0 and len(indices_shape) <= 1:
C
Channingss 已提交
583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611
            if len(val_x.out_shapes[0]) <= 1:
                node.fluid_code.add_layer(
                    'gather',
                    inputs={'input': val_x,
                            'index': indices},
                    output=node,
                    param_attr=None)
            elif len(val_x.out_shapes[0]) > 1:
                if len(indices_shape) == 0:
                    gather_ = node.layer_name + '_1'
                    node.fluid_code.add_layer(
                        'gather',
                        inputs={'input': val_x,
                                'index': indices},
                        output=gather_,
                        param_attr=None)
                    node.fluid_code.add_layer(
                        'squeeze',
                        inputs={'input': gather_,
                                'axes': [0]},
                        output=node,
                        param_attr=None)
                else:
                    node.fluid_code.add_layer(
                        'gather',
                        inputs={'input': val_x,
                                'index': indices},
                        output=node,
                        param_attr=None)
C
channingss 已提交
612 613
        elif axis > 0 and len(indices_shape) <= 1:
            perm = list(range(len(val_x.out_shapes[0])))
C
channingss 已提交
614 615 616
            perm = [axis] + perm[:axis] + perm[axis + 1:]
            attr_trans = {'perm': perm}
            name_trans = val_x.layer_name + '_trans'
617 618 619 620 621 622 623 624 625 626 627 628 629
            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)
C
Channingss 已提交
630 631 632 633
            if len(indices_shape) < 1:
                node.fluid_code.add_layer(
                    'squeeze',
                    inputs={'input': node,
C
Channingss 已提交
634
                            'axes': [axis]},
C
Channingss 已提交
635 636
                    output=node,
                    param_attr=None)
637 638 639
        elif axis == 0 and len(indices_shape) > 1:
            if val_x.out_shapes[0] is not None and isinstance(
                    val_x, ONNXGraphDataNode):
C
Channingss 已提交
640
                indices_cast = indices.layer_name + '_cast'
C
update  
Channingss 已提交
641 642 643
                node.fluid_code.add_layer(
                    'cast',
                    inputs=indices,
C
Channingss 已提交
644
                    output=indices_cast,
C
update  
Channingss 已提交
645
                    param_attr={'dtype': string('int64')})
646 647
                node.fluid_code.add_layer(
                    'embedding',
C
Channingss 已提交
648
                    inputs=indices_cast,
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683
                    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
                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:
C
Channingss 已提交
684
            from functools import reduce
R
root 已提交
685
            reshape_shape = reduce(lambda x, y: x * y, indices_shape)
686 687 688 689 690 691
            indices_reshape = indices.layer_name + '_shape'
            node.fluid_code.add_layer(
                'reshape',
                inputs=indices,
                output=indices_reshape,
                param_attr={'shape': [reshape_shape, ]})
R
root 已提交
692

C
Channingss 已提交
693 694 695
            perm = list(range(len(val_x.out_shapes[0])))
            perm = [axis] + perm[:axis] + perm[axis + 1:]
            attr_trans = {'perm': perm}
C
fix bug  
Channingss 已提交
696
            name_trans = val_x.layer_name + '_transpose'
697 698 699 700 701 702 703 704 705 706 707
            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)
C
fix bug  
Channingss 已提交
708
            input_transpose = node.layer_name + '_transpose'
709
            node.fluid_code.add_layer(
C
fix bug  
Channingss 已提交
710 711 712 713
                'transpose',
                inputs=node,
                output=input_transpose,
                param_attr=attr_trans)
C
Channingss 已提交
714 715 716 717 718 719
            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)
720 721
            node.fluid_code.add_layer(
                'reshape',
C
fix bug  
Channingss 已提交
722
                inputs=input_transpose,
723 724 725
                output=node,
                param_attr={'shape': reshaped_shape})

C
Channingss 已提交
726 727 728 729 730 731 732 733 734 735 736 737 738 739 740
    @print_mapping_info
    def ScatterND(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)
        updates = self.graph.get_input_node(node, idx=2, copy=True)
        if len(indices.out_shapes[0]) == 1:
            node.fluid_code.add_layer(
                'scatter',
                inputs={'input': val_x,
                        'index': indices,
                        'updates': updates},
                output=node,
                param_attr=None)
        else:
            input_inner_indices = node.layer_name + '_input_inner_indices'
741 742 743 744 745 746 747 748
            shape = val_x.out_shapes[0]
            node.fluid_code.add_layer(
                'reshape',
                inputs=indices.layer_name,
                output=indices.layer_name,
                param_attr={'shape': indices.out_shapes[0]})

            zeros_like_val_x = val_x.layer_name + '_zeros'
C
Channingss 已提交
749
            node.fluid_code.add_layer(
750 751 752 753 754 755
                'zeros_like',
                inputs=val_x,
                output=zeros_like_val_x,
                param_attr=None)
            node.fluid_code.add_layer(
                'scatter_nd_add',
C
Channingss 已提交
756
                inputs={
757
                    'ref': zeros_like_val_x,
C
Channingss 已提交
758 759 760 761 762
                    'index': indices,
                    'updates': updates
                },
                output=input_inner_indices,
                param_attr=None)
763
            indices_mask = node.layer_name + '_indices_mask'
C
Channingss 已提交
764
            constant_minus_one = node.layer_name + '_constant_minus_one'
765
            # full_like support create tensor shape like input tensor
C
Channingss 已提交
766
            node.fluid_code.add_layer(
767 768
                'full_like',
                inputs=updates,
C
Channingss 已提交
769
                output=constant_minus_one,
770 771
                param_attr={'dtype': string(updates.dtype),
                            'fill_value': -1})
C
Channingss 已提交
772
            node.fluid_code.add_layer(
773
                'scatter_nd_add',
C
Channingss 已提交
774
                inputs={
775
                    'ref': zeros_like_val_x,
C
Channingss 已提交
776 777 778 779 780
                    'index': indices,
                    'updates': constant_minus_one
                },
                output=indices_mask,
                param_attr=None)
781 782
            constant_one = node.layer_name + '_constant_1'
            # full_like support create tensor shape like input tensor
C
Channingss 已提交
783
            node.fluid_code.add_layer(
784 785 786 787 788
                'full_like',
                inputs=val_x,
                output=constant_one,
                param_attr={'dtype': string(val_x.dtype),
                            'fill_value': 1})
C
Channingss 已提交
789 790 791 792
            input_out_indices_mask = node.layer_name + '_input_out_indices_mask'
            node.fluid_code.add_layer(
                "elementwise_add",
                inputs={"x": indices_mask,
793
                        "y": constant_one},
C
Channingss 已提交
794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811
                output=input_out_indices_mask,
                param_attr=None)

            input_out_indices = node.layer_name + '_input_out_indices'
            node.fluid_code.add_layer(
                "elementwise_mul",
                inputs={"x": val_x,
                        "y": input_out_indices_mask},
                output=input_out_indices,
                param_attr=None)

            node.fluid_code.add_layer(
                "elementwise_add",
                inputs={"x": input_inner_indices,
                        "y": input_out_indices},
                output=node,
                param_attr=None)

812 813 814 815 816 817 818 819 820 821 822 823 824 825
    @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
C
channingss 已提交
826
    def Slice(self, node):
C
channingss 已提交
827
        val_x = self.graph.get_input_node(node, idx=0, copy=True)
C
channings 已提交
828
        starts, ends, axes, steps = None, None, None, None
829
        attr = {}
C
channingss 已提交
830 831 832
        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)
C
Channingss 已提交
833 834 835
            starts_value = _const_weight_or_none(starts)
            ends_value = _const_weight_or_none(ends)

R
root 已提交
836
            if len(node.inputs) > 3:
C
channings 已提交
837
                axes = self.graph.get_input_node(node, idx=3, copy=True)
C
Channingss 已提交
838
                axes = _const_weight_or_none(axes, necessary=True)
R
root 已提交
839
            if len(node.inputs) > 4:
C
channings 已提交
840
                steps = self.graph.get_input_node(node, idx=4, copy=True)
C
update  
Channingss 已提交
841
                steps = _const_weight_or_none(steps)
842 843 844 845 846 847 848 849
            attr = {
                "axes": axes,
                "starts": starts.layer_name,
                "ends": ends.layer_name
            }
            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)
C
Channingss 已提交
850
                starts_value = starts_value.copy()
851
                ends_value = ends_value.copy()
852 853 854 855
                #for idx in range(len(ends_value)):
                #    if ends_value[idx] > 2**31 - 1:
                #        ends_value[idx] = 2**31 - 1
                #print(val_x.out_shapes)
856
                for idx in range(len(ends_value)):
857 858
                    if starts_value[idx] >= val_x.out_shapes[0][axes[idx]]:
                        starts_value[idx] = val_x.out_shapes[0][axes[idx]] - 1
C
Channingss 已提交
859
                        ends_value[idx] = val_x.out_shapes[0][axes[idx]]
860
                        starts_value[idx] = val_x.out_shapes[0][axes[idx]] - 1
C
Channingss 已提交
861
                    elif ends_value[idx] > 2**31 - 1:
862 863 864 865 866 867 868 869
                        ends_value[idx] = 2**31 - 1
                attr = {
                    "axes": axes,
                    "starts": starts_value,
                    "ends": ends_value
                }
            else:
                if starts.dtype != 'int32':
C
fix bug  
Channingss 已提交
870
                    starts_cast = starts.layer_name + '_cast'
871 872 873
                    node.fluid_code.add_layer(
                        'cast',
                        inputs=starts,
C
fix bug  
Channingss 已提交
874
                        output=starts_cast,
875
                        param_attr={'dtype': string('int32')})
C
fix bug  
Channingss 已提交
876
                    attr['starts'] = starts_cast
877
                if ends.dtype != 'int32':
C
update  
Channingss 已提交
878
                    ends_cast = ends.layer_name + '_cast'
C
Channingss 已提交
879 880 881 882 883 884
                node.fluid_code.add_layer(
                    'cast',
                    inputs=ends,
                    output=ends_cast,
                    param_attr={'dtype': string('int32')})
                attr['ends'] = ends_cast
C
channingss 已提交
885 886 887 888
        else:
            starts = node.get_attr('starts')
            ends = node.get_attr('ends')
            axes = node.get_attr('axes')
889 890 891 892
            for idx in range(len(ends)):
                if ends[idx] > 2**31 - 1:
                    ends[idx] = 2**31 - 1
            attr = {"axes": axes, "starts": starts, "ends": ends}
C
channingss 已提交
893

C
Channingss 已提交
894 895 896
        if steps is not None:
            attr['strides'] = steps
            node.fluid_code.add_layer(
897
                'strided_slice', inputs=val_x, output=node, param_attr=attr)
C
Channingss 已提交
898 899
        else:
            node.fluid_code.add_layer(
900
                'slice', inputs=val_x, output=node, param_attr=attr)
C
channingss 已提交
901

902
    @print_mapping_info
C
update  
channingss 已提交
903
    def ConstantOfShape(self, node):
C
channingss 已提交
904
        val_shape = self.graph.get_input_node(node, idx=0, copy=True)
C
channingss 已提交
905
        val_y = self.graph.get_node(node.layer.output[0], copy=True)
C
update  
channingss 已提交
906 907 908 909

        value = node.get_attr('value')
        dtype = value.dtype
        value = value.tolist()
910 911
        assert len(value) == 1, ('given value not Scalar, shape of value > 1, '
                                 'this is not supported')
C
update  
channingss 已提交
912 913
        if len(value) == 1:
            value = value[0]
914 915 916 917 918 919 920
            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)
C
update  
channingss 已提交
921

C
Channingss 已提交
922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942
    @print_mapping_info
    def Clip(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)
        max_value, min_value = None, None
        if len(node.inputs) == 1:
            max_value = node.get_attr('max')
            min_value = node.get_attr('min')
            attr = {
                'max': max_value,
                'min': min_value,
            }
            node.fluid_code.add_layer(
                'clip', inputs=val_x, output=node, param_attr=attr)
        else:
            max_ipt = self.graph.get_input_node(node, idx=1, copy=True)
            min_ipt = self.graph.get_input_node(node, idx=2, copy=True)
            max_value = _const_weight_or_none(max_ipt)
            min_value = _const_weight_or_none(min_ipt)
            self.omit_nodes.append(max_ipt.layer_name)
            self.omit_nodes.append(min_ipt.layer_name)
943
            if max_value.shape == (1, ):
C
Channingss 已提交
944
                max_value = max_value[0]
945
            if min_value.shape == (1, ):
C
Channingss 已提交
946 947
                min_value = min_value[0]
        if max_value is not None and min_value is not None:
948
            attr = {'max': max_value, 'min': min_value}
C
Channingss 已提交
949 950 951 952 953
            node.fluid_code.add_layer(
                'clip', inputs=val_x, output=node, param_attr=attr)
        else:
            raise

954
    @print_mapping_info
C
update  
channingss 已提交
955
    def Split(self, node):
C
channingss 已提交
956 957
        val_x = self.graph.get_input_node(node, idx=0, copy=True)
        val_y = self.graph.get_node(node.layer.output[0], copy=True)
C
update  
channingss 已提交
958 959

        fluid_op = 'split'
C
channingss 已提交
960
        split = node.get_attr('split')
C
update  
channingss 已提交
961
        axis = node.get_attr('axis', 0)
C
channingss 已提交
962 963 964 965 966
        attr = {
            'num_or_sections': split,
            'dim': axis,
            'name': string(node.layer_name)
        }
R
root 已提交
967

968 969
        node.fluid_code.add_layer(
            'split', inputs=val_x, output=val_y, param_attr=attr)
C
update  
channingss 已提交
970

971
    @print_mapping_info
C
update  
channingss 已提交
972
    def Reshape(self, node):
C
channingss 已提交
973 974
        val_x = self.graph.get_input_node(node, idx=0, copy=True)
        val_shape = self.graph.get_input_node(node, idx=1, copy=True)
C
update  
channingss 已提交
975
        val_reshaped = self.graph.get_node(node.layer.output[0], copy=True)
976 977 978 979 980 981 982 983 984 985
        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()})
C
Channingss 已提交
986 987
        elif len(node.out_shapes[0]) > 0 and _is_static_shape(node.out_shapes[
                0]):
C
Channingss 已提交
988 989 990 991 992 993
            node.fluid_code.add_layer(
                'reshape',
                inputs={'x': val_x,
                        'shape': node.out_shapes[0]},
                output=node,
                param_attr=attr)
994 995 996 997 998 999 1000
        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')})
1001 1002 1003 1004 1005 1006 1007
            # shape may be [], come form Gather by scalar indices
            if len(val_shape.out_shapes[0]) > 0:
                node.fluid_code.add_layer(
                    'reshape',
                    inputs=val_shape_cast,
                    output=val_shape_cast,
                    param_attr={'shape': val_shape.out_shapes[0]})
1008 1009 1010 1011 1012 1013 1014
            node.fluid_code.add_layer(
                'reshape',
                inputs={'x': val_x,
                        'shape': val_shape_cast},
                output=node,
                param_attr=attr)
        else:
1015 1016 1017 1018 1019 1020 1021
            # shape may be [], come form Gather by scalar indices
            if len(val_shape.out_shapes[0]) > 0:
                node.fluid_code.add_layer(
                    'reshape',
                    inputs=val_shape,
                    output=val_shape,
                    param_attr={'shape': val_shape.out_shapes[0]})
1022 1023 1024 1025 1026 1027 1028 1029
            node.fluid_code.add_layer(
                'reshape',
                inputs={'x': val_x,
                        'shape': val_shape},
                output=node,
                param_attr=attr)

    @print_mapping_info
C
update  
channingss 已提交
1030
    def Cast(self, node):
C
channingss 已提交
1031
        val_input = self.graph.get_input_node(node, idx=0, copy=True)
C
update  
channingss 已提交
1032 1033 1034 1035 1036 1037 1038 1039 1040 1041
        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)}
1042 1043
        node.fluid_code.add_layer(
            'cast', inputs=val_input, output=node, param_attr=attr)
C
update  
channingss 已提交
1044

C
Channingss 已提交
1045 1046 1047 1048 1049
    @print_mapping_info
    def Not(self, node):
        val_input = self.graph.get_input_node(node, idx=0, copy=True)
        node.fluid_code.add_layer('logical_not', inputs=val_input, output=node)

1050
    @print_mapping_info
C
update  
channingss 已提交
1051
    def AveragePool(self, node):
C
channingss 已提交
1052
        val_x = self.graph.get_input_node(node, idx=0, copy=True)
C
channingss 已提交
1053 1054

        auto_pad = node.get_attr('auto_pad', 'NOTSET')
C
update  
channingss 已提交
1055 1056 1057 1058 1059 1060 1061 1062
        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'
C
channingss 已提交
1063

C
channingss 已提交
1064 1065
        paddings, val_x = self._pad_if_asymmetric(node, pads, val_x)

C
channingss 已提交
1066
        if auto_pad == "SAME_UPPER" or auto_pad == "SAME_LOWER":
C
channingss 已提交
1067
            input_shape = val_x.out_shapes[0]
C
Channingss 已提交
1068 1069 1070 1071 1072
            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])
            paddings = pad_h + pad_w
C
channingss 已提交
1073

C
update  
channingss 已提交
1074 1075 1076 1077 1078 1079 1080 1081 1082 1083
        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)
        }

1084 1085
        node.fluid_code.add_layer(
            fluid_op, inputs=val_x, output=node, param_attr=attr)
C
update  
channingss 已提交
1086

1087
    @print_mapping_info
C
update  
channingss 已提交
1088 1089
    def Concat(self, node):
        inputs = []
C
Channingss 已提交
1090
        dtypes = set()
C
update  
channingss 已提交
1091
        for i in range(len(node.layer.input)):
C
channingss 已提交
1092
            ipt = self.graph.get_input_node(node, idx=i, copy=True)
C
update  
channingss 已提交
1093 1094 1095 1096
            if isinstance(ipt, str):
                inputs.append(ipt)
            else:
                inputs.append(ipt.layer_name)
C
Channingss 已提交
1097 1098 1099
                dtypes.add(ipt.dtype)
        if len(dtypes) > 1:
            assert 'Unspported situation happened, please create issue on https://github.com/PaddlePaddle/X2Paddle/issues.'
C
update  
channingss 已提交
1100 1101
        axis = node.get_attr('axis')
        attr = {'axis': axis}
1102 1103
        node.fluid_code.add_layer(
            'concat', inputs=inputs, output=node, param_attr=attr)
C
update  
channingss 已提交
1104

1105
    @print_mapping_info
C
update  
channingss 已提交
1106
    def Flatten(self, node):
C
channingss 已提交
1107
        val_x = self.graph.get_input_node(node, idx=0, copy=True)
C
update  
channingss 已提交
1108 1109
        axis = node.get_attr('axis', 1)
        attr = {"axis": str(axis), "name": string(node.layer_name)}
1110 1111
        node.fluid_code.add_layer(
            'flatten', inputs=val_x, output=node, param_attr=attr)
C
update  
channingss 已提交
1112

1113
    @print_mapping_info
C
update  
channingss 已提交
1114
    def Gemm(self, node):
C
channingss 已提交
1115 1116 1117
        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)
C
update  
channingss 已提交
1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130

        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)
        }
1131 1132 1133 1134 1135
        node.fluid_code.add_layer(
            'matmul',
            inputs=matmul_inputs,
            output=val_mm,
            param_attr=attr_matmul)
C
channingss 已提交
1136

C
update  
channingss 已提交
1137 1138 1139 1140
        if beta != 0:
            if beta == 1.:
                add_inputs = {"x": val_mm, "y": val_c}
                attr = {"name": string(node.layer_name)}
1141 1142 1143 1144 1145
                node.fluid_code.add_layer(
                    "elementwise_add",
                    inputs=add_inputs,
                    output=node,
                    param_attr=attr)
C
update  
channingss 已提交
1146
            else:
C
channingss 已提交
1147 1148
                var_beta = node.layer_name + '_beta'
                matmul_beta_inputs = {"x": val_c, "y": var_beta}
1149 1150 1151 1152 1153
                node.fluid_code.add_layer(
                    "Constant",
                    inputs=matmul_beta_inputs,
                    output=var_beta,
                    param_attr={'value': beta})
C
channingss 已提交
1154 1155 1156

                add_inputs = {"x": val_mm, "y": var_beta}
                attr = {"name": string(node.layer_name)}
1157 1158 1159 1160 1161
                node.fluid_code.add_layer(
                    "elementwise_add",
                    inputs=add_inputs,
                    output=node,
                    param_attr=attr)
C
update  
channingss 已提交
1162

1163
    @print_mapping_info
C
update  
channingss 已提交
1164
    def Sum(self, node):
1165
        val_inps = node.layer.input
1166
        inputs = {
1167 1168 1169 1170
            "x": self.graph.get_input_node(
                node, idx=0, copy=True),
            "y": self.graph.get_input_node(
                node, idx=1, copy=True),
1171 1172
        }
        node.fluid_code.add_layer("elementwise_add", inputs=inputs, output=node)
1173

C
channingss 已提交
1174 1175
        for idx, ipt in enumerate(val_inps[2:]):
            y = self.graph.get_input_node(node, idx=idx, copy=True)
1176 1177
            inputs = {
                "x": node.layer_name,
C
channingss 已提交
1178
                "y": y,
1179
            }
1180 1181
            node.fluid_code.add_layer(
                "elementwise_add", inputs=inputs, output=node)
C
update  
channingss 已提交
1182

1183
    @print_mapping_info
C
update  
channingss 已提交
1184
    def MatMul(self, node):
C
channingss 已提交
1185 1186
        val_x = self.graph.get_input_node(node, idx=0, copy=True)
        val_y = self.graph.get_input_node(node, idx=1, copy=True)
C
Channingss 已提交
1187 1188
        x_shape = val_x.out_shapes[0]
        y_shape = val_y.out_shapes[0]
C
update  
channingss 已提交
1189
        inputs = {"x": val_x, "y": val_y}
C
Channingss 已提交
1190
        if y_shape[0] == 1 and x_shape[-1] != 1 and x_shape[0] != 1:
C
Channingss 已提交
1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202
            y_squeeze = val_y.layer_name + '_squeeze'
            node.fluid_code.add_layer(
                "squeeze",
                inputs=val_y,
                output=y_squeeze,
                param_attr={'axes': [0]})
            inputs['y'] = y_squeeze
            node.fluid_code.add_layer(
                "matmul", inputs=inputs, output=node, param_attr=None)
        else:
            node.fluid_code.add_layer(
                "matmul", inputs=inputs, output=node, param_attr=None)
C
update  
channingss 已提交
1203

1204
    @print_mapping_info
C
update  
channingss 已提交
1205
    def BatchNormalization(self, node):
C
channingss 已提交
1206 1207 1208 1209 1210
        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)
C
update  
channingss 已提交
1211 1212 1213 1214 1215 1216 1217 1218 1219

        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)

C
channingss 已提交
1220 1221
        # Attribute: spatial is used in BatchNormalization-1,6,7
        spatial = bool(node.get_attr('spatial'))
C
update  
channingss 已提交
1222 1223 1224 1225
        attr = {
            "momentum": momentum,
            "epsilon": epsilon,
            "data_layout": string('NCHW'),
C
channingss 已提交
1226
            "is_test": True,
C
update  
channingss 已提交
1227 1228 1229 1230
            "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),
C
channingss 已提交
1231
            "use_global_stats": spatial,
C
update  
channingss 已提交
1232 1233
            "name": string(node.layer_name)
        }
1234 1235
        node.fluid_code.add_layer(
            "batch_norm", inputs=val_x, output=node, param_attr=attr)
C
update  
channingss 已提交
1236

1237
    @print_mapping_info
C
update  
channingss 已提交
1238
    def Transpose(self, node):
C
channingss 已提交
1239
        val_x = self.graph.get_input_node(node, idx=0, copy=True)
C
update  
channingss 已提交
1240 1241
        perm = node.get_attr('perm')
        attr = {'perm': perm, "name": string(node.layer_name)}
1242 1243
        node.fluid_code.add_layer(
            "transpose", inputs=val_x, output=node, param_attr=attr)
C
update  
channingss 已提交
1244

1245
    @print_mapping_info
C
update  
channingss 已提交
1246
    def Relu(self, node):
C
channingss 已提交
1247
        val_x = self.graph.get_input_node(node, idx=0, copy=True)
C
update  
channingss 已提交
1248
        attr = {"name": string(node.layer_name)}
1249 1250
        node.fluid_code.add_layer(
            "relu", inputs=val_x, output=node, param_attr=attr)
C
update  
channingss 已提交
1251

1252
    @print_mapping_info
C
update  
channingss 已提交
1253
    def PRelu(self, node):
C
channingss 已提交
1254 1255
        val_x = self.graph.get_input_node(node, idx=0, copy=True)
        val_slope = self.graph.get_input_node(node, idx=1, copy=True)
C
update  
channingss 已提交
1256

C
channingss 已提交
1257 1258
        mode = 'channel'
        shape_slope = val_slope.out_shapes[0]
C
Channingss 已提交
1259 1260

        if shape_slope == [1]:
C
channingss 已提交
1261 1262 1263
            mode = 'all'
        elif len(shape_slope) > 2:
            mode = 'element'
C
Channingss 已提交
1264 1265 1266 1267 1268 1269 1270 1271

        if mode == 'channel' and len(shape_slope) == 1:
            # paddle params shape need be [1, channel]
            slope_data = _const_weight_or_none(val_slope)
            slope_data = np.reshape(slope_data, [1] + shape_slope)
            self.weights[val_slope.layer_name] = slope_data

        self.omit_nodes.append(val_slope.layer_name)
C
channingss 已提交
1272 1273 1274 1275
        attr = {
            "param_attr": string(val_slope.layer_name),
            'mode': string(mode)
        }
1276 1277
        node.fluid_code.add_layer(
            "prelu", inputs=val_x, output=node, param_attr=attr)
C
update  
channingss 已提交
1278

1279
    @print_mapping_info
C
update  
channingss 已提交
1280
    def Squeeze(self, node):
C
channingss 已提交
1281 1282 1283
        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)}
1284 1285 1286 1287 1288 1289 1290 1291 1292
        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)
R
root 已提交
1293

1294
    @print_mapping_info
C
channings 已提交
1295 1296 1297
    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)
1298 1299 1300 1301 1302 1303 1304
        node.fluid_code.add_layer(
            "equal",
            inputs={'x': val_x,
                    'y': val_y},
            output=node,
            param_attr=None)

C
Channingss 已提交
1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315
    @print_mapping_info
    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)

1316
    @print_mapping_info
C
channings 已提交
1317 1318 1319 1320
    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)
R
root 已提交
1321

C
channings 已提交
1322
        not_condition = condition.layer_name + '_not'
1323 1324 1325 1326 1327
        node.fluid_code.add_layer(
            "logical_not",
            inputs=condition,
            output=not_condition,
            param_attr=None)
R
root 已提交
1328
        cast_not_condition = not_condition + '_cast'
1329 1330 1331 1332 1333
        node.fluid_code.add_layer(
            "cast",
            inputs=not_condition,
            output=cast_not_condition,
            param_attr={'dtype': string(val_x.dtype)})
C
channings 已提交
1334
        cast_condition = condition.layer_name + '_cast'
1335 1336 1337 1338 1339
        node.fluid_code.add_layer(
            "cast",
            inputs=condition,
            output=cast_condition,
            param_attr={'dtype': string(val_x.dtype)})
R
root 已提交
1340
        mul_val_x = val_x.layer_name + '_mul'
1341 1342 1343 1344 1345 1346
        node.fluid_code.add_layer(
            "elementwise_mul",
            inputs={'x': val_x,
                    'y': cast_condition},
            output=mul_val_x,
            param_attr=None)
C
channings 已提交
1347
        mul_val_y = val_y.layer_name + '_mul'
1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362
        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
R
root 已提交
1363 1364
    def NonZero(self, node):
        val_x = self.graph.get_input_node(node, idx=0, copy=True)
1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383
        val_x_dim = len(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
C
update  
channingss 已提交
1384
    def Identity(self, node):
C
channingss 已提交
1385
        val_x = self.graph.get_input_node(node, idx=0, copy=True)
C
update  
channingss 已提交
1386
        node.fluid_code.add_layer("assign", inputs=val_x, output=node)
R
root 已提交
1387

1388
    @print_mapping_info
C
channings 已提交
1389 1390 1391 1392
    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)
R
root 已提交
1393

1394 1395
        if repeats is None:
            repeats = val_repeats.layer_name
J
jiangjiajun 已提交
1396 1397 1398
            if val_repeats.dtype != 'int32':
                attr = {"dtype": string("int32")}
                node.fluid_code.add_layer(
C
Channingss 已提交
1399 1400
                    "cast",
                    inputs=repeats,
J
jiangjiajun 已提交
1401 1402
                    output="{}.tmp".format(repeats),
                    param_attr=attr)
J
jiangjiajun 已提交
1403 1404
                repeats = "{}.tmp".format(repeats)

1405
        elif isinstance(repeats, int):
C
channings 已提交
1406
            repeats = [repeats]
R
root 已提交
1407

C
channings 已提交
1408
        attr = {
R
root 已提交
1409
            'expand_times': repeats,
C
channings 已提交
1410 1411
            "name": string(node.layer_name),
        }
1412 1413
        node.fluid_code.add_layer(
            "expand", inputs=val_x, output=node, param_attr=attr)
R
root 已提交
1414

1415
    @print_mapping_info
C
update  
channingss 已提交
1416
    def MaxPool(self, node):
C
channingss 已提交
1417
        val_x = self.graph.get_input_node(node, idx=0, copy=True)
C
channingss 已提交
1418
        auto_pad = node.get_attr('auto_pad', 'NOTSET')
C
update  
channingss 已提交
1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429
        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'
C
channingss 已提交
1430

C
channingss 已提交
1431 1432
        paddings, val_x = self._pad_if_asymmetric(node, pads, val_x)

C
channingss 已提交
1433
        if auto_pad == "SAME_UPPER" or auto_pad == "SAME_LOWER":
C
channingss 已提交
1434
            input_shape = val_x.out_shapes[0]
C
Channingss 已提交
1435 1436 1437 1438 1439
            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])
            paddings = pad_h + pad_w
C
channingss 已提交
1440

C
update  
channingss 已提交
1441 1442 1443 1444 1445 1446 1447 1448 1449
        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
        }
1450 1451
        node.fluid_code.add_layer(
            fluid_op, inputs=val_x, output=node, param_attr=attr)
C
update  
channingss 已提交
1452

C
channings 已提交
1453
    def _global_pool(self, node):
C
channingss 已提交
1454
        val_x = self.graph.get_input_node(node, idx=0, copy=True)
C
update  
channingss 已提交
1455
        val_y = self.graph.get_node(node.layer.output[0], copy=True)
1456
        fluid_op = 'pool2d'
C
channings 已提交
1457 1458 1459 1460 1461 1462
        pool_type = None
        if node.layer.op_type == 'GlobalMaxPool':
            pool_type = 'max'
        elif node.layer.op_type == 'GlobalAveragePool':
            pool_type = 'avg'

C
update  
channingss 已提交
1463
        attr = {
C
channings 已提交
1464
            "pool_type": string(pool_type),
C
update  
channingss 已提交
1465 1466 1467
            "global_pooling": True,
            "name": string(node.layer_name)
        }
1468 1469
        node.fluid_code.add_layer(
            fluid_op, inputs=val_x, output=node, param_attr=attr)
R
root 已提交
1470

1471
    @print_mapping_info
C
channings 已提交
1472 1473
    def GlobalMaxPool(self, node):
        self._global_pool(node)
R
root 已提交
1474

1475
    @print_mapping_info
C
channings 已提交
1476 1477
    def GlobalAveragePool(self, node):
        self._global_pool(node)
R
root 已提交
1478

1479
    @print_mapping_info
C
update  
channingss 已提交
1480
    def Conv(self, node):
C
channingss 已提交
1481 1482
        val_x = self.graph.get_input_node(node, idx=0, copy=True)
        val_w = self.graph.get_input_node(node, idx=1, copy=True)
C
update  
channingss 已提交
1483 1484 1485 1486 1487 1488
        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:
C
channingss 已提交
1489
            val_b = self.graph.get_input_node(node, idx=2, copy=True)
C
update  
channingss 已提交
1490 1491 1492
            self.omit_nodes.append(val_b.layer_name)
        auto_pad = node.get_attr('auto_pad', 'NOTSET')

C
channingss 已提交
1493
        kernel_shape = node.get_attr('kernel_shape')
C
update  
channingss 已提交
1494 1495
        convnd = len(kernel_shape)
        assert 2 <= convnd <= 3, 'only conv2d and conv3d is supported'
C
Channingss 已提交
1496
        num_out_channels = val_w.out_shapes[0][0]
C
update  
channingss 已提交
1497 1498 1499
        fluid_op = 'conv{}d'.format(convnd)

        num_groups = node.get_attr('group', 1)
C
Channingss 已提交
1500 1501 1502
        strides = node.get_attr('strides', [1] * convnd)
        dilations = node.get_attr('dilations', [1] * convnd)
        pads = node.get_attr('pads', [0] * (convnd * 2))
C
update  
channingss 已提交
1503

C
channingss 已提交
1504
        input_shape = val_x.out_shapes[0]
C
update  
channingss 已提交
1505 1506
        paddings, val_x = self._pad_if_asymmetric(node, pads, val_x)

C
channingss 已提交
1507
        if auto_pad == "SAME_UPPER" or auto_pad == "SAME_LOWER":
C
Channingss 已提交
1508 1509 1510 1511 1512
            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])
            paddings = pad_h + pad_w
C
update  
channingss 已提交
1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527

        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
1528 1529
        node.fluid_code.add_layer(
            fluid_op, inputs=val_x, output=node, param_attr=attr)
C
channingss 已提交
1530

1531
    @print_mapping_info
C
channingss 已提交
1532
    def ConvTranspose(self, node):
C
channingss 已提交
1533 1534
        val_x = self.graph.get_input_node(node, idx=0, copy=True)
        val_w = self.graph.get_input_node(node, idx=1, copy=True)
C
channingss 已提交
1535
        val_b = None
R
root 已提交
1536
        if len(node.layer.input) > 2:
C
channingss 已提交
1537 1538
            val_b = self.graph.get_input_node(node, idx=2, copy=True)
            self.omit_nodes.append(val_b.layer_name)
C
channingss 已提交
1539 1540 1541 1542 1543 1544
        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])
C
channingss 已提交
1545
        kernel_shape = node.get_attr('kernel_shape')
C
channingss 已提交
1546 1547 1548
        assert kernel_shape, 'kernel_shape not inferred'
        convnd = len(kernel_shape)
        assert 2 <= convnd <= 3, 'only conv2d_transpose and conv3d_transpose supported'
C
channingss 已提交
1549
        num_out_channels = val_w.out_shapes[0][1]
C
channingss 已提交
1550 1551
        fluid_op = 'conv{}d_transpose'.format(convnd)

C
channingss 已提交
1552 1553 1554 1555 1556
        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))
C
channingss 已提交
1557 1558 1559 1560

        paddings, var_x = self._pad_if_asymmetric(node, pads, val_x)

        output_size = [0, 0]
C
channingss 已提交
1561

1562 1563
        output_size[0] = (val_x.out_shapes[0][2] - 1
                          ) * strides[0] - 2 * paddings[0] + dilations[0] * (
C
channingss 已提交
1564
                              kernel_shape[0] - 1) + 1 + out_padding[0]
1565 1566
        output_size[1] = (val_x.out_shapes[0][3] - 1
                          ) * strides[1] - 2 * paddings[1] + dilations[1] * (
C
channingss 已提交
1567 1568 1569 1570 1571 1572 1573 1574 1575 1576
                              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),
C
channingss 已提交
1577
            'bias_attr': None if val_b is None else string(val_b.layer_name),
C
channingss 已提交
1578 1579
            'name': string(node.layer_name),
        }
1580 1581
        node.fluid_code.add_layer(
            fluid_op, inputs=val_x, output=node, param_attr=attr)