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 343 344 345 346
            value = _const_weight_or_none(val_scales)
            if value is not None and value[-1] == value[-2]:
                inputs['scale'] = value.tolist()[-1] 
            else:
                inputs['scale'] = val_scales 
R
root 已提交
347 348

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

360
    @print_mapping_info
C
channings 已提交
361 362 363
    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 已提交
364 365 366

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

    @print_mapping_info
C
channings 已提交
383 384 385
    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 已提交
386

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

449
    @print_mapping_info
C
update  
channingss 已提交
450
    def Unsqueeze(self, node):
C
channingss 已提交
451
        val_x = self.graph.get_input_node(node, idx=0, copy=True)
C
update  
channingss 已提交
452
        axes = node.get_attr('axes')
453
        attr = {'axes': axes, 'name': string(node.layer_name)}
R
root 已提交
454
        if len(val_x.out_shapes[0]) == 0:
455 456 457 458 459 460
            if node.layer_name:
                node.fluid_code.add_layer(
                    'reshape',
                    inputs=val_x,
                    output=node,
                    param_attr={'shape': [1]})
461
        else:
C
update  
Channingss 已提交
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476
            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)
477

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

488
    @print_mapping_info
C
update  
channingss 已提交
489 490 491 492 493 494 495 496
    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 已提交
497

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

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

531
    @print_mapping_info
C
update  
channingss 已提交
532
    def Resize(self, node):
533 534
        self._interpolate(node)

535
    @print_mapping_info
536 537 538
    def Upsample(self, node):
        self._interpolate(node)

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

576
    @print_mapping_info
C
channingss 已提交
577 578 579 580
    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 已提交
581
        axis = node.get_attr('axis', 0)
582 583
        #assert len(
        #    indices_shape) <= 2, "Gather op don't support dim of indice >2 "
R
root 已提交
584
        if axis == 0 and len(indices_shape) <= 1:
C
Channingss 已提交
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 612 613
            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 已提交
614 615
        elif axis > 0 and len(indices_shape) <= 1:
            perm = list(range(len(val_x.out_shapes[0])))
C
channingss 已提交
616 617 618
            perm = [axis] + perm[:axis] + perm[axis + 1:]
            attr_trans = {'perm': perm}
            name_trans = val_x.layer_name + '_trans'
619 620 621 622 623 624 625 626 627 628 629 630 631
            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 已提交
632 633 634 635
            if len(indices_shape) < 1:
                node.fluid_code.add_layer(
                    'squeeze',
                    inputs={'input': node,
C
Channingss 已提交
636
                            'axes': [axis]},
C
Channingss 已提交
637 638
                    output=node,
                    param_attr=None)
639 640 641
        elif axis == 0 and len(indices_shape) > 1:
            if val_x.out_shapes[0] is not None and isinstance(
                    val_x, ONNXGraphDataNode):
C
Channingss 已提交
642
                indices_cast = indices.layer_name + '_cast'
C
update  
Channingss 已提交
643 644 645
                node.fluid_code.add_layer(
                    'cast',
                    inputs=indices,
C
Channingss 已提交
646
                    output=indices_cast,
C
update  
Channingss 已提交
647
                    param_attr={'dtype': string('int64')})
648 649
                node.fluid_code.add_layer(
                    'embedding',
C
Channingss 已提交
650
                    inputs=indices_cast,
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 684 685
                    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 已提交
686
            from functools import reduce
R
root 已提交
687
            reshape_shape = reduce(lambda x, y: x * y, indices_shape)
688 689 690 691 692 693
            indices_reshape = indices.layer_name + '_shape'
            node.fluid_code.add_layer(
                'reshape',
                inputs=indices,
                output=indices_reshape,
                param_attr={'shape': [reshape_shape, ]})
R
root 已提交
694

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

C
Channingss 已提交
728 729 730 731 732 733 734 735 736 737 738 739 740 741 742
    @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'
743 744 745 746 747 748 749 750
            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 已提交
751
            node.fluid_code.add_layer(
752 753 754 755 756 757
                'zeros_like',
                inputs=val_x,
                output=zeros_like_val_x,
                param_attr=None)
            node.fluid_code.add_layer(
                'scatter_nd_add',
C
Channingss 已提交
758
                inputs={
759
                    'ref': zeros_like_val_x,
C
Channingss 已提交
760 761 762 763 764
                    'index': indices,
                    'updates': updates
                },
                output=input_inner_indices,
                param_attr=None)
765
            indices_mask = node.layer_name + '_indices_mask'
C
Channingss 已提交
766
            constant_minus_one = node.layer_name + '_constant_minus_one'
767
            # full_like support create tensor shape like input tensor
C
Channingss 已提交
768
            node.fluid_code.add_layer(
769 770
                'full_like',
                inputs=updates,
C
Channingss 已提交
771
                output=constant_minus_one,
772 773
                param_attr={'dtype': string(updates.dtype),
                            'fill_value': -1})
C
Channingss 已提交
774
            node.fluid_code.add_layer(
775
                'scatter_nd_add',
C
Channingss 已提交
776
                inputs={
777
                    'ref': zeros_like_val_x,
C
Channingss 已提交
778 779 780 781 782
                    'index': indices,
                    'updates': constant_minus_one
                },
                output=indices_mask,
                param_attr=None)
783 784
            constant_one = node.layer_name + '_constant_1'
            # full_like support create tensor shape like input tensor
C
Channingss 已提交
785
            node.fluid_code.add_layer(
786 787 788 789 790
                'full_like',
                inputs=val_x,
                output=constant_one,
                param_attr={'dtype': string(val_x.dtype),
                            'fill_value': 1})
C
Channingss 已提交
791 792 793 794
            input_out_indices_mask = node.layer_name + '_input_out_indices_mask'
            node.fluid_code.add_layer(
                "elementwise_add",
                inputs={"x": indices_mask,
795
                        "y": constant_one},
C
Channingss 已提交
796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813
                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)

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

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

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

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

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

C
Channingss 已提交
924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944
    @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)
945
            if max_value.shape == (1, ):
C
Channingss 已提交
946
                max_value = max_value[0]
947
            if min_value.shape == (1, ):
C
Channingss 已提交
948 949
                min_value = min_value[0]
        if max_value is not None and min_value is not None:
950
            attr = {'max': max_value, 'min': min_value}
C
Channingss 已提交
951 952 953 954 955
            node.fluid_code.add_layer(
                'clip', inputs=val_x, output=node, param_attr=attr)
        else:
            raise

956
    @print_mapping_info
C
update  
channingss 已提交
957
    def Split(self, node):
C
channingss 已提交
958 959
        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 已提交
960 961

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

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

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

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

C
Channingss 已提交
1047 1048 1049 1050 1051
    @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)

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

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

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

C
channingss 已提交
1068
        if auto_pad == "SAME_UPPER" or auto_pad == "SAME_LOWER":
C
channingss 已提交
1069
            input_shape = val_x.out_shapes[0]
C
Channingss 已提交
1070 1071 1072 1073 1074
            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 已提交
1075

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

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

1089
    @print_mapping_info
C
update  
channingss 已提交
1090 1091
    def Concat(self, node):
        inputs = []
C
Channingss 已提交
1092
        dtypes = set()
C
update  
channingss 已提交
1093
        for i in range(len(node.layer.input)):
C
channingss 已提交
1094
            ipt = self.graph.get_input_node(node, idx=i, copy=True)
C
update  
channingss 已提交
1095 1096 1097 1098
            if isinstance(ipt, str):
                inputs.append(ipt)
            else:
                inputs.append(ipt.layer_name)
C
Channingss 已提交
1099 1100 1101
                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 已提交
1102 1103
        axis = node.get_attr('axis')
        attr = {'axis': axis}
1104 1105
        node.fluid_code.add_layer(
            'concat', inputs=inputs, output=node, param_attr=attr)
C
update  
channingss 已提交
1106

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

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

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

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

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

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

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

1185
    @print_mapping_info
C
update  
channingss 已提交
1186
    def MatMul(self, node):
C
channingss 已提交
1187 1188
        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 已提交
1189 1190
        x_shape = val_x.out_shapes[0]
        y_shape = val_y.out_shapes[0]
C
update  
channingss 已提交
1191
        inputs = {"x": val_x, "y": val_y}
C
Channingss 已提交
1192
        if y_shape[0] == 1 and x_shape[-1] != 1 and x_shape[0] != 1:
C
Channingss 已提交
1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204
            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 已提交
1205

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

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

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

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

1254
    @print_mapping_info
C
update  
channingss 已提交
1255
    def PRelu(self, node):
C
channingss 已提交
1256 1257
        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 已提交
1258

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

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

        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 已提交
1274 1275 1276 1277
        attr = {
            "param_attr": string(val_slope.layer_name),
            'mode': string(mode)
        }
1278 1279
        node.fluid_code.add_layer(
            "prelu", inputs=val_x, output=node, param_attr=attr)
C
update  
channingss 已提交
1280

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

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

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

1318
    @print_mapping_info
C
channings 已提交
1319 1320 1321 1322
    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 已提交
1323

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

1390
    @print_mapping_info
C
channings 已提交
1391 1392 1393 1394
    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 已提交
1395

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

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

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

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

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

C
channingss 已提交
1435
        if auto_pad == "SAME_UPPER" or auto_pad == "SAME_LOWER":
C
channingss 已提交
1436
            input_shape = val_x.out_shapes[0]
C
Channingss 已提交
1437 1438 1439 1440 1441
            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 已提交
1442

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

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

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

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

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

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

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

        num_groups = node.get_attr('group', 1)
C
Channingss 已提交
1502 1503 1504
        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 已提交
1505

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

C
channingss 已提交
1509
        if auto_pad == "SAME_UPPER" or auto_pad == "SAME_LOWER":
C
Channingss 已提交
1510 1511 1512 1513 1514
            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 已提交
1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529

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

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

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

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

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

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