# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License" # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from x2paddle.core.util import * def aten_adaptive_avg_pool2d(mapper, graph, node): """ 构造average adaptive pool2d的PaddleLayer。 TorchScript示例: %x.5 : Tensor = aten::adaptive_avg_pool2d(%x.3, %_output_size.1) 参数含义: %x.5 (Tensor): 池化后结果Tensor。 %x.3 (Tensor): 输入Tensor。 %_output_size.1 (list): 自适应池化后的Tensor的宽、高大小。 """ output_name = mapper._get_outputs_name(node)[0] layer_outputs = [output_name] layer_inputs = {} layer_attrs = {} inputs_name, inputs_node = mapper._get_inputs_name(node) # 处理输入0,即%x.3 mapper._check_input(graph, inputs_node[0], inputs_name[0], layer_outputs) layer_inputs["input"] = inputs_name[0] # 获取当前节点输入、输出的list current_inputs = list(layer_inputs.values()) current_outputs = layer_outputs # 处理输入1,即%_output_size.1 if inputs_name[1] in mapper.attrs: layer_attrs["pool_size"] = mapper.attrs[inputs_name[1]] else: layer_attrs["pool_size"] = inputs_name[1] current_inputs.append(inputs_name[1]) layer_attrs["pool_type"] = string("avg") graph.add_layer( "fluid.layers.adaptive_pool2d", inputs=layer_inputs, outputs=layer_outputs, **layer_attrs) return current_inputs, current_outputs def aten_addmm(mapper, graph, node): """ 构造addmm的PaddleLayer,该节点实现out = alpha ∗ x ∗ y + beta ∗ input。 TorchScript示例: %ret.2 : Tensor = aten::addmm(%150, %input.3, %156, %151, %152) 参数含义: %ret.2 (Tensor): addmm结果Tensor。 %150 (Tensor): 输入Tensor input。 %input.3 (Tensor): 输入Tensor x。 %156 (Tensor): 输入Tensor y。 %151 (int/float): 输入alpha。 %152 (int/float): 输入beta。 """ output_name = mapper._get_outputs_name(node)[0] layer_outputs = [output_name] layer_inputs = {} layer_attrs = {} inputs_name, inputs_node = mapper._get_inputs_name(node) # 处理输入0,即%150 mapper._check_input( graph, inputs_node[0], inputs_name[0], layer_outputs, add_dim=True) layer_inputs["input"] = inputs_name[0] # 处理输入1,即%input.3 mapper._check_input(graph, inputs_node[1], inputs_name[1], layer_outputs) layer_inputs["x"] = inputs_name[1] # 处理输入2,即%156 mapper._check_input(graph, inputs_node[2], inputs_name[2], layer_outputs) layer_inputs["y"] = inputs_name[2] # 获取当前节点输入、输出的list current_inputs = list(layer_inputs.values()) current_outputs = layer_outputs # 处理输入3,即%152 if inputs_name[3] in mapper.attrs: layer_attrs["beta"] = mapper.attrs[inputs_name[3]] else: layer_attrs["beta"] = inputs_name[3] current_inputs.append(inputs_name[3]) # 处理输入4,即%151 if inputs_name[4] in mapper.attrs: layer_attrs["alpha"] = mapper.attrs[inputs_name[4]] else: layer_attrs["alpha"] = inputs_name[4] current_inputs.append(inputs_name[4]) graph.add_layer( "fluid.layers.addmm", inputs=layer_inputs, outputs=layer_outputs, **layer_attrs) return current_inputs, current_outputs def aten_add_(mapper, graph, node): """ 构造add的PaddleLayer,该节点实现out = x + alpha * y。 TorchScript示例: %output.5 : Tensor = aten::add_(%output.2, %150, %151) 参数含义: %output.5 (Tensor): add结果Tensor。 %output.2 (Tensor): 输入Tensor x。 %150 (Tensor): 输入Tensor y。 %151 (int/float): 输入alpha。 """ output_name = mapper._get_outputs_name(node)[0] layer_outputs = [output_name] layer_inputs = {} layer_attrs = {} inputs_name, inputs_node = mapper._get_inputs_name(node) # 处理输入0,即%output.2 mapper._check_input(graph, inputs_node[0], inputs_name[0], layer_outputs) layer_inputs["x"] = inputs_name[0] # 处理输入1,即%150 mapper._check_input( graph, inputs_node[1], inputs_name[1], layer_outputs, add_dim=True) layer_inputs["y"] = inputs_name[1] # 获取当前节点输入、输出的list current_inputs = list(layer_inputs.values()) current_outputs = layer_outputs # 处理输入2,即%151 if inputs_name[2] in mapper.attrs: layer_attrs["alpha"] = mapper.attrs[inputs_name[2]] else: layer_attrs["alpha"] = inputs_name[2] current_inputs.append(inputs_name[2]) graph.add_layer( "prim.add", inputs=layer_inputs, outputs=layer_outputs, **layer_attrs) return current_inputs, current_outputs def aten_append(mapper, graph, node): """ 构造对list进行append的PaddleLayer。 TorchScript示例: %90 : int[] = aten::append(%_output_size.1, %v.1) 参数含义: %90 (list): 输出,append后的list。 %_output_size.1 (list): 需要进行append的list。 %v.1 (-): append的元素。 """ output_name = mapper._get_outputs_name(node)[0] layer_outputs = [output_name] layer_inputs = {} inputs_name, inputs_node = mapper._get_inputs_name(node) # 处理输入0,即_output_size.1 mapper._check_input(graph, inputs_node[0], inputs_name[0], layer_outputs) layer_inputs["list"] = inputs_name[0] # 处理输入1,即v.1 mapper._check_input(graph, inputs_node[1], inputs_name[1], layer_outputs) layer_inputs["element"] = inputs_name[1] # 获取当前节点输入、输出的list current_inputs = list(layer_inputs.values()) current_outputs = layer_outputs graph.add_layer("prim.append", inputs=layer_inputs, outputs=layer_outputs) return current_inputs, current_outputs def aten_conv2d(mapper, graph, node): """ 构造conv2d的PaddleLayer。 TorchScript示例: %input.10 : Tensor = aten::conv2d(%input.8, %25, %27, %28, %29, %30, %26) 参数含义: %input.10 (Tensor): 输出,卷积后的结果。 %input.8 (Tensor): 需要进行卷积的特征层。 %25 (Tensor): weights。 %27 (Tensor): bias。 %28 (int): 步长大小。 %29 (int): 填充大小。 %30 (int): 膨胀系数大小。 %26 (int): 卷积的组数。 """ if "conv" in mapper.dygraph_name_id: mapper.dygraph_name_id["conv"] += 1 else: mapper.dygraph_name_id["conv"] = 0 conv2d_name = "conv" + str(mapper.dygraph_name_id["conv"]) output_name = mapper._get_outputs_name(node)[0] layer_outputs = [conv2d_name, output_name] layer_inputs = {} layer_attrs = {} inputs_name, inputs_node = mapper._get_inputs_name(node) # 处理输入0,即%input.8 mapper._check_input(graph, inputs_node[0], inputs_name[0], layer_outputs) layer_inputs["input"] = inputs_name[0] # 获取当前节点输入、输出的list current_inputs = list(layer_inputs.values()) current_outputs = layer_outputs[1:] # 处理输入1,即%25 weights = mapper.pytorch_params[inputs_name[1]] mapper.paddle_params[conv2d_name + ".weight"] = weights layer_attrs["num_filters"] = weights.shape[0] layer_attrs["filter_size"] = weights.shape[2:] # 处理输入2,即%27 if inputs_name[2] in mapper.pytorch_params: bias = mapper.pytorch_params[inputs_name[2]] mapper.paddle_params[conv2d_name + ".bias"] = bias else: mapper.paddle_params[conv2d_name + ".bias"] = False # 处理输入3,即%28 layer_attrs["stride"] = mapper.attrs[inputs_name[3]] # 处理输入4,即%29 layer_attrs["padding"] = mapper.attrs[inputs_name[4]] # 处理输入5,即%30 layer_attrs["dilation"] = mapper.attrs[inputs_name[5]] # 处理输入6,即%26 layer_attrs["groups"] = mapper.attrs[inputs_name[6]] layer_attrs['num_channels'] = weights.shape[1] * mapper.attrs[inputs_name[ 6]] graph.add_layer( "fluid.dygraph.Conv2D", inputs=layer_inputs, outputs=layer_outputs, **layer_attrs) return current_inputs, current_outputs def aten_dim(mapper, graph, node): """ 构造获取维度的PaddleLayer。 TorchScript示例: %106 : int = aten::dim(%101) 参数含义: %106 (int): 输出,Tensor的维度。 %101 (Tensor): 输入的Tensor。 """ output_name = mapper._get_outputs_name(node)[0] layer_outputs = [output_name] layer_inputs = {} inputs_name, inputs_node = mapper._get_inputs_name(node) # 处理输入0,即%input.8 mapper._check_input(graph, inputs_node[0], inputs_name[0], layer_outputs) layer_inputs["input"] = inputs_name[0] # 获取当前节点输入、输出的list current_inputs = list(layer_inputs.values()) current_outputs = layer_outputs graph.add_layer("prim.shape", inputs=layer_inputs, outputs=layer_outputs) graph.add_layer( "prim.len", inputs={"input": output_name}, outputs=layer_outputs) return current_inputs, current_outputs def aten_dropout(mapper, graph, node): """ 构造Dropout的PaddleLayer。 TorchScript示例: %119 : Tensor = aten::dropout(%result.3, %117, %118) 参数含义: %119 (Tensor): Dropout后的Tensor。 %result.3 (Tensor): 输入Tensor。 %118 (bool): 是否是训练阶段。 """ if "dropout" in mapper.dygraph_name_id: mapper.dygraph_name_id["dropout"] += 1 else: mapper.dygraph_name_id["dropout"] = 0 dropout_name = "dropout" + str(mapper.dygraph_name_id["dropout"]) output_name = mapper._get_outputs_name(node)[0] layer_outputs = [dropout_name, output_name] layer_inputs = {} inputs_name, inputs_node = mapper._get_inputs_name(node) # 处理输入0,即%119 mapper._check_input(graph, inputs_node[0], inputs_name[0], layer_outputs) layer_inputs["input"] = inputs_name[0] # 获取当前节点输入、输出的list current_inputs = list(layer_inputs.values()) current_outputs = layer_outputs[1:] graph.add_layer( "fluid.dygraph.Dropout", inputs=layer_inputs, outputs=layer_outputs, p=0.0) return current_inputs, current_outputs def aten_eq(mapper, graph, node): """ 构造判断数值是否相等的PaddleLayer。 TorchScript示例: %125 : bool = aten::eq(%124, %123) 参数含义: %125 (bool): 对比后结果。 %124 (-): 需对比的输入1。 %123 (-): 需对比的输入2。 """ output_name = mapper._get_outputs_name(node)[0] layer_outputs = [output_name] layer_inputs = {} inputs_name, inputs_node = mapper._get_inputs_name(node) # 处理输入0,即%124 mapper._check_input(graph, inputs_node[0], inputs_name[0], layer_outputs) layer_inputs["eq0"] = inputs_name[0] # 处理输入1,即%123 mapper._check_input(graph, inputs_node[1], inputs_name[1], layer_outputs) layer_inputs["eq1"] = inputs_name[1] # 获取当前节点输入、输出的list current_inputs = list(layer_inputs.values()) current_outputs = layer_outputs graph.add_layer("prim.eq", inputs=layer_inputs, outputs=layer_outputs) return current_inputs, current_outputs def aten_flatten(mapper, graph, node): """ 构造flatten的PaddleLayer。 TorchScript示例: %x.8 : Tensor = aten::flatten(%x, %4, %2) 参数含义: %x.8 (Tensor): flatten后结果。 %x (Tensor): 输入Tensor。 %4 (int): flatten的开始维度。 %2 (int): flatten的结束维度。 注意:目前flatten只支持第一维的flatten """ output_name = mapper._get_outputs_name(node)[0] layer_outputs = [output_name] layer_inputs = {} inputs_name, inputs_node = mapper._get_inputs_name(node) # 处理输入1,即%4 graph.add_layer( "prim.assert", inputs={}, outputs=[inputs_name[1]], type='eq', key=mapper.attrs[inputs_name[1]], value=1) # 处理输入2,即%2 graph.add_layer( "prim.assert", inputs={}, outputs=[inputs_name[2]], type='eq', key=mapper.attrs[inputs_name[2]], value=-1) # 处理输入0,即%x mapper._check_input(graph, inputs_node[0], inputs_name[0], layer_outputs) layer_inputs["x"] = inputs_name[0] # 获取当前节点输入、输出的list current_inputs = list(layer_inputs.values()) current_outputs = layer_outputs graph.add_layer( "fluid.layers.flatten", inputs=layer_inputs, outputs=layer_outputs, axis=1) return current_inputs, current_outputs def aten___getitem__(mapper, graph, node): """ 构造获取list中元素的PaddleLayer。 TorchScript示例: %v.1 : int = aten::__getitem__(%72, %88) 参数含义: %v.1 (-): 输出,list中的元素。 %72 (list): 需要获取元素的list。 %88 (int): 索引。 """ output_name = mapper._get_outputs_name(node)[0] layer_outputs = [output_name] layer_inputs = {} inputs_name, inputs_node = mapper._get_inputs_name(node) # 处理输入0,即%72 mapper._check_input(graph, inputs_node[0], inputs_name[0], layer_outputs) layer_inputs["list"] = inputs_name[0] # 处理输入1,即%88 mapper._check_input(graph, inputs_node[1], inputs_name[1], layer_outputs) layer_inputs["index"] = inputs_name[1] # 获取当前节点输入、输出的list current_inputs = list(layer_inputs.values()) current_outputs = layer_outputs graph.add_layer("prim.getitem", inputs=layer_inputs, outputs=layer_outputs) return current_inputs, current_outputs def aten_le(mapper, graph, node): """ 构造对比大小的PaddleLayer。 TorchScript示例: %80 : bool = aten::le(%78, %79) 参数含义: %80 (bool): 输出,第一个元素是否小于第二个元素。 %78 (-): 需对比的输入1。 %79 (-): 需对比的输入2。 """ output_name = mapper._get_outputs_name(node)[0] layer_outputs = [output_name] layer_inputs = {} inputs_name, inputs_node = mapper._get_inputs_name(node) # 处理输入0,即%78 mapper._check_input(graph, inputs_node[0], inputs_name[0], layer_outputs) layer_inputs["input0"] = inputs_name[0] # 处理输入1,即%79 mapper._check_input(graph, inputs_node[1], inputs_name[1], layer_outputs) layer_inputs["input1"] = inputs_name[1] # 获取当前节点输入、输出的list current_inputs = list(layer_inputs.values()) current_outputs = layer_outputs graph.add_layer("prim.le", inputs=layer_inputs, outputs=layer_outputs) return current_inputs, current_outputs def aten_len(mapper, graph, node): """ 构造获取list长度的PaddleLayer。 TorchScript示例: %85 : int = aten::len(%83) 参数含义: %85 (int): 输出,list的长度。 %72 (list): 需要获取长度的list。 """ output_name = mapper._get_outputs_name(node)[0] layer_outputs = [output_name] layer_inputs = {} inputs_name, inputs_node = mapper._get_inputs_name(node) # 处理输入0,即%72 mapper._check_input(graph, inputs_node[0], inputs_name[0], layer_outputs) layer_inputs["input"] = inputs_name[0] # 获取当前节点输入、输出的list current_inputs = list(layer_inputs.values()) current_outputs = layer_outputs graph.add_layer("prim.len", inputs=layer_inputs, outputs=layer_outputs) return current_inputs, current_outputs def aten_max_pool2d(mapper, graph, node): """ 构造最大池化的PaddleLayer。 TorchScript示例: %input.8 : Tensor = aten::max_pool2d(%result.11, %20, %23, %21, %22, %19) 参数含义: %input.8 (Tensor): 输出,池化后的结果。 %result.11 (Tensor): 需要池化的Tensor。 %20 (list): 池化kernel的大小。 %23 (list): 步长大小。 %21 (list): 填充大小。 %22 (list): 膨胀系数大小。 %19 (bool): 是否用ceil函数计算输出高度和宽度。 """ if "pool" in mapper.dygraph_name_id: mapper.dygraph_name_id["pool"] += 1 else: mapper.dygraph_name_id["pool"] = 0 pool_name = "pool" + str(mapper.dygraph_name_id["pool"]) output_name = mapper._get_outputs_name(node)[0] layer_outputs = [pool_name, output_name] layer_inputs = {} layer_attrs = {} inputs_name, inputs_node = mapper._get_inputs_name(node) # 处理输入0,即%result.11 mapper._check_input(graph, inputs_node[0], inputs_name[0], layer_outputs) layer_inputs["input"] = inputs_name[0] # 获取当前节点输入、输出的list current_inputs = list(layer_inputs.values()) current_outputs = layer_outputs[1:] # 处理输入1,即%20 layer_attrs["pool_size"] = mapper.attrs[inputs_name[1]] # 处理输入2,即%23 layer_attrs["pool_stride"] = mapper.attrs[inputs_name[2]] # 处理输入3,即%21 layer_attrs["pool_padding"] = mapper.attrs[inputs_name[3]] # 处理输入4,即%22 graph.add_layer( "prim.assert", inputs={}, outputs=[inputs_name[4]], type="eq", key=mapper.attrs[inputs_name[4]], value=[1, [1, 1]]) # 处理输入5,即%19 layer_attrs["ceil_mode"] = mapper.attrs[inputs_name[5]] layer_attrs["pool_type"] = string("max") graph.add_layer( "fluid.dygraph.Pool2D", inputs=layer_inputs, outputs=layer_outputs, **layer_attrs) return current_inputs, current_outputs def aten_matmul(mapper, graph, node): """ 构造矩阵相乘的PaddleLayer。 TorchScript示例: %output.2 : Tensor = aten::matmul(%101, %111) 参数含义: %output.2 (Tensor): 输出,相乘后的结果。 %101 (Tensor): 矩阵1。 %102 (Tensor): 矩阵2。 """ output_name = mapper._get_outputs_name(node)[0] layer_outputs = [output_name] layer_inputs = {} inputs_name, inputs_node = mapper._get_inputs_name(node) # 处理输入0,即%101 mapper._check_input(graph, inputs_node[0], inputs_name[0], layer_outputs) layer_inputs["x"] = inputs_name[0] # 处理输入1,即%102 mapper._check_input(graph, inputs_node[1], inputs_name[1], layer_outputs) layer_inputs["y"] = inputs_name[1] # 获取当前节点输入、输出的list current_inputs = list(layer_inputs.values()) current_outputs = layer_outputs graph.add_layer( "fluid.layers.matmul", inputs=layer_inputs, outputs=layer_outputs) return current_inputs, current_outputs def aten_relu_(mapper, graph, node): """ 构造ReLU激活的PaddleLayer。 TorchScript示例: %result.3 : Tensor = aten::relu_(%input.5) 参数含义: %result.3 (Tensor): 输出,ReLU后的结果。 %result.5 (Tensor): 需要ReLU的Tensor。 注意: inplace这个参数在paddle中未实现 """ output_name = mapper._get_outputs_name(node)[0] layer_outputs = [output_name] layer_inputs = {} inputs_name, inputs_node = mapper._get_inputs_name(node) # 处理输入0,即%result.5 mapper._check_input(graph, inputs_node[0], inputs_name[0], layer_outputs) layer_inputs["x"] = inputs_name[0] # 获取当前节点输入、输出的list current_inputs = list(layer_inputs.values()) current_outputs = layer_outputs graph.add_layer( "fluid.layers.relu", inputs=layer_inputs, outputs=layer_outputs) return current_inputs, current_outputs def aten_relu6(mapper, graph, node): """ 构造ReLU6激活的PaddleLayer。 TorchScript示例: %result.3 : Tensor = aten::relu6(%input.5) 参数含义: %result.3 (Tensor): 输出,ReLU6后的结果。 %result.5 (Tensor): 需要ReLU6的Tensor。 注意: inplace这个参数在paddle中未实现 """ output_name = mapper._get_outputs_name(node)[0] layer_outputs = [output_name] layer_inputs = {} inputs_name, inputs_node = mapper._get_inputs_name(node) # 处理输入0,即%result.5 mapper._check_input(graph, inputs_node[0], inputs_name[0], layer_outputs) layer_inputs["x"] = inputs_name[0] # 获取当前节点输入、输出的list current_inputs = list(layer_inputs.values()) current_outputs = layer_outputs graph.add_layer( "fluid.layers.relu6", inputs=layer_inputs, outputs=layer_outputs, threshold=6.0) return current_inputs, current_outputs def aten_size(mapper, graph, node): """ 构造获取shape的PaddleLayer。 TorchScript示例: %73 : int[] = aten::size(%x.12) 参数含义: %73 (list): 输出,shape的list。 %x.12 (Tensor): 需要获取shape的Tensor。 """ output_name = mapper._get_outputs_name(node)[0] layer_outputs = [output_name] layer_inputs = {} inputs_name, inputs_node = mapper._get_inputs_name(node) # 处理输入0,即%x.12 mapper._check_input(graph, inputs_node[0], inputs_name[0], layer_outputs) layer_inputs["input"] = inputs_name[0] # 获取当前节点输入、输出的list current_inputs = list(layer_inputs.values()) current_outputs = layer_outputs graph.add_layer("prim.shape", inputs=layer_inputs, outputs=layer_outputs) return current_inputs, current_outputs def aten_slice(mapper, graph, node): """ 构造切分list的PaddleLayer。 TorchScript示例: %83 : int[] = aten::slice(%73, %82, %75, %77) 参数含义: %83 (list): 输出,切分后的list。 %73 (list): 需要切分的list。 %82 (int): 切分的开始索引。 %75 (int): 切分的结束索引。 %77 (int): 切分的步长。 """ output_name = mapper._get_outputs_name(node)[0] layer_outputs = [output_name] layer_inputs = {} layer_attrs = {} inputs_name, inputs_node = mapper._get_inputs_name(node) # 处理输入0,即%73 mapper._check_input(graph, inputs_node[0], inputs_name[0], layer_outputs) layer_inputs["input"] = inputs_name[0] # 获取当前节点输入、输出的list current_inputs = list(layer_inputs.values()) current_outputs = layer_outputs # 处理输入1,即%82 if inputs_name[1] in mapper.attrs: layer_attrs["start"] = mapper.attrs[inputs_name[1]] else: layer_attrs["start"] = inputs_name[1] current_inputs.append(inputs_name[1]) # 处理输入2,即%75 if inputs_name[2] in mapper.attrs: layer_attrs["end"] = mapper.attrs[inputs_name[2]] else: layer_attrs["end"] = inputs_name[2] current_inputs.append(inputs_name[2]) # 处理输入3,即%77 if inputs_name[3] in mapper.attrs: layer_attrs["step"] = mapper.attrs[inputs_name[3]] else: layer_attrs["step"] = inputs_name[3] current_inputs.append(inputs_name[3]) graph.add_layer( "prim.slice", inputs=layer_inputs, outputs=layer_outputs, **layer_attrs) return current_inputs, current_outputs def aten_t(mapper, graph, node): """ 构造矩阵转置的PaddleLayer。 TorchScript示例: %109 : Tensor = aten::t(%102) 参数含义: %109 (Tensor): 输出,转置后的矩阵。 %102 (Tensor): 需要转置的Tensor。 """ output_name = mapper._get_outputs_name(node)[0] layer_outputs = [output_name] layer_inputs = {} inputs_name, inputs_node = mapper._get_inputs_name(node) # 处理输入0,即%x.12 mapper._check_input(graph, inputs_node[0], inputs_name[0], layer_outputs) layer_inputs["x"] = inputs_name[0] # 获取当前节点输入、输出的list current_inputs = list(layer_inputs.values()) current_outputs = layer_outputs graph.add_layer( "fluid.layers.transpose", inputs=layer_inputs, outputs=layer_outputs, perm=[1, 0]) return current_inputs, current_outputs