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

Merge pull request #12 from PaddlePaddle/develop

new
......@@ -10,12 +10,13 @@ X2Paddle在多个主流的CV模型上,测试过TensorFlow/Caffe/ONNX模型的
## 环境依赖
python == 2.7 | python >= 3.5
paddlepaddle >= 1.8.0
paddlepaddle >= 2.0.0
**按需安装以下依赖**
tensorflow : tensorflow == 1.14.0
caffe : 无
onnx : onnx >= 1.6.0
pytorch:torch >=1.5.0 (script方式暂不支持1.7.0)
## 安装
### 安装方式一(推荐)
......@@ -45,10 +46,13 @@ x2paddle --framework=caffe --prototxt=deploy.prototxt --weight=deploy.caffemodel
x2paddle --framework=onnx --model=onnx_model.onnx --save_dir=pd_model
```
### PyTorch
> PyTorch不支持命令行使用方式,详见[PyTorch2Paddle](pytorch2paddle.md)
### Paddle2ONNX
```
Paddle2ONNX功能已迁移至新的github: https://github.com/PaddlePaddle/paddle2onnx, 欢迎大家去新的代码仓库查看详细介绍以及新功能。
```
> Paddle2ONNX功能已迁移至新的github: https://github.com/PaddlePaddle/paddle2onnx, 欢迎大家去新的代码仓库查看详细介绍以及新功能。
### 参数选项
| 参数 | |
|----------|--------------|
......
# PyTorch2Paddle
PyTorch2Paddle支持trace和script两种方式的转换,均是PyTorch动态图到Paddle动态图的转换,转换后的Paddle动态图运用动转静可转换为静态图模型。trace方式生成的代码可读性较强,较为接近原版PyTorch代码的组织结构;script方式不需要知道输入数据的类型和大小即可转换,使用上较为方便,但目前PyTorch支持的script代码方式有所限制,所以支持转换的代码也有所限制。用户可根据自身需求,选择转换方式。
## 环境依赖
python == 2.7 | python >= 3.5
paddlepaddle >= 1.8.0
pytorch:torch >=1.5.0 (script方式暂不支持1.7.0)
**使用trace方式需安装以下依赖**
pandas
treelib
## 使用方式
``` python
from x2paddle.convert import pytorch2paddle
pytorch2paddle(module=torch_module,
save_dir="./pd_model",
jit_type="trace",
input_examples=[torch_input])
# module (torch.nn.Module): PyTorch的Module。
# save_dir (str): 转换后模型的保存路径。
# jit_type (str): 转换方式。默认为"trace"。
# input_examples (list[torch.tensor]): torch.nn.Module的输入示例,list的长度必须与输入的长度一致。默认为None。
```
**注意:** 当jit_type为"trace"时,input_examples不可为None,转换后自动进行动转静;
当jit_type为"script"时",input_examples不为None时,才可以进行动转静。
## 使用示例
``` python
import torch
import numpy as np
from torchvision.models import AlexNet
from torchvision.models.utils import load_state_dict_from_url
# 构建输入
input_data = np.random.rand(1, 3, 224, 224).astype("float32")
# 获取PyTorch Module
torch_module = AlexNet()
torch_state_dict = load_state_dict_from_url('https://download.pytorch.org/models/alexnet-owt-4df8aa71.pth')
torch_module.load_state_dict(torch_state_dict)
# 设置为eval模式
torch_module.eval()
# 进行转换
from x2paddle.convert import pytorch2paddle
pytorch2paddle(torch_model,
save_dir="pd_model_trace",
jit_type="trace",
input_examples=[torch.tensor(input_data)])
```
......@@ -4,6 +4,7 @@
```
python tools/check_for_lite.py paddle_model/inference_model/__model__
```
> 附:check_for_lite工具并不能完全判断模型是否被支持,PaddleLite详细支持的算子请参考[PaddleLite支持算子集](https://github.com/PaddlePaddle/Paddle-Lite/blob/develop/docs/introduction/support_operation_list.md)
### 二、模型参数合并
X2Paddle转换后产出的路径下包括两个目录,
......
__version__ = "0.8.8"
__version__ = "1.0.0rc0"
from .core.program import PaddleGraph
......
......@@ -13,6 +13,7 @@
# limitations under the License.
from six import text_type as _text_type
from x2paddle import program
import argparse
import sys
......@@ -63,12 +64,6 @@ def arg_parser():
action="store_true",
default=False,
help="get version of x2paddle")
parser.add_argument(
"--without_data_format_optimization",
"-wo",
type=_text_type,
default="True",
help="tf model conversion without data format optimization")
parser.add_argument(
"--define_input_shape",
"-d",
......@@ -82,11 +77,19 @@ def arg_parser():
default=False,
help="define whether merge the params")
parser.add_argument(
"--input_shapes",
"-is",
action='append',
default=None,
help="define the inputs' shape")
"--paddle_type",
"-pt",
type=_text_type,
default="dygraph",
help="define the paddle model type after converting(dygraph/static)"
)
parser.add_argument(
"--without_data_format_optimization",
"-wo",
type=_text_type,
default="True",
help="tf model conversion without data format optimization")
return parser
......@@ -94,6 +97,7 @@ def tf2paddle(model_path,
save_dir,
without_data_format_optimization=False,
define_input_shape=False,
paddle_type="dygraph",
params_merge=False):
# check tensorflow installation and version
try:
......@@ -111,33 +115,46 @@ def tf2paddle(model_path,
"[ERROR] Tensorflow is not installed, use \"pip install tensorflow\"."
)
return
from x2paddle import program
from x2paddle.decoder.tf_decoder import TFDecoder
from x2paddle.op_mapper.tf_op_mapper import TFOpMapper
from x2paddle.optimizer.tensorflow.bias import BiasOpt
from x2paddle.optimizer.tensorflow.transpose import TransposeOpt
from x2paddle.optimizer.tensorflow.batch_norm import BatchNormOpt
from x2paddle.optimizer.tensorflow.prelu import PReLUOpt
if paddle_type == "dygraph":
from x2paddle.op_mapper.dygraph.tf2paddle.tf_op_mapper import TFOpMapper
else:
from x2paddle.op_mapper.static.tf2paddle.tf_op_mapper import TFOpMapper
print("Now translating model from tensorflow to paddle.")
model = TFDecoder(model_path, define_input_shape=define_input_shape)
mapper = TFOpMapper(model)
program.build()
bias_opt = BiasOpt()
transpose_opt = TransposeOpt()
batch_norm_opt = BatchNormOpt()
prelu_opt = PReLUOpt()
bias_opt.run(program)
batch_norm_opt.run(program)
prelu_opt.run(program)
transpose_opt.run(program)
program.gen_model(save_dir)
mapper.paddle_graph.build()
if paddle_type == "dygraph":
from x2paddle.optimizer.optimizer import GraphOptimizer
graph_opt = GraphOptimizer(source_frame="tf", paddle_type=paddle_type)
graph_opt.optimize(mapper.paddle_graph)
else:
from x2paddle.optimizer.tensorflow.bias import BiasOpt
from x2paddle.optimizer.tensorflow.transpose import TransposeOpt
from x2paddle.optimizer.tensorflow.batch_norm import BatchNormOpt
from x2paddle.optimizer.tensorflow.prelu import PReLUOpt
bias_opt = BiasOpt()
transpose_opt = TransposeOpt()
batch_norm_opt = BatchNormOpt()
prelu_opt = PReLUOpt()
bias_opt.run(mapper.paddle_graph)
batch_norm_opt.run(mapper.paddle_graph)
prelu_opt.run(mapper.paddle_graph)
transpose_opt.run(mapper.paddle_graph)
mapper.paddle_graph.gen_model(save_dir)
def caffe2paddle(proto, weight, save_dir, caffe_proto, params_merge=False):
def caffe2paddle(proto, weight, save_dir, caffe_proto,
paddle_type, params_merge=False):
from x2paddle.decoder.caffe_decoder import CaffeDecoder
from x2paddle.op_mapper.caffe_op_mapper import CaffeOpMapper
from x2paddle.optimizer.caffe_optimizer import CaffeOptimizer
if paddle_type == "dygraph":
from x2paddle.op_mapper.dygraph.caffe2paddle.caffe_op_mapper import CaffeOpMapper
else:
from x2paddle.op_mapper.static.caffe2paddle.caffe_op_mapper import CaffeOpMapper
import google.protobuf as gpb
ver_part = gpb.__version__.split('.')
version_satisfy = False
......@@ -148,13 +165,16 @@ def caffe2paddle(proto, weight, save_dir, caffe_proto, params_merge=False):
print("Now translating model from caffe to paddle.")
model = CaffeDecoder(proto, weight, caffe_proto)
mapper = CaffeOpMapper(model)
optimizer = CaffeOptimizer(mapper)
optimizer.merge_bn_scale()
optimizer.merge_op_activation()
mapper.save_inference_model(save_dir, params_merge)
mapper.paddle_graph.build()
print("Model optimizing ...")
from x2paddle.optimizer.optimizer import GraphOptimizer
graph_opt = GraphOptimizer(source_frame="caffe", paddle_type=paddle_type)
graph_opt.optimize(mapper.paddle_graph)
print("Model optimized.")
mapper.paddle_graph.gen_model(save_dir)
def onnx2paddle(model_path, save_dir, params_merge=False):
def onnx2paddle(model_path, save_dir, paddle_type, params_merge=False):
# check onnx installation and version
try:
import onnx
......@@ -167,22 +187,26 @@ def onnx2paddle(model_path, save_dir, params_merge=False):
return
print("Now translating model from onnx to paddle.")
from x2paddle.op_mapper.onnx2paddle.onnx_op_mapper import ONNXOpMapper
from x2paddle.decoder.onnx_decoder import ONNXDecoder
from x2paddle.optimizer.onnx_optimizer import ONNXOptimizer
if paddle_type == "dygraph":
from x2paddle.op_mapper.dygraph.onnx2paddle.onnx_op_mapper import ONNXOpMapper
else:
from x2paddle.op_mapper.static.onnx2paddle.onnx_op_mapper import ONNXOpMapper
model = ONNXDecoder(model_path)
mapper = ONNXOpMapper(model)
print("Model optimizing ...")
optimizer = ONNXOptimizer(mapper)
optimizer.delete_redundance_code()
print("Model optimized.")
print("Paddle model and code generating ...")
mapper.save_inference_model(save_dir, params_merge)
print("Paddle model and code generated.")
if paddle_type == "dygraph":
mapper.paddle_graph.build()
mapper.paddle_graph.gen_model(save_dir)
else:
from x2paddle.optimizer.onnx_optimizer import ONNXOptimizer
print("Model optimizing ...")
optimizer = ONNXOptimizer(mapper)
optimizer.delete_redundance_code()
print("Model optimized.")
mapper.save_inference_model(save_dir, params_merge)
def pytorch2paddle(model_path, save_dir, input_shapes):
def pytorch2paddle(module, save_dir, jit_type="trace", input_examples=None):
# check pytorch installation and version
try:
import torch
......@@ -198,27 +222,22 @@ def pytorch2paddle(model_path, save_dir, input_shapes):
)
return
print("Now translating model from pytorch to paddle.")
from x2paddle.decoder.pytorch_decoder import ScriptDecoder, TraceDecoder
from x2paddle.op_mapper.dygraph.pytorch2paddle.pytorch_op_mapper import PyTorchOpMapper
from x2paddle.decoder.pytorch_decoder import PyTorchDecoder
from x2paddle.op_mapper.pytorch2paddle import pytorch_op_mapper
model = PyTorchDecoder(model_path)
mapper = pytorch_op_mapper.PyTorchOpMapper(model)
mapper.graph.build()
if jit_type == "trace":
model = TraceDecoder(module, input_examples)
else:
model = ScriptDecoder(module, input_examples)
mapper = PyTorchOpMapper(model)
mapper.paddle_graph.build()
print("Model optimizing ...")
from x2paddle.optimizer.pytorch_optimizer.optimizer import GraphOptimizer
graph_opt = GraphOptimizer()
graph_opt.optimize(mapper.graph)
from x2paddle.optimizer.optimizer import GraphOptimizer
graph_opt = GraphOptimizer(source_frame="pytorch", paddle_type="dygraph", jit_type=jit_type)
graph_opt.optimize(mapper.paddle_graph)
print("Model optimized.")
if input_shapes is not None:
real_input_shapes = list()
for shape in input_shapes:
sp = shape[1:-1].split(",")
for i, s in enumerate(sp):
sp[i] = int(s)
real_input_shapes.append(sp)
else:
real_input_shapes = None
mapper.graph.gen_model(save_dir, real_input_shapes)
mapper.paddle_graph.gen_model(save_dir, jit_type=jit_type)
def main():
......@@ -239,6 +258,7 @@ def main():
assert args.framework is not None, "--framework is not defined(support tensorflow/caffe/onnx)"
assert args.save_dir is not None, "--save_dir is not defined"
assert args.paddle_type in ["dygraph", "static"], "--paddle_type must be 'dygraph' or 'static'"
try:
import paddle
......@@ -246,8 +266,8 @@ def main():
print("paddle.__version__ = {}".format(paddle.__version__))
if v0 == '0' and v1 == '0' and v2 == '0':
print("[WARNING] You are use develop version of paddlepaddle")
elif int(v0) != 1 or int(v1) < 6:
print("[ERROR] paddlepaddle>=1.6.0 is required")
elif int(v0) != 2 or int(v1) < 0:
print("[ERROR] paddlepaddle>=2.0.0 is required")
return
except:
print(
......@@ -267,7 +287,7 @@ def main():
if args.params_merge:
params_merge = True
tf2paddle(args.model, args.save_dir, without_data_format_optimization,
define_input_shape, params_merge)
define_input_shape, args.paddle_type, params_merge)
elif args.framework == "caffe":
assert args.prototxt is not None and args.weight is not None, "--prototxt and --weight should be defined while translating caffe model"
......@@ -275,21 +295,20 @@ def main():
if args.params_merge:
params_merge = True
caffe2paddle(args.prototxt, args.weight, args.save_dir,
args.caffe_proto, params_merge)
args.caffe_proto, args.paddle_type, params_merge)
elif args.framework == "onnx":
assert args.model is not None, "--model should be defined while translating onnx model"
params_merge = False
if args.params_merge:
params_merge = True
onnx2paddle(args.model, args.save_dir, params_merge)
onnx2paddle(args.model, args.save_dir, args.paddle_type, params_merge)
elif args.framework == "paddle2onnx":
print("Paddle to ONNX tool has been migrated to the new github: https://github.com/PaddlePaddle/paddle2onnx")
else:
raise Exception(
"--framework only support tensorflow/caffe/onnx/ now")
"--framework only support tensorflow/caffe/onnx now")
if __name__ == "__main__":
......
......@@ -41,6 +41,8 @@ class Layer(object):
layer_code = layer_code
elif self.use_fluid:
layer_code = layer_code + "fluid." + self.op + "("
elif self.op == "full_like":
layer_code = layer_code + "paddle." + self.op + "("
else:
layer_code = layer_code + "fluid.layers." + self.op + "("
......
......@@ -128,6 +128,7 @@ class OpMapper(object):
self.add_codes("from paddle.fluid.initializer import Constant")
self.add_codes("from paddle.fluid.param_attr import ParamAttr")
self.add_codes("import paddle.fluid as fluid")
self.add_codes("import paddle")
self.add_codes("")
def save_inference_model(self, save_dir, params_merge):
......@@ -214,6 +215,7 @@ class OpMapper(object):
self.add_codes("", 0)
self.add_codes("\ndef x2paddle_net():", 0)
self.add_codes("paddle.enable_static()", 1)
for i in range(len(self.graph.topo_sort)):
node_name = self.graph.topo_sort[i]
node = self.graph.get_node(node_name)
......
......@@ -16,20 +16,20 @@
from __future__ import print_function
from __future__ import division
import paddle.fluid as fluid
import os.path as osp
import paddle
from paddle.fluid.proto import framework_pb2
from collections import OrderedDict
import numpy
import collections
import sys
import os
import six
import pickle
import numpy as np
from os import path as osp
class PaddleLayer(object):
def __init__(self, id, kernel, inputs, outputs, **kwargs):
def __init__(self, id, kernel, inputs, outputs, scope_name="", **kwargs):
assert isinstance(
inputs,
dict), "parameter 'inputs' for PaddleLayer should be type of dict"
......@@ -53,16 +53,18 @@ class PaddleLayer(object):
self.kernel = kernel
self.inputs = inputs
self.outputs = outputs
self.scope_name = scope_name
self.attrs = kwargs
self.id = id
self.blocks = list()
def add_block(self, block):
self.blocks.append(block)
class PaddleGraph(object):
def __init__(self, parent_layer=None, graph_type="static"):
def __init__(self, source_type=None, parent_layer=None, graph_type="static"):
self.layers = OrderedDict()
self.edges_out = dict()
self.edges_in = dict()
......@@ -71,12 +73,24 @@ class PaddleGraph(object):
self.parameters = dict()
self.parent_layer = parent_layer
self.graph_type = graph_type
self.source_type = source_type
self.custom_code = None
self.inputs_info = None
def set_name(self, name):
self.name = name
self.name = name.replace("-", "_").replace("/", "_")
def set_parameters(self, parameters):
self.parameters = parameters
def set_custom(self, custom_code):
self.custom_code = custom_code
def set_inputs_info(self, inputs_info):
self.inputs_info = inputs_info
def set_script(self, script):
self.script = script
def clear(self):
self.layers = OrderedDict()
......@@ -90,13 +104,13 @@ class PaddleGraph(object):
self.edges_out = dict()
self.edges_in = dict()
def add_layer(self, kernel, inputs, outputs, **kwargs):
def add_layer(self, kernel, inputs, outputs, scope_name="", **kwargs):
layer_id = str(len(self.layers))
if self.parent_layer is not None:
layer_id = "{}.{}.{}".format(self.parent_layer.id,
len(self.parent_layer.blocks),
layer_id)
layer = PaddleLayer(layer_id, kernel, inputs, outputs, **kwargs)
layer = PaddleLayer(layer_id, kernel, inputs, outputs, scope_name=scope_name, **kwargs)
self.layers[layer_id] = layer
return layer_id
......@@ -215,10 +229,75 @@ class PaddleGraph(object):
block_global_layers = update(block.layers)
global_layers.update(block_global_layers)
return global_layers
return update(self.layers)
def gen_code(self, code_dir):
def gen_model(self, save_dir, jit_type=None):
if not osp.exists(save_dir):
os.makedirs(save_dir)
if self.graph_type == "static":
self.gen_static_model(save_dir)
else:
self.gen_dygraph_model(save_dir, jit_type)
def gen_static_model(self, save_dir):
code_dir = osp.join(save_dir, 'model_with_code')
infer_dir = osp.join(save_dir, 'inference_model')
self.gen_static_code(code_dir)
sys.path.append(code_dir)
import x2paddle_model
paddle.enable_static()
scope = paddle.static.Scope()
startup_program = paddle.static.Program()
main_program = paddle.static.Program()
with paddle.static.scope_guard(scope):
with paddle.static.program_guard(main_program, startup_program):
inputs, outputs = x2paddle_model.x2paddle_net()
exe = fluid.Executor(fluid.CPUPlace())
exe.run(startup_program)
param_dir = osp.join(code_dir, 'weights')
for k, v in self.parameters.items():
if scope.find_var(k):
self.dump_parameter(k, v, param_dir)
def if_exist(var):
b = osp.exists(
osp.join(osp.join(param_dir, var.name)))
return b
fluid.io.load_vars(
exe, param_dir, main_program, predicate=if_exist)
fluid.io.save_inference_model(
dirname=infer_dir,
feeded_var_names=[i.name for i in inputs],
target_vars=outputs,
executor=exe)
def gen_dygraph_model(self, save_dir, jit_type=None):
if jit_type == "trace":
from x2paddle.optimizer.code_optimizer import HierarchicalTree
hierarchical_tree = HierarchicalTree(self)
for layer_id, layer in self.layers.items():
hierarchical_tree.insert(layer)
hierarchical_tree.save_source_files(save_dir)
self.dump_dygraph_parameter(save_dir)
else:
self.gen_dygraph_code(save_dir)
self.dump_dygraph_parameter(save_dir)
# 动转静
code_path = osp.join(osp.abspath(save_dir), "x2paddle_code.py")
print("Exporting inference model from python code ('{}')... \n".format(code_path))
if len(self.inputs_info) > 0:
input_shapes = list()
input_types = list()
for input_name in self.inputs:
input_shapes.append(self.inputs_info[input_name][0])
input_types.append(self.inputs_info[input_name][1])
try:
self.dygraph2static(save_dir, input_shapes, input_types)
except Exception as e:
print("Fail to generate inference model! Problem happend while export inference model from python code '{}';\n".format(code_path))
print("===================Error Information===============")
raise e
def gen_static_code(self, code_dir):
def write_code(f, code_list, indent=0):
indent_blank = " " * indent
for code_line in code_list:
......@@ -227,18 +306,32 @@ class PaddleGraph(object):
else:
f.write(indent_blank + code_line + '\n')
if not os.path.exists(code_dir):
if not osp.exists(code_dir):
os.makedirs(code_dir)
f = open(os.path.join(code_dir, 'x2paddle_model.py'), 'w')
f = open(osp.join(code_dir, 'x2paddle_model.py'), 'w')
write_code(
f, [
"from paddle.fluid.initializer import Constant",
"from paddle.fluid.param_attr import ParamAttr",
"import paddle.fluid as fluid", "import math", "",
"def x2paddle_net():"
"import paddle.fluid as fluid",
"import paddle", "import math", "",
],
indent=0)
if self.custom_code is not None:
write_code(
f,
list(self.custom_code.values()),
indent=0)
write_code(f,
["", "def x2paddle_net():"],
indent=0)
write_code(
f, [
"paddle.enable_static()"
],
indent=1)
for layer_id, layer in self.layers.items():
edges_in = self.edges_in.get(layer_id, [])
edges_out = self.edges_out.get(layer_id, [])
......@@ -253,8 +346,10 @@ class PaddleGraph(object):
for output in layer.outputs:
line += "{}, ".format(output)
line = line.strip(", ")
line += " = {}(".format(layer.kernel)
if layer.kernel.startswith("custom_layer"):
line += " = {}(".format(layer.kernel.split(":")[-1].lower() + "_layer")
else:
line += " = {}(".format(layer.kernel)
for k, v in layer.inputs.items():
if isinstance(v, list):
line += "{}=[{}], ".format(k, ", ".join(v))
......@@ -274,50 +369,9 @@ class PaddleGraph(object):
indent=1)
f.close()
def gen_model(self, save_dir, input_shapes=None):
if not os.path.exists(save_dir):
os.makedirs(save_dir)
if self.graph_type == "static":
code_dir = os.path.join(save_dir, 'model_with_code')
infer_dir = os.path.join(save_dir, 'inference_model')
self.gen_code(code_dir)
sys.path.append(code_dir)
import x2paddle_model
scope = fluid.Scope()
startup_program = fluid.Program()
main_program = fluid.Program()
with fluid.scope_guard(scope):
with fluid.program_guard(main_program, startup_program):
inputs, outputs = x2paddle_model.x2paddle_net()
exe = fluid.Executor(fluid.CPUPlace())
exe.run(startup_program)
param_dir = os.path.join(code_dir, 'weights')
for k, v in self.parameters.items():
if scope.find_var(k):
self.dump_parameter(k, v, param_dir)
def if_exist(var):
b = os.path.exists(
os.path.join(os.path.join(param_dir, var.name)))
return b
fluid.io.load_vars(
exe, param_dir, main_program, predicate=if_exist)
fluid.io.save_inference_model(
dirname=infer_dir,
feeded_var_names=[i.name for i in inputs],
target_vars=outputs,
executor=exe)
else:
self.gen_dygraph_code(save_dir)
self.dump_dygraph_parameter(save_dir)
if input_shapes is not None:
# 如果input_shapes非空,则导出推理模型;其值类似[[None, 3, 224, 224]]
self.dygraph2static(save_dir, input_shapes)
def dump_parameter(self, param_name, param, save_dir):
if not os.path.exists(save_dir):
if not osp.exists(save_dir):
os.makedirs(save_dir)
dtype_map = {
"int16": [framework_pb2.VarType.INT16, 'h'],
......@@ -337,7 +391,7 @@ class PaddleGraph(object):
assert str(
param.dtype) in dtype_map, "Unknown dtype {} of params: {}.".format(
str(param.dtype), param_name)
fp = open(os.path.join(save_dir, param_name), 'wb')
fp = open(osp.join(save_dir, param_name), 'wb')
numpy.array([0], dtype='int32').tofile(fp)
numpy.array([0], dtype='int64').tofile(fp)
numpy.array([0], dtype='int32').tofile(fp)
......@@ -356,10 +410,10 @@ class PaddleGraph(object):
if self.edges_in.get(layer_id, 0) == 0 and self.edges_out.get(
layer_id, 0) == 0:
continue
if layer.kernel == "fluid.dygraph.base.to_variable":
value = layer.attrs["value"]
if not value.startswith("params["):
self.inputs.append(value)
if layer.kernel == "paddle.to_tensor":
data = layer.attrs["data"]
if not data.startswith("params["):
self.inputs.append(data)
if len(layer.blocks) > 0:
for block in layer.blocks:
block.get_dygraph_inputs()
......@@ -376,11 +430,13 @@ class PaddleGraph(object):
layer_id, 0) == 0:
continue
if self.edges_out.get(layer_id, 0) == 0:
for output_name in layer.outputs:
if not output_name.startswith("x"):
continue
self.outputs.append(output_name)
self.outputs = list(set(self.outputs))
for i, output_name in enumerate(layer.outputs):
if ("paddle.nn" in layer.kernel and "functional" not in layer.kernel):
if i == 0:
continue
if output_name not in self.outputs:
self.outputs.append(output_name)
def gen_dygraph_code(self, code_dir=None, indent=2):
def gen_codes(code_list, indent=0):
......@@ -394,20 +450,30 @@ class PaddleGraph(object):
return codes
def gen_head():
if self.source_type == "caffe":
custom_import = "from x2paddle.op_mapper.dygraph.caffe2paddle " + \
"import caffe_custom_layer as x2paddle_nn"
elif self.source_type == "pytorch":
custom_import = "from x2paddle.op_mapper.dygraph.pytorch2paddle " + \
"import pytorch_custom_layer as x2paddle_nn"
else:
custom_import = ""
self.head = gen_codes(
[
"from paddle.fluid.initializer import Constant",
"from paddle.fluid.param_attr import ParamAttr",
"import paddle",
"import paddle.fluid as fluid",
"import math",
custom_import,
"",
"class {}(fluid.dygraph.Layer):".format(self.name),
"class {}(paddle.nn.Layer):".format(self.name),
],
indent=0)
input_data_name = ', '.join(self.inputs)
self.init_func.extend(
gen_codes(
["def __init__(self, params):"], indent=1))
["def __init__(self):"], indent=1))
self.init_func.extend(
gen_codes(
["super({}, self).__init__()".format(self.name)], indent=2))
......@@ -415,9 +481,35 @@ class PaddleGraph(object):
gen_codes(
["def forward(self, {}):".format(input_data_name)],
indent=1))
def gen_main_code(code_dir):
input_data_name = ', '.join(self.inputs)
self.run_func = gen_codes(
[
"",
"def main({}):".format(input_data_name),
],
indent=0)
comment_list = list()
comment_list.append("# 共{}个输入".format(len(self.inputs_info)))
for k, v in self.inputs_info.items():
comment_list.append("# {}: 形状为{},类型为{}。".format(k, v[0], v[1]))
self.run_func.extend(
gen_codes(
comment_list,
indent=1))
use_structured_name = False if self.source_type in ["tf", "onnx"] else True
self.run_func.extend(
gen_codes(["paddle.disable_static()",
"params = paddle.load('{}/model.pdparams')".format(osp.abspath(code_dir)),
"model = {}()".format(self.name),
"model.set_dict(params, use_structured_name={})".format(use_structured_name),
"model.eval()",
"out = model({})".format(input_data_name),
"return out"], indent=1))
def write_code(code_dir):
f = open(os.path.join(code_dir, 'x2paddle_code.py'), 'w')
f = open(osp.join(code_dir, 'x2paddle_code.py'), 'w')
for code_line in self.head:
f.write(code_line)
init_writen_codes = []
......@@ -430,6 +522,10 @@ class PaddleGraph(object):
return_code = "return {}".format(", ".join(self.outputs))
self.forward_func.extend(gen_codes([return_code], indent=2))
for code_line in self.forward_func:
if "assert [1, 1] == 1 or [1, 1] == [1, 1], 'The [1, 1] must be [1, [1, 1]]!'" in code_line:
continue
f.write(code_line)
for code_line in self.run_func:
f.write(code_line)
f.close()
......@@ -440,21 +536,25 @@ class PaddleGraph(object):
for layer_id, layer in self.layers.items():
if ("paddle.nn" in layer.kernel and "functional" not in layer.kernel
) or layer.kernel == "fluid.dygraph.base.to_variable" or \
"paddle.fluid.dygraph" in layer.kernel:
) or layer.kernel == "paddle.to_tensor" or \
layer.kernel.startswith("custom_layer") or \
layer.kernel.startswith("paddle.fluid.dygraph"):
line = "{}".format(
layer.outputs[0]
) if layer.kernel == "fluid.dygraph.base.to_variable" and not layer.attrs[
"value"].startswith("params[") else "self.{}".format(
) if layer.kernel == "paddle.to_tensor" and not layer.attrs[
"data"].startswith("params[") else "self.{}".format(
layer.outputs[0])
line += " = {}(".format(layer.kernel)
if layer.kernel.startswith("custom_layer"):
line += "= x2paddle_nn.{}(".format(layer.kernel.split(":")[-1])
else:
line += " = {}(".format(layer.kernel)
for k, v in layer.attrs.items():
line += "{}={}, ".format(k, v)
line = line.strip(", ")
line += ")"
if layer.kernel == "fluid.dygraph.base.to_variable" and not layer.attrs[
"value"].startswith("params["):
if layer.kernel == "paddle.to_tensor" and not layer.attrs[
"data"].startswith("params["):
self.forward_func.extend(gen_codes([line], indent=indent))
continue
else:
......@@ -466,8 +566,8 @@ class PaddleGraph(object):
line = layer.outputs[1]
else:
line = ','.join(layer.outputs[1:])
if layer.kernel == "fluid.dygraph.base.to_variable" and layer.attrs[
"value"].startswith("params["):
if layer.kernel == "paddle.to_tensor" and layer.attrs[
"data"].startswith("params["):
line += " = self.{}".format(layer.outputs[0])
else:
line += " = self.{}(".format(layer.outputs[0])
......@@ -475,10 +575,10 @@ class PaddleGraph(object):
line += "{}, ".format(v)
line = line.strip(", ")
line += ")"
self.forward_func.extend(gen_codes([line], indent=indent))
self.forward_func.extend(gen_codes([line], indent=indent))
elif "prim" in layer.kernel:
func_name = layer.kernel.replace(".", "_")
from x2paddle.op_mapper.pytorch2paddle import prim2code
from x2paddle.op_mapper.dygraph.pytorch2paddle import prim2code
if hasattr(prim2code, func_name):
func = getattr(prim2code, func_name)
func(
......@@ -497,39 +597,58 @@ class PaddleGraph(object):
line = ','.join(layer.outputs)
line += " = {}(".format(layer.kernel)
for k, v in layer.inputs.items():
line += "{}={}, ".format(k, v)
if isinstance(v, list):
line += "{}=[{}], ".format(k, ", ".join(v))
else:
if k == "args":
line += v
else:
line += "{}={}, ".format(k, v)
for k, v in layer.attrs.items():
line += "{}={}, ".format(k, v)
line = line.strip(", ")
line += ")"
self.forward_func.extend(gen_codes([line], indent=indent))
if layer.kernel == "self.create_parameter":
self.init_func.extend(gen_codes(["self." + line], indent=2))
self.forward_func.extend(gen_codes(["{} = self.{}".format(layer.outputs[0],
layer.outputs[0])], indent=indent))
else:
self.forward_func.extend(gen_codes([line], indent=indent))
if indent == 2:
gen_main_code(code_dir)
write_code(code_dir)
else:
return self.init_func, self.forward_func
def dump_dygraph_parameter(self, code_dir):
params_output = open(os.path.join(code_dir, 'model.pdparams'), 'wb')
pickle.dump(self.parameters, params_output)
params_output.close()
save_path = osp.join(code_dir, 'model.pdparams')
paddle.save(self.parameters, save_path)
def dygraph2static(self, save_dir, input_shapes=[]):
def dygraph2static(self, save_dir, input_shapes=[], input_types=[]):
from paddle.fluid.dygraph.jit import declarative
sepc_list = list()
for i, name in enumerate(self.inputs):
sepc_list.append(
paddle.static.InputSpec(
shape=input_shapes[i], name=name))
shape=input_shapes[i], name=name, dtype=input_types[i]))
import sys
path = osp.abspath(save_dir)
sys.path.insert(0, save_dir)
import x2paddle_code
place = fluid.CPUPlace()
with fluid.dygraph.guard(place):
restore, _ = fluid.load_dygraph(osp.join(save_dir, "model"))
model = getattr(x2paddle_code, self.name)(restore)
paddle.disable_static()
restore = paddle.load(osp.join(save_dir, "model.pdparams"))
model = getattr(x2paddle_code, self.name)()
if self.source_type in ["tf", "onnx"]:
model.set_dict(restore, use_structured_name=False)
else:
model.set_dict(restore)
model.eval()
model.forward = declarative(model.forward, sepc_list)
fluid.dygraph.jit.save(
layer=model, model_path=osp.join(save_dir, "inference"))
model.eval()
static_model = paddle.jit.to_static(model, input_spec=sepc_list)
try:
paddle.jit.save(static_model, osp.join(save_dir, "inference_model/model"))
except ValueError as e:
if str(e) == "'target_vars' should be a list of Variable.":
print("[DyGraph2StaticGraph Error] Can not convert the dygraph to static! The output of PyTorch mustbe Variable or a list of Variable.")
else:
print(e)
exit(0)
# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"
# you may not use this file except in compliance with the License.
......@@ -18,3 +18,11 @@ import os
def string(param):
return "\'{}\'".format(param)
def name_generator(nn_name, nn_name2id):
if nn_name in nn_name2id:
nn_name2id[nn_name] += 1
else:
nn_name2id[nn_name] = 0
real_nn_name = nn_name + str(nn_name2id[nn_name])
return real_nn_name
\ No newline at end of file
......@@ -18,7 +18,7 @@ from google.protobuf import text_format
import numpy as np
from x2paddle.core.graph import GraphNode, Graph
from x2paddle.core.fluid_code import FluidCode
from x2paddle.op_mapper import caffe_shape
from x2paddle.decoder import caffe_shape_inference
class CaffeResolver(object):
......@@ -50,22 +50,51 @@ class CaffeGraphNode(GraphNode):
def __init__(self, layer, type_str, layer_name=None):
if layer_name is None:
super(CaffeGraphNode, self).__init__(
layer, layer.name.replace('/', '_').replace('-', '_'))
layer, layer.name.replace('/', '_').replace('-', '_').lower())
else:
super(CaffeGraphNode, self).__init__(
layer, layer_name.replace('/', '_').replace('-', '_'))
layer, layer_name.replace('/', '_').replace('-', '_').lower())
self.layer_type = type_str
self.fluid_code = FluidCode()
self.data = None
def set_params(self, params):
self.data = params
@property
def name(self):
if hasattr(self, 'index'):
return "{}_p{}".format(self.layer_name, self.index)
return self.layer_name
@property
def out_shapes(self):
return self._out_shapes
@out_shapes.setter
def out_shapes(self, value):
self._out_shapes = value
@property
def in_shapes(self):
return self._in_shapes
@in_shapes.setter
def in_shapes(self, value):
self._in_shapes = value
class CaffeGraph(Graph):
def __init__(self, model, params, caffe_pb):
self.params = params
self.caffe_pb = caffe_pb
if hasattr(model, "name"):
if model.name == "":
self.graph_name = "CaffeModel"
else:
self.graph_name = model.name
else:
self.graph_name = "CaffeModel"
super(CaffeGraph, self).__init__(model)
def filter_layers(self, layers):
......@@ -220,8 +249,11 @@ class CaffeGraph(Graph):
layer_name)
super(CaffeGraph, self).build()
for i, node_name in enumerate(self.topo_sort):
node = self.get_node(node_name)
self.set_node_shape(node)
def get_bottom_node(self, node, idx=0, copy=False):
def get_input_node(self, node, idx=0, copy=False):
input_node_name = node.inputs[idx]
assert input_node_name in self.node_map, 'The {} isn\'t a valid node'.format(
name)
......@@ -232,6 +264,19 @@ class CaffeGraph(Graph):
else:
name = input_node_name
return self.get_node(name, copy=copy)
def set_node_shape(self, node):
inputs = node.inputs
input_shape = []
for i, nm in enumerate(inputs):
last_node = self.get_node(nm)
tmp = node.layer.bottom[i]
idx = list(last_node.layer.top).index(tmp)
input_shape.append(last_node.out_shapes[idx])
node.in_shapes = input_shape
func_name = 'shape_' + node.layer_type.lower()
node.out_shapes = getattr(caffe_shape_inference, func_name)(node.layer,
input_shape)
class CaffeDecoder(object):
......@@ -244,7 +289,7 @@ class CaffeDecoder(object):
with open(proto_path, 'rb') as proto_file:
proto_str = proto_file.read()
text_format.Merge(proto_str, self.net)
self.load_using_pb()
self.caffe_graph = CaffeGraph(self.net, self.params,
......
# 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.
import math
import numbers
from functools import reduce
def get_kernel_parameters(params):
[k_h, k_w] = [1, 1]
if isinstance(params.kernel_size, numbers.Number):
[k_h, k_w] = [params.kernel_size] * 2
elif len(params.kernel_size) > 0:
k_h = params.kernel_h if params.kernel_h > 0 else params.kernel_size[0]
k_w = params.kernel_w if params.kernel_w > 0 else params.kernel_size[
len(params.kernel_size) - 1]
elif params.kernel_h > 0 or params.kernel_w > 0:
k_h = params.kernel_h
k_w = params.kernel_w
[s_h, s_w] = [1, 1]
if isinstance(params.stride, numbers.Number):
[s_h, s_w] = [params.stride] * 2
elif len(params.stride) > 0:
s_h = params.stride_h if params.stride_h > 0 else params.stride[0]
s_w = params.stride_w if params.stride_w > 0 else params.stride[len(
params.stride) - 1]
elif params.stride_h > 0 or params.stride_w > 0:
s_h = params.stride_h
s_w = params.stride_w
[p_h, p_w] = [0, 0]
if isinstance(params.pad, numbers.Number):
[p_h, p_w] = [params.pad] * 2
elif len(params.pad) > 0:
p_h = params.pad_h if params.pad_h > 0 else params.pad[0]
p_w = params.pad_w if params.pad_w > 0 else params.pad[len(params.pad) -
1]
elif params.pad_h > 0 or params.pad_w > 0:
p_h = params.pad_h
p_w = params.pad_w
dila_h = dila_w = 1
if hasattr(params, 'dilation'):
dila_len = len(params.dilation)
if dila_len == 2:
dila_h = params.dilation[0]
dila_w = params.dilation[1]
elif dila_len == 1:
dila_h = dila_w = params.dilation[0]
else:
assert dila_len == 0, "invalid length[%s] of dilation in convolution" % (
dila_len)
return dila_h, dila_w, p_h, p_w, k_h, k_w, s_h, s_w
def get_strided_kernel_output_shape(params, input_shape, round_func):
i_h = input_shape[2]
i_w = input_shape[3]
dila_h, dila_w, pad_h, pad_w, kernel_h, kernel_w, stride_h, stride_w = get_kernel_parameters(
params)
o_h = (i_h + 2 * pad_h - (dila_h *
(kernel_h - 1) + 1)) / float(stride_h) + 1
o_w = (i_w + 2 * pad_w - (dila_w *
(kernel_w - 1) + 1)) / float(stride_w) + 1
o_h = int(round_func(o_h))
o_w = int(round_func(o_w))
has_c_o = hasattr(params, 'num_output')
c = params.num_output if has_c_o else input_shape[1]
return [[input_shape[0], c, o_h, o_w]]
def shape_convolution(layer, input_shape):
params = layer.convolution_param
return get_strided_kernel_output_shape(params, input_shape[0], math.floor)
def shape_depthwiseconvolution(layer, input_shape):
return shape_convolution(layer, input_shape)
def shape_deconvolution(layer, input_shape):
h_i = input_shape[0][2]
w_i = input_shape[0][3]
params = layer.convolution_param
dila_h, dila_w, pad_h, pad_w, kernel_h, kernel_w, stride_h, stride_w = get_kernel_parameters(
params)
h_o = (h_i - 1) * stride_h - 2 * pad_h + dila_h * (kernel_h - 1) + 1
w_o = (w_i - 1) * stride_w - 2 * pad_w + dila_w * (kernel_w - 1) + 1
has_c_o = hasattr(params, 'num_output')
c = params.num_output if has_c_o else input_shape.channels
return [[input_shape[0][0], c, h_o, w_o]]
def shape_pooling(layer, input_shape):
params = layer.pooling_param
global_pool = getattr(params, 'global_pooling', False)
if global_pool:
return [[input_shape[0][0], input_shape[0][1], 1, 1]]
ceil_mode = getattr(params, 'ceil_mode', True)
if ceil_mode is True:
method = math.ceil
else:
method = math.floor
return get_strided_kernel_output_shape(params, input_shape[0], method)
def shape_convolutiondepthwise(layer, input_shape):
params = layer.convolution_param
return get_strided_kernel_output_shape(params, input_shape[0], math.floor)
def shape_innerproduct(layer, input_shape):
params = layer.inner_product_param
return [[input_shape[0][0], params.num_output]]
def shape_lrn(layer, input_shape):
return input_shape
def shape_relu(layer, input_shape):
return input_shape
def shape_softmax(layer, input_shape):
return input_shape
def shape_input(layer, input_shape):
return [list(layer.input_param.shape[0].dim)]
def shape_memorydata(layer, input_shape):
params = layer.memory_data_param
shape = []
shape.append(int(params.batch_size))
shape.append(int(params.channels))
shape.append(int(params.height))
shape.append(int(params.width))
return [shape]
def shape_concat(layer, input_shape):
params = layer.concat_param
axis = params.axis
output_shape = None
for shape in input_shape:
if output_shape is None:
output_shape = []
for i in range(len(shape)):
output_shape.append(shape[i])
else:
output_shape[axis] += shape[axis]
return [output_shape]
def shape_slice(layer, input_shape):
inshape = input_shape[0]
top_len = len(layer.top)
params = layer.slice_param
axis = params.axis
slice_dim = params.slice_dim
if slice_dim != 1 and axis == 1:
axis = slice_dim
points = list(params.slice_point)
count = inshape[axis]
if len(points) == 0:
assert count % top_len == 0, "the parameter of Slice is wrong"
part = count / top_len
t = part
while t < count:
points.append(int(t))
t += part
points = [0] + points + [count]
output_shape = []
for i in range(len(points)):
shape = []
for ii in range(len(inshape)):
shape.append(inshape[ii])
size = points[i + 1] - points[i]
shape[axis] = size
output_shape.append(shape)
if i == len(points) - 2:
break
return output_shape
def shape_prelu(layer, input_shape):
return input_shape
def shape_sigmoid(layer, input_shape):
return input_shape
def shape_absval(layer, input_shape):
return input_shape
def shape_accuracy(layer, input_shape):
return [[1]]
def shape_tanh(layer, input_shape):
return input_shape
def shape_eltwise(layer, input_shape):
return [input_shape[0]]
def shape_batchnorm(layer, input_shape):
return input_shape
def shape_scale(layer, input_shape):
return input_shape
def shape_reshape(layer, input_shape):
def count(num_list):
return reduce(lambda a, b: a * b, num_list)
inshape = input_shape[0]
params = layer.reshape_param
axis = params.axis if hasattr(params, 'axis') else 0
num_axes = params.num_axes if hasattr(params, 'num_axes') else -1
if inshape[0] == -1:
inshape[0] = 1
input_count = count(inshape)
input_num_axes = len(inshape)
input_start_axis = axis
start_axis = input_start_axis if input_start_axis >= 0 \
else input_num_axes + input_start_axis + 1
assert start_axis >= 0, "[Reshape]axis %d out of range" % (input_start_axis)
assert start_axis <= input_num_axes, "[Reshape]axis %d out of range for %d-D input data"\
% (input_start_axis, input_num_axes)
assert num_axes >= -1, "[Reshape]num_axes must be >= 0, or -1 for all"
end_axis = input_num_axes if num_axes == -1 else start_axis + num_axes
assert end_axis <= input_num_axes, "end_axis[%d] = axis[%d] + num_axes[%d] is out of range"\
% (end_axis, start_axis, num_axes)
num_axes_replaced = end_axis - start_axis
num_axes_retained = input_num_axes - num_axes_replaced
num_new_axes = len(list(params.shape.dim))
output_shape = []
for i in range(start_axis):
output_shape.append(inshape[i])
for i in range(num_new_axes):
output_shape.append(params.shape.dim[i])
for i in range(end_axis, input_num_axes):
output_shape.append(inshape[i])
assert len(output_shape) == num_axes_retained + num_new_axes,\
"[Reshape]invalid dims of output shape[%s]" % (str(output_shape))
inferred_axis = -1
copy_axes = []
constant_count = 1
for i in range(num_new_axes):
top_dim = params.shape.dim[i]
if top_dim == 0:
copy_axes.append(i)
copy_axis_index = start_axis + i
output_shape[copy_axis_index] = inshape[copy_axis_index]
elif top_dim == -1:
assert inferred_axis == -1, "[Reshape]new shape contains multiple -1 dims"
inferred_axis = i
else:
constant_count *= top_dim
if inferred_axis >= 0:
explicit_count = constant_count
l = inshape[0:start_axis]
if len(l) > 0:
explicit_count *= count(l)
l = inshape[end_axis:]
if len(l) > 0:
explicit_count *= count(l)
for i in range(len(copy_axes)):
explicit_count *= output_shape[start_axis + copy_axes[i]]
assert input_count % explicit_count == 0, "[Reshape]botom count[%d] "\
"must be divisible by product of the specified dimensions[%d] "\
% (input_count, explicit_count)
output_shape[start_axis + inferred_axis] = int(input_count / explicit_count)
output_count = count(output_shape)
assert output_count == input_count, "[Reshape]output count[%d] must match input count[%d]" % (
output_count, input_count)
output_shape[0] = -1
return [output_shape]
def shape_argmax(layer, input_shape):
inshape = input_shape[0]
params = layer.argmax_param
out_max_val = params.out_max_val if hasattr(params, out_max_val) else False
top_k = params.top_k if hasattr(params, top_k) else 1
axis = parmas.axis if hasattr(params, axis) else -1
if axis < 0:
axis += len(inshape)
assert (axis + 1 == len(inshape)
), 'only can be applied on the last dimension[axis:%d, %s] now,'\
'make sure you have set axis param in xxx.prototxt file' \
% (axis, str(inshape))
output_shape = inshape
output_shape[-1] = top_k
if out_max_val is True:
output_shape[-1] *= 2
return [output_shape]
def shape_crop(layer, input_shape):
assert len(input_shape) == 2, "the number of crop's inputs must be 2"
return [input_shape[1]]
def shape_flatten(layer, input_shape):
assert len(input_shape) == 1, "the number of flatten's inputs must be 1"
inshape = input_shape[0]
params = layer.flatten_param
start_axis = params.axis
end_axis = params.end_axis
if start_axis < 0:
start_axis += len(inshape)
if end_axis < 0:
end_axis += len(inshape) + 1
assert start_axis <= end_axis, 'invalid axis[%d] or end_axis[%d] params'\
% (start_axis, end_axis)
output_shape = inshape[0:start_axis]
if len(inshape[start_axis:end_axis]) != 0:
flat_sz = reduce(lambda a, b: a * b, inshape[start_axis:end_axis])
output_shape += [flat_sz]
output_shape += inshape[end_axis:len(inshape)]
output_shape[0] = -1
return [output_shape]
def shape_power(layer, input_shape):
return input_shape
def shape_reduction(layer, input_shape):
params = layer.reduction_param
axis = params.axis
if axis < 0:
axis += len(input_shape[0]) + 1
assert axis <= len(input_shape[0]), 'invalid axis[%d] error' % (axis)
return [input_shape[0:axis]]
def shape_axpy(layer, input_shape):
assert len(input_shapes) == 3, "not valid input shape for axpy layer"
assert len(input_shapes[0]) == len(input_shapes[1]), 'should have same dims'
output_shape = input_shapes[1]
assert (input_shapes[2] == output_shape),\
"shape not consistent for axpy[%s <--> %s]" \
% (str(output_shape), str(input_shapes[2]))
return [output_shape]
def shape_detectionoutput(layer, input_shape):
return [[-1, 6]]
def shape_normalize(layer, input_shape):
return input_shape
def shape_permute(layer, input_shape):
order = layer.permute_param.order
inshape = input_shape[0]
output_shape = []
order = list(order)
for ii in order:
assert ii < len(inshape), "invalid order for permute[%s]" % (name)
output_shape.append(inshape[ii])
return [output_shape]
def shape_priorbox(layer, input_shape):
max_size = layer.prior_box_param.max_size
aspect_ratio = layer.prior_box_param.aspect_ratio
fc_shape = input_shape[0]
N = 1
if not max_size == None:
N += 1
if not aspect_ratio == None:
N += 2 * len(aspect_ratio)
N_bbx = fc_shape[2] * fc_shape[3] * N
output_shape = [1, 2, 4 * N_bbx]
return [output_shape]
def shape_relu6(layer, input_shape):
return input_shape
def shape_roipooling(layer, input_shape):
pooled_w = layer.roi_pooling_param.pooled_w
pooled_h = layer.roi_pooling_param.pooled_h
base_fea_shape = input_shapes[0]
rois_shape = input_shapes[1]
output_shape = base_fea_shape
output_shape[0] = rois_shape[0]
output_shape[2] = pooled_h
output_shape[3] = pooled_w
return [output_shape]
def shape_shufflechannel(layer, input_shape):
return input_shape
def shape_upsample(layer, input_shape):
scale = layer.upsample_param.scale
assert len(input_shapes) == 1, "not valid input shape for upsample layer"
assert type(scale) is int
input_shape = input_shapes[0]
new_h = scale * input_shape[2]
new_w = scale * input_shape[3]
output_shape = [input_shape[0], input_shape[1], new_h, new_w]
return [output_shape]
def shape_select(layer, input_shape):
slice_point = layer.select_param.slice_point
axis = layer.select_param.axis
input_shape = input_shapes[0]
start = slice_point[0]
if len(slice_point) == 2:
end = slice_point[1]
else:
end = input_shape[axis]
assert end > start, "invalid slice_point with [start:%d, end:%d]"\
% (start, end)
output_shape = input_shape
output_shape[axis] = end - start
return [output_shape]
......@@ -64,6 +64,12 @@ class ONNXGraphNode(GraphNode):
if 'value' not in self.attr_map:
return None
return self.attr_map['value']
@property
def name(self):
if hasattr(self, 'index'):
return "{}_p{}".format(self.layer_name, self.index)
return self.layer_name
def get_attribute_value(self, attr):
"""
......@@ -118,6 +124,10 @@ class ONNXGraphDataNode(GraphNode):
out_shapes = list()
out_shapes.append(values)
return out_shapes
@property
def name(self):
return self.layer_name
@property
def dtype(self):
......@@ -144,11 +154,12 @@ class ONNXGraph(Graph):
if self.graph is None:
print('[WARNING] Shape inference by ONNX offical interface.')
onnx_model = shape_inference.infer_shapes(onnx_model)
self.graph = onnx_model.graph
self.graph = onnx_model.graph
print("shape inferenced.")
self.build()
self.collect_value_infos()
self.allocate_shapes()
self.graph_name = "ONNXModel"
def get_inner_nodes(self):
"""
......@@ -307,6 +318,7 @@ class ONNXGraph(Graph):
if ipt_node.layer_name in node.which_child:
ipt_node.index = node.which_child[ipt_node.layer_name]
return ipt_node
def graph_weights(self):
"""
......@@ -538,4 +550,4 @@ class ONNXDecoder(object):
node.input[i] = self.make_variable_name(node.input[i])
for i in range(len(node.output)):
node.output[i] = self.make_variable_name(node.output[i])
return model
return model
\ No newline at end of file
......@@ -1601,11 +1601,11 @@ class SymbolicShapeInference:
in_mp)
symbolic_shape_inference._update_output_from_vi()
if not all_shapes_inferred:
print('!' * 10)
symbolic_shape_inference.out_mp_ = shape_inference.infer_shapes(
symbolic_shape_inference.out_mp_)
print('[INFO] Complete symbolic shape inference.')
except:
print('[WARNING] Incomplete symbolic shape inference.')
print('[WARNING] Incomplete symbolic shape inference')
symbolic_shape_inference.out_mp_ = shape_inference.infer_shapes(
symbolic_shape_inference.out_mp_)
return symbolic_shape_inference.out_mp_.graph
return symbolic_shape_inference.out_mp_.graph
\ No newline at end of file
......@@ -12,15 +12,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import sys
import torch
import numpy as np
class PyTorchDecoder(object):
def __init__(self, script_path):
self.script = torch.jit.load(script_path)
self.graph = self._optimize_graph(self.script.inlined_graph)
def _optimize_graph(self, graph):
class Decoder(object):
def _optimize_graph(self, graph):
torch._C._jit_pass_constant_propagation(graph)
torch._C._jit_pass_dce(graph)
torch._C._jit_pass_lint(graph)
......@@ -31,4 +30,40 @@ class PyTorchDecoder(object):
torch._C._jit_pass_canonicalize(graph)
torch._C._jit_pass_lint(graph)
torch._C._jit_pass_constant_propagation(graph)
return graph
return graph
class ScriptDecoder(Decoder):
""" 当script_path非None,直接load ScriptModule;
当model_path非None,load PyTorchModule后使用script方式转换为ScriptModule。
Args:
script_path (str): ScriptModule保存路径。
model_path (str): PyTorchModule保存路径。
"""
def __init__(self, module, input_examples=None):
self.script = torch.jit.script(module)
self.graph = self._optimize_graph(self.script.inlined_graph)
self.input_examples = input_examples
class TraceDecoder(Decoder):
""" PyTorchModule后使用trace方式转换为ScriptModule。
Args:
model_path (str): PyTorchModule保存路径。
input_files (list): 输入网络的numpy,每个numpy保存成.npy文件,
文件路径存储在input_files中。
"""
def __init__(self, module, input_examples):
try:
self.script = torch.jit.trace(module, input_examples)
except RuntimeError as e:
if "strict" in str(e):
self.script = torch.jit.trace(module, input_examples, strict=False)
else:
print(e)
exit(0)
self.graph = self._optimize_graph(self.script.inlined_graph)
self.input_examples = input_examples
......@@ -132,6 +132,7 @@ class TFGraph(Graph):
self.identity_map = dict()
self.multi_out_ops = ['Split', 'SplitV', 'IteratorV2']
self.tf_data_format = data_format
self.graph_name = "TFModel"
def build(self):
for layer in self.model.node:
......@@ -188,6 +189,10 @@ class TFGraph(Graph):
if len(items) == 1 and node.layer_type in self.multi_out_ops:
node.index = 0
return node
def get_input_node(self, node, idx=0, copy=False):
input_node_name = node.layer.input[idx]
return self.get_node(input_node_name, copy)
def remove_node(self, node_name):
if node_name not in self.node_map:
......@@ -315,7 +320,7 @@ class TFDecoder(object):
self.sess = tf.compat.v1.Session()
except:
self.sess = tf.Session()
self.input_info = dict()
self.inputs_info = dict()
self.define_input_shape = define_input_shape
with open(pb_model, 'rb') as f:
try:
......@@ -397,7 +402,7 @@ class TFDecoder(object):
right_shape_been_input = False
while not right_shape_been_input:
try:
shape = raw_input(
shape = input(
"Shape of Input(e.g. None,224,224,3): ")
except:
shape = input("Shape of Input(e.g. None,224,224,3): ")
......@@ -425,50 +430,40 @@ class TFDecoder(object):
input_map["{}:0".format(layer.name)] = x2paddle_input
if shape.count(None) > 0:
shape[shape.index(None)] = -1
self.input_info["x2paddle_{}".format(layer.name)] = (shape,
self.inputs_info["x2paddle_{}".format(layer.name)] = (shape,
dtype)
else:
value = graph_node.layer.attr["shape"].shape
shape = [dim.size for dim in value.dim]
self.input_info[layer.name] = (shape, dtype)
self.inputs_info[layer.name] = (shape, dtype)
return input_map
# trick method
# should be removed after PaddlePaddle V1.6 been released
def infer_tensor(self, graph_node):
def infer_tensor(self, graph_node, out_shape=None, use_diff_inputs=True):
if hasattr(graph_node, "index"):
tensor_name = graph_node.layer.name + ":{}".format(graph_node.index)
else:
tensor_name = graph_node.layer.name + ":0"
feed = dict()
for input_name, info in self.input_info.items():
(shape, dtype) = cp.deepcopy(info)
input_tensor = self.sess.graph.get_tensor_by_name(input_name + ":0")
if shape.count(-1) > 0:
shape[shape.index(-1)] = 2
feed[input_tensor] = numpy.random.random_sample(shape)
output_tensor = self.sess.graph.get_tensor_by_name(tensor_name)
return self.sess.run([output_tensor], feed)[0]
def infer_shape_tensor(self, graph_node, out_shape=None):
if hasattr(graph_node, "index"):
tensor_name = graph_node.layer.name + ":{}".format(graph_node.index)
if use_diff_inputs:
batch_size = [2, 3, 5]
else:
tensor_name = graph_node.layer.name + ":0"
feed = dict()
batch_size = [2, 3, 5]
batch_size = [2]
results = list()
for b in batch_size:
for input_name, info in self.input_info.items():
for input_name, info in self.inputs_info.items():
(shape, dtype) = cp.deepcopy(info)
input_tensor = self.sess.graph.get_tensor_by_name(input_name +
":0")
input_tensor = self.sess.graph.get_tensor_by_name(input_name + ":0")
if shape.count(-1) > 0:
shape[shape.index(-1)] = b
feed[input_tensor] = numpy.random.random_sample(shape)
output_tensor = self.sess.graph.get_tensor_by_name(tensor_name)
results.append(self.sess.run([output_tensor], feed)[0].flatten())
if use_diff_inputs:
results.append(self.sess.run([output_tensor], feed)[0].flatten())
else:
return self.sess.run([output_tensor], feed)[0]
compare01 = (results[0] == results[1])
compare12 = (results[1] == results[2])
......@@ -493,38 +488,4 @@ class TFDecoder(object):
return results[0].tolist()
else:
raise Exception("Couldn't infer a stable shape shape tensor value")
def infer_tensor_shape(self, graph_node):
if hasattr(graph_node, "index"):
tensor_name = graph_node.layer.name + ":{}".format(graph_node.index)
else:
tensor_name = graph_node.layer.name + ":0"
feed = dict()
batch_size = [2, 3, 5]
shapes = list()
for b in batch_size:
for input_name, info in self.input_info.items():
(shape, dtype) = cp.deepcopy(info)
input_tensor = self.sess.graph.get_tensor_by_name(input_name +
":0")
if shape.count(-1) > 0:
shape[shape.index(-1)] = b
feed[input_tensor] = numpy.random.random_sample(shape)
output_tensor = self.sess.graph.get_tensor_by_name(tensor_name)
shape = self.sess.run([output_tensor], feed)[0].shape
shapes.append(numpy.array(shape))
compare01 = (shapes[0] == shapes[1])
compare12 = (shapes[1] == shapes[2])
if compare01.all() and compare12.all():
return shape[0].tolist()
if (compare01 == compare12).all():
index = numpy.argwhere(compare01 == False).flatten()
if index.shape[0] != 1:
raise Exception("There's not only one unstable dimension")
if index[0] != 0:
raise Exception("Batch size not in the first dimension")
shapes[0][0] = -1
return shapes[0].tolist()
\ No newline at end of file
# 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 .detectionoutput import DetectionOutput
from .normalize import Normalize
from .priorbox import PriorBox
from .roipooling import ROIPooling
from .select import Select
\ No newline at end of file
# 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.
import paddle
import paddle.fluid as fluid
class DetectionOutput(object):
def __init__(self, nms_threshold, nms_top_k, keep_top_k, nms_eta, score_threshold, background_label):
self.detection_output_layer_attrs = {
"background_label": background_label,
"nms_threshold": nms_threshold,
"nms_top_k": nms_top_k,
"keep_top_k": keep_top_k,
"score_threshold": score_threshold,
"nms_eta": nms_eta}
def __call__(self, x0, x1, x2):
priorbox_list = paddle.split(x2, num_or_sections=2, axis=1)
pb = priorbox_list[0]
pbv = priorbox_list[1]
pb = paddle.reshape(x=pb, shape=[-1, 4])
pbv = paddle.reshape(x=pbv, shape=[-1, 4])
pb_dim = fluid.layers.shape(pb)[0]
loc = paddle.reshape(x0, shape=[-1, pb_dim, 4])
conf_flatten = paddle.reshape(x1, shape=[0, pb_dim, -1])
out = fluid.layers.detection_output(loc=loc,
scores=conf_flatten,
prior_box=pb,
prior_box_var=pbv,
**self.detection_output_layer_attrs)
return out
\ No newline at end of file
# 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.
import paddle
import paddle.fluid as fluid
class Normalize(object):
def __init__(self, axis, param_name, param_shape):
self.axis = axis
self.param_name = param_name
self.param_shape = param_shape
def __call__(self, x):
l2 = fluid.layers.prior_box(x=x, p=2, axis=1)
attr = fluid.ParamAttr(name=self.param_name, trainable=False)
param = paddle.nn.Layer.create_parameter(shape=self.param_shape,
attr=atr)
out = paddle.multiply(x=l2, y=param, axis=self.axis)
return out
\ No newline at end of file
# 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.
import paddle
import paddle.fluid as fluid
class PriorBox(object):
def __init__(self, min_sizes, max_sizes,
aspect_ratios, variance, flip,
clip, steps, offset,
min_max_aspect_ratios_order):
self.priorbox_layer_attrs = {
"min_sizes": min_sizes,
"max_sizes": max_sizes,
"aspect_ratios": aspect_ratios,
"variance": variance,
"flip": flip,
"clip": clip,
"steps": steps,
"offset": offset,
"min_max_aspect_ratios_order": min_max_aspect_ratios_order}
def __call__(self, x0, x1):
box, var = fluid.layers.prior_box(input=x0,
image=x1,
**self.priorbox_layer_attrs)
box = paddle.reshape(x=box, shape=[1, 1, -1])
var = paddle.reshape(x=var, shape=[1, 1, -1])
out = paddle.concat(x=[box, var], axis=1)
return out
\ No newline at end of file
# 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.
import paddle
import paddle.fluid as fluid
class ROIPooling(object):
def __init__(self, pooled_height, pooled_width, spatial_scale):
self.roipooling_layer_attrs = {
"pooled_height": pooled_height,
"pooled_width": pooled_width,
"spatial_scale": spatial_scale}
def __call__(self, x0, x1):
slice_x1 = paddle.slice(input=x1, axes=[1],
starts=[1], ends=[5])
out = fluid.layers.roi_pool(input=x0,
rois=slice_x1,
**self.roipooling_layer_attrs)
return out
\ No newline at end of file
# 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.
import paddle
import paddle.fluid as fluid
class Select(object):
def __init__(self, input_shape, point, axis):
self.point = point
self.input_shape = input_shape
self.axis = axis
def __call__(self, x):
start = self.point[0]
if len(self.point) == 2:
end = self.point[1]
else:
end = self.input_shape[self.axis]
out = paddle.slice(x=x,
start=start,
end=end,
axes=[self.axis])
return out
\ No newline at end of file
# 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.
import sys
import numbers
import numpy as np
from x2paddle.core.op_mapper import OpMapper
from x2paddle.core.util import *
from x2paddle.core.program import PaddleGraph
from x2paddle.decoder.caffe_decoder import CaffeGraphNode
def _adjust_parameters(node):
data = node.data
# When using the protobuf-backend, each parameter initially has four dimensions.
# In certain cases (like FC layers), we want to eliminate the singleton dimensions.
# This implementation takes care of the common cases. However, it does leave the
# potential for future issues.
# The Caffe-backend does not suffer from this problem.
data = list(data)
squeeze_indices = [1] # Squeeze biases.
if node.layer_type == 'InnerProduct':
squeeze_indices.append(0) # Squeeze FC.
for idx in squeeze_indices:
if idx >= len(data):
continue
d = data[idx]
assert len(
d.shape
) == 4, 'invalid shape[%s] from caffe when adjust_parameters' % (
str(d.shape))
shape_old = d.shape
sq_axis = None
if idx == 0:
sq_axis = (0, 1)
elif idx == 1:
sq_axis = (0, 1, 2)
else:
continue
data[idx] = np.squeeze(d, axis=sq_axis)
shape_new = data[idx].shape
return data
def _get_kernel_parameters(kind, params):
assert kind in ["Convolution", "Pooling", "Deconvolution", "ConvolutionDepthwise"]
[k_h, k_w] = [1, 1]
if isinstance(params.kernel_size, numbers.Number):
[k_h, k_w] = [params.kernel_size] * 2
elif len(params.kernel_size) > 0:
k_h = params.kernel_h if params.kernel_h > 0 else params.kernel_size[
0]
k_w = params.kernel_w if params.kernel_w > 0 else params.kernel_size[
len(params.kernel_size) - 1]
elif params.kernel_h > 0 or params.kernel_w > 0:
k_h = params.kernel_h
k_w = params.kernel_w
[s_h, s_w] = [1, 1]
if isinstance(params.stride, numbers.Number):
[s_h, s_w] = [params.stride] * 2
elif len(params.stride) > 0:
s_h = params.stride_h if params.stride_h > 0 else params.stride[0]
s_w = params.stride_w if params.stride_w > 0 else params.stride[len(
params.stride) - 1]
elif params.stride_h > 0 or params.stride_w > 0:
s_h = params.stride_h
s_w = params.stride_w
[p_h, p_w] = [0, 0]
if isinstance(params.pad, numbers.Number):
[p_h, p_w] = [params.pad] * 2
elif len(params.pad) > 0:
p_h = params.pad_h if params.pad_h > 0 else params.pad[0]
p_w = params.pad_w if params.pad_w > 0 else params.pad[len(
params.pad) - 1]
elif params.pad_h > 0 or params.pad_w > 0:
p_h = params.pad_h
p_w = params.pad_w
dila_h = dila_w = 1
group = 1
c_o = 1
if kind in ["Convolution", "Deconvolution", "ConvolutionDepthwise"]:
if kind in ["Convolution", "Deconvolution"]:
c_o = params.num_output
dila_len = len(params.dilation)
if dila_len == 2:
dila_h = params.dilation[0]
dila_w = params.dilation[1]
elif dila_len == 1:
dila_h = dila_w = params.dilation[0]
else:
assert dila_len == 0, "invalid length[%s] of dilation in convolution" % (
dila_len)
if kind in ['Convolution', 'Deconvolution']:
group = params.group
kernel = [k_h, k_w]
stride = [s_h, s_w]
pad = [p_h, p_w]
dilation = [dila_h, dila_w]
return c_o, kernel, stride, pad, dilation, group
class CaffeOpMapper(OpMapper):
directly_map_ops = {
'Sigmoid': ['paddle.nn.layer.Sigmoid'],
'TanH': ['paddle.nn.Tanh'],
}
def __init__(self, decoder):
super(CaffeOpMapper, self).__init__()
self.graph = decoder.caffe_graph
if not self.op_checker():
raise Exception("Model is not supported yet.")
self.params = dict()
self.paddle_graph = PaddleGraph(parent_layer=None, graph_type="dygraph", source_type="caffe")
self.paddle_graph.outputs = self.graph.output_nodes
self.input_index = 0
self.inputs_info = {}
self.nn_name2id = {}
print("Total nodes: {}".format(
sum([
isinstance(node, CaffeGraphNode)
for name, node in self.graph.node_map.items()
])))
print("Nodes converting ...")
for i, node_name in enumerate(self.graph.topo_sort):
sys.stderr.write("\rConverting node {} ... ".format(i + 1))
node = self.graph.get_node(node_name)
op = node.layer_type
if hasattr(self, op):
func = getattr(self, op)
func(node)
elif op in self.directly_map_ops:
self.directly_map(node)
print("\nNodes converted.")
self.paddle_graph.set_name(self.graph.graph_name)
self.paddle_graph.set_parameters(self.params)
self.paddle_graph.set_inputs_info(self.inputs_info)
def op_checker(self):
unsupported_ops = set()
for node_name in self.graph.topo_sort:
node = self.graph.get_node(node_name)
op = node.layer_type
if not hasattr(self, op) and op not in self.directly_map_ops:
unsupported_ops.add(op)
if len(unsupported_ops) == 0:
return True
else:
if len(unsupported_ops) > 0:
print("\n========= {} OPs are not supported yet ===========".format(
len(unsupported_ops)))
for op in unsupported_ops:
print("========== {} ============".format(op))
return False
def directly_map(self, node):
inputs = node.layer.input
assert len(inputs) == 1, 'directly_map error with multi inputs'
op_info = self.directly_map_ops[node.layer_type]
input = self.graph.get_input_node(node, 0)
paddle_op = op_info[0]
if paddle_op.startswith("paddle.nn"):
op_name = paddle_op[10:].lower()
op_name = name_generator(op_name, self.nn_name2id)
output_name = node.name
layer_outputs = [op_name, output_name]
self.paddle_graph.add_layer(
kernel=paddle_op,
inputs={"x": input.name},
outputs=layer_outputs)
else:
self.paddle_graph.add_layer(
kernel=paddle_op,
inputs={"x": input.name},
outputs=[node.name])
def Input(self, node):
self.paddle_graph.add_layer(
"paddle.to_tensor",
inputs={},
outputs=[node.layer_name],
data="x{}".format(self.input_index))
shape = list(node.layer.input_param.shape[0].dim)[1:]
self.inputs_info["x{}".format(self.input_index)] = [[-1] + shape, "float32"]
self.input_index += 1
def Convolution(self, node):
conv2d_name = name_generator("conv", self.nn_name2id)
output_name = node.layer_name
layer_outputs = [conv2d_name, output_name]
data = node.data
params = node.layer.convolution_param
out_channel, kernel, stride, pad, dilation, group = _get_kernel_parameters(
node.layer_type, params)
if data is None:
data = []
print(
"The parameter of {} (type is {}) is not set. So we set the parameters as 0"
.format(node.layer_name, node.layer_type))
data.append(
np.zeros([out_channel, node.in_shapes[0][1], kernel[0], kernel[1]]).astype(
'float32'))
data.append(np.zeros([out_channel, ]).astype('float32'))
else:
data = _adjust_parameters(node)
self.params[conv2d_name + ".weight"] = data[0]
if len(data) == 2:
self.params[conv2d_name + ".bias"] = data[1]
assert len(node.inputs
) == 1, "The count of Convolution node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
layer_attrs = {
"in_channels": node.in_shapes[0][1],
"out_channels": out_channel,
"kernel_size": kernel,
"stride": stride,
"padding": pad,
"dilation": dilation,
"groups": group
}
if len(data) == 1:
layer_attrs["bias_attr"] = False
self.paddle_graph.add_layer(
"paddle.nn.Conv2D",
inputs={"input": input.name},
outputs=layer_outputs,
**layer_attrs)
def DepthwiseConvolution(self, node):
node.layer_type = "ConvolutionDepthwise"
self.ConvolutionDepthwise(node)
def Deconvolution(self, node):
conv2d_name = name_generator("conv", self.nn_name2id)
output_name = node.layer_name
layer_outputs = [conv2d_name, output_name]
data = node.data
params = node.layer.convolution_param
out_channel, kernel, stride, pad, dilation, group = _get_kernel_parameters(
node.layer_type, params)
if data is None:
data = []
print(
"The parameter of {} (type is {}) is not set. So we set the parameters as 0"
.format(node.layer_name, node.layer_type))
data.append(
np.zeros([out_channel, node.in_shapes[0][1], kernel[0], kernel[1]]).astype(
'float32'))
data.append(np.zeros([out_channel, ]).astype('float32'))
else:
data = _adjust_parameters(node)
self.params[conv2d_name + ".weight"] = data[0]
if len(data) == 2:
self.params[conv2d_name + ".bias"] = data[1]
assert len(node.inputs
) == 1, "The count of Deconvolution node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
layer_attrs = {
"in_channels": node.in_shapes[0][1],
"out_channels": out_channel,
"kernel_size": kernel,
"stride": stride,
"padding": pad,
"dilation": dilation,
"groups": group
}
if len(data) == 1:
layer_attrs["bias_attr"] = False
self.paddle_graph.add_layer(
"paddle.nn.Conv2DTranspose",
inputs={"input": input.name},
outputs=layer_outputs,
**layer_attrs)
def ConvolutionDepthwise(self, node):
conv2d_name = name_generator("conv", self.nn_name2id)
output_name = node.layer_name
layer_outputs = [conv2d_name, output_name]
data = node.data
params = node.layer.convolution_param
out_channel, kernel, stride, pad, dilation, group = _get_kernel_parameters(
node.layer_type, params)
out_channel = params.num_output if params.num_output is not None else node.in_shapes[0][1]
in_channel = node.in_shapes[0][1]
group = int(in_channel / (in_channel / out_channel)) if in_channel > out_channel else int(in_channel /
(out_channel / in_channel))
if data is None:
data = []
print(
"The parameter of {} (type is {}) is not set. So we set the parameters as 0"
.format(node.layer_name, node.layer_type))
data.append(
np.zeros([out_channel, node.in_shapes[0][1], kernel[0], kernel[1]]).astype(
'float32'))
data.append(np.zeros([out_channel, ]).astype('float32'))
else:
data = _adjust_parameters(node)
self.params[conv2d_name + ".weight"] = data[0]
if len(data) == 2:
self.params[conv2d_name + ".bias"] = data[1]
assert len(node.inputs
) == 1, "The count of Deconvolution node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
layer_attrs = {
"in_channels": in_channel,
"out_channels": out_channel,
"kernel_size": kernel,
"stride": stride,
"padding": pad,
"dilation": dilation,
"groups": group
}
if len(data) == 1:
layer_attrs["bias_attr"] = False
self.paddle_graph.add_layer(
"paddle.nn.Conv2D",
inputs={"input": input.name},
outputs=layer_outputs,
**layer_attrs)
def Pooling(self, node):
pool2d_name = name_generator("pool", self.nn_name2id)
output_name = node.layer_name
layer_outputs = [pool2d_name, output_name]
params = node.layer.pooling_param
ceil_mode = getattr(params, "ceil_mod", True)
global_pool = getattr(params, "global_pooling", False)
kernel_default = [1, 1]
channel, kernel, stride, pad, dilation, group = _get_kernel_parameters(
node.layer_type, params)
if params.pool == 0:
pool_type = "max"
else:
pool_type = "avg"
assert len(
node.inputs) == 1, "The count of Pooling node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
if global_pool:
if kernel[0] == 0:
kernel = [1, 1]
if params.pool == 0:
self.paddle_graph.add_layer(
"paddle.nn.AdaptiveMaxPool2D",
inputs={"input": input.name},
outputs=layer_outputs,
output_size=kernel)
else:
self.paddle_graph.add_layer(
"paddle.nn.AdaptiveAvgPool2D",
inputs={"input": input.name},
outputs=layer_outputs,
output_size=kernel)
else:
layer_attrs = {
'pool_size': kernel,
'pool_stride': stride,
'pool_padding': pad,
'ceil_mode': ceil_mode,
'pool_type': string(pool_type),
'exclusive': False,
'global_pooling': global_pool,
}
self.paddle_graph.add_layer(
"paddle.fluid.dygraph.Pool2D",
inputs={"input": input.name},
outputs=layer_outputs,
**layer_attrs)
# layer_attrs = {
# 'kernel_size': kernel,
# 'stride': stride,
# 'padding': pad,
# 'ceil_mode': ceil_mode,
# }
# if params.pool == 0:
# self.paddle_graph.add_layer(
# "paddle.nn.MaxPool2D",
# inputs={"input": input.name},
# outputs=layer_outputs,
# **layer_attrs)
# else:
# layer_attrs["count_include_pad"] = True
# self.paddle_graph.add_layer(
# "paddle.nn.AvgPool2D",
# inputs={"input": input.name},
# outputs=layer_outputs,
# **layer_attrs)
def LRN(self, node):
assert len(node.inputs) == 1, "The count of LRN node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.lrn_param
assert params.local_size % 2 == 1
alpha = params.alpha / float(params.local_size)
layer_attrs = {
"n": params.local_size,
"k": params.k,
"alpha": alpha,
"beta": params.beta,
}
self.paddle_graph.add_layer(
"fluid.layers.lrn",
inputs={"input": input.name},
outputs=[node.layer_name],
**layer_attrs)
def InnerProduct(self, node):
linear_name = name_generator("linear", self.nn_name2id)
output_name = node.layer_name
layer_outputs = [linear_name, output_name]
data = node.data
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.inner_product_param
if data is None:
print(
"The parameter of {} (type is {}) is not set. So we set the parameters as 0."
.format(node.layer_name, node.layer_type))
data = []
data.append(
np.zeros([node.in_shapes[0][1], params.num_output]).astype("float32").astype(
"float32"))
data.append(
np.zeros([params.num_output]).astype("float32").astype("float32"))
else:
data = _adjust_parameters(node)
# Reshape the parameters to Paddle's ordering
transpose_order = (1, 0)
w = data[0]
fc_shape = w.shape
output_channels = fc_shape[0]
w = w.reshape((output_channels, -1))
w = w.transpose(transpose_order)
data[0] = w
self.params[linear_name + ".weight"] = data[0]
if len(data) == 2:
self.params[linear_name + ".bias"] = data[1]
assert len(node.inputs
) == 1, "The count of InnerProduct node\'s input is not 1."
assert params.axis == 1
assert params.bias_term == True
layer_attrs = {
"in_features": data[0].shape[0],
"out_features": params.num_output
}
if len(data) == 1:
layer_attrs["bias"] = False
if node.in_shapes[0][-1] != data[0].shape[0]:
self.paddle_graph.add_layer(
"paddle.reshape",
inputs={"x": input.name},
outputs=[output_name],
shape=[-1, data[0].shape[0]])
self.paddle_graph.add_layer(
"paddle.nn.Linear",
inputs={"input": output_name},
outputs=layer_outputs,
**layer_attrs)
else:
self.paddle_graph.add_layer(
"paddle.nn.Linear",
inputs={"input": input.name},
outputs=layer_outputs,
**layer_attrs)
def AbsVal(self, node):
assert len(
node.inputs
) >= 1, "The count of AbsVal node\'s input is not more than 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
self.paddle_graph.add_layer(
"paddle.abs",
inputs={"input": input.name},
outputs=[node.layer_name])
def Softmax(self, node):
softmax_name = name_generator("softmax", self.nn_name2id)
output_name = node.layer_name
layer_outputs = [softmax_name, output_name]
assert len(
node.inputs) == 1, "The count of Softmax node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.softmax_param
axis = params.axis
shape = node.in_shapes[0]
dims = len(shape)
axis = axis + dims if axis < 0 else axis
layer_attrs = {'axis': axis}
self.paddle_graph.add_layer(
"paddle.nn.Softmax",
inputs={"input": input.name},
outputs=layer_outputs,
**layer_attrs)
def Slice(self, node):
assert len(
node.inputs) == 1, "The count of Slice node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
top_len = len(node.layer.top)
params = node.layer.slice_param
axis = params.axis
slice_dim = params.slice_dim
if slice_dim != 1 and axis == 1:
axis = slice_dim
output_shape = node.out_shapes
sections_list = list()
outputs_list = list()
for i, s in enumerate(output_shape):
sections_list.append(s[axis])
outputs_list.append("{}_p{}".format(node.layer_name, i))
layer_attrs = {
'num_or_sections': sections_list,
'axis': axis,
}
self.paddle_graph.add_layer(
"paddle.split",
inputs={"x": input.name},
outputs=outputs_list,
**layer_attrs)
def Concat(self, node):
assert len(
node.inputs
) >= 1, "The count of Concat node\'s input is not more than 1."
inputs_list = list()
for i in range(len(node.inputs)):
input = self.graph.get_input_node(node, idx=i, copy=True)
inputs_list.append(input.name)
params = node.layer.concat_param
axis = params.axis
layer_attrs = {'axis': axis}
self.paddle_graph.add_layer(
"paddle.concat",
inputs={"x": inputs_list},
outputs=[node.layer_name],
**layer_attrs)
def ReLU(self, node):
relu_name = name_generator("relu", self.nn_name2id)
output_name = node.layer_name
layer_outputs = [relu_name, output_name]
assert len(
node.inputs) == 1, "The count of RelU node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.relu_param
if params.HasField('negative_slope') and params.negative_slope != 0:
negative_slope = float(params.negative_slope)
layer_attrs = {'alpha': negative_slope}
self.paddle_graph.add_layer(
"paddle.nn.LeakyReLU",
inputs={"input": input.name},
outputs=layer_outputs,
**layer_attrs)
else:
self.paddle_graph.add_layer(
"paddle.nn.ReLU",
inputs={"input": input.name},
outputs=layer_outputs)
def PReLU(self, node):
prelu_name = name_generator("prelu", self.nn_name2id)
output_name = node.layer_name
layer_outputs = [prelu_name, output_name]
assert len(
node.inputs) == 1, "The count of PReLU node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.prelu_param
mode_bool = params.channel_shared
output_shape = node.out_shapes[0]
if mode_bool:
num_parameters = 1
else:
num_parameters = output_shape[1]
data = node.data
self.params[prelu_name + '._weight'] = np.squeeze(data[0])
assert data is not None, "The parameter of {} (type is {}) is not set. You need to use python package of caffe to set the default value.".format(
node.layer_name, node.layer_type)
self.paddle_graph.add_layer(
"paddle.nn.PReLU",
inputs={"input": input.name},
outputs=layer_outputs,
num_parameters=num_parameters)
def Eltwise(self, node):
assert len(
node.inputs) == 2, "The count of Eltwise node\'s input is not 2."
params = node.layer.eltwise_param
mode = params.operation
inputs = []
input0 = self.graph.get_input_node(node, idx=0, copy=True)
input1 = self.graph.get_input_node(node, idx=1, copy=True)
input0_name = input0.name
input1_name = input1.name
if mode == 0:
inputs_dict = {}
inputs_dict['x'] = input0_name
inputs_dict['y'] = input1_name
self.paddle_graph.add_layer(
"paddle.multiply",
inputs=inputs_dict,
outputs=[node.layer_name])
elif mode == 1:
if hasattr(params, 'coeff') and len(params.coeff) == 2:
coeff = params.coeff
self.paddle_graph.add_layer(
"paddle.scale",
inputs={"x": input0_name},
outputs=[node.layer_name + '_mul0'],
scale=coeff[0])
self.paddle_graph.add_layer(
"paddle.scale",
inputs={"x": input1_name},
outputs=[node.layer_name + '_mul1'],
scale=coeff[2])
inputs_dict = {}
inputs_dict['x'] = node.layer_name + '_mul0'
inputs_dict['y'] = node.layer_name + '_mul1'
self.paddle_graph.add_layer(
"paddle.add",
inputs=inputs_dict,
outputs=[node.layer_name])
else:
inputs_dict = {}
inputs_dict['x'] = input0_name
inputs_dict['y'] = input1_name
self.paddle_graph.add_layer(
"paddle.add",
inputs=inputs_dict,
outputs=[node.layer_name])
else:
inputs_dict = {}
inputs_dict['x'] = input0_name
inputs_dict['y'] = input1_name
self.paddle_graph.add_layer(
"paddle.max",
inputs=inputs_dict,
outputs=[node.layer_name])
def BatchNorm(self, node):
batchnorm_name = name_generator("batchnorm", self.nn_name2id)
output_name = node.layer_name
layer_outputs = [batchnorm_name, output_name]
assert len(
node.inputs) == 1, "The count of BatchNorm node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.batch_norm_param
if hasattr(params, "eps"):
eps = params.eps
else:
eps = 1e-5
if node.data is None or len(node.data) != 3:
print(
"The parameter of {} (type is {}) is not set. So we set the parameters as 0"
.format(node.layer_name, node.layer_type))
mean = np.zeros([node.in_shapes[0][1], ]).astype("float32")
variance = np.zeros([node.in_shapes[0][1], ]).astype("float32")
scale = 0
else:
node.data = [np.squeeze(i).astype("float32") for i in node.data]
mean, variance, scale = node.data
# Prescale the stats
scaling_factor = 1.0 / scale if scale != 0 else 0
mean *= scaling_factor
variance *= scaling_factor
self.params[batchnorm_name + "._mean"] = mean
self.params[batchnorm_name + '._variance'] = variance
layer_attrs = {
"num_features": node.in_shapes[0][1],
"epsilon": eps,
"weight_attr": False,
"bias_attr": False,
}
self.paddle_graph.add_layer(
"paddle.nn.BatchNorm2D",
inputs={"input": input.name},
outputs=layer_outputs,
**layer_attrs)
def Scale(self, node):
if node.data is None:
print(
"The parameter of {} (type is {}) is not set. So we set the parameters as 0"
.format(node.layer_name, node.layer_type))
self.params[node.layer_name + "_cparam1"] = np.zeros([
node.in_shapes[0][1],
]).astype("float32")
self.params[node.layer_name + "_cparam2"] = np.zeros([
node.in_shapes[0][1],
]).astype("float32")
else:
self.params[node.layer_name + "_cparam1"] = np.squeeze(node.data[
0]).astype("float32")
self.params[node.layer_name + "_cparam2"] = np.squeeze(node.data[
1]).astype("float32")
params = node.layer.scale_param
axis = params.axis
inputs = []
if len(node.inputs) == 2:
input0 = self.graph.get_input_node(node, idx=0, copy=True)
input1 = self.graph.get_input_node(node, idx=1, copy=True)
input0_name = input0.name
input1_name = input1.name
inputs_dict = {}
inputs_dict['x'] = input0_name
inputs_dict['y'] = input1_name
self.paddle_graph.add_layer(
"paddle.multiply",
inputs=inputs_dict,
outputs=[node.layer_name + "_mul"],
axis=1)
else:
self.paddle_graph.add_layer(
"self.create_parameter",
inputs={},
outputs=[node.layer_name + "_cparam1"],
shape=self.params[node.layer_name + "_cparam1"].shape,
attr=string(node.layer_name + "_cparam1"))
input0 = self.graph.get_input_node(node, idx=0, copy=True)
input0_name = input0.name
inputs_dict = {}
inputs_dict['x'] = input0_name
inputs_dict['y'] = node.layer_name + "_cparam1"
self.paddle_graph.add_layer(
"paddle.multiply",
inputs=inputs_dict,
outputs=[node.layer_name + "_mul"],
axis=axis)
self.paddle_graph.add_layer(
"self.create_parameter",
inputs={},
outputs=[node.layer_name + "_cparam2"],
shape=self.params[node.layer_name + "_cparam2"].shape,
attr=string(node.layer_name + "_cparam2"))
inputs_dict = {}
inputs_dict['x'] = node.layer_name + "_mul"
inputs_dict['y'] = node.layer_name + "_cparam2"
output_shape = node.out_shapes[0]
if axis == -1:
self.paddle_graph.add_layer(
"paddle.add",
inputs=inputs_dict,
outputs=[node.layer_name])
else:
if axis < 0:
axis = axis + len(output_shape)
param2_shape = self.params[node.layer_name + "_cparam2"].shape
param2_shape_len = len(param2_shape)
diff_len = len(output_shape) - axis - param2_shape_len
new_shape = list(param2_shape) + [1] * diff_len
self.paddle_graph.add_layer(
"paddle.reshape",
inputs={"x": node.layer_name + "_cparam2"},
outputs=[node.layer_name + "_cparam2"],
shape=new_shape)
self.paddle_graph.add_layer(
"paddle.add",
inputs=inputs_dict,
outputs=[node.layer_name])
def Reshape(self, node):
input = self.graph.get_input_node(node, idx=0, copy=True)
output_shape = node.out_shapes[0]
self.paddle_graph.add_layer(
"paddle.reshape",
inputs={"x": input.name},
outputs=[node.layer_name],
shape=output_shape)
def ArgMax(self, node):
assert len(node.inputs) == 1 and len(
node.outputs
) == 1, "The count of ArgMax node\'s input and output is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
input_shape = node.in_shapes[0]
params = node.layer.argmax_param
out_max_val = params.out_max_val if hasattr(params,
out_max_val) else False
top_k = params.top_k if hasattr(params, top_k) else 1
axis = parmas.axis if hasattr(params, axis) else -1
if axis < 0:
axis += len(input_shape)
if out_max_val is True:
self.paddle_graph.add_layer(
"paddle.topk",
inputs={"x": input.name},
outputs=[node.layer_name + "_topk_var", node.layer_name + "_index_var"],
k=top_k)
self.paddle_graph.add_layer(
"paddle.cast",
inputs={"x": node.layer_name + "_index_var"},
outputs=[node.layer_name + "_index_var"],
dtype="{}_topk_var.dtype".format(node.layer_name))
self.paddle_graph.add_layer(
"paddle.concat",
inputs={"x": [node.layer_name + "_topk_var", node.layer_name + "_index_var"]},
outputs=[node.layer_name],
axis=axis)
else:
self.paddle_graph.add_layer(
"paddle.topk",
inputs={"x": input.name},
outputs=["_", node.layer_name],
k=top_k)
def Axpy(self, node):
assert len(node.inputs) == 1 and len(
node.outputs
) == 1, "The count of Axpy node\'s input and output is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.axpy_param
input0 = self.graph.get_input_node(node, idx=0, copy=True)
input1 = self.graph.get_input_node(node, idx=1, copy=True)
input2 = self.graph.get_input_node(node, idx=2, copy=True)
input0_name = input0.name
input1_name = input1.name
input2_name = input2.name
inputs_dict = {}
inputs_dict['x'] = input1_name
inputs_dict['y'] = input0_name
self.paddle_graph.add_layer(
"paddle.multiply",
inputs=inputs_dict,
outputs=[node.layer_name + "_mul"],
axis=0)
inputs_dict = {}
inputs_dict['x'] = node.layer_name + "_mul"
inputs_dict['y'] = input2_name
self.paddle_graph.add_layer(
"paddle.add",
inputs=inputs_dict,
outputs=[node.layer_name + "_mul"])
def Crop(self, node):
assert len(
node.inputs) == 2, "The count of Crop node\'s input is not 2."
input = self.graph.get_input_node(node, idx=0, copy=True)
example = self.graph.get_input_node(node, idx=1, copy=True)
params = node.layer.crop_param
axis = params.axis
input_shape = node.in_shapes[0]
if axis < 0:
axis += len(input_shape)
offset_real = [0] * len(input_shape)
if hasattr(params, "offset") and len(params.offset) > 0:
offset = list(params.offset)
assert (len(input_shape) - axis
) == len(offset), "invalid offset[%s] in crop layer" % (
str(offset))
offset_real = [0] * axis + offset
self.paddle_graph.add_layer(
"paddle.crop",
inputs={"x": input.name},
outputs=[node.layer_name],
shape=node.in_shapes[1],
offsets=list(offset_real))
def Flatten(self, node):
assert len(
node.
inputs) == 1, "The count of DetectionOutput node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
self.paddle_graph.add_layer(
"paddle.reshape",
inputs={"x": input.name},
outputs=[node.layer_name],
shape=node.out_shapes[0])
def Power(self, node):
assert len(
node.inputs) == 1, "The count of Permute node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.power_param
layer_attrs = {
'scale': params.scale,
'bias': params.shift,
'bias_after_scale': True
}
self.paddle_graph.add_layer(
"paddle.scale",
inputs={"x": input.name},
outputs=[node.layer_name],
**layer_attrs)
self.paddle_graph.add_layer(
"paddle.pow",
inputs={"x": node.layer_name},
outputs=[node.layer_name],
exponent=params.power)
def Reduction(self, node):
assert len(
node.inputs) == 1, "The count of Reduction node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.reduction_param
operation = params.operation
axis = params.axis
coeff = params.coeff
assert operation >= 1 and operation <= 4, "reduction reduction [%s] error" % (
operation)
input_len = len(node.in_shapes[0])
if axis < 0:
axis += input_len + 1
dim = list(range(input_len))
# operation = SUM
if operation == 1:
layer_attrs = {
"dim": dim[axis:],
"keep_dim": False,
}
self.paddle_graph.add_layer(
"paddle.sum",
inputs={"input": input.name},
outputs=[node.layer_name],
**layer_attrs)
# operation = ASUM
elif operation == 2:
self.paddle_graph.add_layer(
"paddle.abs",
inputs={"x": input.name},
outputs=[node.layer_name])
layer_attrs = {
"dim": dim[axis:],
"keep_dim": False,
}
self.paddle_graph.add_layer(
"paddle.sum",
inputs={"input": node.layer_name},
outputs=[node.layer_name],
**layer_attrs)
# operation = SUMSQ
elif operation == 3:
self.paddle_graph.add_layer(
"paddle.pow",
inputs={"x": input.name},
outputs=[node.layer_name],
exponent=2.0)
layer_attrs = {
"dim": dim[axis:],
"keep_dim": False,
}
self.paddle_graph.add_layer(
"paddle.sum",
inputs={"input": node.layer_name},
outputs=[node.layer_name],
**layer_attrs)
# operation = MEAN
else:
layer_attrs = {
"dim": dim[axis:],
"keep_dim": False,
}
self.paddle_graph.add_layer(
"paddle.mean",
inputs={"input": input.name},
outputs=[node.layer_name],
**layer_attrs)
self.paddle_graph.add_layer(
"paddle.scale",
inputs={"x": node.layer_name},
outputs=[node.layer_name],
scale=coeff)
def DetectionOutput(self, node):
detection_output_name = name_generator("detection_output", self.nn_name2id)
output_name = node.layer_name
layer_outputs = [detection_output_name, output_name]
assert len(
node.inputs) == 3, "The count of DetectionOutput node\'s input is not 3."
inputs_dict = dict()
for i in range(len(node.inputs)):
input = self.graph.get_input_node(node, idx=i, copy=True)
if i == 1:
input = self.graph.get_input_node(node, idx=i, copy=True)
while input is not None \
and input.layer_type != 'Softmax' \
and input.layer_type != 'Sigmoid':
input = self.graph.get_input_node(input, idx=0, copy=True)
assert input is not None, 'This kind of DetectionOutput is not supported!'
input = self.graph.get_input_node(input, idx=0, copy=True)
inputs_dict["x{}".format(i)] = input.name
params = node.layer.detection_output_param
nms_param = params.nms_param
nms_param_dict = dict()
nms_param_dict["nms_threshold"] = nms_param.nms_threshold
nms_param_dict["top_k"] = nms_param.top_k
nms_param_dict["eta"] = nms_param.eta
if nms_param is None:
nms_param_dict = {"nms_threshold": 0.3, "top_k": 10, "eta": 1.0}
default = {"nms_threshold": 0.3, "top_k": 10, "eta": 1.0}
fields = ["eta", "top_k", "nms_threshold"]
for f in default.keys():
if f not in nms_param_dict:
nms_param_dict[f] = default[f]
layer_attrs = {
"background_label": params.background_label_id,
"nms_threshold": nms_param_dict["nms_threshold"],
"nms_top_k": nms_param_dict["top_k"],
"keep_top_k": params.keep_top_k,
"score_threshold": params.confidence_threshold,
"nms_eta": nms_param_dict["eta"]}
self.paddle_graph.add_layer(
kernel="custom_layer:DetectionOutput",
inputs=inputs_dict,
outputs=layer_outputs,
**layer_attrs)
def Normalize(self, node):
normalize_name = name_generator("normalize", self.nn_name2id)
output_name = node.layer_name
layer_outputs = [normalize_name, output_name]
assert len(
node.inputs) == 1, "The count of Normalize node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.norm_param
if node.data is None or len(node.data) != 1:
print(
"The parameter of {} (type is {}) is not set. So we set the parameters as 0"
.format(node.layer_name, node.layer_type))
self.parmas[node.layer_name + ".scale"] = \
np.zeros([1] if params.channel_shared else [1, 1, 1, node.in_shapes[0][1]]).astype("float32")
else:
self.parmas[node.layer_name + ".scale"] = _adjust_parameters(node)[0]
layer_attrs = {
"axis": -1 if params.channel_shared else 1,
"param_name": node.layer_name + ".scale",
"param_shape": self.parmas[node.layer_name + ".scale"].shape}
self.pd_pdgraph.add_layer(
"custom_layer:Normalize",
inputs={"x": input.name},
outputs=layer_outputs,
**layer_attrs)
def Permute(self, node):
assert len(
node.inputs) == 1, "The count of Permute node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.permute_param
order = list(params.order)
self.paddle_graph.add_layer(
"paddle.transpose",
inputs={"x": input.name},
outputs=[node.layer_name],
perm=order)
def PriorBox(self, node):
priorbox_name = name_generator("priorbox", self.nn_name2id)
output_name = node.layer_name
layer_outputs = [priorbox_name, output_name]
assert len(
node.inputs) == 2, "The count of PriorBox node\'s input is not 2."
input0 = self.graph.get_input_node(node, idx=0, copy=True)
input1 = self.graph.get_input_node(node, idx=1, copy=True)
inputs_dict = {}
inputs_dict["x0"] = input0.name
inputs_dict["x1"] = input1.name
params = node.layer.prior_box_param
steps = tuple(params.step) if type(params.step) \
is list or type(params.step) is tuple \
else (params.step, params.step)
layer_attrs = {
"min_sizes": params.min_size,
"max_sizes": params.max_size,
"aspect_ratios": params.aspect_ratio,
"variance": params.variance,
"flip": params.flip,
"clip": params.clip,
"steps": steps,
"offset": params.offset,
"min_max_aspect_ratios_order": True}
self.paddle_graph.add_layer(
"custom_layer:PriorBox",
inputs=inputs_dict,
outputs=layer_outputs,
**layer_attrs)
def ReLU6(self, node):
if "relu6" in self.nn_name2id:
self.nn_name2id["relu6"] += 1
else:
self.nn_name2id["relu6"] = 0
relu6_name = "relu6" + str(self.nn_name2id["relu6"])
output_name = node.layer_name
layer_outputs = [relu6_name, output_name]
assert len(
node.inputs) == 1, "The count of RelU6 node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
self.paddle_graph.add_layer(
"paddle.nn.ReLU6",
inputs={"input": input.name},
outputs=layer_outputs)
def ROIPooling(self, node):
roipooling_name = name_generator("roipooling", self.nn_name2id)
output_name = node.layer_name
layer_outputs = [roipooling_name, output_name]
assert len(
node.inputs) == 2, "The count of ROIPooling node\'s input is not 2."
input0 = self.graph.get_input_node(node, idx=0, copy=True)
input1 = self.graph.get_input_node(node, idx=1, copy=True)
inputs_dict = {}
inputs_dict["x0"] = input0.name
inputs_dict["x1"] = input1.name
params = node.layer.roi_pooling_param
layer_attrs = {
"pooled_height": params.pooled_h,
"pooled_width": params.pooled_w,
"spatial_scale": params.spatial_scale}
self.paddle_graph.add_layer(
"custom_layer:ROIPooling",
inputs=inputs_dict,
outputs=layer_outputs,
**layer_attrs)
def ShuffleChannel(self, node):
assert len(
node.inputs) == 1, "The count of ShuffleChannel node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.shuffle_channel_param
self.paddle_graph.add_layer(
"fluid.layers.shuffle_channel",
inputs={"x": input.name},
outputs=[node.layer_name],
group=params.group)
def Upsample(self, node):
assert len(
node.inputs) == 1, "The count of Upsample node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.upsample_param
layer_attrs = {
"align_corners": False,
"scale_factor": params.scale,
"mode": "nearest"}
self.paddle_graph.add_layer(
"paddle.nn.functioanl.interpolate",
inputs={"input": input.name},
outputs=[node.layer_name],
**layer_attrs)
def Select(self, node):
select_name = name_generator("select", self.nn_name2id)
output_name = node.layer_name
layer_outputs = [select_name, output_name]
assert len(
node.inputs) == 1, "The count of Select node\'s input is not 1."
input = self.graph.get_input_node(node, idx=0, copy=True)
input_shape = node.in_shapes[0]
params = node.layer.select_param
layer_attrs = {
"input_shape": input_shape,
"point": params.slice_point,
"axis": params.axis}
self.paddle_graph.add_layer(
"custom_layer:Select",
inputs={"x": input.name},
outputs=layer_outputs,
**layer_attrs)
# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
from x2paddle.op_mapper.dygraph.onnx2paddle.opset9 import OpSet9
from x2paddle.core.op_mapper import OpMapper
from x2paddle.decoder.onnx_decoder import ONNXGraphNode
from x2paddle.core.program import PaddleGraph
class ONNXOpMapper(OpMapper):
def __init__(self, decoder):
super(ONNXOpMapper, self).__init__()
self.support_op_sets = [9, ]
self.default_op_set = 9
self.graph = decoder.graph
self.paddle_graph = PaddleGraph(parent_layer=None, graph_type="dygraph", source_type="onnx")
self.paddle_graph.outputs = self.graph.output_nodes
self.opset = self.create_opset(decoder)
if not self.op_checker():
raise Exception("Model is not supported yet.")
print("Total nodes: {}".format(
sum([
isinstance(node, ONNXGraphNode)
for name, node in self.graph.node_map.items()
])))
print("Nodes converting ...")
for i, node_name in enumerate(self.graph.topo_sort):
sys.stderr.write("\rConverting node {} ... ".format(i + 1))
node = self.graph.get_node(node_name)
op = node.layer_type
if hasattr(self.opset, op):
func = getattr(self.opset, op)
func(node)
elif op in self.opset.directly_map_ops:
self.opset.directly_map(node)
elif op in self.opset.elementwise_ops:
self.opset.elementwise_map(node)
print("\nNodes converted.")
self.paddle_graph.set_name(self.graph.graph_name)
self.paddle_graph.set_parameters(self.opset.weights)
self.paddle_graph.set_inputs_info(self.opset.inputs_info)
def op_checker(self):
unsupported_ops = set()
for node_name in self.graph.topo_sort:
node = self.graph.get_node(node_name)
op = node.layer_type
if not hasattr(self.opset, op) and \
op not in self.opset.directly_map_ops and \
op not in self.opset.elementwise_ops:
unsupported_ops.add(op)
if len(unsupported_ops) == 0:
return True
else:
if len(unsupported_ops) > 0:
print("\n========= {} OPs are not supported yet ===========".format(
len(unsupported_ops)))
for op in unsupported_ops:
print("========== {} ============".format(op))
return False
def create_opset(self, decoder):
run_op_set = self.default_op_set
opset = ''
if decoder.op_set in self.support_op_sets:
opset = 'OpSet' + str(decoder.op_set)
elif decoder.op_set < self.default_op_set:
opset = 'OpSet' + str(self.default_op_set)
else:
for op_set in self.support_op_sets:
if decoder.op_set > op_set:
run_op_set = op_set
else:
break
opset = 'OpSet' + str(run_op_set)
print(
'Now, onnx2paddle support convert onnx model opset_verison {},'
'opset_verison of your onnx model is {}, automatically treated as op_set: {}.'
.format(self.support_op_sets, decoder.op_set, run_op_set))
return eval(opset)(decoder, self.paddle_graph)
# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from x2paddle.decoder.onnx_decoder import ONNXGraph, ONNXGraphNode, ONNXGraphDataNode
from x2paddle.core.graph import GraphNode
from x2paddle.core.fluid_code import Layer
from x2paddle.core.fluid_code import FluidCode
from x2paddle.core.util import *
from functools import reduce
import numpy as np
import onnx
import onnx.numpy_helper as numpy_helper
from onnx.mapping import TENSOR_TYPE_TO_NP_TYPE
import logging as _logging
from collections import OrderedDict
import math
import os
import copy
import sys
import shutil
_logger = _logging.getLogger(__name__)
def _const_weight_or_none(node, necessary=False):
if 'Constant' in node.layer_type:
return node.value
if isinstance(node, ONNXGraphDataNode):
return node.weight
if necessary:
assert '{} should be an initializer or Constant operator.'.format(
node.name)
return None
def _is_static_shape(shape):
negtive_dims = 0
error_dims = 0
for dim in shape:
if dim < 0:
negtive_dims += 1
if dim < -1:
error_dims += 1
if negtive_dims > 1:
return False
if error_dims > 0:
return False
return True
def _get_same_padding(in_size, kernel_size, stride):
new_size = int(math.ceil(in_size * 1.0 / stride))
pad_size = (new_size - 1) * stride + kernel_size - in_size
pad0 = int(pad_size / 2)
pad1 = pad_size - pad0
return [pad0, pad1]
def print_mapping_info(func):
def run_mapping(*args, **kwargs):
node = args[1]
try:
res = func(*args, **kwargs)
except:
print("convert failed node:{}, op_type is {}".format(
node.name[9:], node.layer_type))
raise
else:
return res
return run_mapping
class OpSet9():
elementwise_ops = {
'Add': 'paddle.add',
'Div': 'paddle.divide',
'Sub': 'fluid.layers.elementwise_sub',
'Mul': 'paddle.multiply',
'Pow': 'paddle.pow',
}
directly_map_ops = {
'Ceil': ['paddle.ceil'],
# reduce function
'ReduceMean': ['paddle.mean',
dict(axes='axis', keepdims='keepdim'),
dict(keepdims=1)],
'ReduceSum': ['paddle.sum',
dict(axes='axis', keepdims='keepdim'),
dict(keepdims=1)],
'ReduceMin': ['paddle.min',
dict(axes='axis', keepdims='keepdim'),
dict(keepdim=1)],
'ReduceMax': ['paddle.max',
dict(axes='axis', keepdims='keepdim'),
dict(keepdim=1)],
# active function
'Relu': ['paddle.nn.ReLU'],
'LeakyRelu': ['paddle.nn.LeakyReLU',
dict(alpha='negative_slope'),
dict(negative_slope=.01)],
'Elu': ['paddle.nn.functional.elu',
dict(alpha='alpha'),
dict(alpha=1.)],
'ThresholdedRelu': ['paddle.nn.functional.thresholded_relu',
dict(alpha='threshold'),
dict(alpha=1.)],
'Tanh': ['paddle.nn.Tanh'],
'Sigmoid': ['paddle.nn.Sigmoid'],
'Softsign': ['paddle.nn.Softsign'],
'Softplus': ['paddle.nn.Softplus',
dict(threshold='threshold'),
dict(threshold=float(sys.maxsize))],
'Exp': ['paddle.exp'],
'Softmax': ['paddle.nn.Softmax',
dict(axis='axis'),
dict(axis=1)],
'Sqrt': ['paddle.sqrt'],
'Floor': ['paddle.floor'],
'Abs': ['paddle.abs'],
'Erf': ['paddle.erf'],
}
def __init__(self, decoder, paddle_graph):
super(OpSet9, self).__init__()
self.graph = decoder.graph
self.paddle_graph = paddle_graph
self.input_index = 0
self.inputs_info = dict()
self.weights = dict()
self.nn_name2id = dict()
@print_mapping_info
def directly_map(self, node, *args, **kwargs):
inputs = node.layer.input
assert len(inputs) == 1, 'directly_map error with multi inputs'
input = self.graph.get_input_node(node, idx=0, copy=True)
onnx_attrs = node.attr_map
if '' in onnx_attrs:
onnx_attrs.pop('')
if '_' in onnx_attrs:
onnx_attrs.pop('_')
op_info = self.directly_map_ops[node.layer_type]
paddle_op = op_info[0]
layer_attrs = dict()
if len(op_info) > 1:
attrs_name_map_dict = op_info[1]
for onnx_attr_name, pd_attr_name in attrs_name_map_dict.items():
if onnx_attr_name in onnx_attrs:
layer_attrs[pd_attr_name] = onnx_attrs[onnx_attr_name]
else:
layer_attrs[pd_attr_name] = op_info[2][onnx_attr_name]
if paddle_op.startswith("paddle.nn"):
op_name = paddle_op[10:].lower()
op_name = name_generator(op_name, self.nn_name2id)
output_name = node.name
layer_outputs = [op_name, output_name]
self.paddle_graph.add_layer(
kernel=paddle_op,
inputs={"x": input.name},
outputs=layer_outputs,
**layer_attrs)
else:
self.paddle_graph.add_layer(
kernel=paddle_op,
inputs={"x": input.name},
outputs=[node.name],
**layer_attrs)
@print_mapping_info
def elementwise_map(self, node):
op_type = self.elementwise_ops[node.layer_type]
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_y = self.graph.get_input_node(node, idx=1, copy=True)
inputs_dict = {'x': val_x.name,
'y': val_y.name}
self.paddle_graph.add_layer(
op_type,
inputs=inputs_dict,
outputs=[node.name])
@print_mapping_info
def place_holder(self, node):
shape = node.out_shapes[0]
for i, dim_shape in enumerate(shape):
if dim_shape == 0 and i == 0:
shape[i] = 1
if dim_shape == 0 and i != 0:
assert 'shape of input is not assigned'
self.paddle_graph.add_layer(
kernel="paddle.to_tensor",
inputs={},
outputs=[node.name],
data="x{}".format(self.input_index))
self.inputs_info["x{}".format(self.input_index)] = [shape, node.dtype]
self.input_index += 1
@print_mapping_info
def create_parameter(self, node, parameter=None):
if parameter is not None:
node = parameter
dtype = node.dtype
shape = node.out_shapes[0]
if len(node.weight.shape) == 0:
self.paddle_graph.add_layer(
"paddle.full",
inputs={},
outputs=[node.name],
dtype=string(dtype),
shape=[1],
fill_value=node.weight)
else:
self.weights[node.name] = node.weight
self.paddle_graph.add_layer(
"self.create_parameter",
inputs={},
outputs=[node.name],
shape=shape,
attr=string(node.name),
dtype=string(dtype),
default_initializer="paddle.nn.initializer.Constant(value=0.0)")
def _pad_if_asymmetric(self, node, pads, val_name): # pads: SSEE
assert len(pads) & 1 == 0
symmetric = True
ndims = len(pads) // 2
for idx_dim in range(ndims):
if pads[idx_dim] != pads[ndims + idx_dim]:
symmetric = False
break
if symmetric:
return pads[:ndims], val_name
val_padded = self.Pad(node, op_independent=False)
return [0] * ndims, val_padded
def _interpolate(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
inputs = {'x': val_x.name}
if node.layer_type == 'Resize':
if len(node.layer.input) == 2:
# opset 10
val_scales = self.graph.get_input_node(node, idx=1, copy=True)
inputs['scale_factor'] = val_scales.name
elif len(node.layer.input) == 3:
# opset 11
val_scales = self.graph.get_input_node(node, idx=2, copy=True)
inputs['scale_factor'] = val_scales.name
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.name + '_nc', val_sizes.name + '_hw'
self.paddle_graph.add_layer(
'paddle.split',
inputs={"x": val_sizes.name},
outputs=[var_nc, var_hw],
num_or_sections=[2, 2],
axis=0)
self.paddle_graph.add_layer(
"paddle.cast",
inputs={"x": var_hw},
outputs=[var_hw],
dtype=string('int32'))
# inputs['size'] = var_hw
# TODO(syf): all use
inputs['out_shape'] = var_hw
ipt = inputs.pop("x")
inputs["input"] = ipt
mode = node.get_attr('mode', 'nearest')
attrs = {"align_corners": False}
self.paddle_graph.add_layer(
kernel="fluid.layers.resize_nearest",
inputs=inputs,
outputs=[node.name],
**attrs)
return
elif node.layer_type == 'Upsample':
val_scales = self.graph.get_input_node(node, idx=1, copy=True)
inputs['scale'] = val_scales
mode = node.get_attr('mode', 'nearest')
attrs = {"align_corners": False,
"mode": string(mode),
"align_mode": 1}
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.interpolate",
inputs=inputs,
outputs=[node.name],
**attrs)
@print_mapping_info
def HardSigmoid(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
alpha = node.get_attr('alpha', 0.2)
beta = node.get_attr('beta', 0.5)
self.paddle_graph.add_layer(
kernel="paddle.scale",
inputs={"x": val_x.name},
outputs=[node.name + "_val"],
scale=alpha,
bias=beta)
self.paddle_graph.add_layer(
kernel="paddle.clip",
inputs={"x": node.name + "_val"},
outputs=[node.name],
min=0.0,
max=1.0)
@print_mapping_info
def Shape(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
self.paddle_graph.add_layer(
kernel="paddle.shape",
inputs={"input": val_x.name},
outputs=[node.name])
self.paddle_graph.add_layer(
'paddle.cast',
inputs={"x": node.name},
outputs=[node.name],
dtype=string('int64'))
@print_mapping_info
def RoiAlign(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_rois = self.graph.get_input_node(node, idx=1, copy=True)
pooled_height = node.get_attr('output_height')
pooled_width = node.get_attr('output_width')
spatial_scale = node.get_attr('spatial_scale')
sampling_ratio = node.get_attr('sampling_ratio')
layer_attrs = {
'pooled_height': pooled_height,
'pooled_width': pooled_width,
'spatial_scale': spatial_scale,
'sampling_ratio': sampling_ratio,
}
self.paddle_graph.add_layer(
'fluid.layers.roi_align',
inputs={'input': val_x.name,
'rois': val_rois.name},
outputs=[node.name],
**layer_attrs)
@print_mapping_info
def MaxRoiPool(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_rois = self.graph.get_input_node(node, idx=1, copy=True)
spatial_scale = node.get_attr('spatial_scale')
pooled_height, pooled_width = node.get_attr('pooled_shape')
layer_attrs = {
'pooled_height': pooled_height,
'pooled_width': pooled_width,
'spatial_scale': spatial_scale,
}
self.paddle_graph.add_layer(
'fluid.layers.roi_pool',
inputs={'input': val_x.name,
'rois': val_rois.name},
outputs=[node.name],
**layer_attrs)
@print_mapping_info
def Pad(self, node, op_independent=True):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
pads = node.get_attr('pads')
mode = node.get_attr('mode', 'constant')
value = node.get_attr('value', 0.)
data_shape = val_x.out_shapes[0]
output_shape = node.out_shapes[0]
assume_pad2d = False
layer_attrs = {}
layer_attrs['mode'] = string(mode)
paddings = []
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:
paddle_op = 'paddle.nn.Pad2D'
layer_attrs['data_format'] = string('NCHW')
layer_attrs['value'] = value
else:
paddle_op = 'fluid.layers.pad'
layer_attrs["pad_value"] = value
if len(pads) == 4:
paddings = np.array(pads).reshape(
(-1, 2)).transpose().flatten().tolist() # SSEE -> SESE
elif len(pads) == 8:
paddings = np.array(pads).reshape(
(-1, 4)).transpose().flatten().tolist() # SSEE -> SESE
if sum(paddings[:4]) == 0:
paddle_op = 'paddle.nn.Pad2D'
paddings = paddings[4:]
layer_attrs['value'] = value
if 'pad_value' in layer_attrs:
layer_attrs.pop('pad_value')
tmp_paddings = copy.deepcopy(paddings)
paddings[0] = tmp_paddings[2]
paddings[1] = tmp_paddings[3]
paddings[2] = tmp_paddings[0]
paddings[3] = tmp_paddings[1]
if paddle_op == 'paddle.nn.Pad2D':
layer_attrs['padding'] = paddings
nn_op_name = name_generator("pad2d", self.nn_name2id)
else:
layer_attrs['paddings'] = paddings
if op_independent:
self.paddle_graph.add_layer(
paddle_op,
inputs={'x': val_x.name},
outputs=[nn_op_name, node.name] if paddle_op == 'paddle.nn.Pad2D' else [node.name],
**layer_attrs)
else:
self.paddle_graph.add_layer(
paddle_op,
inputs={'x': val_x.name},
outputs=[nn_op_name, node.name + '_paded'] if paddle_op == 'paddle.nn.Pad2D' \
else [node.name + '_paded'],
**layer_attrs)
return node.name + '_paded'
@print_mapping_info
def Unsqueeze(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
axes = node.get_attr('axes')
layer_attrs = {'axis': axes}
if len(val_x.out_shapes[0]) == 0:
if node.name:
self.paddle_graph.add_layer(
'paddle.reshape',
inputs={"x": val_x.name},
outputs=[node.name],
shape=[1])
else:
self.paddle_graph.add_layer(
'paddle.unsqueeze',
inputs={"x": val_x.name},
outputs=[node.name],
**layer_attrs)
@print_mapping_info
def Shrink(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
bias = node.get_attr('bias')
lambd = node.get_attr('lambd')
assert bias == 0.0, 'not support bias!=0'
self.paddle_graph.add_layer(
'paddle.nn.functional.hardshrink',
inputs={"x": val_x.name},
outputs=[node.name],
threshold=lambd)
@print_mapping_info
def Constant(self, node):
val_output = self.graph.get_node(node.layer.output[0], copy=True)
value = node.get_attr('value')
dtype = np.dtype(value.dtype)
output_dtype = val_output.dtype
if output_dtype:
assert dtype == output_dtype, 'tensor dtype unmatches storage dtype'
shape = node.get_attr('shape', None)
if shape is None:
shape = val_output.out_shapes[0]
if shape is None:
shape = list(value.shape)
_logger.warning('in (Constant -> %s): '
'attribute "shape" of %s not inferred, '
'using value as 1-D tensor may lead to fails',
val_output.name, val_output.name)
if len(value) == 1:
value = value.tolist()
value = value[0]
self.paddle_graph.add_layer(
"paddle.full",
inputs={},
outputs=[node.name],
dtype=string(dtype),
shape=[1],
fill_value=value)
else:
value = np.reshape(value, shape)
self.weights[node.name] = value
self.paddle_graph.add_layer(
"self.create_parameter",
inputs={},
outputs=[node.name],
shape=shape,
attr=string(node.name),
dtype=string(dtype),
default_initializer="paddle.nn.initializer.Constant(value=0.0)")
@print_mapping_info
def Resize(self, node):
self._interpolate(node)
@print_mapping_info
def Upsample(self, node):
self._interpolate(node)
@print_mapping_info
def InstanceNormalization(self, node):
op_name = name_generator("instanse_norm", self.nn_name2id)
output_name = node.name
layer_outputs = [op_name, output_name]
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)
layer_attrs = {
'num_features': node.out_shapes[0][1],
'epsilon': epsilon,
'weight_attr': string(val_scale.name),
'bias_attr': string(val_b.name)
}
dim = len(val_x.out_shapes[0])
if dim == 2 or dim == 3:
paddle_op = "paddle.nn.InstanceNorm1D"
elif dim == 4:
paddle_op = "paddle.nn.InstanceNorm2D"
elif dim == 5:
paddle_op = "paddle.nn.InstanceNorm3D"
else:
raise Exception("The paddle only support 2D, 3D, 4D or 5D input in InstanceNormalization.")
self.paddle_graph.add_layer(
paddle_op,
inputs={"x": val_x.name},
outputs=layer_outputs,
**layer_attrs)
@print_mapping_info
def Expand(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_shape = self.graph.get_input_node(node, idx=1, copy=True)
val_x_dtype = val_x.dtype
name_ones = node.name + '_ones'
attr_ones = {
'shape': val_shape.name,
'dtype': string(val_x_dtype),
'fill_value': 1
}
self.paddle_graph.add_layer(
'paddle.full',
inputs={},
outputs=[name_ones],
**attr_ones)
inputs_dict = {'x': name_ones,
'y': val_x.name}
self.paddle_graph.add_layer(
'paddle.multiply',
inputs=inputs_dict,
outputs=[node.name])
@print_mapping_info
def Gather(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
indices = self.graph.get_input_node(node, idx=1, copy=True)
indices_shape = indices.out_shapes[0]
axis = node.get_attr('axis', 0)
#assert len(
# indices_shape) <= 2, "Gather op don't support dim of indice >2 "
if axis == 0 and len(indices_shape) <= 1:
if len(val_x.out_shapes[0]) <= 1:
self.paddle_graph.add_layer(
'paddle.gather',
inputs={'x': val_x.name,
'index': indices.name},
outputs=[node.name])
elif len(val_x.out_shapes[0]) > 1:
if len(indices_shape) == 0:
gather_ = node.name + '_1'
self.paddle_graph.add_layer(
'paddle.gather',
inputs={'x': val_x.name,
'index': indices.name},
outputs=[gather_])
self.paddle_graph.add_layer(
'paddle.squeeze',
inputs={'x': gather_},
outputs=[node.name],
axis=[0])
else:
self.paddle_graph.add_layer(
'paddle.gather',
inputs={'x': val_x.name,
'index': indices.name},
outputs=[node.name])
elif axis > 0 and len(indices_shape) <= 1:
perm = list(range(len(val_x.out_shapes[0])))
perm = [axis] + perm[:axis] + perm[axis + 1:]
name_trans = val_x.name + '_trans'
self.paddle_graph.add_layer(
'paddle.transpose',
inputs={"x": val_x.name},
outputs=[name_trans],
perm=perm)
self.paddle_graph.add_layer(
'paddle.gather',
inputs={'x': name_trans,
'index': indices.name},
outputs=[node.name])
self.paddle_graph.add_layer(
'paddle.transpose',
inputs={"x": node.name},
outputs=[node.name],
perm=perm)
if len(indices_shape) < 1:
self.paddle_graph.add_layer(
'paddle.squeeze',
inputs={'x': node.name},
outputs=[node.name],
axis=[axis])
elif axis == 0 and len(indices_shape) > 1:
if val_x.out_shapes[0] is not None and isinstance(
val_x, ONNXGraphDataNode):
indices_cast = indices.name + '_cast'
self.paddle_graph.add_layer(
'paddle.cast',
inputs={"x": indices.name},
outputs=indices_cast,
dtype=string('int64'))
op_name = name_generator("embedding", self.nn_name2id)
output_name = node.name
layer_outputs = [op_name, output_name]
self.paddle_graph.add_layer(
'paddle.nn.Embedding',
inputs={"x": indices_cast},
outputs=layer_outputs,
param_attr=string(val_x.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.name + '_shape'
self.paddle_graph.add_layer(
'paddle.reshape',
inputs={"x": indices.name},
outputs=[indices_reshape],
shape=[reshape_shape, ])
perm = list(range(len(val_x.out_shapes[0])))
self.paddle_graph.add_layer(
'paddle.gather',
inputs={'x': val_x.name,
'index': indices_reshape},
outputs=[node.name])
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)
self.paddle_graph.add_layer(
'paddle.reshape',
inputs={"x": node.name},
outputs=[node.name],
shape=reshaped_shape)
elif axis > 0 and len(indices_shape) > 1:
from functools import reduce
reshape_shape = reduce(lambda x, y: x * y, indices_shape)
indices_reshape = indices.name + '_shape'
self.paddle_graph.add_layer(
'paddle.reshape',
inputs={"x": indices.name},
outputs=[indices_reshape],
shape=[reshape_shape, ])
perm = list(range(len(val_x.out_shapes[0])))
perm = [axis] + perm[:axis] + perm[axis + 1:]
name_trans = val_x.name + '_transpose'
self.paddle_graph.add_layer(
'paddle.transpose',
inputs={"x": val_x.name},
outputs=[name_trans],
perm=perm)
self.paddle_graph.add_layer(
'paddle.gather',
inputs={'x': name_trans,
'index': indices_reshape},
outputs=[node.name])
input_transpose = node.name + '_transpose'
self.paddle_graph.add_layer(
'paddle.transpose',
inputs={"x": node.name},
outputs=[input_transpose],
perm=perm)
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)
self.paddle_graph.add_layer(
'paddle.reshape',
inputs={"x": input_transpose},
outputs=[node.name],
shape=reshaped_shape)
@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:
self.paddle_graph.add_layer(
'paddle.scatter',
inputs={'x': val_x.name,
'index': indices.name,
'updates': updates.name},
outputs=[node.name])
else:
input_inner_indices = node.name + '_input_inner_indices'
shape = val_x.out_shapes[0]
self.paddle_graph.add_layer(
'paddle.reshape',
inputs={"x": indices.name},
outputs=[indices.name],
shape=indices.out_shapes[0])
zeros_like_val_x = val_x.name + '_zeros'
self.paddle_graph.add_layer(
'paddle.zeros_like',
inputs={"x": val_x.name},
outputs=[zeros_like_val_x])
self.paddle_graph.add_layer(
'paddle.scatter_nd_add',
inputs={
'x': zeros_like_val_x,
'index': indices.name,
'updates': updates.name
},
outputs=[input_inner_indices])
indices_mask = node.name + '_indices_mask'
constant_minus_one = node.name + '_constant_minus_one'
# full_like support create tensor shape like input tensor
self.paddle_graph.add_layer(
'paddle.full_like',
inputs={"x": updates.name},
outputs=[constant_minus_one],
dtype=string(updates.dtype),
fill_value=-1)
self.paddle_graph.add_layer(
'paddle.scatter_nd_add',
inputs={
'x': zeros_like_val_x,
'index': indices.name,
'updates': constant_minus_one
},
outputs=[indices_mask])
constant_one = node.name + '_constant_1'
# full_like support create tensor shape like input tensor
self.paddle_graph.add_layer(
'paddle.full_like',
inputs={"x": val_x.name},
outputs=[constant_one],
dtype=string(val_x.dtype),
fill_value=1)
input_out_indices_mask = node.name + '_input_out_indices_mask'
self.paddle_graph.add_layer(
"paddle.add",
inputs={"x": indices_mask,
"y": constant_one},
outputs=[input_out_indices_mask])
input_out_indices = node.name + '_input_out_indices'
self.paddle_graph.add_layer(
"paddle.multiply",
inputs={"x": val_x.name,
"y": input_out_indices_mask},
outputs=[input_out_indices])
self.paddle_graph.add_layer(
"paddle.add",
inputs={"x": input_inner_indices,
"y": input_out_indices},
outputs=[node.name])
@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.name,
'end': val_limit.name,
'step': val_delta.name}
self.paddle_graph.add_layer(
'paddle.arange',
inputs=inputs,
outputs=[node.name],
dtype=string(dtype))
@print_mapping_info
def Slice(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
starts, ends, axes, steps = None, None, None, None
layer_attrs = {}
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)
starts_value = _const_weight_or_none(starts)
ends_value = _const_weight_or_none(ends)
if len(node.inputs) > 3:
axes = self.graph.get_input_node(node, idx=3, copy=True)
axes = _const_weight_or_none(axes, necessary=True)
if len(node.inputs) > 4:
steps = self.graph.get_input_node(node, idx=4, copy=True)
steps = _const_weight_or_none(steps)
layer_attrs = {
"axes": axes,
"starts": starts.name,
"ends": ends.name
}
if starts_value is not None and ends_value is not None:
starts_value = starts_value.copy()
ends_value = ends_value.copy()
#for idx in range(len(ends_value)):
# if ends_value[idx] > 2**31 - 1:
# ends_value[idx] = 2**31 - 1
#print(val_x.out_shapes)
for idx in range(len(ends_value)):
if starts_value[idx] >= val_x.out_shapes[0][axes[idx]]:
starts_value[idx] = val_x.out_shapes[0][axes[idx]] - 1
ends_value[idx] = val_x.out_shapes[0][axes[idx]]
starts_value[idx] = val_x.out_shapes[0][axes[idx]] - 1
elif ends_value[idx] > 2**31 - 1:
ends_value[idx] = 2**31 - 1
layer_attrs = {
"axes": axes,
"starts": starts_value,
"ends": ends_value
}
else:
if starts.dtype != 'int32':
starts_cast = starts.name + '_cast'
self.paddle_graph.add_layer(
'paddle.cast',
inputs={"x": starts.name},
outputs=[starts_cast],
dtype=string('int32'))
layer_attrs['starts'] = starts_cast
if ends.dtype != 'int32':
ends_cast = ends.name + '_cast'
self.paddle_graph.add_layer(
'paddle.cast',
inputs={"x": ends.name},
outputs=[ends_cast],
dtype=string('int32'))
layer_attrs['ends'] = ends_cast
else:
starts = node.get_attr('starts')
ends = node.get_attr('ends')
axes = node.get_attr('axes')
for idx in range(len(ends)):
if ends[idx] > 2**31 - 1:
ends[idx] = 2**31 - 1
layer_attrs = {"axes": axes, "starts": starts, "ends": ends}
if steps is not None:
layer_attrs['strides'] = steps
self.paddle_graph.add_layer(
'paddle.strided_slice',
inputs={"x": val_x.name},
outputs=[node.name],
**layer_attrs)
else:
self.paddle_graph.add_layer(
'paddle.slice',
inputs={"input": val_x.name},
outputs=[node.name],
**layer_attrs)
@print_mapping_info
def ConstantOfShape(self, node):
val_shape = self.graph.get_input_node(node, idx=0, copy=True)
val_y = self.graph.get_node(node.layer.output[0], copy=True)
value = node.get_attr('value')
dtype = value.dtype
value = value.tolist()
assert len(value) == 1, ('given value not Scalar, shape of value > 1, '
'this is not supported')
if len(value) == 1:
value = value[0]
layer_attrs = {
'shape': val_shape.name,
'dtype': string(dtype),
'fill_value': value
}
self.paddle_graph.add_layer(
"paddle.full",
inputs={},
outputs=[node.name],
**layer_attrs)
@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')
layer_attrs = {
'max': max_value,
'min': min_value,
}
self.paddle_graph.add_layer(
'paddle.clip',
inputs={"x": val_x.name},
outputs=[node.name],
**layer_attrs)
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)
if max_value.shape == (1, ):
max_value = max_value[0]
if min_value.shape == (1, ):
min_value = min_value[0]
if max_value is not None and min_value is not None:
layer_attrs = {'max': max_value, 'min': min_value}
self.paddle_graph.add_layer(
'paddle.clip',
inputs={"x": val_x.name},
outputs=[node.name],
**layer_attrs)
else:
raise
@print_mapping_info
def Split(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
paddle_op = 'split'
split = node.get_attr('split')
axis = node.get_attr('axis', 0)
layer_attrs = {
'num_or_sections': split,
'axis': axis,
}
outputs_list = list()
if isinstance(split, list) or isinstance(split, tuple):
for i in range(len(split)):
outputs_list.append("{}_p{}".format(node.layer_name, i))
else:
outputs_list.append(node.name)
self.paddle_graph.add_layer(
'paddle.split',
inputs={"x": val_x.name},
outputs=outputs_list,
**layer_attrs)
@print_mapping_info
def Reshape(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_shape = self.graph.get_input_node(node, idx=1, copy=True)
val_reshaped = self.graph.get_node(node.layer.output[0], copy=True)
shape_value = _const_weight_or_none(val_shape)
shape_dims = len(val_shape.out_shapes[0])
if shape_value is not None:
self.paddle_graph.add_layer(
'paddle.reshape',
inputs={'x': val_x.name},
outputs=[node.name],
shape=shape_value.tolist())
elif len(node.out_shapes[0]) > 0 and _is_static_shape(node.out_shapes[
0]):
self.paddle_graph.add_layer(
'paddle.reshape',
inputs={'x': val_x.name},
outputs=[node.name],
shape=node.out_shapes[0])
else:
# shape may be [], come form Gather by scalar indices
if len(val_shape.out_shapes[0]) > 0:
self.paddle_graph.add_layer(
'paddle.reshape',
inputs={'x': val_shape.name},
outputs=[val_shape.name],
shape=val_shape.out_shapes[0])
self.paddle_graph.add_layer(
'paddle.reshape',
inputs={'x': val_x.name,
'shape': val_shape.name},
outputs=node)
@print_mapping_info
def Cast(self, node):
val_input = self.graph.get_input_node(node, idx=0, copy=True)
val_output = self.graph.get_node(node.layer.output[0], copy=True)
dtype = node.get_attr('to')
if not isinstance(dtype, np.dtype):
dtype = TENSOR_TYPE_TO_NP_TYPE[dtype]
output_dtype = val_output.dtype
if output_dtype:
assert dtype == output_dtype, 'dtype of to unmatches output'
self.paddle_graph.add_layer(
'paddle.cast',
inputs={'x': val_input.name},
outputs=[node.name],
dtype=string(dtype))
@print_mapping_info
def Not(self, node):
val_input = self.graph.get_input_node(node, idx=0, copy=True)
self.paddle_graph.add_layer('paddle.logical_not',
inputs={'x': val_input.name},
outputs=[node.name])
@print_mapping_info
def AveragePool(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
auto_pad = node.get_attr('auto_pad', 'NOTSET')
kernel_shape = node.get_attr("kernel_shape")
poolnd = len(kernel_shape)
strides = node.get_attr("strides")
pad_mode = node.get_attr("pads")
ceil_mode = bool(node.get_attr('ceil_mode', 0))
pads = node.get_attr('pads', [0] * (poolnd * 2))
paddings, val_x = self._pad_if_asymmetric(node, pads, val_x)
if auto_pad == "SAME_UPPER" or auto_pad == "SAME_LOWER":
input_shape = val_x.out_shapes[0]
pad_h = _get_same_padding(input_shape[2], kernel_shape[0],
strides[0])
pad_w = _get_same_padding(input_shape[3], kernel_shape[1],
strides[1])
paddings = pad_h + pad_w
paddle_op = 'fluid.layers.pool{}d'.format(poolnd)
assert 2 <= poolnd <= 3, 'only pool2d and pool3d are supported'
layer_attrs = {
"pool_size": kernel_shape,
"pool_type": string('avg'),
"pool_stride": strides,
"pool_padding": paddings,
"ceil_mode": ceil_mode,
"exclusive": 'True',
"name": string(node.name)
}
self.paddle_graph.add_layer(
paddle_op,
inputs={'input': val_x if isinstance(val_x, str) else val_x.name},
outputs=[node.name],
**layer_attrs)
# TODO(syf): op has diff
# op_name = name_generator("pool", self.nn_name2id)
# output_name = node.name
# layer_outputs = [op_name, output_name]
# paddle_op = 'paddle.nn.Pool{}D'.format(poolnd)
# assert 1 <= poolnd <= 3, 'only Pool1D, Pool2D and Pool3D are supported'
# layer_attrs = {
# "kernel_size": kernel_shape,
# "stride": strides,
# "padding": paddings,
# "ceil_mode": ceil_mode,
# "exclusive": 'True',
# }
# self.paddle_graph.add_layer(
# paddle_op,
# inputs={'x': val_x.name},
# outputs=layer_outputs,
# **layer_attrs)
@print_mapping_info
def Concat(self, node):
inputs_list = []
dtypes = set()
for i in range(len(node.layer.input)):
ipt = self.graph.get_input_node(node, idx=i, copy=True)
inputs_list.append(ipt.name)
dtypes.add(ipt.dtype)
if len(dtypes) > 1:
assert 'Unspported situation happened, please create issue on https://github.com/PaddlePaddle/X2Paddle/issues.'
axis = node.get_attr('axis')
self.paddle_graph.add_layer(
'paddle.concat',
inputs={"x": inputs_list},
outputs=[node.name],
axis=axis)
@print_mapping_info
def Flatten(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
output_shape = node.out_shapes[0]
axis = node.get_attr('axis', 1)
shape_list = [1, 1]
if axis == 0:
for s in output_shape:
shape_list[1] *= s
else:
for s in output_shape[:axis]:
shape_list[0] *= s
for s in output_shape[axis:]:
shape_list[1] *= s
self.paddle_graph.add_layer(
'paddle.reshape',
inputs={"x": val_x.name},
outputs=[node.name],
shape=shape_list)
@print_mapping_info
def Gemm(self, node):
val_a = self.graph.get_input_node(node, idx=0, copy=True)
val_b = self.graph.get_input_node(node, idx=1, copy=True)
val_c = self.graph.get_input_node(node, idx=2, copy=True)
alpha = node.get_attr('alpha', 1.) # optional
beta = node.get_attr('beta', 1.) # optional
trans_a = bool(node.get_attr('transA', 0)) # optional
trans_b = bool(node.get_attr('transB', 0)) # optional
val_mm = node.name + '_mm'
matmul_inputs = {"x": val_a.name,
"y": val_b.name}
attr_matmul = {
"transpose_x": trans_a,
"transpose_y": trans_b,
}
self.paddle_graph.add_layer(
'paddle.matmul',
inputs=matmul_inputs,
outputs=[val_mm],
**attr_matmul)
self.paddle_graph.add_layer(
"paddle.scale",
inputs={"x": val_mm},
outputs=[val_mm],
scale=alpha)
if beta != 0:
if beta == 1.:
add_inputs = {"x": val_mm,
"y": val_c.name}
self.paddle_graph.add_layer(
"paddle.add",
inputs=add_inputs,
outputs=[node.name])
else:
var_beta = node.name + '_beta'
self.paddle_graph.add_layer(
"paddle.scale",
inputs={"x": val_c.name},
outputs=[var_beta],
scale=beta)
add_inputs = {"x": val_mm, "y": var_beta}
self.paddle_graph.add_layer(
"paddle.add",
inputs=add_inputs,
outputs=[node.name])
@print_mapping_info
def Sum(self, node):
val_inps = node.layer.input
inputs_dict = {
"x": self.graph.get_input_node(
node, idx=0, copy=True).name,
"y": self.graph.get_input_node(
node, idx=1, copy=True).name,
}
self.paddle_graph.add_layer("paddle.add",
inputs=inputs_dict,
outputs=[node.name])
for idx, ipt in enumerate(val_inps[2:]):
y = self.graph.get_input_node(node, idx=idx, copy=True)
inputs_dict = {
"x": node.name,
"y": y.name,
}
self.paddle_graph.add_layer(
"paddle.add",
inputs=inputs_dict,
outputs=[node.name])
@print_mapping_info
def MatMul(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_y = self.graph.get_input_node(node, idx=1, copy=True)
x_shape = val_x.out_shapes[0]
y_shape = val_y.out_shapes[0]
inputs_dict = {"x": val_x.name,
"y": val_y.name}
if y_shape[0] == 1 and x_shape[-1] != 1 and x_shape[0] != 1:
y_squeeze = val_y.name + '_squeeze'
self.paddle_graph.add_layer(
"paddle.squeeze",
inputs={"x": val_y.name},
outputs=[y_squeeze],
axis=[0])
inputs_dict['y'] = y_squeeze
self.paddle_graph.add_layer(
"paddle.matmul",
inputs=inputs_dict,
outputs=[node.name])
else:
self.paddle_graph.add_layer(
"paddle.matmul",
inputs=inputs_dict,
outputs=[node.name])
@print_mapping_info
def BatchNormalization(self, node):
op_name = name_generator("batchnorm", self.nn_name2id)
output_name = node.name
layer_outputs = [op_name, output_name]
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)
momentum = node.get_attr('momentum', .9)
epsilon = node.get_attr('epsilon', 1e-5)
c = val_x.out_shapes[0][1]
# Attribute: spatial is used in BatchNormalization-1,6,7
spatial = bool(node.get_attr('spatial'))
layer_attrs = {
"num_channels": c,
"momentum": momentum,
"epsilon": epsilon,
"is_test": True,
"param_attr": string(val_scale.name),
"bias_attr": string(val_b.name),
"moving_mean_name": string(val_mean.name),
"moving_variance_name": string(val_var.name),
"use_global_stats": False,
}
self.paddle_graph.add_layer(
"paddle.nn.BatchNorm",
inputs={"x": val_x.name},
outputs=layer_outputs,
**layer_attrs)
@print_mapping_info
def Transpose(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
perm = node.get_attr('perm')
self.paddle_graph.add_layer(
"paddle.transpose",
inputs={"x": val_x.name},
outputs=[node.name],
perm=perm)
@print_mapping_info
def PRelu(self, node):
op_name = name_generator("prelu", self.nn_name2id)
output_name = node.name
layer_outputs = [op_name, output_name]
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_slope = self.graph.get_input_node(node, idx=1, copy=True)
mode = 'channel'
shape_slope = val_slope.out_shapes[0]
if shape_slope == [1]:
mode = 'all'
elif len(shape_slope) > 2:
raise Exception("The 'element' mode is not supported yet!")
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.name] = slope_data
num_parameters = val_x.out_shapes[0][1]
else:
num_parameters = 1
self.paddle_graph.add_layer(
"paddle.nn.PReLU",
inputs={"x": val_x.name},
outputs=layer_outputs,
num_parameters=num_parameters,
weight_attr=string(val_slope.name))
@print_mapping_info
def Squeeze(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
axes = node.get_attr('axes')
if len(val_x.out_shapes[0]) == 1:
self.paddle_graph.add_layer(
"paddle.cast",
inputs={"x": val_x.name},
outputs=[node.name],
dtype=string(val_x.dtype))
else:
self.paddle_graph.add_layer(
"paddle.squeeze",
inputs={"x": val_x.name},
outputs=[node.name],
axis=axes)
@print_mapping_info
def Equal(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_y = self.graph.get_input_node(node, idx=1, copy=True)
self.paddle_graph.add_layer(
"paddle.equal",
inputs={'x': val_x.name,
'y': val_y.name},
outputs=[node.name])
@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)
self.paddle_graph.add_layer(
"paddle.greater_than",
inputs={'x': val_x.name,
'y': val_y.name},
outputs=node,
param_attr=None)
@print_mapping_info
def Where(self, node):
condition = self.graph.get_input_node(node, idx=0, copy=True)
val_x = self.graph.get_input_node(node, idx=1, copy=True)
val_y = self.graph.get_input_node(node, idx=2, copy=True)
not_condition = condition.name + '_not'
self.paddle_graph.add_layer(
"paddle.logical_not",
inputs={"x": condition.name},
outputs=[not_condition])
cast_not_condition = not_condition + '_cast'
self.paddle_graph.add_layer(
"paddle.cast",
inputs={"x": not_condition},
outputs=[cast_not_condition],
dtype=string(val_x.dtype))
cast_condition = condition.name + '_cast'
self.paddle_graph.add_layer(
"paddle.cast",
inputs={"x": condition.name},
outputs=[cast_condition],
dtype=string(val_x.dtype))
mul_val_x = val_x.name + '_mul'
self.paddle_graph.add_layer(
"paddle.multiply",
inputs={'x': val_x.name,
'y': cast_condition},
outputs=[mul_val_x])
mul_val_y = val_y.name + '_mul'
self.paddle_graph.add_layer(
"paddle.multiply",
inputs={'x': val_y.name,
'y': cast_not_condition},
outputs=[mul_val_y])
self.paddle_graph.add_layer(
"paddle.add",
inputs={'x': mul_val_x,
'y': mul_val_y},
outputs=[node.name])
@print_mapping_info
def NonZero(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_x_dim = len(val_x.out_shapes[0])
if val_x_dim == 1:
self.paddle_graph.add_layer(
"paddle.nonzero",
inputs={"x": val_x.name},
outputs=[val_x.name])
self.paddle_graph.add_layer(
"paddle.transpose",
inputs={"x": val_x.name},
outputs=[node.layer_naem],
perm=[1, 0])
if val_x_dim > 1:
self.paddle_graph.add_layer(
"paddle.nonzero",
inputs={"x": val_x.name},
outputs=[val_x.name])
self.paddle_graph.add_layer(
"paddle.split",
inputs={"x": val_x.name},
outputs=[val_x.name],
num_or_sections=1,
axis=val_x_dim)
self.paddle_graph.add_layer(
"paddle.concat",
inputs={"x": val_x.name},
outputs=[node.name])
@print_mapping_info
def Identity(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
self.paddle_graph.add_layer(
"paddle.assign",
inputs={"x": val_x.name},
outputs=[node.name])
@print_mapping_info
def Tile(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_repeats = self.graph.get_input_node(node, idx=1, copy=True)
repeats = _const_weight_or_none(val_repeats)
if repeats is None:
repeats = val_repeats.name
if val_repeats.dtype != 'int32':
self.paddle_graph.add_layer(
"paddle.cast",
inputs={"x": repeats},
outputs=["{}.tmp".format(repeats)],
dtype=string("int32"))
repeats = "{}.tmp".format(repeats)
elif isinstance(repeats, int):
repeats = [repeats]
attr = {
'expand_times': repeats,
"name": string(node.name),
}
self.paddle_graph.add_layer(
"paddle.tile",
inputs={"x": val_x.name},
outputs=[node.name],
repeat_times=repeats)
@print_mapping_info
def MaxPool(self, node):
op_name = name_generator("pool", self.nn_name2id)
output_name = node.name
layer_outputs = [op_name, output_name]
val_x = self.graph.get_input_node(node, idx=0, copy=True)
auto_pad = node.get_attr('auto_pad', 'NOTSET')
assert node.get_attr(
"dilations") is None, 'only dilations = 0 is supported' # optional
kernel_shape = node.get_attr("kernel_shape")
poolnd = len(kernel_shape)
strides = node.get_attr("strides")
pad_mode = node.get_attr("pads")
ceil_mode = bool(node.get_attr('ceil_mode', 0)) # optional
pads = node.get_attr('pads', [0] * (poolnd * 2)) # optional
paddle_op = 'paddle.nn.MaxPool{}D'.format(poolnd)
assert 1 <= poolnd <= 3, 'only Pool1D, Pool2D and Pool3D are supported'
paddings, val_x = self._pad_if_asymmetric(node, pads, val_x)
if auto_pad == "SAME_UPPER" or auto_pad == "SAME_LOWER":
input_shape = val_x.out_shapes[0]
pad_h = _get_same_padding(input_shape[2], kernel_shape[0],
strides[0])
pad_w = _get_same_padding(input_shape[3], kernel_shape[1],
strides[1])
paddings = pad_h + pad_w
layer_attrs = {
"kernel_size": kernel_shape,
"stride": strides,
"padding": paddings,
"ceil_mode": ceil_mode,
}
self.paddle_graph.add_layer(
paddle_op,
inputs={'x': val_x if isinstance(val_x, str) else val_x.name},
outputs=layer_outputs,
**layer_attrs)
@print_mapping_info
def GlobalMaxPool(self, node):
op_name = name_generator("pool", self.nn_name2id)
output_name = node.name
layer_outputs = [op_name, output_name]
val_x = self.graph.get_input_node(node, idx=0, copy=True)
input_shape = val_x.out_shapes[0]
if len(input_shape) == 4:
poolnd = 2
elif len(input_shape) == 5:
poolnd = 3
elif len(input_shape) == 3:
poolnd = 1
paddle_op = 'paddle.nn.AdaptiveMaxPool{}D'.format(poolnd)
assert 1 <= poolnd <= 3, 'only Pool1D, Pool2D and Pool3D are supported'
output_shape = node.out_shapes[0]
self.paddle_graph.add_layer(
paddle_op,
inputs={'x': val_x.name},
outputs=layer_outputs,
output_size=output_shape[2:])
@print_mapping_info
def GlobalAveragePool(self, node):
op_name = name_generator("pool", self.nn_name2id)
output_name = node.name
layer_outputs = [op_name, output_name]
val_x = self.graph.get_input_node(node, idx=0, copy=True)
input_shape = val_x.out_shapes[0]
if len(input_shape) == 4:
poolnd = 2
elif len(input_shape) == 5:
poolnd = 3
elif len(input_shape) == 3:
poolnd = 1
paddle_op = 'paddle.nn.AdaptiveAvgPool{}D'.format(poolnd)
assert 1 <= poolnd <= 3, 'only Pool1D, Pool2D and Pool3D are supported'
output_shape = node.out_shapes[0]
self.paddle_graph.add_layer(
paddle_op,
inputs={'x': val_x.name},
outputs=layer_outputs,
output_size=output_shape[2:])
@print_mapping_info
def Conv(self, node):
op_name = name_generator("conv", self.nn_name2id)
output_name = node.name
layer_outputs = [op_name, output_name]
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_w = self.graph.get_input_node(node, idx=1, copy=True)
val_y = self.graph.get_node(node.layer.output[0], copy=True)
has_bias = len(node.layer.input) == 3
if has_bias:
val_b = self.graph.get_input_node(node, idx=2, copy=True)
auto_pad = node.get_attr('auto_pad', 'NOTSET')
kernel_shape = node.get_attr('kernel_shape')
convnd = len(kernel_shape)
assert 2 <= convnd <= 3, 'only Conv2D and Conv3D is supported'
num_out_channels = val_w.out_shapes[0][0]
num_in_channels = val_w.out_shapes[0][1]
paddle_op = 'paddle.nn.Conv{}D'.format(convnd)
num_groups = node.get_attr('group', 1)
strides = node.get_attr('strides', [1] * convnd)
dilations = node.get_attr('dilations', [1] * convnd)
pads = node.get_attr('pads', [0] * (convnd * 2))
input_shape = val_x.out_shapes[0]
paddings, val_x = self._pad_if_asymmetric(node, pads, val_x)
if auto_pad == "SAME_UPPER" or auto_pad == "SAME_LOWER":
pad_h = _get_same_padding(input_shape[2], kernel_shape[0],
strides[0])
pad_w = _get_same_padding(input_shape[3], kernel_shape[1],
strides[1])
paddings = pad_h + pad_w
layer_attrs = {
"in_channels": num_in_channels * num_groups,
"out_channels": num_out_channels,
"kernel_size": kernel_shape,
"stride": strides,
"padding": paddings,
"dilation": dilations,
"groups": num_groups,
'weight_attr': string(val_w.name),
}
if has_bias:
layer_attrs["bias_attr"] = string(val_b.name)
else:
layer_attrs["bias_attr"] = False
self.paddle_graph.add_layer(
paddle_op,
inputs={'x': val_x if isinstance(val_x, str) else val_x.name},
outputs=layer_outputs,
**layer_attrs)
@print_mapping_info
def ConvTranspose(self, node):
val_x = self.graph.get_input_node(node, idx=0, copy=True)
val_w = self.graph.get_input_node(node, idx=1, copy=True)
val_b = None
if len(node.layer.input) > 2:
val_b = self.graph.get_input_node(node, idx=2, copy=True)
auto_pad = node.get_attr('auto_pad', 'NOTSET')
out_padding = node.get_attr('output_padding', [0, 0])
kernel_shape = node.get_attr('kernel_shape')
assert kernel_shape, 'kernel_shape not inferred'
convnd = len(kernel_shape)
assert 2 <= convnd <= 3, 'only Conv2DTranspose and Conv3DTranspose supported'
num_in_channels = val_w.out_shapes[0][0]
num_out_channels = val_w.out_shapes[0][1]
paddle_op = 'paddle.nn.functional.conv{}d_transpose'.format(convnd)
num_groups = node.get_attr('group', 1)
strides = node.get_attr('strides', [1] * convnd)
dilations = node.get_attr('dilations', [1] * convnd)
output_size = node.get_attr('output_shape', [])
pads = node.get_attr('pads', [0] * (convnd * 2))
paddings, var_x = self._pad_if_asymmetric(node, pads, val_x)
output_size = [0, 0]
output_size[0] = (val_x.out_shapes[0][2] - 1
) * strides[0] - 2 * paddings[0] + dilations[0] * (
kernel_shape[0] - 1) + 1 + out_padding[0]
output_size[1] = (val_x.out_shapes[0][3] - 1
) * strides[1] - 2 * paddings[1] + dilations[1] * (
kernel_shape[1] - 1) + 1 + out_padding[1]
# layer_attrs = {
# 'in_channels': num_in_channels,
# 'out_channels': num_out_channels,
# 'output_size': output_size or None,
# 'kernel_size': kernel_shape,
# 'padding': paddings,
# 'stride': strides,
# 'dilation': dilations,
# 'groups': num_groups,
# 'weight_attr': string(val_w.name),
# 'bias_attr': None if val_b is None else string(val_b.name),
# }
# self.paddle_graph.add_layer(
# paddle_op,
# inputs={"x": val_x.name},
# outputs=layer_outputs,
# **layer_attrs)
inputs_dict = {'x': val_x if isinstance(val_x, str) else val_x.name,
"weight": val_w.name}
layer_attrs = {
"stride": strides,
"dilation": dilations,
"padding": paddings,
"groups": num_groups,
"output_size": node.out_shapes[0][2:]}
if val_b is not None:
inputs_dict["bias"] = val_b.name
else:
layer_attrs["bias"] = None
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.conv2d_transpose",
inputs=inputs_dict,
outputs=[node.name],
**layer_attrs)
......@@ -12,7 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
NO_OUTPUT_COUNT = 0
def gen_codes(code_list, indent=0):
indent_blank = " " * indent
codes = []
......@@ -24,43 +25,61 @@ def gen_codes(code_list, indent=0):
return codes
def get_value(layer, key):
def get_value(layer, key, layer_id=None, different_attrs=None):
""" 进行optimizer后可能把inputs的value直接用数值代替(ConstantFuser),
会把input换成attr,所以需要此处的操作。
"""
if key in layer.inputs:
return layer.inputs[key]
else:
return str(layer.attrs[key])
def prim_add(layer, indent=1, init_func=[], forward_func=[]):
if different_attrs is None:
return str(layer.attrs[key])
else:
key_name = "{}_{}".format(layer.outputs[0], key)
if key_name in different_attrs:
return key_name
else:
if layer_id is None:
return str(layer.attrs[key])
key_name = "{}_{}".format("layer_id/{}".format(layer_id), key)
if key_name in different_attrs:
new_key_name = "attr_{}".format(NO_OUTPUT_COUNT)
NO_OUTPUT_COUNT += 1
diff_index = different_attrs.index(key_name)
different_attrs[diff_index] = new_key_name
return new_key_name
else:
return str(layer.attrs[key])
def prim_add(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} + {}".format(layer.outputs[0],
get_value(layer, "x"), get_value(layer, "y"))
get_value(layer, "x", different_attrs), get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_add_(layer, indent=1, init_func=[], forward_func=[]):
def prim_add_(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} + {} * {}".format(layer.outputs[0],
get_value(layer, "x"),
get_value(layer, "x", different_attrs),
layer.attrs["alpha"],
get_value(layer, "y"))
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_and(layer, indent=1, init_func=[], forward_func=[]):
def prim_and(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} and {}".format(layer.outputs[0],
get_value(layer, "x"), get_value(layer, "y"))
get_value(layer, "x", different_attrs), get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_append(layer, indent=1, init_func=[], forward_func=[]):
def prim_append(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{}.append({})".format(
get_value(layer, "list"), get_value(layer, "element"))
get_value(layer, "list", layer_id, different_attrs),
get_value(layer, "element", layer_id, different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_assert(layer, indent=1, init_func=[], forward_func=[]):
def prim_assert(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
if layer.attrs["type"] == "eq":
values = get_value(layer, "key")
if "value" in layer.attrs:
......@@ -83,88 +102,104 @@ def prim_assert(layer, indent=1, init_func=[], forward_func=[]):
forward_func.extend(gen_codes([line], indent=indent))
def prim_check_dim(layer, indent=1, init_func=[], forward_func=[]):
def prim_check_dim(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
lines = []
lines.append("if {} < 0:".format(get_value(layer, "dim")))
dim = get_value(layer, "dim", different_attrs)
lines.append("if {} < 0:".format(dim))
lines.append(" {} = {} + {}".format(layer.outputs[
0], get_value(layer, "dim"), get_value(layer, "len")))
0], dim, get_value(layer, "len", different_attrs)))
lines.append("else:")
lines.append(" {} = {}".format(layer.outputs[0], get_value(layer,
"dim")))
lines.append(" {} = {}".format(layer.outputs[0], dim))
forward_func.extend(gen_codes(lines, indent=indent))
def prim_constant(layer, indent=1, init_func=[], forward_func=[]):
def prim_constant(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {}".format(layer.outputs[0], layer.attrs["value"])
forward_func.extend(gen_codes([line], indent=indent))
def prim_contain(layer, indent=1, init_func=[], forward_func=[]):
def prim_contain(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} in {}".format(layer.outputs[0],
get_value(layer, "element"),
get_value(layer, "input"))
get_value(layer, "element", different_attrs),
get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_dict(layer, indent=1, init_func=[], forward_func=[]):
def prim_dict(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = dict()".format(layer.outputs[0])
forward_func.extend(gen_codes([line], indent=indent))
def prim_dict_construct(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
lines = list()
line = "{} = dict()".format(layer.outputs[0])
lines.append(line)
for i in range(len(layer.inputs)):
line = "{}[{}] = {}".format(layer.outputs[0],
get_value(layer, "key{}".format(i), different_attrs),
get_value(layer, "value{}".format(i), different_attrs))
lines.append(line)
forward_func.extend(gen_codes(lines, indent=indent))
def prim_div(layer, indent=1, init_func=[], forward_func=[]):
def prim_div(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} / {}".format(layer.outputs[0],
get_value(layer, "x"), get_value(layer, "y"))
get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_eq(layer, indent=1, init_func=[], forward_func=[]):
def prim_eq(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} == {}".format(layer.outputs[0],
get_value(layer, "x"), get_value(layer, "y"))
get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_equal(layer, indent=1, init_func=[], forward_func=[]):
line = "{} = {}".format(layer.outputs[0], get_value(layer, "input"))
def prim_equal(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {}".format(layer.outputs[0], get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_exception(layer, indent=1, init_func=[], forward_func=[]):
line = "raise RaiseException({})".format(get_value(layer, "input"))
def prim_exception(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "raise RaiseException({})".format(get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_float(layer, indent=1, init_func=[], forward_func=[]):
line = "{} = float({})".format(layer.outputs[0], get_value(layer, "input"))
def prim_float(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = float({})".format(layer.outputs[0], get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_floor(layer, indent=1, init_func=[], forward_func=[]):
def prim_floor(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = math.floor({})".format(layer.outputs[0],
get_value(layer, "input"))
get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_floordiv(layer, indent=1, init_func=[], forward_func=[]):
def prim_floordiv(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} // {}".format(layer.outputs[0],
get_value(layer, "x"), get_value(layer, "y"))
get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_getitem(layer, indent=1, init_func=[], forward_func=[]):
def prim_getitem(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {}[{}]".format(layer.outputs[0],
get_value(layer, "list"),
get_value(layer, "index"))
get_value(layer, "list", different_attrs),
get_value(layer, "index", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_gt(layer, indent=1, init_func=[], forward_func=[]):
def prim_gt(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} > {}".format(layer.outputs[0],
get_value(layer, "x"), get_value(layer, "y"))
get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_if(layer, indent=1, init_func=[], forward_func=[]):
line = "if {} :".format(get_value(layer, "input"))
def prim_if(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "if {} :".format(get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
block = layer.blocks[0]
b_init_lines, b_forward_lines = block.gen_dygraph_code(indent=indent + 1)
......@@ -181,73 +216,76 @@ def prim_if(layer, indent=1, init_func=[], forward_func=[]):
forward_func.extend(b_forward_lines)
def prim_int(layer, indent=1, init_func=[], forward_func=[]):
line = "{} = int({})".format(layer.outputs[0], get_value(layer, "input"))
def prim_int(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = int({})".format(layer.outputs[0], get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_is(layer, indent=1, init_func=[], forward_func=[]):
def prim_is(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} is {}".format(layer.outputs[0],
get_value(layer, "x"), get_value(layer, "y"))
get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_isinstance(layer, indent=1, init_func=[], forward_func=[]):
def prim_isinstance(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = isinstance({}, {})".format(layer.outputs[0],
get_value(layer, "input"),
get_value(layer, "input", different_attrs),
layer.attrs["cls"])
forward_func.extend(gen_codes([line], indent=indent))
def prim_isnot(layer, indent=1, init_func=[], forward_func=[]):
def prim_isnot(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} is not {}".format(layer.outputs[0],
get_value(layer, "x"),
get_value(layer, "y"))
get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_le(layer, indent=1, init_func=[], forward_func=[]):
def prim_le(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} <= {}".format(layer.outputs[0],
get_value(layer, "x"), get_value(layer, "y"))
get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_len(layer, indent=1, init_func=[], forward_func=[]):
line = "{} = len({})".format(layer.outputs[0], get_value(layer, "input"))
def prim_len(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = len({})".format(layer.outputs[0], get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_len2list(layer, indent=1, init_func=[], forward_func=[]):
def prim_len2list(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
lines = []
lines.append("{} = []".format(layer.outputs[0]))
lines.append("for i in range({}):".format(get_value(layer, "len")))
lines.append("for i in range({}):".format(get_value(layer, "len", different_attrs)))
lines.append(" {}.append(i)".format(layer.outputs[0]))
forward_func.extend(gen_codes(lines, indent=indent))
def prim_lt(layer, indent=1, init_func=[], forward_func=[]):
def prim_lt(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} < {}".format(layer.outputs[0],
get_value(layer, "x"), get_value(layer, "y"))
get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_list(layer, indent=1, init_func=[], forward_func=[]):
def prim_list(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
input_len = len(layer.inputs) + len(layer.attrs)
inputs_list = list()
for i in range(input_len):
inputs_list.append(get_value(layer, "input{}".format(i)))
inputs_list.append(get_value(layer, "input{}".format(i), different_attrs))
inputs_str = ', '.join(inputs_list)
line = "{} = [{}]".format(layer.outputs[0], inputs_str)
forward_func.extend(gen_codes([line], indent=indent))
def prim_list_unpack(layer, indent=1, init_func=[], forward_func=[]):
line = "{} = {}".format(", ".join(layer.outputs), get_value(layer, "input"))
def prim_list_unpack(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {}".format(", ".join(layer.outputs), get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_loop(layer, indent=1, init_func=[], forward_func=[]):
loop_range = get_value(layer, "input")
def prim_loop(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
loop_range = get_value(layer, "input", different_attrs)
line = "for {} in range({}):".format(layer.outputs[1], loop_range)
forward_func.extend(gen_codes([line], indent=indent))
block = layer.blocks[0]
......@@ -256,137 +294,142 @@ def prim_loop(layer, indent=1, init_func=[], forward_func=[]):
forward_func.extend(b_forward_lines)
def prim_min(layer, indent=1, init_func=[], forward_func=[]):
line = "{} = min({})".format(layer.outputs[0], get_value(layer, "input"))
def prim_min(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = min({})".format(layer.outputs[0], get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_mul(layer, indent=1, init_func=[], forward_func=[]):
def prim_mul(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} * {}".format(layer.outputs[0],
get_value(layer, "x"), get_value(layer, "y"))
get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_ne(layer, indent=1, init_func=[], forward_func=[]):
def prim_ne(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} != {}".format(layer.outputs[0],
get_value(layer, "x"), get_value(layer, "y"))
get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_neg(layer, indent=1, init_func=[], forward_func=[]):
line = "{} = -{}".format(layer.outputs[0], get_value(layer, "input"))
def prim_neg(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = -{}".format(layer.outputs[0], get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_not(layer, indent=1, init_func=[], forward_func=[]):
line = "{} = not {}".format(layer.outputs[0], get_value(layer, "input"))
def prim_not(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = not {}".format(layer.outputs[0], get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_or(layer, indent=1, init_func=[], forward_func=[]):
def prim_or(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} or {}".format(layer.outputs[0],
get_value(layer, "x"), get_value(layer, "y"))
get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_replaceitem(layer, indent=1, init_func=[], forward_func=[]):
def prim_replaceitem(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{}[{}] = {}".format(
get_value(layer, "list"),
get_value(layer, "index"), get_value(layer, "item"))
get_value(layer, "list", layer_id, different_attrs),
get_value(layer, "index", layer_id, different_attrs),
get_value(layer, "item", layer_id, different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_requires_grad(layer, indent=1, init_func=[], forward_func=[]):
def prim_requires_grad(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = not {}.stop_gradient".format(layer.outputs[0],
get_value(layer, "input"))
get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_rsub(layer, indent=1, init_func=[], forward_func=[]):
def prim_rsub(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} - {} * {}".format(layer.outputs[0],
get_value(layer, "y"),
get_value(layer, "x"),
get_value(layer, "alpha"))
get_value(layer, "y", different_attrs),
get_value(layer, "x", different_attrs),
get_value(layer, "alpha", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_select(layer, indent=1, init_func=[], forward_func=[]):
line = "{} = {}[".format(layer.outputs[0], get_value(layer, "input"))
def prim_select(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {}[".format(layer.outputs[0], get_value(layer, "input", different_attrs))
for dim in range(layer.attrs["dim"]):
line += ":, "
line += (get_value(layer, "index") + "]")
line += (get_value(layer, "index", different_attrs) + "]")
forward_func.extend(gen_codes([line], indent=indent))
def prim_set_attr(layer, indent=1, init_func=[], forward_func=[]):
line = "{} = {}".format(layer.outputs[0], get_value(layer, "input"))
def prim_set_attr(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {}".format(layer.outputs[0], get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_set_item(layer, indent=1, init_func=[], forward_func=[]):
def prim_set_item(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{}[{}] = {}".format(
get_value(layer, "dict"),
get_value(layer, "key"), get_value(layer, "value"))
get_value(layer, "dict", different_attrs),
get_value(layer, "key", different_attrs), get_value(layer, "value", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_shape_dim(layer, indent=1, init_func=[], forward_func=[]):
def prim_shape_dim(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = fluid.layers.shape({})[{}]".format(layer.outputs[0],
get_value(layer, "input"),
get_value(layer, "dim"))
get_value(layer, "input", different_attrs),
get_value(layer, "dim", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_slice(layer, indent=1, init_func=[], forward_func=[]):
def prim_slice(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {}[{}: {}: {}]".format(layer.outputs[0],
get_value(layer, "input"),
get_value(layer, "start"),
get_value(layer, "end"),
get_value(layer, "step"))
get_value(layer, "input", different_attrs),
get_value(layer, "start", different_attrs),
get_value(layer, "end", different_attrs),
get_value(layer, "step", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_str(layer, indent=1, init_func=[], forward_func=[]):
line = "{} = str({})".format(layer.outputs[0], get_value(layer, "input"))
def prim_str(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = str({})".format(layer.outputs[0], get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_sub(layer, indent=1, init_func=[], forward_func=[]):
def prim_sub(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} - {}".format(layer.outputs[0],
get_value(layer, "x"), get_value(layer, "y"))
get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_tuple(layer, indent=1, init_func=[], forward_func=[]):
def prim_tuple(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
input_len = len(layer.inputs) + len(layer.attrs)
inputs_list = list()
for i in range(input_len):
inputs_list.append(get_value(layer, "input{}".format(i)))
inputs_list.append(get_value(layer, "input{}".format(i), different_attrs))
inputs_str = ', '.join(inputs_list)
line = "{} = ({})".format(layer.outputs[0], inputs_str)
forward_func.extend(gen_codes([line], indent=indent))
def prim_tuple_unpack(layer, indent=1, init_func=[], forward_func=[]):
def prim_tuple_unpack(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
outputs_str = ', '.join(layer.outputs)
line = "{} = {}".format(outputs_str, get_value(layer, "input"))
line = "{} = {}".format(outputs_str, get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_type(layer, indent=1, init_func=[], forward_func=[]):
line = "{} = {}.dtype".format(layer.outputs[0], get_value(layer, "input"))
def prim_type(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {}.dtype".format(layer.outputs[0], get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_var2list(layer, indent=1, init_func=[], forward_func=[]):
def prim_var2list(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {}.numpy().tolist()".format(layer.outputs[0],
get_value(layer, "input"))
get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_warnings(layer, indent=1, init_func=[], forward_func=[]):
def prim_warnings(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
lines = ["import warnings"]
line = "warnings.warn({}, stacklevel={})".format(
get_value(layer, "input"), layer.attrs["stacklevel"])
get_value(layer, "input", different_attrs), layer.attrs["stacklevel"])
lines.append(line)
forward_func.extend(gen_codes(lines, indent=indent))
# -*- coding:UTF-8 -*-
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"
......@@ -12,6 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import copy
import numpy as np
from x2paddle.core.util import *
from x2paddle.core.program import PaddleGraph
......@@ -37,6 +40,7 @@ def aten_abs(mapper, graph, node):
%n0.3 (Tensor): 绝对值后的Tensor。
%n.3 (Tensor): 绝对值前的Tensor。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -44,13 +48,13 @@ def aten_abs(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%n.3
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer(
"paddle.fluid.layers.abs", inputs=layer_inputs, outputs=layer_outputs)
"paddle.abs", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -64,33 +68,40 @@ def aten_adaptive_avg_pool2d(mapper, graph, node):
%x.3 (Tensor): 输入Tensor。
%_output_size.1 (list): 自适应池化后的Tensor的宽、高大小。
"""
scope_name = mapper.normalize_scope_name(node)
op_name = name_generator("pool2d", mapper.nn_name2id)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_outputs = [op_name, output_name]
layer_inputs = {}
layer_attrs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%x.3
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
layer_inputs["input"] = inputs_name[0]
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
# 处理输入1,即%_output_size.1
if inputs_name[1] in mapper.attrs:
layer_attrs["pool_size"] = mapper.attrs[inputs_name[1]]
layer_attrs["output_size"] = mapper.attrs[inputs_name[1]]
graph.add_layer(
"paddle.nn.AdaptiveAvgPool2D",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
else:
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs)
layer_inputs["pool_size"] = inputs_name[1]
current_outputs, scope_name)
layer_inputs["output_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)
graph.add_layer(
"paddle.nn.functional.adaptive_avg_pool2d",
inputs=layer_inputs,
outputs=layer_outputs[1:],
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -107,6 +118,7 @@ def aten_addmm(mapper, graph, node):
%151 (int/float): 输入alpha。
%152 (int/float): 输入beta。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -116,13 +128,13 @@ def aten_addmm(mapper, graph, node):
current_outputs = [output_name]
# 处理输入0,即%150
mapper._check_input(
graph, inputs_node[0], inputs_name[0], current_outputs, add_dim=True)
graph, inputs_node[0], inputs_name[0], current_outputs, scope_name, add_dim=True)
layer_inputs["input"] = inputs_name[0]
# 处理输入1,即%input.3
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[1]
# 处理输入2,即%156
mapper._check_input(graph, inputs_node[2], inputs_name[2], current_outputs)
mapper._check_input(graph, inputs_node[2], inputs_name[2], current_outputs, scope_name)
layer_inputs["y"] = inputs_name[2]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
......@@ -131,7 +143,7 @@ def aten_addmm(mapper, graph, node):
layer_attrs["beta"] = mapper.attrs[inputs_name[3]]
else:
mapper._check_input(graph, inputs_node[3], inputs_name[3],
current_outputs)
current_outputs, scope_name)
layer_inputs["beta"] = inputs_name[3]
current_inputs.append(inputs_name[3])
# 处理输入4,即%151
......@@ -139,7 +151,7 @@ def aten_addmm(mapper, graph, node):
layer_attrs["alpha"] = mapper.attrs[inputs_name[4]]
else:
mapper._check_input(graph, inputs_node[4], inputs_name[4],
current_outputs)
current_outputs, scope_name)
layer_inputs["alpha"] = inputs_name[4]
current_inputs.append(inputs_name[4])
......@@ -147,6 +159,7 @@ def aten_addmm(mapper, graph, node):
"paddle.addmm",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -161,6 +174,7 @@ def aten_add(mapper, graph, node):
%i.12 (-): 输入数值 x。
%288 (-): 输入数值 y。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -168,16 +182,16 @@ def aten_add(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%i.12
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 处理输入1,即%288
mapper._check_input(
graph, inputs_node[1], inputs_name[1], current_outputs, add_dim=True)
graph, inputs_node[1], inputs_name[1], current_outputs, scope_name, add_dim=True)
layer_inputs["y"] = inputs_name[1]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.add", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.add", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -192,6 +206,7 @@ def aten_add_(mapper, graph, node):
%150 (Tensor): 输入Tensor y。
%151 (int/float): 输入alpha。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -200,11 +215,11 @@ def aten_add_(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%output.2
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 处理输入1,即%150
mapper._check_input(
graph, inputs_node[1], inputs_name[1], current_outputs, add_dim=True)
graph, inputs_node[1], inputs_name[1], current_outputs, scope_name, add_dim=True)
layer_inputs["y"] = inputs_name[1]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
......@@ -213,12 +228,12 @@ def aten_add_(mapper, graph, node):
layer_attrs["alpha"] = mapper.attrs[inputs_name[2]]
else:
mapper._check_input(graph, inputs_node[2], inputs_name[2],
current_outputs)
current_outputs, scope_name)
layer_inputs["alpha"] = inputs_name[2]
current_inputs.append(inputs_name[2])
graph.add_layer(
"prim.add_", inputs=layer_inputs, outputs=layer_outputs, **layer_attrs)
"prim.add_", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name, **layer_attrs)
return current_inputs, current_outputs
......@@ -232,6 +247,7 @@ def aten___and__(mapper, graph, node):
%360 (-): 输入 x。
%358 (-): 输入 y。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -239,15 +255,15 @@ def aten___and__(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%i.12
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 处理输入1,即%288
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
layer_inputs["y"] = inputs_name[1]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.and", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.and", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -261,21 +277,22 @@ def aten_append(mapper, graph, node):
%_output_size.1 (list): 需要进行append的list。
%v.1 (-): append的元素。
"""
scope_name = mapper.normalize_scope_name(node)
layer_inputs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
layer_outputs = [inputs_name[0]]
# 获取当前节点输出的list
current_outputs = [inputs_name[0]]
# 处理输入0,即_output_size.1
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["list"] = inputs_name[0]
# 处理输入1,即v.1
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
layer_inputs["element"] = inputs_name[1]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.append", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.append", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -285,6 +302,7 @@ def aten_arange(mapper, graph, node):
TorchScript示例:
有三种情况,分别处理。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -301,7 +319,7 @@ def aten_arange(mapper, graph, node):
layer_attrs["end"] = mapper.attrs[inputs_name[0]]
else:
mapper._check_input(graph, inputs_node[0], inputs_name[0],
current_outputs)
current_outputs, scope_name)
layer_inputs["end"] = inputs_name[0]
current_inputs.append(inputs_name[0])
# 处理输入1,即%43,代表dtype
......@@ -317,7 +335,7 @@ def aten_arange(mapper, graph, node):
layer_attrs["start"] = mapper.attrs[inputs_name[0]]
else:
mapper._check_input(graph, inputs_node[0], inputs_name[0],
current_outputs)
current_outputs, scope_name)
layer_inputs["start"] = inputs_name[0]
current_inputs.append(inputs_name[0])
# 处理输入1,即%52,代表end
......@@ -325,7 +343,7 @@ def aten_arange(mapper, graph, node):
layer_attrs["end"] = mapper.attrs[inputs_name[1]]
else:
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs)
current_outputs, scope_name)
layer_inputs["end"] = inputs_name[1]
current_inputs.append(inputs_name[1])
# 处理输入2,即%43,代表dtype
......@@ -341,7 +359,7 @@ def aten_arange(mapper, graph, node):
layer_attrs["start"] = mapper.attrs[inputs_name[0]]
else:
mapper._check_input(graph, inputs_node[0], inputs_name[0],
current_outputs)
current_outputs, scope_name)
layer_inputs["start"] = inputs_name[0]
current_inputs.append(inputs_name[0])
# 处理输入1,即%52,代表end
......@@ -349,7 +367,7 @@ def aten_arange(mapper, graph, node):
layer_attrs["end"] = mapper.attrs[inputs_name[1]]
else:
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs)
current_outputs, scope_name)
layer_inputs["end"] = inputs_name[1]
current_inputs.append(inputs_name[1])
# 处理输入2,即%53,代表step
......@@ -357,7 +375,7 @@ def aten_arange(mapper, graph, node):
layer_attrs["step"] = mapper.attrs[inputs_name[2]]
else:
mapper._check_input(graph, inputs_node[2], inputs_name[2],
current_outputs)
current_outputs, scope_name)
layer_inputs["step"] = inputs_name[2]
current_inputs.append(inputs_name[2])
# 处理输入3,即%43,代表dtype
......@@ -373,6 +391,7 @@ def aten_arange(mapper, graph, node):
"paddle.arange",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -392,20 +411,84 @@ def aten_avg_pool2d(mapper, graph, node):
%272 (bool): 是否在平均池化模式不忽略填充值,False为忽略。
%271 (int): 如果指定,它将用作除数,否则将使用池化区域的大小。
"""
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"])
scope_name = mapper.normalize_scope_name(node)
op_name = name_generator("pool2d", mapper.nn_name2id)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [op_name, output_name]
layer_inputs = {}
layer_attrs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%x.34
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
# 处理输入1,即%538
layer_attrs["pool_size"] = mapper.attrs[inputs_name[1]]
# 处理输入2,即%539
layer_attrs["pool_stride"] = mapper.attrs[inputs_name[2]]
# 处理输入3,即%540
layer_attrs["pool_padding"] = mapper.attrs[inputs_name[3]]
# 处理输入4,即%273
layer_attrs["ceil_mode"] = mapper.attrs[inputs_name[4]]
# 处理输入5,即%272
layer_attrs["exclusive"] = not mapper.attrs[inputs_name[5]]
# 处理输入6,即%271
graph.add_layer(
"prim.assert",
inputs={},
outputs=[inputs_name[6] + "_assert"],
scope_name=scope_name if scope_name == "" else scope_name + "_assert",
type="eq",
key=mapper.attrs[inputs_name[6]],
value=None)
# TODO(syf): The op has diff.
# self.paddle_graph.add_layer(
# kernel="paddle.nn.AvgPool2D",
# inputs={"input": input_name},
# outputs=layer_outputs,
# kernel_size=k_size[2:4],
# stride=strides[2:4],
# padding=string(pad_mode))
layer_attrs["pool_type"] = string("avg")
graph.add_layer(
"fluid.layers.pool2d",
inputs=layer_inputs,
outputs=layer_outputs[1:],
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
def aten_avg_pool3d(mapper, graph, node):
""" 构造最大池化的PaddleLayer。
TorchScript示例:
%branch_pool.2 : Tensor = aten::avg_pool2d(%x.43, %538, %539, %540, %273, %272, %271)
参数含义:
%branch_pool.2 (Tensor): 输出,池化后的结果。
%x.43 (Tensor): 需要池化的Tensor。
%538 (list): 池化kernel的大小。
%539 (list): 步长大小。
%540 (list): 填充大小。
%273 (bool): 是否用ceil函数计算输出高度和宽度。
%272 (bool): 是否在平均池化模式不忽略填充值,False为忽略。
%271 (int): 如果指定,它将用作除数,否则将使用池化区域的大小。
"""
scope_name = mapper.normalize_scope_name(node)
op_name = name_generator("pool2d", mapper.nn_name2id)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [pool_name, output_name]
layer_outputs = [op_name, output_name]
layer_inputs = {}
layer_attrs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%x.34
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
......@@ -424,15 +507,94 @@ def aten_avg_pool2d(mapper, graph, node):
"prim.assert",
inputs={},
outputs=[inputs_name[6] + "_assert"],
scope_name=scope_name if scope_name == "" else scope_name + "_assert",
type="eq",
key=mapper.attrs[inputs_name[6]],
value=None)
# TODO(syf): The op has diff.
# self.paddle_graph.add_layer(
# kernel="paddle.nn.AvgPool2D",
# inputs={"input": input_name},
# outputs=layer_outputs,
# kernel_size=k_size[2:4],
# stride=strides[2:4],
# padding=string(pad_mode))
layer_attrs["pool_type"] = string("avg")
graph.add_layer(
"fluid.layers.pool3d",
inputs=layer_inputs,
outputs=layer_outputs[1:],
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
def aten_avg_pool1d(mapper, graph, node):
""" 构造最大池化的PaddleLayer。
TorchScript示例:
%branch_pool.2 : Tensor = aten::avg_pool1d(%x.43, %538, %539, %540, %273, %272, %271)
参数含义:
%branch_pool.2 (Tensor): 输出,池化后的结果。
%x.43 (Tensor): 需要池化的Tensor。
%538 (list): 池化kernel的大小。
%539 (list): 步长大小。
%540 (list): 填充大小。
%273 (bool): 是否用ceil函数计算输出高度和宽度。
%272 (bool): 是否在平均池化模式不忽略填充值,False为忽略。
%271 (int): 如果指定,它将用作除数,否则将使用池化区域的大小。
"""
scope_name = mapper.normalize_scope_name(node)
op_name = name_generator("pool2d", mapper.nn_name2id)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [op_name, output_name]
layer_inputs = {}
layer_attrs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%x.34
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
# 处理输入1,即%538
layer_attrs["pool_size"] = mapper.attrs[inputs_name[1]]
# 处理输入2,即%539
layer_attrs["pool_stride"] = mapper.attrs[inputs_name[2]]
# 处理输入3,即%540
layer_attrs["pool_padding"] = mapper.attrs[inputs_name[3]]
# 处理输入4,即%273
layer_attrs["ceil_mode"] = mapper.attrs[inputs_name[4]]
# 处理输入5,即%272
layer_attrs["exclusive"] = not mapper.attrs[inputs_name[5]]
# 处理输入6,即%271
graph.add_layer(
"prim.assert",
inputs={},
outputs=[inputs_name[6] + "_assert"],
scope_name=scope_name if scope_name == "" else scope_name + "_assert",
type="eq",
key=mapper.attrs[inputs_name[6]],
value=None)
# TODO(syf): The op has diff.
# self.paddle_graph.add_layer(
# kernel="paddle.nn.AvgPool2D",
# inputs={"input": input_name},
# outputs=layer_outputs,
# kernel_size=k_size[2:4],
# stride=strides[2:4],
# padding=string(pad_mode))
layer_attrs["pool_type"] = string("avg")
graph.add_layer(
"paddle.nn.Pool2D",
"fluid.layers.pool1d",
inputs=layer_inputs,
outputs=layer_outputs,
outputs=layer_outputs[1:],
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -455,13 +617,10 @@ def aten_batch_norm(mapper, graph, node):
%766 (float): 为了数值稳定加在分母上的值。
%781 (bool): 是否启用cudnn。
"""
if "batchnorm" in mapper.dygraph_name_id:
mapper.dygraph_name_id["batchnorm"] += 1
else:
mapper.dygraph_name_id["batchnorm"] = 0
batchnorm_name = "batchnorm" + str(mapper.dygraph_name_id["batchnorm"])
scope_name = mapper.normalize_scope_name(node)
op_name = name_generator("batchnorm", mapper.nn_name2id)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [batchnorm_name, output_name]
layer_outputs = [op_name, output_name]
layer_inputs = {}
layer_attrs = {}
layer_attrs["is_test"] = True
......@@ -469,27 +628,27 @@ def aten_batch_norm(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%input.80
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入、输出的list
current_inputs = list(layer_inputs.values())
# 处理输入1,即%778
weights = mapper.pytorch_params[inputs_name[1]]
mapper.paddle_params[batchnorm_name + ".weight"] = weights
mapper.paddle_params[op_name + ".weight"] = weights
layer_attrs['num_channels'] = weights.shape[0]
# 处理输入2,即%779
if inputs_name[2] in mapper.pytorch_params:
bias = mapper.pytorch_params[inputs_name[2]]
if bias is not None:
mapper.paddle_params[batchnorm_name + ".bias"] = bias
mapper.paddle_params[op_name + ".bias"] = bias
else:
mapper.paddle_params[batchnorm_name + ".bias"] = False
mapper.paddle_params[op_name + ".bias"] = False
# 处理输入3,即%776
mean = mapper.pytorch_params[inputs_name[3]]
mapper.paddle_params[batchnorm_name + "._mean"] = mean
mapper.paddle_params[op_name + "._mean"] = mean
# 处理输入4,即%777
var = mapper.pytorch_params[inputs_name[4]]
mapper.paddle_params[batchnorm_name + "._variance"] = var
mapper.paddle_params[op_name + "._variance"] = var
# 处理输入6,即%exponential_average_factor.23
layer_attrs["momentum"] = mapper.attrs[inputs_name[6]]
# 处理输入7,即%766
......@@ -499,6 +658,7 @@ def aten_batch_norm(mapper, graph, node):
"paddle.nn.BatchNorm",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -513,6 +673,7 @@ def aten_cat(mapper, graph, node):
%i.12 (list): 需要连接的Tensor组成的list。
%7 (int): 连接的轴。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -521,8 +682,8 @@ def aten_cat(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%13
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
layer_inputs["input"] = inputs_name[0]
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
# 处理输入1,即%12
......@@ -530,13 +691,14 @@ def aten_cat(mapper, graph, node):
layer_attrs["axis"] = mapper.attrs[inputs_name[1]]
else:
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs)
current_outputs, scope_name)
layer_inputs["axis"] = inputs_name[1]
current_inputs.append(inputs_name[1])
graph.add_layer(
"fluid.layers.concat",
"paddle.concat",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -552,6 +714,7 @@ def aten_chunk(mapper, graph, node):
%720 (int): 分割的块数。
%719 (int): 分割的维度。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -560,8 +723,8 @@ def aten_chunk(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%input.170
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
layer_inputs["input"] = inputs_name[0]
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
# 处理输入1,即%720
......@@ -569,21 +732,72 @@ def aten_chunk(mapper, graph, node):
layer_attrs["num_or_sections"] = mapper.attrs[inputs_name[1]]
else:
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs)
current_outputs, scope_name)
layer_inputs["num_or_sections"] = inputs_name[1]
current_inputs.append(inputs_name[1])
# 处理输入2,即%719
if inputs_name[2] in mapper.attrs:
layer_attrs["dim"] = mapper.attrs[inputs_name[2]]
layer_attrs["axis"] = mapper.attrs[inputs_name[2]]
else:
mapper._check_input(graph, inputs_node[2], inputs_name[2],
current_outputs)
layer_inputs["dim"] = inputs_name[2]
current_outputs, scope_name)
layer_inputs["axis"] = inputs_name[2]
current_inputs.append(inputs_name[2])
graph.add_layer(
"fluid.layers.split",
"paddle.split",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
def aten_clamp(mapper, graph, node):
""" 构造元素剪裁的PaddleLayer。
TorchScript示例:
%56 : Tensor = aten::clamp(%input.1, %46, %48, %49)
参数含义:
%56 (Tensor): 输出,累加后的结果。
%input.1 (Tensor): 输入,需要剪裁的Tensor。
%46 (float/Tensor): 最小值。
%48 (float/Tensor): 最大值。
"""
scope_name = mapper.normalize_scope_name(node)
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)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%input.1
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入、输出的list
current_inputs = list(layer_inputs.values())
# 处理输入1,即%46
if inputs_name[1] in mapper.attrs:
layer_attrs["min"] = mapper.attrs[inputs_name[1]]
else:
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs, scope_name)
layer_inputs["min"] = inputs_name[1]
current_inputs.append(inputs_name[1])
# 处理输入2,即%48,代表dtype
if inputs_name[2] in mapper.attrs:
layer_attrs["max"] = mapper.attrs[inputs_name[2]]
else:
mapper._check_input(graph, inputs_node[2], inputs_name[2],
current_outputs, scope_name)
layer_inputs["max"] = inputs_name[2]
current_inputs.append(inputs_name[2])
graph.add_layer(
"paddle.clip",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -598,6 +812,7 @@ def aten___contains__(mapper, graph, node):
%50 (-): 需对比的输入1。
%name.1 (-): 需对比的输入2。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -605,15 +820,15 @@ def aten___contains__(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%50
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 处理输入1,即%name.1
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
layer_inputs["element"] = inputs_name[1]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.contain", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.contain", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -628,21 +843,17 @@ def aten_constant_pad_nd(mapper, graph, node):
%4876 (list): 填充大小。
%42 (-): 填充值。
"""
if "constant_pad" in mapper.dygraph_name_id:
mapper.dygraph_name_id["constant_pad"] += 1
else:
mapper.dygraph_name_id["constant_pad"] = 0
constant_pad_name = "constant_pad" + str(mapper.dygraph_name_id[
"constant_pad"])
scope_name = mapper.normalize_scope_name(node)
op_name = name_generator("pad", mapper.nn_name2id)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [constant_pad_name, output_name]
layer_outputs = [op_name, output_name]
layer_inputs = {}
layer_attrs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%input1.24
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
......@@ -652,64 +863,73 @@ def aten_constant_pad_nd(mapper, graph, node):
layer_attrs["value"] = mapper.attrs[inputs_name[2]]
graph.add_layer(
"fluid.layers.shape",
"prim.shape",
inputs={"input": inputs_name[0]},
outputs=[inputs_name[0] + "_shape"])
outputs=[inputs_name[0] + "_shape"],
scope_name=scope_name)
graph.add_layer(
"prim.len",
inputs={"input": inputs_name[0] + "_shape"},
outputs=[inputs_name[0] + "_len"])
outputs=[inputs_name[0] + "_len"],
scope_name=scope_name)
def add_pad_layers(kernel, dim):
graph.add_layer(
"prim.ne",
inputs={"x": inputs_name[0] + "_len"},
outputs=[inputs_name[0] + "_cond"],
scope_name=scope_name,
y=dim)
graph.add_layer(
"prim.if", {'input': inputs_name[0] + "_cond"},
outputs=[inputs_name[0] + "_if", output_name])
outputs=[inputs_name[0] + "_if", output_name],
scope_name=scope_name)
if_layer = graph.layers[list(graph.layers.keys())[-1]]
block = PaddleGraph(if_layer, graph_type="dygraph")
block = PaddleGraph(parent_layer=if_layer, graph_type="dygraph")
block.add_layer(
"prim.sub",
inputs={"y": inputs_name[0] + "_len"},
outputs=[inputs_name[0] + "_len0"],
scope_name=scope_name,
x=dim)
block.add_layer(
"prim.len2list",
inputs={"len": inputs_name[0] + "_len0"},
outputs=[inputs_name[0] + "_list"])
outputs=[inputs_name[0] + "_list"],
scope_name=scope_name)
block.add_layer(
"paddle.tensor.unsqueeze",
inputs={"x": inputs_name[0],
"axis": inputs_name[0] + "_list"},
outputs=[inputs_name[0] + "_var"])
outputs=[inputs_name[0] + "_var"],
scope_name=scope_name)
block.add_layer(
kernel,
inputs={"input": inputs_name[0] + "_var"},
outputs=layer_outputs,
outputs=copy.deepcopy(layer_outputs),
scope_name=scope_name,
**layer_attrs)
block.add_layer(
"paddle.tensor.squeeze",
inputs={"x": output_name,
"axis": inputs_name[0] + "_list"},
outputs=[output_name])
outputs=[output_name],
scope_name=scope_name)
if_layer.add_block(block)
block = PaddleGraph(if_layer, graph_type="dygraph")
block = PaddleGraph(parent_layer=if_layer, graph_type="dygraph")
layer_inputs["input"] = inputs_name[0]
block.add_layer(
kernel, inputs=layer_inputs, outputs=layer_outputs, **layer_attrs)
kernel, inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name, **layer_attrs)
if_layer.add_block(block)
if_layer.inputs["input-0"] = inputs_name[0]
if_layer.inputs["input-1"] = inputs_name[0] + "_len"
if len(layer_attrs["padding"]) == 2:
add_pad_layers("paddle.nn.ConstantPad1d", 3)
add_pad_layers("paddle.nn.Pad1D", 3)
elif len(layer_attrs["padding"]) == 4:
add_pad_layers("paddle.nn.ConstantPad2d", 4)
add_pad_layers("paddle.nn.Pad2D", 4)
elif len(layer_attrs["padding"]) == 6:
add_pad_layers("paddle.nn.ConstantPad3d", 5)
add_pad_layers("paddle.nn.Pad3D", 5)
else:
raise Exception("The lenght of padding list must be 2, 4 or 6!")
return current_inputs, current_outputs
......@@ -727,6 +947,7 @@ def aten_contiguous(mapper, graph, node):
【注意】Paddle中无此用法,所以此处翻译成赋值。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -735,12 +956,12 @@ def aten_contiguous(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%4058
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.equal", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.equal", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -756,36 +977,33 @@ def aten_conv2d(mapper, graph, node):
%27 (Tensor): bias。
%28 (int): 步长大小。
%29 (int): 填充大小。
%30 (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"])
scope_name = mapper.normalize_scope_name(node)
op_name = name_generator("conv2d", mapper.nn_name2id)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [conv2d_name, output_name]
layer_outputs = [op_name, output_name]
layer_inputs = {}
layer_attrs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%input.8
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
# 处理输入1,即%25
weights = mapper.pytorch_params[inputs_name[1]]
mapper.paddle_params[conv2d_name + ".weight"] = weights
mapper.paddle_params[op_name + ".weight"] = weights
layer_attrs["out_channels"] = weights.shape[0]
layer_attrs["kernel_size"] = weights.shape[2:]
# 处理输入2,即%27
if inputs_name[2] in mapper.pytorch_params:
bias = mapper.pytorch_params[inputs_name[2]]
if bias is not None:
mapper.paddle_params[conv2d_name + ".bias"] = bias
mapper.paddle_params[op_name + ".bias"] = bias
else:
layer_attrs["bias_attr"] = False
else:
......@@ -801,9 +1019,10 @@ def aten_conv2d(mapper, graph, node):
layer_attrs['in_channels'] = weights.shape[1] * mapper.attrs[inputs_name[6]]
graph.add_layer(
"paddle.nn.Conv2d",
"paddle.nn.Conv2D",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -812,63 +1031,146 @@ def aten__convolution(mapper, graph, node):
""" 构造conv2d的PaddleLayer。
TorchScript示例:
%input.10 : Tensor = aten::_convolution(%input.8, %25, %27, %28, %29, %30, %26)
%input.10 : Tensor = aten::_convolution(%input.1, %18, %10, %19, %20, %21, %13, %22, %12, %13, %13, %15)
参数含义:
%input.10 (Tensor): 输出,卷积后的结果。
%input.8 (Tensor): 需要进行卷积的特征层。
%25 (Tensor): weights。
%27 (Tensor): bias。
%28 (int): 步长大小。
%29 (int): 填充大小。
%30 (int): 膨胀系数大小。
%26 (int): 卷积的组数。
%18 (Tensor): weights。
%10 (Tensor): bias。
%19 (list): 步长大小。
%20 (list): 填充大小。
%21 (list): 空洞大小。
%13 (bool): 是否进行转置卷积。
%22 (list): 输出形状上一侧额外添加的大小。
%12 (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"])
scope_name = mapper.normalize_scope_name(node)
op_name = name_generator("conv2d", mapper.nn_name2id)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [conv2d_name, output_name]
layer_outputs = [op_name, output_name]
layer_inputs = {}
layer_attrs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%input.8
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
# 处理输入1,即%25
# 处理输入1,即%18
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
mapper.paddle_params[op_name + ".weight"] = weights #np.swapaxes(weights, 0, 1)
if mapper.attrs[inputs_name[6]]:
layer_attrs["out_channels"] = weights.shape[1]
else:
layer_attrs["out_channels"] = weights.shape[0]
layer_attrs["kernel_size"] = weights.shape[2:]
# 处理输入2,即%10
if inputs_name[2] in mapper.pytorch_params:
bias = mapper.pytorch_params[inputs_name[2]]
if bias is not None:
mapper.paddle_params[conv2d_name + ".bias"] = bias
mapper.paddle_params[op_name + ".bias"] = bias
else:
layer_attrs["bias_attr"] = False
else:
layer_attrs["bias_attr"] = False
# 处理输入3,即%28
# 处理输入3,即%19
layer_attrs["stride"] = mapper.attrs[inputs_name[3]]
# 处理输入4,即%29
# 处理输入4,即%20
layer_attrs["padding"] = mapper.attrs[inputs_name[4]]
# 处理输入5,即%30
# 处理输入5,即%21
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]]
# 处理输入6,即%13
if mapper.attrs[inputs_name[6]]:
# 处理输入7,即%22
layer_attrs["output_padding"] = mapper.attrs[inputs_name[7]]
# 处理输入8,即%12
layer_attrs["groups"] = mapper.attrs[inputs_name[8]]
if mapper.attrs[inputs_name[6]]:
layer_attrs['in_channels'] = weights.shape[0] * mapper.attrs[inputs_name[
8]]
else:
layer_attrs['in_channels'] = weights.shape[1] * mapper.attrs[inputs_name[
8]]
if mapper.attrs[inputs_name[6]]:
graph.add_layer(
"paddle.nn.Conv2DTranspose",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
else:
graph.add_layer(
"paddle.nn.Conv2D",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
def aten_conv_transpose2d(mapper, graph, node):
""" 构造conv_transpose2d的PaddleLayer。
TorchScript示例:
%input.10 : Tensor = aten::conv_transpose2d(%input.1, %18, %10, %19, %20, %21, %13, %22)
参数含义:
%input.10 (Tensor): 输出,卷积后的结果。
%input.8 (Tensor): 需要进行卷积的特征层。
%18 (Tensor): weights。
%10 (Tensor): bias。
%19 (list): 步长大小。
%20 (list): 填充大小。
%21 (int/tuple): 输出形状上一侧额外添加的大小。
%13 (int): 二维卷积层的组数。
%22 (int/tuple): 空洞大小。
"""
scope_name = mapper.normalize_scope_name(node)
op_name = name_generator("conv2d", mapper.nn_name2id)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [op_name, output_name]
layer_inputs = {}
layer_attrs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%input.8
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
# 处理输入1,即%18
weights = mapper.pytorch_params[inputs_name[1]]
mapper.paddle_params[op_name + ".weight"] = weights
layer_attrs["out_channels"] = weights.shape[1]
layer_attrs["kernel_size"] = weights.shape[2:]
# 处理输入2,即%10
if inputs_name[2] in mapper.pytorch_params:
bias = mapper.pytorch_params[inputs_name[2]]
if bias is not None:
mapper.paddle_params[op_name + ".bias"] = bias
else:
layer_attrs["bias_attr"] = False
else:
layer_attrs["bias_attr"] = False
# 处理输入3,即%19
layer_attrs["stride"] = mapper.attrs[inputs_name[3]]
# 处理输入4,即%20
layer_attrs["padding"] = mapper.attrs[inputs_name[4]]
# 处理输入5,即%21
layer_attrs["output_padding"] = mapper.attrs[inputs_name[5]]
# 处理输入6,即%13
layer_attrs["groups"] = mapper.attrs[inputs_name[6]]
# 处理输入7,即%22
layer_attrs["dilation"] = mapper.attrs[inputs_name[7]]
layer_attrs['in_channels'] = weights.shape[0] * mapper.attrs[inputs_name[
6]]
graph.add_layer(
"paddle.nn.Conv2D",
"paddle.nn.Conv2DTranspose",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -882,6 +1184,7 @@ def aten_cos(mapper, graph, node):
%94 (Tensor): 输出,cos之后的结果。
%sinusoid_inp.1 (Tensor): 需要进行shape的Tensor。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -889,12 +1192,12 @@ def aten_cos(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%sinusoid_inp.1
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入、输出的list
current_inputs = list(layer_inputs.values())
graph.add_layer("paddle.cos", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("paddle.cos", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -909,6 +1212,7 @@ def aten_cumsum(mapper, graph, node):
%46 (int): 累加的维度。
%48 (int/None): Tensor的类型。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -917,7 +1221,7 @@ def aten_cumsum(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%mask.1
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入、输出的list
current_inputs = list(layer_inputs.values())
......@@ -926,7 +1230,7 @@ def aten_cumsum(mapper, graph, node):
layer_attrs["axis"] = mapper.attrs[inputs_name[1]]
else:
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs)
current_outputs, scope_name)
layer_inputs["axis"] = inputs_name[1]
current_inputs.append(inputs_name[1])
# 处理输入1,即%48,代表dtype
......@@ -939,6 +1243,7 @@ def aten_cumsum(mapper, graph, node):
"paddle.cumsum",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -954,6 +1259,7 @@ def aten_detach(mapper, graph, node):
【注意】由于Paddle无此操作,所以此处制转换为赋值。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -962,11 +1268,11 @@ def aten_detach(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%end.1
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.equal", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.equal", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -979,6 +1285,7 @@ def aten_dict(mapper, graph, node):
参数含义:
%features.1: 输出,初始化的dict。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -986,7 +1293,7 @@ def aten_dict(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
graph.add_layer("prim.dict", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.dict", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -999,6 +1306,7 @@ def aten_dim(mapper, graph, node):
%106 (int): 输出,Tensor的维度。
%101 (Tensor): 输入的Tensor。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -1006,15 +1314,15 @@ def aten_dim(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%input.8
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer(
"fluid.layers.shape", inputs=layer_inputs, outputs=layer_outputs)
"prim.shape", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
graph.add_layer(
"prim.len", inputs={"input": output_name}, outputs=layer_outputs)
"prim.len", inputs={"input": output_name}, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -1035,15 +1343,15 @@ def aten_div_(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%124
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 处理输入1,即%123
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
layer_inputs["y"] = inputs_name[1]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.div", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.div", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -1057,6 +1365,7 @@ def aten_div(mapper, graph, node):
%bx_bw.3 (-): 被除数。
%2678 (int): 除数。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -1064,15 +1373,15 @@ def aten_div(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%124
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 处理输入1,即%123
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
layer_inputs["y"] = inputs_name[1]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.div", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.div", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -1086,25 +1395,22 @@ def aten_dropout(mapper, graph, node):
%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"])
scope_name = mapper.normalize_scope_name(node)
op_name = name_generator("dropout", mapper.nn_name2id)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [dropout_name, output_name]
layer_outputs = [op_name, output_name]
layer_inputs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%119
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入、输出的list
current_inputs = list(layer_inputs.values())
graph.add_layer(
"paddle.nn.Dropout", inputs=layer_inputs, outputs=layer_outputs, p=0.0)
"paddle.nn.Dropout", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name, p=0.0)
return current_inputs, current_outputs
......@@ -1118,25 +1424,22 @@ def aten_dropout_(mapper, graph, node):
%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"])
scope_name = mapper.normalize_scope_name(node)
op_name = name_generator("dropout", mapper.nn_name2id)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [dropout_name, output_name]
layer_outputs = [op_name, output_name]
layer_inputs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%119
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入、输出的list
current_inputs = list(layer_inputs.values())
graph.add_layer(
"paddle.nn.Dropout", inputs=layer_inputs, outputs=layer_outputs, p=0.0)
"paddle.nn.Dropout", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name, p=0.0)
return current_inputs, current_outputs
......@@ -1153,13 +1456,10 @@ def aten_embedding(mapper, graph, node):
%46 (bool): scale_grad_by_freq。
%46 (bool): sparse。
"""
if "embedding" in mapper.dygraph_name_id:
mapper.dygraph_name_id["embedding"] += 1
else:
mapper.dygraph_name_id["embedding"] = 0
embedding_name = "embedding" + str(mapper.dygraph_name_id["embedding"])
scope_name = mapper.normalize_scope_name(node)
op_name = name_generator("embedding", mapper.nn_name2id)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [embedding_name, output_name]
layer_outputs = [op_name, output_name]
layer_inputs = {}
layer_attrs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
......@@ -1167,12 +1467,11 @@ def aten_embedding(mapper, graph, node):
current_outputs = [output_name]
# 处理输入0,即%57
weights = mapper.pytorch_params[inputs_name[0]]
mapper.paddle_params[embedding_name + ".weight"] = weights
# layer_attrs["num_embeddings"] = weights.shape[0]
# layer_attrs["embedding_dim"] = weights.shape[1]
layer_attrs["size"] = weights.shape
mapper.paddle_params[op_name + ".weight"] = weights
layer_attrs["num_embeddings"] = weights.shape[0]
layer_attrs["embedding_dim"] = weights.shape[1]
# 处理输入1,即%input_ids.1
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[1]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
......@@ -1182,13 +1481,13 @@ def aten_embedding(mapper, graph, node):
else:
layer_attrs["padding_idx"] = mapper.attrs[inputs_name[2]]
# 处理输入4,即%46
# layer_attrs["sparse"] = mapper.attrs[inputs_name[4]]
layer_attrs["is_sparse"] = mapper.attrs[inputs_name[4]]
layer_attrs["sparse"] = mapper.attrs[inputs_name[4]]
graph.add_layer(
"paddle.fluid.dygraph.Embedding",
"paddle.nn.Embedding",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -1203,6 +1502,7 @@ def aten_eq(mapper, graph, node):
%124 (-): 需对比的输入1。
%123 (-): 需对比的输入2。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -1210,18 +1510,18 @@ def aten_eq(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%124
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
x_value = list(node.inputs())[0]
x_type = x_value.type()
# 处理输入1,即%123
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
layer_inputs["y"] = inputs_name[1]
y_value = list(node.inputs())[1]
y_type = y_value.type()
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.eq", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.eq", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -1234,6 +1534,7 @@ def aten_exp(mapper, graph, node):
%55 (Tensor): 输出,运算后的结果。
%54 (Tensor): 需要指数运算的Tensor。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -1241,13 +1542,13 @@ def aten_exp(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%result.5
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入、输出的list
current_inputs = list(layer_inputs.values())
graph.add_layer(
"fluid.layers.exp", inputs=layer_inputs, outputs=layer_outputs)
"paddle.exp", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -1262,73 +1563,32 @@ def aten_expand(mapper, graph, node):
%1888 (int): 广播的维度。
%1567 (bool): 未使用。
"""
scope_name = mapper.normalize_scope_name(node)
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)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%1875
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 处理输入1,即%1888
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
graph.add_layer(
"prim.type",
inputs={"input": inputs_name[0]},
outputs=[inputs_name[0] + "_type"])
graph.add_layer(
"prim.str",
inputs={"input": inputs_name[0] + "_type"},
outputs=[inputs_name[0] + "_type"])
graph.add_layer(
"prim.eq",
inputs={"x": inputs_name[0] + "_type"},
outputs=[inputs_name[0] + "_cond"],
y=string("VarType.BOOL"))
graph.add_layer(
"prim.if", {'input': inputs_name[0] + "_cond"},
outputs=[inputs_name[0] + "_if1", inputs_name[1] + "_var"])
if_layer = graph.layers[list(graph.layers.keys())[-1]]
block = PaddleGraph(if_layer, graph_type="dygraph")
block.add_layer(
"fluid.layers.cast",
inputs={"x": inputs_name[0]},
outputs=[inputs_name[0]],
dtype=string("int64"))
block.add_layer(
"fluid.layers.create_global_var",
inputs={"shape": inputs_name[1]},
outputs=[inputs_name[1] + "_var"],
value=1.0,
dtype=string("int64"),
persistable=True)
if_layer.add_block(block)
block = PaddleGraph(if_layer, graph_type="dygraph")
block.add_layer(
"prim.type",
inputs={"input": inputs_name[0]},
outputs=[inputs_name[0] + "_type"])
block.add_layer(
"fluid.layers.create_global_var",
inputs={"shape": inputs_name[1]},
outputs=[inputs_name[1] + "_var"],
value=1.0,
dtype=inputs_name[0] + "_type",
persistable=True)
if_layer.add_block(block)
if_layer.inputs["input-0"] = inputs_name[0]
if_layer.inputs["input-1"] = inputs_name[1]
layer_inputs["target_tensor"] = inputs_name[1] + "_var"
current_outputs.append(inputs_name[1] + "_var")
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
current_inputs.append(inputs_name[1])
# 处理输入1,即%51
if inputs_name[1] in mapper.attrs:
layer_attrs["shape"] = mapper.attrs[inputs_name[1]]
else:
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs, scope_name)
layer_inputs["shape"] = inputs_name[1]
current_inputs.append(inputs_name[1])
graph.add_layer(
"fluid.layers.expand_as", inputs=layer_inputs, outputs=layer_outputs)
"paddle.expand",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -1342,6 +1602,7 @@ def aten_expand_as(mapper, graph, node):
%1875 (Tensor): 需要广播的Tensor。
%1888 (Tensor): 广播的示例。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -1349,62 +1610,81 @@ def aten_expand_as(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%1875
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 处理输入1,即%1888
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
layer_inputs["target_tensor"] = inputs_name[1]
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
layer_inputs["y"] = inputs_name[1]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer(
"prim.type",
inputs={"input": inputs_name[0]},
outputs=[inputs_name[0] + "_type"])
outputs=[inputs_name[0] + "_type"],
scope_name=scope_name)
graph.add_layer(
"prim.str",
inputs={"input": inputs_name[0] + "_type"},
outputs=[inputs_name[0] + "_type"])
outputs=[inputs_name[0] + "_type"],
scope_name=scope_name)
graph.add_layer(
"prim.eq",
inputs={"x": inputs_name[0] + "_type"},
outputs=[inputs_name[0] + "_cond"],
scope_name=scope_name,
y=string("VarType.BOOL"))
graph.add_layer(
"prim.if", {'input': inputs_name[0] + "_cond"},
outputs=[inputs_name[0] + "_if1"])
outputs=[inputs_name[0] + "_if1"],
scope_name=scope_name)
if_layer = graph.layers[list(graph.layers.keys())[-1]]
block = PaddleGraph(if_layer, graph_type="dygraph")
block = PaddleGraph(parent_layer=if_layer, graph_type="dygraph")
block.add_layer(
"prim.type",
inputs={"input": inputs_name[1]},
outputs=[inputs_name[1] + "_type"])
outputs=[inputs_name[1] + "_type"],
scope_name=scope_name)
block.add_layer(
"fluid.layers.cast",
inputs={"x": inputs_name[0]},
outputs=[inputs_name[0]],
scope_name=scope_name,
dtype=inputs_name[1] + "_type")
if_layer.add_block(block)
block = PaddleGraph(if_layer, graph_type="dygraph")
block = PaddleGraph(parent_layer=if_layer, graph_type="dygraph")
if_layer.add_block(block)
if_layer.inputs["input-0"] = inputs_name[0]
if_layer.inputs["input-1"] = inputs_name[1]
graph.add_layer(
"fluid.layers.expand_as", inputs=layer_inputs, outputs=layer_outputs)
"paddle.expand_as", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
graph.add_layer(
"prim.if", {'input': inputs_name[0] + "_cond"},
outputs=[inputs_name[0] + "_if2"])
outputs=[inputs_name[0] + "_if2"],
scope_name=scope_name)
if_layer = graph.layers[list(graph.layers.keys())[-1]]
block = PaddleGraph(if_layer, graph_type="dygraph")
block = PaddleGraph(parent_layer=if_layer, graph_type="dygraph")
block.add_layer(
"fluid.layers.cast",
inputs={"x": layer_outputs[0]},
outputs=layer_outputs,
outputs=copy.deepcopy(layer_outputs),
scope_name=scope_name,
dtype=string("bool"))
if_layer.add_block(block)
block = PaddleGraph(if_layer, graph_type="dygraph")
if_layer.add_block(block)
if_layer.inputs["input-0"] = layer_outputs[0]
# TODO(syf): check expand_as
# # 处理输入0,即%1875
# mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
# layer_inputs["x"] = inputs_name[0]
# # 处理输入1,即%1888
# mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
# layer_inputs["y"] = inputs_name[1]
# # 获取当前节点输入的list
# current_inputs = list(layer_inputs.values())
# graph.add_layer(
# "paddle.expand_as", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -1422,6 +1702,7 @@ def aten_eye(mapper, graph, node):
%67 (str): 设备。
%7 (bool): 是否计算梯度。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -1430,12 +1711,12 @@ def aten_eye(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%49
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["num_rows"] = inputs_name[0]
if len(inputs_name) > 5:
# 处理输入1,即%_50
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs)
current_outputs, scope_name)
layer_inputs["num_columns"] = inputs_name[1]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
......@@ -1443,12 +1724,41 @@ def aten_eye(mapper, graph, node):
layer_attrs["dtype"] = dtype_dict[mapper.attrs[inputs_name[-4]]]
graph.add_layer(
"fluid.layers.eye",
"paddle.eye",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
def aten_feature_dropout(mapper, graph, node):
""" 构造Dropout的PaddleLayer。
TorchScript示例:
%119 : Tensor = aten::feature_dropout(%result.3, %117, %118)
参数含义:
%119 (Tensor): Dropout后的Tensor。
%result.3 (Tensor): 输入Tensor。
%118 (bool): 是否是训练阶段。
"""
scope_name = mapper.normalize_scope_name(node)
op_name = name_generator("dropout", mapper.nn_name2id)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [op_name, output_name]
layer_inputs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%119
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入、输出的list
current_inputs = list(layer_inputs.values())
graph.add_layer(
"paddle.nn.Dropout", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name, p=0.0)
return current_inputs, current_outputs
def aten_flatten(mapper, graph, node):
""" 构造flatten的PaddleLayer。
......@@ -1461,41 +1771,31 @@ def aten_flatten(mapper, graph, node):
%4 (int): flatten的开始维度。
%2 (int): flatten的结束维度。
注意:目前flatten只支持第一维的flatten
"""
scope_name = mapper.normalize_scope_name(node)
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)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入1,即%4
graph.add_layer(
"prim.assert",
inputs={},
outputs=[inputs_name[1] + "_assert"],
type='eq',
key=mapper.attrs[inputs_name[1]],
value=1)
# 处理输入2,即%2
graph.add_layer(
"prim.assert",
inputs={},
outputs=[inputs_name[2] + "_assert"],
type='eq',
key=mapper.attrs[inputs_name[2]],
value=-1)
# 处理输入0,即%x
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
# 处理输入1,即%4
layer_attrs["start_axis"] = mapper.attrs[inputs_name[1]]
# 处理输入2,即%20
layer_attrs["stop_axis"] = mapper.attrs[inputs_name[2]]
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer(
"fluid.layers.flatten",
"paddle.flatten",
inputs=layer_inputs,
outputs=layer_outputs,
axis=1)
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -1508,6 +1808,7 @@ def aten_Float(mapper, graph, node):
%3992 (int): 向上取整后的整数。
%3991 (float): 需要取整的浮点数。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -1515,12 +1816,12 @@ def aten_Float(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%3991
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.float", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.float", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -1533,6 +1834,7 @@ def aten_floor(mapper, graph, node):
%3978 (int): 向上取整后的整数。
%scale.18 (float): 需要取整的浮点数。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -1540,12 +1842,40 @@ def aten_floor(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%scale.18
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
layer_inputs["input"] = inputs_name[0]
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.floor", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer(
"prim.type",
{'input': inputs_name[0]},
outputs=[inputs_name[0] + "_type"],
scope_name=scope_name)
graph.add_layer(
"prim.str",
{'input': inputs_name[0] + "_type"},
outputs=[inputs_name[0] + "_type"],
scope_name=scope_name)
graph.add_layer(
"prim.startswith",
{'input': inputs_name[0] + "_type"},
outputs=[inputs_name[0] + "_cond"],
scope_name=scope_name,
start_str=string("VarType"))
graph.add_layer(
"prim.if",
{'input': inputs_name[0] + "_cond"},
outputs=[inputs_name[0] + "_if"],
scope_name=scope_name)
if_layer = graph.layers[list(graph.layers.keys())[-1]]
block = PaddleGraph(parent_layer=if_layer, graph_type="dygraph")
block.add_layer("paddle.floor", inputs=copy.deepcopy(layer_inputs), outputs=copy.deepcopy(layer_outputs), scope_name=scope_name)
if_layer.add_block(block)
block = PaddleGraph(parent_layer=if_layer, graph_type="dygraph")
block.add_layer("prim.floor", inputs=copy.deepcopy(layer_inputs), outputs=copy.deepcopy(layer_outputs), scope_name=scope_name)
if_layer.add_block(block)
if_layer.inputs["input-0"] = inputs_name[0]
if_layer.outputs.append(output_name)
return current_inputs, current_outputs
......@@ -1559,6 +1889,7 @@ def aten_floordiv(mapper, graph, node):
%num_channels.2 (-): 被除数。
%2 (int): 除数。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -1566,15 +1897,15 @@ def aten_floordiv(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%124
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 处理输入1,即%123
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
layer_inputs["y"] = inputs_name[1]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.floordiv", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.floordiv", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -1588,6 +1919,7 @@ def aten_floor_divide(mapper, graph, node):
%num_channels.2 (-): 被除数。
%2 (int): 除数。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -1595,15 +1927,15 @@ def aten_floor_divide(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%124
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 处理输入1,即%123
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
layer_inputs["y"] = inputs_name[1]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.floordiv", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.floordiv", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -1622,6 +1954,7 @@ def aten_full_like(mapper, graph, node):
%65 (bool): 是否计算梯度。
%66 (int): 内存形式。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -1630,7 +1963,7 @@ def aten_full_like(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%val_if_large.3
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
......@@ -1639,7 +1972,7 @@ def aten_full_like(mapper, graph, node):
layer_attrs["fill_value"] = mapper.attrs[inputs_name[1]]
else:
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs)
current_outputs, scope_name)
layer_inputs["fill_value"] = inputs_name[1]
current_inputs.append(inputs_name[1])
# 处理输入2,即%50,代表dtype
......@@ -1649,6 +1982,47 @@ def aten_full_like(mapper, graph, node):
"paddle.full_like",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
def aten_gather(mapper, graph, node):
""" 构造gather激活的PaddleLayer。
TorchScript示例:
%result.3 : Tensor = aten::gather(%input.5, %18, %19, %20, %21)
参数含义:
%result.3 (Tensor): 输出,gather后的结果。
%result.5 (Tensor): 需要gather的Tensor。
%18 (int): 需要gather的维度。
%19 (Tensor): 需要gather的索引。
"""
scope_name = mapper.normalize_scope_name(node)
op_name = name_generator("gather", mapper.nn_name2id)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [op_name, output_name]
layer_inputs = {}
layer_attrs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%result.5
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 处理输入1,即%18
layer_attrs["dim"] = mapper.attrs[inputs_name[1]]
# 处理输入2,即%19
mapper._check_input(graph, inputs_node[2], inputs_name[2], current_outputs, scope_name)
layer_inputs["index"] = inputs_name[2]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer(
"custom_layer:Gather",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -1664,25 +2038,22 @@ def aten_gelu(mapper, graph, node):
注意: inplace这个参数在paddle中未实现
"""
if "gelu" in mapper.dygraph_name_id:
mapper.dygraph_name_id["gelu"] += 1
else:
mapper.dygraph_name_id["gelu"] = 0
gelu_name = "gelu" + str(mapper.dygraph_name_id["gelu"])
scope_name = mapper.normalize_scope_name(node)
op_name = name_generator("gelu", mapper.nn_name2id)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [gelu_name, output_name]
layer_outputs = [op_name, output_name]
layer_inputs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%result.5
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer(
"paddle.nn.GELU", inputs=layer_inputs, outputs=layer_outputs)
"paddle.nn.GELU", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -1696,6 +2067,7 @@ def aten___getitem__(mapper, graph, node):
%72 (list): 需要获取元素的list。
%88 (int): 索引。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -1703,15 +2075,15 @@ def aten___getitem__(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%72
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["list"] = inputs_name[0]
# 处理输入1,即%88
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
layer_inputs["index"] = inputs_name[1]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.getitem", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.getitem", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -1725,6 +2097,7 @@ def aten_gt(mapper, graph, node):
%82 (-): 需对比的输入1。
%78 (-): 需对比的输入2。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -1732,15 +2105,15 @@ def aten_gt(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%82
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 处理输入1,即%78
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
layer_inputs["y"] = inputs_name[1]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.gt", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.gt", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -1755,20 +2128,17 @@ def aten_hardtanh_(mapper, graph, node):
%67 (float): hardtanh激活的最小阈值。
%66 (float): hardtanh激活的最大阈值。
"""
if "tanh" in mapper.dygraph_name_id:
mapper.dygraph_name_id["tanh"] += 1
else:
mapper.dygraph_name_id["tanh"] = 0
tanh_name = "tanh" + str(mapper.dygraph_name_id["tanh"])
scope_name = mapper.normalize_scope_name(node)
op_name = name_generator("hardtanh", mapper.nn_name2id)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [tanh_name, output_name]
layer_outputs = [op_name, output_name]
layer_inputs = {}
layer_attrs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%input.20
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
......@@ -1781,6 +2151,7 @@ def aten_hardtanh_(mapper, graph, node):
'paddle.nn.Hardtanh',
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -1796,6 +2167,7 @@ def aten_index_select(mapper, graph, node):
%320 (int): 维度。
%371 (Tensor): 选择的索引。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -1804,18 +2176,18 @@ def aten_index_select(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%x2.3
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 处理输入1,即%320
if inputs_name[1] in mapper.attrs:
layer_attrs["axis"] = mapper.attrs[inputs_name[1]]
else:
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs)
current_outputs, scope_name)
layer_inputs["axis"] = inputs_name[1]
current_inputs.append(inputs_name[1])
# 处理输入2,即%371
mapper._check_input(graph, inputs_node[2], inputs_name[2], current_outputs)
mapper._check_input(graph, inputs_node[2], inputs_name[2], current_outputs, scope_name)
layer_inputs["index"] = inputs_name[2]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
......@@ -1824,6 +2196,7 @@ def aten_index_select(mapper, graph, node):
"prim.index_select",
inputs=layer_inputs,
outputs=current_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -1837,6 +2210,7 @@ def aten_Int(mapper, graph, node):
%1739 (int): 输出,int型数据。
%1738 (-): 需要强转的数据。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -1844,12 +2218,12 @@ def aten_Int(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%1738
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.int", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.int", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -1863,6 +2237,7 @@ def aten___is__(mapper, graph, node):
%size.122 (-): 需对比的输入1。
%3931 (-): 需对比的输入2。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -1870,15 +2245,15 @@ def aten___is__(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%size.122
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 处理输入1,即%3931
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
layer_inputs["y"] = inputs_name[1]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.is", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.is", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -1892,6 +2267,7 @@ def aten___isnot__(mapper, graph, node):
%size.122 (-): 需对比的输入1。
%3931 (-): 需对比的输入2。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -1899,15 +2275,15 @@ def aten___isnot__(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%size.122
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 处理输入1,即%3931
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
layer_inputs["y"] = inputs_name[1]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.isnot", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.isnot", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -1925,20 +2301,17 @@ def aten_layer_norm(mapper, graph, node):
%70 (float): 指明在计算过程中是否添加较小的值到方差中以防止除零。
%71 (bool): 是否启用cudnn。
"""
if "layernorm" in mapper.dygraph_name_id:
mapper.dygraph_name_id["layernorm"] += 1
else:
mapper.dygraph_name_id["layernorm"] = 0
layernorm_name = "layernorm" + str(mapper.dygraph_name_id["layernorm"])
scope_name = mapper.normalize_scope_name(node)
op_name = name_generator("layernorm", mapper.nn_name2id)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [layernorm_name, output_name]
layer_outputs = [op_name, output_name]
layer_inputs = {}
layer_attrs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%input.6
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入、输出的list
current_inputs = list(layer_inputs.values())
......@@ -1946,14 +2319,14 @@ def aten_layer_norm(mapper, graph, node):
layer_attrs["normalized_shape"] = mapper.attrs[inputs_name[1]]
# 处理输入2,即%174
weights = mapper.pytorch_params[inputs_name[2]]
mapper.paddle_params[layernorm_name + ".weight"] = weights
mapper.paddle_params[op_name + ".weight"] = weights
# 处理输入3,即%173
if inputs_name[3] in mapper.pytorch_params:
bias = mapper.pytorch_params[inputs_name[3]]
if bias is not None:
mapper.paddle_params[layernorm_name + ".bias"] = bias
mapper.paddle_params[op_name + ".bias"] = bias
else:
mapper.paddle_params[layernorm_name + ".bias"] = False
mapper.paddle_params[op_name + ".bias"] = False
# 处理输入4,即%70
layer_attrs["epsilon"] = mapper.attrs[inputs_name[4]]
......@@ -1961,6 +2334,7 @@ def aten_layer_norm(mapper, graph, node):
"paddle.nn.LayerNorm",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -1975,6 +2349,7 @@ def aten_le(mapper, graph, node):
%78 (-): 需对比的输入1。
%79 (-): 需对比的输入2。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -1982,15 +2357,15 @@ def aten_le(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%78
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 处理输入1,即%79
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
layer_inputs["y"] = inputs_name[1]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.le", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.le", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -2004,20 +2379,17 @@ def aten_leaky_relu_(mapper, graph, node):
%input.114 (Tensor): 需要leaky relu的Tensor。
%1570 (float): 输入中的元素小于0时的斜率。
"""
if "leaky_relu" in mapper.dygraph_name_id:
mapper.dygraph_name_id["leaky_relu"] += 1
else:
mapper.dygraph_name_id["leaky_relu"] = 0
leaky_relu_name = "leaky_relu" + str(mapper.dygraph_name_id["leaky_relu"])
scope_name = mapper.normalize_scope_name(node)
op_name = name_generator("leakly_relu", mapper.nn_name2id)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [leaky_relu_name, output_name]
layer_outputs = [op_name, output_name]
layer_inputs = {}
layer_attrs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%result.5
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入、输出的list
current_inputs = list(layer_inputs.values())
......@@ -2028,6 +2400,7 @@ def aten_leaky_relu_(mapper, graph, node):
"paddle.nn.LeakyReLU",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -2041,6 +2414,7 @@ def aten_len(mapper, graph, node):
%85 (int): 输出,list的长度。
%72 (list): 需要获取长度的list。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -2048,12 +2422,12 @@ def aten_len(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%72
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.len", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.len", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -2066,6 +2440,7 @@ def aten_log(mapper, graph, node):
%787 (Tensor): 输出,取log的Tensor。
%786 (Tensor): 需要获取log的Tensor。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -2073,13 +2448,13 @@ def aten_log(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%786
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer(
"fluid.layers.log", inputs=layer_inputs, outputs=layer_outputs)
"paddle.log", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -2093,6 +2468,7 @@ def aten_lt(mapper, graph, node):
%78 (-): 需对比的输入1。
%79 (-): 需对比的输入2。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -2100,15 +2476,15 @@ def aten_lt(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%78
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 处理输入1,即%79
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
layer_inputs["y"] = inputs_name[1]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.lt", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.lt", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -2123,6 +2499,7 @@ def aten_masked_fill_(mapper, graph, node):
%mask.2 (Tensor): bool型的Tensor,哪些位置需要填充。
%46 (-): 填充的值。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -2132,45 +2509,52 @@ def aten_masked_fill_(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%input.4
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
current_inputs.append(inputs_name[0])
graph.add_layer(
"prim.type",
inputs={"input": inputs_name[0]},
outputs=[inputs_name[0] + "_type"])
outputs=[inputs_name[0] + "_type"],
scope_name=scope_name)
# 处理输入1,即%scores.2
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
current_inputs.append(inputs_name[1])
graph.add_layer(
"paddle.logical_not",
inputs={"x": inputs_name[1]},
outputs=[inputs_name[1] + "_not"])
outputs=[inputs_name[1] + "_not"],
scope_name=scope_name)
graph.add_layer(
"fluid.layers.cast",
"paddle.cast",
inputs={"x": inputs_name[1]},
outputs=[inputs_name[1] + "_mask"],
scope_name=scope_name,
dtype=inputs_name[0] + "_type")
graph.add_layer(
"fluid.layers.cast",
"paddle.cast",
inputs={"x": inputs_name[1] + "_not"},
outputs=[inputs_name[1] + "_not_mask"],
scope_name=scope_name,
dtype=inputs_name[0] + "_type")
graph.add_layer(
"paddle.multiply",
inputs={"x": inputs_name[0],
"y": inputs_name[1] + "_not_mask"},
outputs=[inputs_name[0] + "_not_mask"])
outputs=[inputs_name[0] + "_not_mask"],
scope_name=scope_name)
# 处理输入2,即%46
mapper._check_input(graph, inputs_node[2], inputs_name[2], current_outputs)
mapper._check_input(graph, inputs_node[2], inputs_name[2], current_outputs, scope_name)
graph.add_layer(
"prim.eq",
inputs={"x": inputs_name[2]},
outputs=[inputs_name[2] + "_cond1"],
scope_name=scope_name,
y="-float('inf')")
graph.add_layer(
"prim.eq",
inputs={"x": inputs_name[2]},
outputs=[inputs_name[2] + "_cond2"],
scope_name=scope_name,
y="float('inf')")
graph.add_layer(
"prim.or",
......@@ -2178,32 +2562,37 @@ def aten_masked_fill_(mapper, graph, node):
"x": inputs_name[2] + "_cond1",
"y": inputs_name[2] + "_cond2"
},
outputs=[inputs_name[2] + "_cond"])
outputs=[inputs_name[2] + "_cond"],
scope_name=scope_name)
graph.add_layer(
"prim.if", {'input': inputs_name[2] + "_cond"},
outputs=[inputs_name[2] + "_if"])
outputs=[inputs_name[2] + "_if"],
scope_name=scope_name)
if_layer = graph.layers[list(graph.layers.keys())[-1]]
block = PaddleGraph(if_layer, graph_type="dygraph")
block = PaddleGraph(parent_layer=if_layer, graph_type="dygraph")
block.add_layer(
"prim.equal",
inputs={"input": inputs_name[1] + "_mask"},
outputs=[inputs_name[2] + "_1"])
outputs=[inputs_name[2] + "_1"],
scope_name=scope_name)
if_layer.add_block(block)
block = PaddleGraph(if_layer, graph_type="dygraph")
block = PaddleGraph(parent_layer=if_layer, graph_type="dygraph")
block.add_layer(
"prim.mul",
inputs={"x": inputs_name[1] + "_mask",
"y": inputs_name[2]},
outputs=[inputs_name[2] + "_1"])
outputs=[inputs_name[2] + "_1"],
scope_name=scope_name)
if_layer.add_block(block)
if_layer.inputs["input-0"] = inputs_name[1] + "_mask"
if_layer.inputs["input-1"] = inputs_name[2]
if_layer.outputs.append(inputs_name[2] + "_1")
graph.add_layer(
"fluid.layers.elementwise_add",
"paddle.add",
inputs={"x": inputs_name[2] + "_1",
"y": inputs_name[0] + "_not_mask"},
outputs=layer_outputs)
outputs=layer_outputs,
scope_name=scope_name)
return current_inputs, current_outputs
......@@ -2218,6 +2607,7 @@ def aten_masked_fill(mapper, graph, node):
%mask.2 (Tensor): bool型的Tensor,哪些位置需要填充。
%46 (-): 填充的值。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -2227,45 +2617,52 @@ def aten_masked_fill(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%input.4
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
current_inputs.append(inputs_name[0])
graph.add_layer(
"prim.type",
inputs={"input": inputs_name[0]},
outputs=[inputs_name[0] + "_type"])
outputs=[inputs_name[0] + "_type"],
scope_name=scope_name)
# 处理输入1,即%scores.2
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
current_inputs.append(inputs_name[1])
graph.add_layer(
"paddle.logical_not",
inputs={"x": inputs_name[1]},
outputs=[inputs_name[1] + "_not"])
outputs=[inputs_name[1] + "_not"],
scope_name=scope_name)
graph.add_layer(
"fluid.layers.cast",
"paddle.cast",
inputs={"x": inputs_name[1]},
outputs=[inputs_name[1] + "_mask"],
scope_name=scope_name,
dtype=inputs_name[0] + "_type")
graph.add_layer(
"fluid.layers.cast",
"paddle.cast",
inputs={"x": inputs_name[1] + "_not"},
outputs=[inputs_name[1] + "_not_mask"],
scope_name=scope_name,
dtype=inputs_name[0] + "_type")
graph.add_layer(
"paddle.multiply",
inputs={"x": inputs_name[0],
"y": inputs_name[1] + "_not_mask"},
outputs=[inputs_name[0] + "_not_mask"])
outputs=[inputs_name[0] + "_not_mask"],
scope_name=scope_name)
# 处理输入2,即%46
mapper._check_input(graph, inputs_node[2], inputs_name[2], current_outputs)
mapper._check_input(graph, inputs_node[2], inputs_name[2], current_outputs, scope_name)
graph.add_layer(
"prim.eq",
inputs={"x": inputs_name[2]},
outputs=[inputs_name[2] + "_cond1"],
scope_name=scope_name,
y="-float('inf')")
graph.add_layer(
"prim.eq",
inputs={"x": inputs_name[2]},
outputs=[inputs_name[2] + "_cond2"],
scope_name=scope_name,
y="float('inf')")
graph.add_layer(
"prim.or",
......@@ -2273,32 +2670,37 @@ def aten_masked_fill(mapper, graph, node):
"x": inputs_name[2] + "_cond1",
"y": inputs_name[2] + "_cond2"
},
outputs=[inputs_name[2] + "_cond"])
outputs=[inputs_name[2] + "_cond"],
scope_name=scope_name)
graph.add_layer(
"prim.if", {'input': inputs_name[2] + "_cond"},
outputs=[inputs_name[2] + "_if"])
outputs=[inputs_name[2] + "_if"],
scope_name=scope_name)
if_layer = graph.layers[list(graph.layers.keys())[-1]]
block = PaddleGraph(if_layer, graph_type="dygraph")
block = PaddleGraph(parent_layer=if_layer, graph_type="dygraph")
block.add_layer(
"prim.equal",
inputs={"input": inputs_name[1] + "_mask"},
outputs=[inputs_name[2] + "_1"])
outputs=[inputs_name[2] + "_1"],
scope_name=scope_name)
if_layer.add_block(block)
block = PaddleGraph(if_layer, graph_type="dygraph")
block = PaddleGraph(parent_layer=if_layer, graph_type="dygraph")
block.add_layer(
"prim.mul",
inputs={"x": inputs_name[1] + "_mask",
"y": inputs_name[2]},
outputs=[inputs_name[2] + "_1"])
outputs=[inputs_name[2] + "_1"],
scope_name=scope_name)
if_layer.add_block(block)
if_layer.inputs["input-0"] = inputs_name[1] + "_mask"
if_layer.inputs["input-1"] = inputs_name[2]
if_layer.outputs.append(inputs_name[2] + "_1")
graph.add_layer(
"fluid.layers.elementwise_add",
"paddle.add",
inputs={"x": inputs_name[2] + "_1",
"y": inputs_name[0] + "_not_mask"},
outputs=layer_outputs)
outputs=layer_outputs,
scope_name=scope_name)
return current_inputs, current_outputs
......@@ -2312,6 +2714,7 @@ def aten_max(mapper, graph, node):
%val_if_large.3 (Tensor): 输入,需要对比的Tensor1。
%159 (Tensor): 输入,需要对比的Tensor2。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -2322,16 +2725,16 @@ def aten_max(mapper, graph, node):
if str(input_type) == "Tensor":
# 处理输入0,即%val_if_large.3
mapper._check_input(graph, inputs_node[0], inputs_name[0],
current_outputs)
current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 处理输入1,即%159
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs)
current_outputs, scope_name)
layer_inputs["y"] = inputs_name[1]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer(
"paddle.maximum", inputs=layer_inputs, outputs=layer_outputs)
"paddle.maximum", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
else:
pass
return current_inputs, current_outputs
......@@ -2351,46 +2754,58 @@ def aten_max_pool2d(mapper, graph, node):
%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"])
scope_name = mapper.normalize_scope_name(node)
op_name = name_generator("pool2d", mapper.nn_name2id)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [pool_name, output_name]
layer_outputs = [op_name, output_name]
layer_inputs = {}
layer_attrs = {}
layer_attrs_tmp = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%result.11
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
# 处理输入1,即%20
layer_attrs["pool_size"] = mapper.attrs[inputs_name[1]]
layer_attrs["kernel_size"] = mapper.attrs[inputs_name[1]]
layer_attrs_tmp["pool_size"] = mapper.attrs[inputs_name[1]]
# 处理输入2,即%23
layer_attrs["pool_stride"] = mapper.attrs[inputs_name[2]]
layer_attrs["stride"] = mapper.attrs[inputs_name[2]]
layer_attrs_tmp["pool_stride"] = mapper.attrs[inputs_name[2]]
# 处理输入3,即%21
layer_attrs["pool_padding"] = mapper.attrs[inputs_name[3]]
layer_attrs["padding"] = mapper.attrs[inputs_name[3]]
layer_attrs_tmp["pool_padding"] = mapper.attrs[inputs_name[3]]
# 处理输入4,即%22
graph.add_layer(
"prim.assert",
inputs={},
outputs=[inputs_name[4] + "_assert"],
scope_name=scope_name + "_assert",
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")
layer_attrs_tmp["ceil_mode"] = mapper.attrs[inputs_name[5]]
graph.add_layer(
"paddle.nn.Pool2D",
inputs=layer_inputs,
outputs=layer_outputs,
**layer_attrs)
if mapper.attrs[inputs_name[5]] == True:
layer_attrs["pool_type"] = string("max")
graph.add_layer(
"fluid.layers.pool2d",
inputs=layer_inputs,
outputs=layer_outputs[1:],
scope_name=scope_name,
**layer_attrs_tmp)
else:
graph.add_layer(
"paddle.nn.MaxPool2D",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -2404,6 +2819,7 @@ def aten_matmul(mapper, graph, node):
%101 (Tensor): 矩阵1。
%102 (Tensor): 矩阵2。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -2411,15 +2827,15 @@ def aten_matmul(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%101
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 处理输入1,即%102
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
layer_inputs["y"] = inputs_name[1]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("paddle.matmul", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("paddle.matmul", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -2433,6 +2849,7 @@ def aten_min(mapper, graph, node):
%val_if_large.3 (Tensor): 输入,需要对比的Tensor1。
%159 (Tensor): 输入,需要对比的Tensor2。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -2443,16 +2860,16 @@ def aten_min(mapper, graph, node):
if str(input_type) == "Tensor":
# 处理输入0,即%val_if_large.3
mapper._check_input(graph, inputs_node[0], inputs_name[0],
current_outputs)
current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 处理输入1,即%159
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs)
current_outputs, scope_name)
layer_inputs["y"] = inputs_name[1]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer(
"paddle.minimum", inputs=layer_inputs, outputs=layer_outputs)
"paddle.minimum", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
else:
pass
return current_inputs, current_outputs
......@@ -2470,6 +2887,7 @@ def aten_mean(mapper, graph, node):
%3 (bool): 是否在输出Tensor中保留减小的维度。
%2 (Tensor): 结果Tensor。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -2478,34 +2896,62 @@ def aten_mean(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%result.1
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
layer_inputs["input"] = inputs_name[0]
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
current_inputs = list(layer_inputs.values())
# 处理输入1,即%4967
if inputs_name[1] in mapper.attrs:
layer_attrs["dim"] = mapper.attrs[inputs_name[1]]
layer_attrs["axis"] = mapper.attrs[inputs_name[1]]
else:
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs)
layer_inputs["dim"] = inputs_name[1]
current_outputs, scope_name)
layer_inputs["axis"] = inputs_name[1]
current_inputs.append(inputs_name[1])
# 处理输入2,即%3
if inputs_name[1] in mapper.attrs:
layer_attrs["keep_dim"] = mapper.attrs[inputs_name[2]]
layer_attrs["keepdim"] = mapper.attrs[inputs_name[2]]
else:
mapper._check_input(graph, inputs_node[2], inputs_name[2],
current_outputs)
layer_inputs["keep_dim"] = inputs_name[2]
current_outputs, scope_name)
layer_inputs["keepdim"] = inputs_name[2]
current_inputs.append(inputs_name[2])
graph.add_layer(
"fluid.layers.reduce_mean",
"paddle.mean",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
def aten_meshgrid(mapper, graph, node):
""" 构造对每个张量做扩充操作的PaddleLayer。
TorchScript示例:
%out.39 : int = aten::mshgrid(%input.1)
参数含义:
%out.39 (Tensor): 输出,扩充后的结果。
%input.1 (Tensor): 输入。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%input.1
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["args"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = layer_inputs.values()
current_outputs = layer_outputs
graph.add_layer("paddle.meshgrid", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
def aten_mul(mapper, graph, node):
""" 构造数值相乘的PaddleLayer。
......@@ -2516,6 +2962,7 @@ def aten_mul(mapper, graph, node):
%size_prods.38 (-): 数值1。
%114 (-): 数值2。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -2523,16 +2970,16 @@ def aten_mul(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%size_prods.38
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 处理输入1,即%114
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
layer_inputs["y"] = inputs_name[1]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
current_outputs = layer_outputs
graph.add_layer("prim.mul", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.mul", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -2546,6 +2993,7 @@ def aten_mul_(mapper, graph, node):
%size_prods.38 (-): 数值1。
%114 (-): 数值2。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -2553,16 +3001,16 @@ def aten_mul_(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%size_prods.38
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 处理输入1,即%114
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
layer_inputs["y"] = inputs_name[1]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
current_outputs = layer_outputs
graph.add_layer("prim.mul", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.mul", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -2576,6 +3024,7 @@ def aten_ne(mapper, graph, node):
%133 (-): 需对比的输入1。
%132 (-): 需对比的输入2。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -2583,15 +3032,15 @@ def aten_ne(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%124
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 处理输入1,即%123
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
layer_inputs["y"] = inputs_name[1]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.ne", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.ne", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -2604,6 +3053,7 @@ def aten_neg(mapper, graph, node):
%909 (int): 取负后结果。
%908 (int): 需取负的输入。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -2611,12 +3061,12 @@ def aten_neg(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%124
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.neg", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.neg", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -2629,6 +3079,7 @@ def aten___not__(mapper, graph, node):
%4498 (bool): 取负后结果。
%aux_defined.2 (bool): 需取负的输入。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -2636,12 +3087,12 @@ def aten___not__(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%124
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.not", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.not", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -2658,6 +3109,7 @@ def aten_ones(mapper, graph, node):
%4995 (Device): 设备。
%4995 (bool): 是否计算梯度。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -2671,7 +3123,7 @@ def aten_ones(mapper, graph, node):
layer_attrs["shape"] = mapper.attrs[inputs_name[0]]
else:
mapper._check_input(graph, inputs_node[0], inputs_name[0],
current_outputs)
current_outputs, scope_name)
layer_inputs["shape"] = inputs_name[0]
current_inputs.append(inputs_name[0])
# 处理输入1,即%8,代表dtype
......@@ -2681,6 +3133,7 @@ def aten_ones(mapper, graph, node):
"paddle.ones",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -2695,6 +3148,7 @@ def aten_permute(mapper, graph, node):
%cls_confs0.2 (Tensor): 需要重排的Tensor。
%2348 (list): 依照此参数进行重排。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -2703,7 +3157,7 @@ def aten_permute(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%cls_confs0.2
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
......@@ -2712,14 +3166,15 @@ def aten_permute(mapper, graph, node):
layer_attrs["perm"] = mapper.attrs[inputs_name[1]]
else:
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs)
current_outputs, scope_name)
layer_inputs["perm"] = inputs_name[1]
current_inputs.append(inputs_name[1])
graph.add_layer(
"fluid.layers.transpose",
"paddle.transpose",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -2733,6 +3188,7 @@ def aten_pow(mapper, graph, node):
%x.6 (Tensor): 输出,指数激活后的Tensor。
%4700 (Tensor): 需要指数激活的Tensor。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -2741,23 +3197,24 @@ def aten_pow(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%4700
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入、输出的list
current_inputs = list(layer_inputs.values())
# 处理输入1,即%4703
if inputs_name[1] in mapper.attrs:
layer_attrs["factor"] = mapper.attrs[inputs_name[1]]
layer_attrs["y"] = mapper.attrs[inputs_name[1]]
else:
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs)
layer_inputs["factor"] = inputs_name[1]
current_outputs, scope_name)
layer_inputs["y"] = inputs_name[1]
current_inputs.append(inputs_name[1])
graph.add_layer(
"fluid.layers.pow",
"paddle.pow",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -2773,25 +3230,22 @@ def aten_relu(mapper, graph, node):
注意: inplace这个参数在paddle中未实现
"""
if "relu" in mapper.dygraph_name_id:
mapper.dygraph_name_id["relu"] += 1
else:
mapper.dygraph_name_id["relu"] = 0
relu_name = "relu" + str(mapper.dygraph_name_id["relu"])
scope_name = mapper.normalize_scope_name(node)
op_name = name_generator("relu", mapper.nn_name2id)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [relu_name, output_name]
layer_outputs = [op_name, output_name]
layer_inputs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%result.5
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer(
"paddle.nn.ReLU", inputs=layer_inputs, outputs=layer_outputs)
"paddle.nn.ReLU", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -2806,25 +3260,22 @@ def aten_relu_(mapper, graph, node):
注意: inplace这个参数在paddle中未实现
"""
if "relu" in mapper.dygraph_name_id:
mapper.dygraph_name_id["relu"] += 1
else:
mapper.dygraph_name_id["relu"] = 0
relu_name = "relu" + str(mapper.dygraph_name_id["relu"])
scope_name = mapper.normalize_scope_name(node)
op_name = name_generator("relu", mapper.nn_name2id)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [relu_name, output_name]
layer_outputs = [op_name, output_name]
layer_inputs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%result.5
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer(
"paddle.nn.ReLU", inputs=layer_inputs, outputs=layer_outputs)
"paddle.nn.ReLU", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -2839,25 +3290,22 @@ def aten_relu6(mapper, graph, node):
注意: inplace这个参数在paddle中未实现
"""
if "relu6" in mapper.dygraph_name_id:
mapper.dygraph_name_id["relu6"] += 1
else:
mapper.dygraph_name_id["relu6"] = 0
relu6_name = "relu6" + str(mapper.dygraph_name_id["relu6"])
scope_name = mapper.normalize_scope_name(node)
op_name = name_generator("relu6", mapper.nn_name2id)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [relu6_name, output_name]
layer_outputs = [op_name, output_name]
layer_inputs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%result.5
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer(
"paddle.nn.ReLU6", inputs=layer_inputs, outputs=layer_outputs)
"paddle.nn.ReLU6", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -2871,6 +3319,7 @@ def aten_repeat(mapper, graph, node):
%699 (Tensor): 需要复制的Tensor。
%700 (list): 指定每个维度复制的次数。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -2879,7 +3328,7 @@ def aten_repeat(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%699
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入、输出的list
current_inputs = list(layer_inputs.values())
......@@ -2888,7 +3337,7 @@ def aten_repeat(mapper, graph, node):
layer_attrs["repeat_times"] = mapper.attrs[inputs_name[1]]
else:
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs)
current_outputs, scope_name)
layer_inputs["repeat_times"] = inputs_name[1]
current_inputs.append(inputs_name[1])
......@@ -2896,6 +3345,7 @@ def aten_repeat(mapper, graph, node):
"paddle.tile",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -2910,6 +3360,7 @@ def aten_reshape(mapper, graph, node):
%4700 (Tensor): 需要reshape的Tensor。
%4703 (list): 形状大小组成的list。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -2918,7 +3369,7 @@ def aten_reshape(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%4700
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入、输出的list
current_inputs = list(layer_inputs.values())
......@@ -2927,56 +3378,16 @@ def aten_reshape(mapper, graph, node):
layer_attrs["shape"] = mapper.attrs[inputs_name[1]]
else:
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs)
current_outputs, scope_name)
layer_inputs["shape"] = inputs_name[1]
current_inputs.append(inputs_name[1])
graph.add_layer(
"prim.type",
inputs={"input": inputs_name[0]},
outputs=[inputs_name[0] + "_type"])
graph.add_layer(
"prim.str",
inputs={"input": inputs_name[0] + "_type"},
outputs=[inputs_name[0] + "_type"])
graph.add_layer(
"prim.eq",
inputs={"x": inputs_name[0] + "_type"},
outputs=[inputs_name[0] + "_cond"],
y=string("VarType.BOOL"))
graph.add_layer(
"prim.if", {'input': inputs_name[0] + "_cond"},
outputs=[inputs_name[0] + "_if1"])
if_layer = graph.layers[list(graph.layers.keys())[-1]]
block = PaddleGraph(if_layer, graph_type="dygraph")
block.add_layer(
"fluid.layers.cast",
inputs={"x": inputs_name[0]},
outputs=[inputs_name[0]],
dtype=string("int32"))
if_layer.add_block(block)
block = PaddleGraph(if_layer, graph_type="dygraph")
if_layer.add_block(block)
if_layer.inputs["input-0"] = inputs_name[0]
graph.add_layer(
"fluid.layers.reshape",
"paddle.reshape",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
graph.add_layer(
"prim.if", {'input': inputs_name[0] + "_cond"},
outputs=[inputs_name[0] + "_if2"])
if_layer = graph.layers[list(graph.layers.keys())[-1]]
block = PaddleGraph(if_layer, graph_type="dygraph")
block.add_layer(
"fluid.layers.cast",
inputs={"x": layer_outputs[0]},
outputs=layer_outputs,
dtype=string("bool"))
if_layer.add_block(block)
block = PaddleGraph(if_layer, graph_type="dygraph")
if_layer.add_block(block)
if_layer.inputs["input-0"] = layer_outputs[0]
return current_inputs, current_outputs
......@@ -2991,6 +3402,7 @@ def aten_rsub(mapper, graph, node):
%13 (int/float): 输入数值 y。
%7 (int/float): alpha。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -2999,18 +3411,18 @@ def aten_rsub(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%30
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 处理输入1,即%13
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
layer_inputs["y"] = inputs_name[1]
# 处理输入2,即%7
mapper._check_input(graph, inputs_node[2], inputs_name[2], current_outputs)
mapper._check_input(graph, inputs_node[2], inputs_name[2], current_outputs, scope_name)
layer_inputs["alpha"] = inputs_name[2]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.rsub", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.rsub", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -3025,6 +3437,7 @@ def aten_ScalarImplicit(mapper, graph, node):
【注意】由于Paddle无Scalar,所以最后转换为Tensor。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -3033,14 +3446,14 @@ def aten_ScalarImplicit(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%end.1
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
input_type = list(node.inputs())[0].type()
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
if str(input_type) == "Tensor":
graph.add_layer(
"prim.equal", inputs=layer_inputs, outputs=layer_outputs)
"prim.equal", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
else:
raise Exception(
"The input type {} of aten::ScalarImplicit is not implemented yet!"
......@@ -3059,6 +3472,7 @@ def aten_select(mapper, graph, node):
%8 (int): select的维度。
%7 (int): select的第n个向量。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -3067,12 +3481,12 @@ def aten_select(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%18
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 处理输入1,即%8
layer_attrs["dim"] = mapper.attrs[inputs_name[1]]
# 处理输入2,即%75
mapper._check_input(graph, inputs_node[2], inputs_name[2], current_outputs)
mapper._check_input(graph, inputs_node[2], inputs_name[2], current_outputs, scope_name)
layer_inputs["index"] = inputs_name[2]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
......@@ -3081,6 +3495,7 @@ def aten_select(mapper, graph, node):
"prim.select",
inputs=layer_inputs,
outputs=current_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -3095,23 +3510,24 @@ def aten__set_item(mapper, graph, node):
%out_name.1 (-): dict的key。
%x.3 (-): dict的value。
"""
scope_name = mapper.normalize_scope_name(node)
layer_inputs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = []
# 处理输入0,即%features.1
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["dict"] = inputs_name[0]
# 处理输入1,即%out_name.1
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
layer_inputs["key"] = inputs_name[1]
# 处理输入2,即%x.3
mapper._check_input(graph, inputs_node[2], inputs_name[2], current_outputs)
mapper._check_input(graph, inputs_node[2], inputs_name[2], current_outputs, scope_name)
layer_inputs["value"] = inputs_name[2]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.set_item", inputs=layer_inputs, outputs=[])
graph.add_layer("prim.set_item", inputs=layer_inputs, outputs=[], scope_name=scope_name)
return current_inputs, current_outputs
......@@ -3124,20 +3540,22 @@ def aten_sigmoid(mapper, graph, node):
%55 (Tensor): 输出,sigmoid后的结果。
%54 (Tensor): 需要tanh的Tensor。
"""
scope_name = mapper.normalize_scope_name(node)
op_name = name_generator("sigmoid", mapper.nn_name2id)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_outputs = [op_name, output_name]
layer_inputs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%54
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入、输出的list
current_inputs = list(layer_inputs.values())
graph.add_layer(
"fluid.layers.sigmoid", inputs=layer_inputs, outputs=layer_outputs)
"paddle.nn.Sigmoid", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -3150,6 +3568,7 @@ def aten_sin(mapper, graph, node):
%94 (Tensor): 输出,sin之后的结果。
%sinusoid_inp.1 (Tensor): 需要进行shape的Tensor。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -3157,12 +3576,12 @@ def aten_sin(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%sinusoid_inp.1
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入、输出的list
current_inputs = list(layer_inputs.values())
graph.add_layer("paddle.sin", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("paddle.sin", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -3176,6 +3595,7 @@ def aten_size(mapper, graph, node):
%x.12 (Tensor): 需要获取shape的Tensor。
%10 (int): 非必须,代表维度。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -3184,7 +3604,7 @@ def aten_size(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%x.12
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
......@@ -3194,18 +3614,19 @@ def aten_size(mapper, graph, node):
layer_attrs["dim"] = mapper.attrs[inputs_name[1]]
else:
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs)
current_outputs, scope_name)
layer_inputs["dim"] = inputs_name[1]
current_inputs.append(inputs_name[1])
graph.add_layer(
"prim.shape_dim",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
graph.add_layer(
"fluid.layers.shape", inputs=layer_inputs, outputs=layer_outputs)
"prim.shape", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -3222,6 +3643,7 @@ def aten_slice(mapper, graph, node):
%75 (int): 切分的结束索引。
%77 (int): 切分的步长。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -3231,8 +3653,8 @@ def aten_slice(mapper, graph, node):
if len(inputs_name) == 5:
# 处理输入0,即%73
mapper._check_input(graph, inputs_node[0], inputs_name[0],
current_outputs)
layer_inputs["input"] = inputs_name[0]
current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
......@@ -3242,14 +3664,16 @@ def aten_slice(mapper, graph, node):
"prim.list",
inputs={},
outputs=[inputs_name[1] + "_list"],
scope_name=scope_name,
input0=mapper.attrs[inputs_name[1]])
else:
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs)
current_outputs, scope_name)
graph.add_layer(
"prim.list",
inputs={"input0": inputs_name[1]},
outputs=[inputs_name[1] + "_list"])
outputs=[inputs_name[1] + "_list"],
scope_name=scope_name)
current_inputs.append(inputs_name[1])
layer_inputs["axes"] = inputs_name[1] + "_list"
current_inputs.append(inputs_name[1] + "_list")
......@@ -3260,14 +3684,16 @@ def aten_slice(mapper, graph, node):
"prim.list",
inputs={},
outputs=[inputs_name[2] + "_list"],
scope_name=scope_name,
input0=mapper.attrs[inputs_name[2]])
else:
mapper._check_input(graph, inputs_node[2], inputs_name[2],
current_outputs)
current_outputs, scope_name)
graph.add_layer(
"prim.list",
inputs={"input0": inputs_name[2]},
outputs=[inputs_name[2] + "_list"])
outputs=[inputs_name[2] + "_list"],
scope_name=scope_name)
current_inputs.append(inputs_name[2])
layer_inputs["starts"] = inputs_name[2] + "_list"
current_inputs.append(inputs_name[2] + "_list")
......@@ -3278,14 +3704,16 @@ def aten_slice(mapper, graph, node):
"prim.list",
inputs={},
outputs=[inputs_name[3] + "_list"],
scope_name=scope_name,
input0=mapper.attrs[inputs_name[3]])
else:
mapper._check_input(graph, inputs_node[3], inputs_name[3],
current_outputs)
current_outputs, scope_name)
graph.add_layer(
"prim.list",
inputs={"input0": inputs_name[3]},
outputs=[inputs_name[3] + "_list"])
outputs=[inputs_name[3] + "_list"],
scope_name=scope_name)
current_inputs.append(inputs_name[3])
layer_inputs["ends"] = inputs_name[3] + "_list"
current_inputs.append(inputs_name[3] + "_list")
......@@ -3296,45 +3724,48 @@ def aten_slice(mapper, graph, node):
"prim.list",
inputs={},
outputs=[inputs_name[4] + "_list"],
scope_name=scope_name,
input0=mapper.attrs[inputs_name[4]])
else:
mapper._check_input(graph, inputs_node[4], inputs_name[4],
current_outputs)
current_outputs, scope_name)
graph.add_layer(
"prim.list",
inputs={"input0": inputs_name[4]},
outputs=[inputs_name[4] + "_list"])
outputs=[inputs_name[4] + "_list"],
scope_name=scope_name)
current_inputs.append(inputs_name[4])
layer_inputs["strides"] = inputs_name[4] + "_list"
current_inputs.append(inputs_name[4] + "_list")
current_outputs.append(inputs_name[4] + "_list")
graph.add_layer(
"fluid.layers.strided_slice",
"paddle.strided_slice",
inputs=layer_inputs,
outputs=layer_outputs)
outputs=layer_outputs,
scope_name=scope_name)
else:
# 处理输入0,即%73
mapper._check_input(graph, inputs_node[0], inputs_name[0],
current_outputs)
current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 处理输入1,即%82
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs)
current_outputs, scope_name)
layer_inputs["start"] = inputs_name[1]
# 处理输入2,即%75
mapper._check_input(graph, inputs_node[2], inputs_name[2],
current_outputs)
current_outputs, scope_name)
layer_inputs["end"] = inputs_name[2]
# 处理输入3,即%77
mapper._check_input(graph, inputs_node[3], inputs_name[3],
current_outputs)
current_outputs, scope_name)
layer_inputs["step"] = inputs_name[3]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer(
"prim.slice", inputs=layer_inputs, outputs=layer_outputs)
"prim.slice", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -3349,20 +3780,17 @@ def aten_softmax(mapper, graph, node):
%80 (int): 指定对输入Tensor进行运算的轴。
%72 (str): 类型,默认为None。
"""
if "softmax" in mapper.dygraph_name_id:
mapper.dygraph_name_id["softmax"] += 1
else:
mapper.dygraph_name_id["softmax"] = 0
softmax_name = "softmax" + str(mapper.dygraph_name_id["softmax"])
scope_name = mapper.normalize_scope_name(node)
op_name = name_generator("softmax", mapper.nn_name2id)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [softmax_name, output_name]
layer_outputs = [op_name, output_name]
layer_inputs = {}
layer_attrs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%x.31
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
......@@ -3372,6 +3800,7 @@ def aten_softmax(mapper, graph, node):
"paddle.nn.Softmax",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -3387,20 +3816,17 @@ def aten_softplus(mapper, graph, node):
%30 (int): beta。
%29 (int): 阈值。
"""
if "softplus" in mapper.dygraph_name_id:
mapper.dygraph_name_id["softplus"] += 1
else:
mapper.dygraph_name_id["softplus"] = 0
softplus_name = "softplus" + str(mapper.dygraph_name_id["softplus"])
scope_name = mapper.normalize_scope_name(node)
op_name = name_generator("softplus", mapper.nn_name2id)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [softplus_name, output_name]
layer_outputs = [op_name, output_name]
layer_inputs = {}
layer_attrs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%x.31
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
......@@ -3411,6 +3837,7 @@ def aten_softplus(mapper, graph, node):
"paddle.nn.Softplus",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -3424,6 +3851,7 @@ def aten_sqrt(mapper, graph, node):
%787 (Tensor): 输出,取sqrt的Tensor。
%786 (Tensor): 需要获取sqrt的Tensor。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -3431,13 +3859,13 @@ def aten_sqrt(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%786
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer(
"fluid.layers.sqrt", inputs=layer_inputs, outputs=layer_outputs)
"paddle.sqrt", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -3451,6 +3879,7 @@ def aten_squeeze(mapper, graph, node):
%start_logits.1 (Tensor): 需要删除维度的Tensor。
%4 (int): 维度。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -3459,7 +3888,7 @@ def aten_squeeze(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%start_logits.1
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
......@@ -3468,13 +3897,14 @@ def aten_squeeze(mapper, graph, node):
layer_attrs["axis"] = mapper.attrs[inputs_name[1]]
else:
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs)
current_outputs, scope_name)
layer_inputs["axis"] = inputs_name[1]
current_inputs.append(inputs_name[1])
graph.add_layer(
"paddle.tensor.squeeze",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -3489,6 +3919,7 @@ def aten_stack(mapper, graph, node):
%i.12 (Tensor): 需要堆叠的Tensor组成的Tensor。
%7 (int): 堆叠的轴。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -3497,7 +3928,7 @@ def aten_stack(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%13
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
......@@ -3506,13 +3937,14 @@ def aten_stack(mapper, graph, node):
layer_attrs["axis"] = mapper.attrs[inputs_name[1]]
else:
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs)
current_outputs, scope_name)
layer_inputs["axis"] = inputs_name[1]
current_inputs.append(inputs_name[1])
graph.add_layer(
"paddle.stack",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -3527,6 +3959,7 @@ def aten_sub(mapper, graph, node):
%839 (-): 输入数值 x。
%836 (-): 输入数值 y。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -3534,16 +3967,16 @@ def aten_sub(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%839
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 处理输入1,即%836
mapper._check_input(
graph, inputs_node[1], inputs_name[1], current_outputs, add_dim=True)
graph, inputs_node[1], inputs_name[1], current_outputs, scope_name, add_dim=True)
layer_inputs["y"] = inputs_name[1]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.sub", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.sub", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -3556,6 +3989,7 @@ def aten_t(mapper, graph, node):
%109 (Tensor): 输出,转置后的矩阵。
%102 (Tensor): 需要转置的Tensor。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -3563,15 +3997,16 @@ def aten_t(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%x.12
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer(
"fluid.layers.transpose",
"paddle.transpose",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
perm=[1, 0])
return current_inputs, current_outputs
......@@ -3585,25 +4020,22 @@ def aten_tanh(mapper, graph, node):
%55 (Tensor): 输出,tanh后的结果。
%54 (Tensor): 需要tanh的Tensor。
"""
if "tanh" in mapper.dygraph_name_id:
mapper.dygraph_name_id["tanh"] += 1
else:
mapper.dygraph_name_id["tanh"] = 0
tanh_name = "tanh" + str(mapper.dygraph_name_id["tanh"])
scope_name = mapper.normalize_scope_name(node)
op_name = name_generator("tanh", mapper.nn_name2id)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [tanh_name, output_name]
layer_outputs = [op_name, output_name]
layer_inputs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%result.5
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入、输出的list
current_inputs = list(layer_inputs.values())
graph.add_layer(
"paddle.nn.Tanh", inputs=layer_inputs, outputs=layer_outputs)
"paddle.nn.Tanh", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -3618,6 +4050,7 @@ def aten_split(mapper, graph, node):
%135 (int): 分割的数量。
%723 (int): 轴。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -3626,13 +4059,13 @@ def aten_split(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%159
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
layer_inputs["input"] = inputs_name[0]
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 处理输入2,即%723
mapper._check_input(graph, inputs_node[2], inputs_name[2], current_outputs)
layer_inputs["dim"] = inputs_name[2]
mapper._check_input(graph, inputs_node[2], inputs_name[2], current_outputs, scope_name)
layer_inputs["axis"] = inputs_name[2]
# 处理输入1,即%135
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
input_type = list(node.inputs())[0].type()
if "[]" in str(input_type):
layer_inputs["num_or_sections"] = inputs_name[1]
......@@ -3642,9 +4075,10 @@ def aten_split(mapper, graph, node):
current_inputs = list(layer_inputs.values())
graph.add_layer(
"fluid.layers.split",
"paddle.split",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -3660,6 +4094,7 @@ def aten_transpose(mapper, graph, node):
%704 (int): 转置的维度1。
%705 (int): 转置的维度2。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -3668,43 +4103,48 @@ def aten_transpose(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%x.21
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 处理输入1,即%704
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
dim1 = inputs_name[1]
# 处理输入2,即%705
mapper._check_input(graph, inputs_node[2], inputs_name[2], current_outputs)
mapper._check_input(graph, inputs_node[2], inputs_name[2], current_outputs, scope_name)
dim2 = inputs_name[2]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
current_inputs = list(layer_inputs.values())
graph.add_layer(
"fluid.layers.shape",
"prim.shape",
inputs={"input": inputs_name[0]},
outputs=[output_name + "_shape"])
outputs=[output_name + "_shape"],
scope_name=scope_name)
current_outputs.append(output_name + "_shape")
graph.add_layer(
"prim.len",
inputs={"input": output_name + "_shape"},
outputs=[output_name + "_len"])
outputs=[output_name + "_len"],
scope_name=scope_name)
current_outputs.append(output_name + "_len")
current_inputs.append(output_name + "_shape")
graph.add_layer(
"prim.len2list",
inputs={"len": output_name + "_len"},
outputs=[output_name + "_list"])
outputs=[output_name + "_list"],
scope_name=scope_name)
current_outputs.append(output_name + "_list")
current_inputs.append(output_name + "_len")
graph.add_layer(
"prim.check_dim",
inputs={"len": output_name + "_len",
"dim": dim1},
outputs=[dim1 + "_new"])
outputs=[dim1 + "_new"],
scope_name=scope_name)
graph.add_layer(
"prim.check_dim",
inputs={"len": output_name + "_len",
"dim": dim2},
outputs=[dim2 + "_new"])
outputs=[dim2 + "_new"],
scope_name=scope_name)
graph.add_layer(
"prim.replaceitem",
inputs={
......@@ -3712,7 +4152,8 @@ def aten_transpose(mapper, graph, node):
"index": dim1 + "_new",
"item": dim2 + "_new"
},
outputs=[])
outputs=[],
scope_name=scope_name)
graph.add_layer(
"prim.replaceitem",
inputs={
......@@ -3720,11 +4161,13 @@ def aten_transpose(mapper, graph, node):
"index": dim2 + "_new",
"item": dim1 + "_new"
},
outputs=[])
outputs=[],
scope_name=scope_name)
graph.add_layer(
"fluid.layers.transpose",
"paddle.transpose",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
perm=output_name + "_list")
return current_inputs, current_outputs
......@@ -3739,6 +4182,7 @@ def aten_to(mapper, graph, node):
%extended_attention_mask.1 (Tensor): 需要转换的Tensor。
%12 (int): 转换的类型。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -3747,7 +4191,7 @@ def aten_to(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%13
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
......@@ -3758,9 +4202,10 @@ def aten_to(mapper, graph, node):
layer_attrs["dtype"] = dtype_dict[mapper.attrs[inputs_name[1]]]
graph.add_layer(
"fluid.layers.cast",
"paddle.cast",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -3775,6 +4220,7 @@ def aten_type_as(mapper, graph, node):
%56 (Tensor): 需要改变类型的Tensor。
%mask.1 (Tensor): 转换成与该Tensor相一致的类型。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -3782,21 +4228,22 @@ def aten_type_as(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%56
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
# 处理输入0,即%mask.1
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
graph.add_layer(
"prim.type",
inputs={"input": inputs_name[1]},
outputs=[inputs_name[1] + "_type"])
outputs=[inputs_name[1] + "_type"],
scope_name=scope_name)
layer_inputs["dtype"] = inputs_name[1] + "_type"
current_inputs.append(inputs_name[1])
graph.add_layer(
"fluid.layers.cast", inputs=layer_inputs, outputs=layer_outputs)
"paddle.cast", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -3810,6 +4257,7 @@ def aten_unsqueeze(mapper, graph, node):
%12 (Tensor): 需要插入维度的Tensor。
%7 (int): 维度。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -3818,7 +4266,7 @@ def aten_unsqueeze(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%13
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
......@@ -3827,13 +4275,14 @@ def aten_unsqueeze(mapper, graph, node):
layer_attrs["axis"] = mapper.attrs[inputs_name[1]]
else:
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs)
current_outputs, scope_name)
layer_inputs["axis"] = inputs_name[1]
current_inputs.append(inputs_name[1])
graph.add_layer(
"paddle.tensor.unsqueeze",
"paddle.unsqueeze",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -3851,6 +4300,7 @@ def aten_upsample_bilinear2d(mapper, graph, node):
%4995 (float): 高度的乘数因子。
%4995 (float): 宽度的乘数因子。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -3859,7 +4309,7 @@ def aten_upsample_bilinear2d(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%x.13
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
......@@ -3868,25 +4318,29 @@ def aten_upsample_bilinear2d(mapper, graph, node):
layer_attrs["size"] = mapper.attrs[inputs_name[1]]
else:
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs)
current_outputs, scope_name)
layer_inputs["size"] = inputs_name[1]
current_inputs.append(inputs_name[1])
graph.add_layer(
"prim.isinstance",
inputs={"input": inputs_name[1]},
outputs=[inputs_name[1] + "_isinstance"],
scope_name=scope_name,
cls="paddle.fluid.Variable")
# TODO(syf): paddle.Variable
graph.add_layer(
"prim.if", {"input": inputs_name[1] + "_isinstance"},
outputs=[inputs_name[0] + "_if1"])
outputs=[inputs_name[0] + "_if1"],
scope_name=scope_name)
if_layer = graph.layers[list(graph.layers.keys())[-1]]
block = PaddleGraph(if_layer, graph_type="dygraph")
block = PaddleGraph(parent_layer=if_layer, graph_type="dygraph")
block.add_layer(
"prim.var2list",
inputs={"input": inputs_name[1]},
outputs=[inputs_name[1]])
outputs=[inputs_name[1]],
scope_name=scope_name)
if_layer.add_block(block)
block = PaddleGraph(if_layer, graph_type="dygraph")
block = PaddleGraph(parent_layer=if_layer, graph_type="dygraph")
if_layer.add_block(block)
if_layer.inputs["input-0"] = inputs_name[1]
# 处理输入2,即%5421
......@@ -3894,22 +4348,23 @@ def aten_upsample_bilinear2d(mapper, graph, node):
layer_attrs["align_corners"] = mapper.attrs[inputs_name[2]]
else:
mapper._check_input(graph, inputs_node[2], inputs_name[2],
current_outputs)
current_outputs, scope_name)
layer_inputs["align_corners"] = inputs_name[2]
current_inputs.append(inputs_name[2])
# 处理输入3和4,构造assert
list_layer_inputs = {}
mapper._check_input(graph, inputs_node[3], inputs_name[3], current_outputs)
list_layer_inputs["key"] = inputs_name[3]
current_inputs.append(inputs_name[3])
mapper._check_input(graph, inputs_node[4], inputs_name[4], current_outputs)
list_layer_inputs["value"] = inputs_name[4]
current_inputs.append(inputs_name[4])
graph.add_layer(
"prim.assert",
inputs=list_layer_inputs,
outputs=[output_name + "_assert"],
type="eq")
# # 处理输入3和4,构造assert
# list_layer_inputs = {}
# mapper._check_input(graph, inputs_node[3], inputs_name[3], current_outputs, scope_name)
# list_layer_inputs["key"] = inputs_name[3]
# current_inputs.append(inputs_name[3])
# mapper._check_input(graph, inputs_node[4], inputs_name[4], current_outputs, scope_name)
# list_layer_inputs["value"] = inputs_name[4]
# current_inputs.append(inputs_name[4])
# graph.add_layer(
# "prim.assert",
# inputs=list_layer_inputs,
# outputs=[output_name + "_assert"],
# scope_name=scope_name,
# type="eq")
layer_inputs["scale_factor"] = inputs_name[3]
layer_attrs["align_mode"] = 0
layer_attrs["mode"] = string("bilinear")
......@@ -3917,10 +4372,37 @@ def aten_upsample_bilinear2d(mapper, graph, node):
"paddle.nn.functional.interpolate",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
def aten_values(mapper, graph, node):
""" 构造对比大小的PaddleLayer。
TorchScript示例:
%5 : Float(1, *, 1024, 2048)[] = aten::values(%1)
参数含义:
%5 (list): 输出,由字典获取的values的list。
%1 (dict): 字典。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
inputs_name, inputs_node = mapper._get_inputs_name(node)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%78
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.dict2values", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
def aten_view(mapper, graph, node):
""" 构造调整大小的PaddleLayer。
......@@ -3937,6 +4419,7 @@ def aten_view(mapper, graph, node):
此时就不能再调用view函数。因此,需要先使用contiguous来返回一个contiguous copy。
reshape则不需要依赖目标Tensor是否在内存中是连续的。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -3945,7 +4428,7 @@ def aten_view(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%x.20
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入、输出的list
current_inputs = list(layer_inputs.values())
......@@ -3954,55 +4437,15 @@ def aten_view(mapper, graph, node):
layer_attrs["shape"] = mapper.attrs[inputs_name[1]]
else:
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs)
current_outputs, scope_name)
layer_inputs["shape"] = inputs_name[1]
current_inputs.append(inputs_name[1])
graph.add_layer(
"prim.type",
inputs={"input": inputs_name[0]},
outputs=[inputs_name[0] + "_type"])
graph.add_layer(
"prim.str",
inputs={"input": inputs_name[0] + "_type"},
outputs=[inputs_name[0] + "_type"])
graph.add_layer(
"prim.eq",
inputs={"x": inputs_name[0] + "_type"},
outputs=[inputs_name[0] + "_cond"],
y=string("VarType.BOOL"))
graph.add_layer(
"prim.if", {'input': inputs_name[0] + "_cond"},
outputs=[inputs_name[0] + "_if1"])
if_layer = graph.layers[list(graph.layers.keys())[-1]]
block = PaddleGraph(if_layer, graph_type="dygraph")
block.add_layer(
"fluid.layers.cast",
inputs={"x": inputs_name[0]},
outputs=[inputs_name[0]],
dtype=string("int32"))
if_layer.add_block(block)
block = PaddleGraph(if_layer, graph_type="dygraph")
if_layer.add_block(block)
if_layer.inputs["input-0"] = inputs_name[0]
graph.add_layer(
"fluid.layers.reshape",
"paddle.reshape",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
graph.add_layer(
"prim.if", {'input': inputs_name[0] + "_cond"},
outputs=[inputs_name[0] + "_if2"])
if_layer = graph.layers[list(graph.layers.keys())[-1]]
block = PaddleGraph(if_layer, graph_type="dygraph")
block.add_layer(
"fluid.layers.cast",
inputs={"x": layer_outputs[0]},
outputs=layer_outputs,
dtype=string("bool"))
if_layer.add_block(block)
block = PaddleGraph(if_layer, graph_type="dygraph")
if_layer.add_block(block)
if_layer.inputs["input-0"] = layer_outputs[0]
return current_inputs, current_outputs
......@@ -4015,6 +4458,7 @@ def aten_warn(mapper, graph, node):
%3 (str): warning的提示字符串。
%2 (int): warning的stacklevel。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -4023,7 +4467,7 @@ def aten_warn(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%3
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
......@@ -4032,7 +4476,7 @@ def aten_warn(mapper, graph, node):
layer_attrs["stacklevel"] = mapper.attrs[inputs_name[1]]
else:
mapper._check_input(graph, inputs_node[1], inputs_name[1],
current_outputs)
current_outputs, scope_name)
layer_inputs["stacklevel"] = inputs_name[1]
current_inputs.append(inputs_name[1])
......@@ -4040,6 +4484,7 @@ def aten_warn(mapper, graph, node):
"prim.warnings",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -4055,6 +4500,7 @@ def aten_where(mapper, graph, node):
%w0.2 (Tensor): 输入数值 x。
%210 (Tensor): 输入数值 y。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -4062,18 +4508,18 @@ def aten_where(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%209
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["condition"] = inputs_name[0]
# 处理输入1,即%w0.2
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs)
mapper._check_input(graph, inputs_node[1], inputs_name[1], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[1]
# 处理输入1,即%w0.2
mapper._check_input(graph, inputs_node[2], inputs_name[2], current_outputs)
mapper._check_input(graph, inputs_node[2], inputs_name[2], current_outputs, scope_name)
layer_inputs["y"] = inputs_name[2]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("paddle.where", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("paddle.where", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -4090,6 +4536,7 @@ def aten_zeros(mapper, graph, node):
%4995 (Device): 设备。
%4995 (bool): 是否计算梯度。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -4103,7 +4550,7 @@ def aten_zeros(mapper, graph, node):
layer_attrs["shape"] = mapper.attrs[inputs_name[0]]
else:
mapper._check_input(graph, inputs_node[0], inputs_name[0],
current_outputs)
current_outputs, scope_name)
layer_inputs["shape"] = inputs_name[0]
current_inputs.append(inputs_name[0])
# 处理输入1,即%8,代表dtype
......@@ -4113,6 +4560,7 @@ def aten_zeros(mapper, graph, node):
"paddle.zeros",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -4131,6 +4579,7 @@ def aten_zeros_like(mapper, graph, node):
%671 (bool): 是否计算梯度。
%672 (memory_format): 存储类型。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -4139,7 +4588,7 @@ def aten_zeros_like(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%n.2
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["x"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
......@@ -4150,5 +4599,6 @@ def aten_zeros_like(mapper, graph, node):
"paddle.zeros_like",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
# -*- coding:UTF-8 -*-
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"
......@@ -25,6 +26,7 @@ def prim_Constant(mapper, graph, node):
参数含义:
%2 (常量类型由赋值类型定义,该示例中为int型): 常量赋值结果输出。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
output = list(node.outputs())[0]
value = output.toIValue()
......@@ -32,7 +34,10 @@ def prim_Constant(mapper, graph, node):
if isinstance(value, str):
value = string(value)
if str(output_type) == "Tensor":
tensor_value = value
value = "{}".format(value)
if "tensor" in value:
mapper.pytorch_params[output_name] = tensor_value.cpu().detach().numpy()
if "inf" in str(value):
t = str(type(value)).split("'")[1]
......@@ -45,7 +50,7 @@ def prim_Constant(mapper, graph, node):
value = int(math.pow(2, 31) - 1)
mapper.attrs[output_name] = value
graph.add_layer(
"prim.constant", inputs={}, outputs=[output_name], value=value)
"prim.constant", inputs={}, outputs=[output_name], scope_name=scope_name, value=value)
return [], [output_name]
......@@ -60,6 +65,7 @@ def prim_data(mapper, graph, node):
【注意】Paddle中无此用法,所以此处翻译成赋值。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -68,15 +74,53 @@ def prim_data(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%4336
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.equal", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.equal", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
def prim_DictConstruct(mapper, graph, node):
""" 构建dict。
TorchScript示例:
%32 : Dict(str, Tensor) = prim::DictConstruct(%30, %23, %31, %29)
参数含义:
%32 (dict): 组成的字典。
%30 (str): key。
%23 (-): value。
%31 (str): key。
%29 (-): value。
"""
scope_name = mapper.normalize_scope_name(node)
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)
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理每个输入
for i, input_name in enumerate(inputs_name):
if i%2 == 0:
layer_attrs["key{}".format(int(i/2))] = mapper.attrs[input_name]
else:
layer_inputs["value{}".format(int(i/2))] = input_name
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.dict_construct",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
def prim_GetAttr(mapper, graph, node):
""" 获取attribute信息。
......@@ -86,6 +130,7 @@ def prim_GetAttr(mapper, graph, node):
%7 (Tensor): 输入Tensor。
%27 (Tensor): 输入Tensor。
"""
scope_name = mapper.normalize_scope_name(node)
current_node = node
field_name_list = [node.s('name')]
while True:
......@@ -102,7 +147,7 @@ def prim_GetAttr(mapper, graph, node):
if hasattr(part_script, field_name):
param = getattr(part_script, field_name)
if isinstance(param, torch.Tensor):
param = param.detach().numpy()
param = param.cpu().detach().numpy()
if len(param.shape) == 0:
param = np.reshape(param, 1)
if str(param.dtype) == "uint8":
......@@ -129,14 +174,15 @@ def prim_If(mapper, graph, node):
%107 (bool): if判断条件。
%input.5 (Tensor): if控制流的输出,与%output.4对应。
"""
scope_name = mapper.normalize_scope_name(node)
outputs_name = mapper._get_outputs_name(node)
node_outputs = outputs_name.copy()
current_outputs = outputs_name.copy()
input_node = list(node.inputs())[0].node()
script_input_unique_id = list(node.inputs())[0].unique()
input_node_name = mapper.outputs_info[script_input_unique_id]
mapper._check_input(graph, input_node, input_node_name, current_outputs)
graph.add_layer("prim.if", {'input': input_node_name}, node_outputs)
mapper._check_input(graph, input_node, input_node_name, current_outputs, scope_name)
graph.add_layer("prim.if", inputs={'input': input_node_name}, outputs=node_outputs, scope_name=scope_name)
current_layer = list(graph.layers.values())[-1]
block0 = list(node.blocks())[0]
block0_graph, graph_inputs0 = mapper.traverse(block0, current_layer)
......@@ -163,6 +209,7 @@ def prim_ListConstruct(mapper, graph, node):
%84 (int/其他): list第一个元素信息。
%85 (int/其他): list第二个元素信息。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -175,7 +222,7 @@ def prim_ListConstruct(mapper, graph, node):
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.list", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.list", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -189,6 +236,7 @@ def prim_ListUnpack(mapper, graph, node):
%x2.4 (Tensor): 输出,list的第二个元素。
%4354 (list): 列表。
"""
scope_name = mapper.normalize_scope_name(node)
outputs_name = mapper._get_outputs_name(node)
layer_outputs = outputs_name.copy()
layer_inputs = {}
......@@ -196,13 +244,13 @@ def prim_ListUnpack(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = layer_outputs.copy()
# 处理输入0,即%4354
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer(
"prim.list_unpack", inputs=layer_inputs, outputs=layer_outputs)
"prim.list_unpack", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
mapper.split_len[list(layer_inputs.values())[0]] = len(layer_outputs)
return current_inputs, current_outputs
......@@ -223,6 +271,7 @@ def prim_Loop(mapper, graph, node):
%x.3 (Tensor): 循环中修改的Tensor。
%x (Tensor): loop循环的输出,与%x.5对应。
"""
scope_name = mapper.normalize_scope_name(node)
node_outputs = mapper._get_outputs_name(node)
loop_inputs = {}
block = list(node.blocks())[0]
......@@ -242,7 +291,7 @@ def prim_Loop(mapper, graph, node):
loop_input_node_name = mapper.outputs_info[
script_loop_input_unique_id]
mapper._check_input(graph, loop_input_node, loop_input_node_name,
node_outputs)
node_outputs, scope_name)
loop_inputs['input'] = loop_input_node_name
loop_outputs.append(block_input_node_name)
node_outputs.append(block_input_node_name)
......@@ -252,14 +301,15 @@ def prim_Loop(mapper, graph, node):
loop_input_node_name = mapper.outputs_info[
script_loop_input_unique_id]
mapper._check_input(graph, loop_input_node, loop_input_node_name,
node_outputs)
node_outputs, scope_name)
graph.add_layer(
"prim.equal",
inputs={'input': loop_input_node_name},
outputs=[block_input_node_name])
outputs=[block_input_node_name],
scope_name=scope_name)
node_outputs.append(block_input_node_name)
graph.add_layer("prim.loop", inputs=loop_inputs, outputs=loop_outputs)
graph.add_layer("prim.loop", inputs=loop_inputs, outputs=loop_outputs, scope_name=scope_name)
current_layer = list(graph.layers.values())[-1]
block_graph, graph_inputs = mapper.traverse(block, current_layer)
for i, input_name in enumerate(graph_inputs):
......@@ -279,6 +329,7 @@ def prim_min(mapper, graph, node):
%86 (list): 输入。
%87 (int): 输出。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -286,12 +337,12 @@ def prim_min(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%86
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.min", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.min", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -304,6 +355,7 @@ def prim_NumToTensor(mapper, graph, node):
%other.2 (Tensor): 输出。
%1736 (-): 输入。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -312,25 +364,26 @@ def prim_NumToTensor(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%86
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
if inputs_node[0].kind() == "aten::size":
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
inputs_inputs_name, inputs_inputs_node = mapper._get_inputs_name(inputs_node[0])
if inputs_node[0].kind() == "aten::size" and len(inputs_inputs_name) > 1:
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer(
"prim_equal", inputs=layer_inputs, outputs=layer_outputs)
"prim_equal", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
else:
layer_inputs["value"] = inputs_name[0]
layer_inputs["fill_value"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
input_type = list(node.inputs())[0].type()
layer_attrs["dtype"] = input_type
layer_attrs["persistable"] = True
layer_attrs["shape"] = [1]
graph.add_layer(
"fluid.layers.create_global_var",
"paddle.full",
inputs=layer_inputs,
outputs=layer_outputs,
scope_name=scope_name,
**layer_attrs)
return current_inputs, current_outputs
......@@ -343,6 +396,7 @@ def prim_RaiseException(mapper, graph, node):
参数含义:
%76 (str): 异常信息。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -350,13 +404,13 @@ def prim_RaiseException(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%76
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer(
"prim.exception", inputs=layer_inputs, outputs=layer_outputs)
"prim.exception", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -369,6 +423,7 @@ def prim_requires_grad(mapper, graph, node):
%356 (bool): 输出,当前Tensor是否计算梯度。
%tensor.31 (Tensor): 输入的Tensor。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -376,13 +431,13 @@ def prim_requires_grad(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%86
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer(
"prim.requires_grad", inputs=layer_inputs, outputs=layer_outputs)
"prim.requires_grad", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -395,6 +450,7 @@ def prim_SetAttr(mapper, graph, node):
%260 (-): 属性名前缀。
%277 (-): 需要设置的值。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
field_name_list = []
tmp_node = node
......@@ -416,7 +472,8 @@ def prim_SetAttr(mapper, graph, node):
graph.add_layer(
"prim.set_attr",
inputs={"input": inputs_name[1]},
outputs=["self." + ".".join(field_name_list).replace(".", "_")])
outputs=["self." + ".".join(field_name_list).replace(".", "_")],
scope_name=scope_name)
return [], [output_name]
......@@ -429,6 +486,7 @@ def prim_shape(mapper, graph, node):
%4701 (list): 输出,shape信息。
%result.1 (Tensor): 需要获取shape的值。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -436,13 +494,13 @@ def prim_shape(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%input.8
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer(
"fluid.layers.shape", inputs=layer_inputs, outputs=layer_outputs)
"paddle.shape", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -456,6 +514,7 @@ def prim_TupleConstruct(mapper, graph, node):
%x.46 (Tensor/其他): tuple第一个元素信息。
%aux (Tensor/其他): tuple第二个元素信息。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -468,7 +527,7 @@ def prim_TupleConstruct(mapper, graph, node):
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.tuple", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.tuple", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -482,6 +541,7 @@ def prim_TupleUnpack(mapper, graph, node):
%aux.3 (Tensor/其他): 输出,tuple第二个元素信息。
%4492 (tuple): 需要获取元素的tuple。
"""
scope_name = mapper.normalize_scope_name(node)
outputs_name = mapper._get_outputs_name(node)
layer_outputs = outputs_name
layer_inputs = {}
......@@ -493,7 +553,7 @@ def prim_TupleUnpack(mapper, graph, node):
current_inputs = list(layer_inputs.values())
graph.add_layer(
"prim.tuple_unpack", inputs=layer_inputs, outputs=layer_outputs)
"prim.tuple_unpack", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -508,6 +568,7 @@ def prim_unchecked_cast(mapper, graph, node):
【注意】Paddle中无此用法,所以此处翻译成赋值。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
layer_outputs = [output_name]
layer_inputs = {}
......@@ -516,12 +577,12 @@ def prim_unchecked_cast(mapper, graph, node):
# 获取当前节点输出的list
current_outputs = [output_name]
# 处理输入0,即%size.63
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs)
mapper._check_input(graph, inputs_node[0], inputs_name[0], current_outputs, scope_name)
layer_inputs["input"] = inputs_name[0]
# 获取当前节点输入的list
current_inputs = list(layer_inputs.values())
graph.add_layer("prim.equal", inputs=layer_inputs, outputs=layer_outputs)
graph.add_layer("prim.equal", inputs=layer_inputs, outputs=layer_outputs, scope_name=scope_name)
return current_inputs, current_outputs
......@@ -533,9 +594,10 @@ def prim_Uninitialized(mapper, graph, node):
参数含义:
%345 (bool): 输出,为赋值的bool。
"""
scope_name = mapper.normalize_scope_name(node)
output_name = mapper._get_outputs_name(node)[0]
output = list(node.outputs())[0]
mapper.attrs[output_name] = None
graph.add_layer(
"prim.constant", inputs={}, outputs=[output_name], value=None)
"prim.constant", inputs={}, outputs=[output_name], scope_name=scope_name, value=None)
return [], [output_name]
# -*- coding:UTF-8 -*-
# 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.
NO_OUTPUT_COUNT = 0
def gen_codes(code_list, indent=0):
indent_blank = " " * indent
codes = []
for code_line in code_list:
if code_line.strip() == "":
codes.append('\n')
else:
codes.append(indent_blank + code_line + '\n')
return codes
def get_value(layer, key, layer_id=None, different_attrs=None):
""" 进行optimizer后可能把inputs的value直接用数值代替(ConstantFuser),
会把input换成attr,所以需要此处的操作。
"""
if key in layer.inputs:
return layer.inputs[key]
else:
if different_attrs is None:
return str(layer.attrs[key])
else:
key_name = "{}_{}".format(layer.outputs[0], key)
if key_name in different_attrs:
return key_name
else:
if layer_id is None:
return str(layer.attrs[key])
key_name = "{}_{}".format("layer_id/{}".format(layer_id), key)
if key_name in different_attrs:
new_key_name = "attr_{}".format(NO_OUTPUT_COUNT)
NO_OUTPUT_COUNT += 1
diff_index = different_attrs.index(key_name)
different_attrs[diff_index] = new_key_name
return new_key_name
else:
return str(layer.attrs[key])
def prim_add(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} + {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs), get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_add_(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} + {} * {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs),
layer.attrs["alpha"],
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_and(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} and {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs), get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_append(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{}.append({})".format(
get_value(layer, "list", layer_id, different_attrs),
get_value(layer, "element", layer_id, different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_assert(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
if layer.attrs["type"] == "eq":
values = get_value(layer, "key")
if "value" in layer.attrs:
values = layer.attrs["value"]
if isinstance(values, list):
s = ""
for v in values:
s += "{} == {} or ".format(get_value(layer, "key"), v)
if len(s) > 0:
s = s[:-4]
line = "assert {}, \'The {} must be {}!\'".format(
s, get_value(layer, "key"), get_value(layer, "value"))
else:
line = "assert {} == {}, \'The {} must be {}!\'".format(
get_value(layer, "key"),
get_value(layer, "value"),
get_value(layer, "key"), get_value(layer, "value"))
else:
raise Exception("Not implement yet!")
forward_func.extend(gen_codes([line], indent=indent))
def prim_check_dim(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
lines = []
dim = get_value(layer, "dim", different_attrs)
lines.append("if {} < 0:".format(dim))
lines.append(" {} = {} + {}".format(layer.outputs[
0], dim, get_value(layer, "len", different_attrs)))
lines.append("else:")
lines.append(" {} = {}".format(layer.outputs[0], dim))
forward_func.extend(gen_codes(lines, indent=indent))
def prim_constant(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {}".format(layer.outputs[0], layer.attrs["value"])
forward_func.extend(gen_codes([line], indent=indent))
def prim_contain(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} in {}".format(layer.outputs[0],
get_value(layer, "element", different_attrs),
get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_dict(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = dict()".format(layer.outputs[0])
forward_func.extend(gen_codes([line], indent=indent))
def prim_dict_construct(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
lines = list()
line = "{} = dict()".format(layer.outputs[0])
lines.append(line)
for i in range(len(layer.inputs)):
line = "{}[{}] = {}".format(layer.outputs[0],
get_value(layer, "key{}".format(i), different_attrs),
get_value(layer, "value{}".format(i), different_attrs))
lines.append(line)
forward_func.extend(gen_codes(lines, indent=indent))
def prim_dict2values(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = list({}.values())".format(layer.outputs[0],
get_value(layer, "x", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_div(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} / {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_eq(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} == {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_equal(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {}".format(layer.outputs[0], get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_exception(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "raise RaiseException({})".format(get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_float(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = float({})".format(layer.outputs[0], get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_floor(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = math.floor({})".format(layer.outputs[0],
get_value(layer, "x", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_floordiv(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} // {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_getitem(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {}[{}]".format(layer.outputs[0],
get_value(layer, "list", different_attrs),
get_value(layer, "index", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_gt(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} > {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_if(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "if {} :".format(get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
block = layer.blocks[0]
if len(block.layers) == 0:
line = "pass"
forward_func.extend(gen_codes([line], indent=indent + 1))
else:
b_init_lines, b_forward_lines = block.gen_dygraph_code(indent=indent + 1)
init_func.extend(b_init_lines)
forward_func.extend(b_forward_lines)
block = layer.blocks[1]
if len(block.layers) > 0:
b_init_lines, b_forward_lines = block.gen_dygraph_code(
indent=indent + 1)
if len(b_forward_lines) != 0:
line = "else:"
forward_func.extend(gen_codes([line], indent=indent))
init_func.extend(b_init_lines)
forward_func.extend(b_forward_lines)
def prim_int(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = int({})".format(layer.outputs[0], get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_is(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} is {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_isinstance(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = isinstance({}, {})".format(layer.outputs[0],
get_value(layer, "input", different_attrs),
layer.attrs["cls"])
forward_func.extend(gen_codes([line], indent=indent))
def prim_isnot(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} is not {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_le(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} <= {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_len(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = len({})".format(layer.outputs[0], get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_len2list(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
lines = []
lines.append("{} = []".format(layer.outputs[0]))
lines.append("for i in range({}):".format(get_value(layer, "len", different_attrs)))
lines.append(" {}.append(i)".format(layer.outputs[0]))
forward_func.extend(gen_codes(lines, indent=indent))
def prim_lt(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} < {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_list(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
input_len = len(layer.inputs) + len(layer.attrs)
inputs_list = list()
for i in range(input_len):
inputs_list.append(get_value(layer, "input{}".format(i), different_attrs))
inputs_str = ', '.join(inputs_list)
line = "{} = [{}]".format(layer.outputs[0], inputs_str)
forward_func.extend(gen_codes([line], indent=indent))
def prim_list_unpack(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {}".format(", ".join(layer.outputs), get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_loop(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
loop_range = get_value(layer, "input", different_attrs)
line = "for {} in range({}):".format(layer.outputs[1], loop_range)
forward_func.extend(gen_codes([line], indent=indent))
block = layer.blocks[0]
b_init_lines, b_forward_lines = block.gen_dygraph_code(indent=indent + 1)
init_func.extend(b_init_lines)
forward_func.extend(b_forward_lines)
def prim_min(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = min({})".format(layer.outputs[0], get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_mul(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} * {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_ne(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} != {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_neg(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = -{}".format(layer.outputs[0], get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_not(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = not {}".format(layer.outputs[0], get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_or(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} or {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_replaceitem(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{}[{}] = {}".format(
get_value(layer, "list", layer_id, different_attrs),
get_value(layer, "index", layer_id, different_attrs),
get_value(layer, "item", layer_id, different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_requires_grad(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = not {}.stop_gradient".format(layer.outputs[0],
get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_rsub(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} - {} * {}".format(layer.outputs[0],
get_value(layer, "y", different_attrs),
get_value(layer, "x", different_attrs),
get_value(layer, "alpha", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_select(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {}[".format(layer.outputs[0], get_value(layer, "input", different_attrs))
for dim in range(layer.attrs["dim"]):
line += ":, "
line += (get_value(layer, "index", different_attrs) + "]")
forward_func.extend(gen_codes([line], indent=indent))
def prim_set_attr(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {}".format(layer.outputs[0], get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_set_item(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{}[{}] = {}".format(
get_value(layer, "dict", different_attrs),
get_value(layer, "key", different_attrs), get_value(layer, "value", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_shape(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {}.shape".format(layer.outputs[0],
get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_shape_dim(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {}.shape[{}]".format(layer.outputs[0],
get_value(layer, "input", different_attrs),
get_value(layer, "dim", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_slice(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {}[{}: {}: {}]".format(layer.outputs[0],
get_value(layer, "input", different_attrs),
get_value(layer, "start", different_attrs),
get_value(layer, "end", different_attrs),
get_value(layer, "step", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_startswith(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {}.startswith({})".format(layer.outputs[0],
get_value(layer, "input", different_attrs),
get_value(layer, "start_str", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_str(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = str({})".format(layer.outputs[0], get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_sub(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {} - {}".format(layer.outputs[0],
get_value(layer, "x", different_attrs),
get_value(layer, "y", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_tuple(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
input_len = len(layer.inputs) + len(layer.attrs)
inputs_list = list()
for i in range(input_len):
inputs_list.append(get_value(layer, "input{}".format(i), different_attrs))
inputs_str = ', '.join(inputs_list)
line = "{} = ({})".format(layer.outputs[0], inputs_str)
forward_func.extend(gen_codes([line], indent=indent))
def prim_tuple_unpack(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
outputs_str = ', '.join(layer.outputs)
line = "{} = {}".format(outputs_str, get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_type(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {}.dtype".format(layer.outputs[0], get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_var2list(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
line = "{} = {}.numpy().tolist()".format(layer.outputs[0],
get_value(layer, "input", different_attrs))
forward_func.extend(gen_codes([line], indent=indent))
def prim_warnings(layer, indent=1, init_func=[], forward_func=[], layer_id=None, different_attrs=None):
lines = ["import warnings"]
line = "warnings.warn({}, stacklevel={})".format(
get_value(layer, "input", different_attrs), layer.attrs["stacklevel"])
lines.append(line)
forward_func.extend(gen_codes(lines, indent=indent))
# 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 .gather import Gather
\ No newline at end of file
# 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.
import paddle
import paddle.fluid as fluid
from itertools import product
import numpy as np
class Gather(object):
def __init__(self, dim):
self.dim = dim
self.dtype_mapping = {"VarType.INT32": "int32",
"VarType.INT64": "int64"}
def __call__(self, x, index):
if self.dim < 0:
self.dim += len(x.shape)
x_range = list(range(len(x.shape)))
x_range[0] = self.dim
x_range[self.dim] = 0
x_swaped = paddle.transpose(x, perm=x_range)
index_range = list(range(len(index.shape)))
index_range[0] = self.dim
index_range[self.dim] = 0
index_swaped = paddle.transpose(index, perm=index_range)
dtype = self.dtype_mapping[str(index.dtype)]
x_shape = paddle.shape(x_swaped)
index_shape = paddle.shape(index_swaped)
prod = paddle.prod(x_shape, dtype=dtype) / x_shape[0]
x_swaped_flattend = paddle.flatten(x_swaped)
index_swaped_flattend = paddle.flatten(index_swaped)
index_swaped_flattend *= prod
bias = paddle.arange(start=0, end=prod, dtype=dtype)
bias = paddle.reshape(bias, x_shape[1:])
bias = paddle.crop(bias, index_shape[1:])
bias = paddle.flatten(bias)
bias = paddle.tile(bias, [index_shape[0]])
index_swaped_flattend += bias
gathered = paddle.index_select(x_swaped_flattend, index_swaped_flattend)
gathered = paddle.reshape(gathered, index_swaped.shape)
out = paddle.transpose(gathered, perm=x_range)
return out
# -*- coding:UTF-8 -*-
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"
......@@ -17,43 +18,54 @@ import numpy as np
from x2paddle.core.op_mapper import OpMapper
from x2paddle.core.util import *
from x2paddle.core.program import PaddleGraph
from x2paddle.op_mapper.pytorch2paddle import prim
from x2paddle.op_mapper.pytorch2paddle import aten
from x2paddle.op_mapper.dygraph.pytorch2paddle import prim
from x2paddle.op_mapper.dygraph.pytorch2paddle import aten
class PyTorchOpMapper(OpMapper):
def __init__(self, decoder):
super(PyTorchOpMapper, self).__init__()
self.script = decoder.script
self.input_examples = decoder.input_examples
self.paddle_params = dict()
self.outputs_info = {} # key为output unique id,value为当前节点的输出名字
self.pytorch_params = {} # key为节点名,value为参数
self.attrs = {} # key为节点名,value为属性值
self.output_index = 0
self.dygraph_name_id = {} # 动态图__init__输出名字中的id,key为kernel类型,value为id
self.nn_name2id = {} # 动态图__init__输出名字中的id,key为kernel类型,value为id
self.split_len = {} # split的长度
self.scope_name_list = list()
self.scope_name2id = dict()
self.inputs_info = dict()
# 转换
self.check_op(decoder.graph)
self.graph, _ = self.traverse(decoder.graph)
if not self.op_checker(decoder.graph):
raise Exception("Model is not supported yet.")
self.paddle_graph, _ = self.traverse(decoder.graph)
self.paddle_graph.set_inputs_info(self.inputs_info)
def check_op(self, script_graph):
def op_checker(self, script_graph):
def _update_op_list(graph):
for node in graph.nodes():
op_list.append(node.kind())
for block in node.blocks():
_update_op_list(block)
op_list = list()
_update_op_list(script_graph)
op_list = list(set(op_list))
unsupported_op_list = []
unsupported_ops = []
for op in op_list:
func_name = op.replace('::', '_')
if not (hasattr(prim, func_name) or hasattr(aten, func_name)):
unsupported_op_list.append(op)
if len(unsupported_op_list) > 0:
raise Exception("The kind {} in model is not supported yet.".format(
unsupported_op_list))
unsupported_ops.append(op)
if len(unsupported_ops) == 0:
return True
else:
if len(unsupported_ops) > 0:
print("\n========= {} OPs are not supported yet ===========".format(
len(unsupported_ops)))
for op in unsupported_ops:
print("========== {} ============".format(op))
return False
def traverse(self, script_graph, parent_layer=None):
# 用于获取graph的输入
......@@ -72,17 +84,21 @@ class PyTorchOpMapper(OpMapper):
current_node_outputs.extend(outputs)
# 初始化
graph = PaddleGraph(parent_layer, graph_type="dygraph")
graph = PaddleGraph(parent_layer=parent_layer, graph_type="dygraph")
if "TopLevelTracedModule" in str(type(self.script)):
graph.set_script(self.script)
current_node_outputs = []
graph_inputs = []
# 转换输入节点
if isinstance(script_graph, torch._C.Graph):
input_ct = 0
for i, ivalue in enumerate(script_graph.inputs()):
node = ivalue.node()
if str(ivalue.type()) != "Tensor":
if str(ivalue.type()) not in ["Tensor", "Dict[str, Tensor]"]:
graph.set_name(str(ivalue.type()).split(".")[-1])
continue
inputs, outputs = self.data(graph, node, ivalue.unique())
inputs, outputs = self.data(graph, node, ivalue.unique(), input_ct)
input_ct += 1
# 转换中间节点
for node in script_graph.nodes():
kind = node.kind()
......@@ -120,7 +136,7 @@ class PyTorchOpMapper(OpMapper):
graph.outputs = inputs_name
# 更新split参数
for layer in graph.layers.values():
if layer.kernel == "fluid.layers.split" and "num_or_sections" in layer.attrs:
if layer.kernel == "paddle.split" and "num_or_sections" in layer.attrs:
layer.attrs["num_or_sections"] = self.split_len[layer.outputs[
0]]
return graph, graph_inputs
......@@ -151,6 +167,7 @@ class PyTorchOpMapper(OpMapper):
node,
output_name,
node_outputs,
scope_name,
add_dim=False):
if node.kind() == "prim::GetAttr":
param = self.pytorch_params[output_name]
......@@ -159,10 +176,13 @@ class PyTorchOpMapper(OpMapper):
param = param[np.newaxis, :]
self.paddle_params[output_name] = param
graph.add_layer(
"fluid.dygraph.base.to_variable",
"self.create_parameter",
inputs={},
outputs=[output_name],
value="params[{}]".format(string(output_name)))
scope_name=scope_name,
dtype=string(str(param.dtype)),
shape = param.shape,
default_initializer="paddle.nn.initializer.Constant(value=0.0)")
else:
if isinstance(param, dict) and "Tensor" in param and \
"parent_layer_id" in param:
......@@ -183,11 +203,13 @@ class PyTorchOpMapper(OpMapper):
param = param[np.newaxis, :]
self.paddle_params[output_name] = param
graph.add_layer(
"fluid.dygraph.base.to_variable",
"self.create_parameter",
inputs={},
outputs=[output_name],
value="params[{}]".format(
string(output_name)))
scope_name=scope_name,
dtype=string(str(param.dtype)),
shape = param.shape,
default_initializer="paddle.nn.initializer.Constant(value=0.0)")
node_outputs.append(output_name)
return
# 若if-else外,则可直接引用if-else中的赋值结果
......@@ -195,16 +217,30 @@ class PyTorchOpMapper(OpMapper):
"prim.constant",
inputs={},
outputs=[output_name],
scope_name=scope_name,
value=param["Tensor"])
else:
graph.add_layer(
"prim.constant",
inputs={},
outputs=[output_name],
scope_name=scope_name,
value=string(param)
if isinstance(param, str) else param)
node_outputs.append(output_name)
elif node.kind() == "prim::Constant" and output_name in self.pytorch_params:
param = self.pytorch_params[output_name]
self.paddle_params[output_name] = param
graph.add_layer(
"self.create_parameter",
inputs={},
outputs=[output_name],
scope_name=scope_name,
dtype=string(str(param.dtype)),
shape = param.shape,
default_initializer="paddle.nn.initializer.Constant(value=0.0)")
def _get_inputs_name(self, node):
inputs_name = []
inputs_node = []
......@@ -215,8 +251,10 @@ class PyTorchOpMapper(OpMapper):
inputs_node.append(script_input_node)
inputs_name.append(input_name)
return inputs_name, inputs_node
def data(self, graph, node, uid):
def data(self, graph, node, uid, input_ct):
scope_name = self.normalize_scope_name(node)
for output_ivalue in node.outputs():
script_unique_id = output_ivalue.unique()
if script_unique_id in self.outputs_info or script_unique_id != uid:
......@@ -226,13 +264,18 @@ class PyTorchOpMapper(OpMapper):
self.output_index += 1
output_name = self.outputs_info[uid]
graph.add_layer(
"fluid.dygraph.base.to_variable",
"paddle.to_tensor",
inputs={},
outputs=[node_name],
value=output_name)
scope_name=scope_name,
data=output_name)
if self.input_examples is not None:
input_np = self.input_examples[input_ct].detach().numpy()
self.inputs_info[output_name] = [list(input_np.shape), str(input_np.dtype)]
return [], [output_name]
def equal(self, graph, node, uid=None, parent_layer=None, index=None):
scope_name = self.normalize_scope_name(node)
if parent_layer is not None and index is not None:
# block的输出
input_node_name = self.outputs_info[uid]
......@@ -241,9 +284,61 @@ class PyTorchOpMapper(OpMapper):
control_output_id = index - 1
output_node_name = parent_layer.outputs[control_output_id]
current_outputs = [output_node_name]
self._check_input(graph, node, input_node_name, current_outputs)
self._check_input(graph, node, input_node_name, current_outputs, scope_name)
graph.add_layer(
"prim.equal",
inputs={'input': input_node_name},
outputs=[output_node_name])
outputs=[output_node_name],
scope_name=scope_name)
return [input_node_name], current_outputs
def normalize_scope_name(self, node):
""" 对scope的名字进行标准化。
"""
scope_name = node.scopeName()
if scope_name == "":
return scope_name
scope_name_part = scope_name.split("/")
for index in range(len(scope_name_part) - 1):
if scope_name_part[index] in scope_name_part[index + 1]:
continue
last_name_segments = scope_name_part[index].split(".")
name_segments = scope_name_part[index + 1].split(".")
for j, name in enumerate(last_name_segments):
name_segments[j] = name
scope_name_part[index + 1] = ".".join(name_segments)
last_name = scope_name_part[-1]
name_segments = last_name.split(".")
for i, ns in enumerate(name_segments):
if i not in self.scope_name2id:
self.scope_name2id[i] = dict()
if ns not in self.scope_name2id[i]:
self.scope_name2id[i][ns] = 0
real_scope_name = "/".join(name_segments[1:])
real_father_scope_name = "/".join(name_segments[1:-1])
for i, ns in enumerate(name_segments):
if i == 0:
continue
if self.scope_name2id[i][ns] != 0:
name_segments[i] = name_segments[i] + \
"__{}".format(self.scope_name2id[i][ns])
prefix_scope_name = "/".join(name_segments[1 :i + 1])
is_found = False
for j in range(len(self.scope_name_list)):
last_scope_name = self.scope_name_list[-1-j]
if last_scope_name.startswith(prefix_scope_name + "/") \
or last_scope_name == prefix_scope_name:
if j != 0: # and i != len(name_segments) - 1:
is_found = True
origin_name_segment_i = name_segments[i].split("__")[0]
self.scope_name2id[i][origin_name_segment_i] += 1
name_segments[i] = origin_name_segment_i + \
"__" + str(self.scope_name2id[i][origin_name_segment_i])
break
if is_found:
break
real_scope_name = "/".join(name_segments[1:])
self.scope_name_list.append(real_scope_name)
return real_scope_name
\ No newline at end of file
# 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.decoder.tf_decoder import TFGraph, TFGraphNode
from x2paddle.core.program import PaddleGraph
from x2paddle.core.op_mapper import OpMapper
from x2paddle.core.util import *
import traceback
import math
import inspect
import numpy
import sys
name_counter = dict()
def gen_name(op_name, var_name):
name = "{}_{}".format(op_name, var_name)
if name not in name_counter:
name_counter[name] = 0
else:
name_counter[name] += 1
name = name + '_' + str(name_counter[name])
return name
# compute padding size for SAME mode
def get_same_padding(in_size, kernel_size, stride):
new_size = int(math.ceil(in_size * 1.0 / stride))
pad_size = (new_size - 1) * stride + kernel_size - in_size
if pad_size < 0:
pad_size = 0
pad0 = int(pad_size / 2)
pad1 = pad_size - pad0
return [pad0, pad1]
class TFOpMapper(OpMapper):
directly_map_ops = {
'Relu': ['paddle.nn.ReLU'],
'Relu6': ['paddle.nn.ReLU6'],
'Abs': ['paddle.abs'],
'Sigmoid': ['paddle.nn.Sigmoid'],
'Exp': ['paddle.exp'],
'Rsqrt': ['paddle.rsqrt'],
'Sqrt': ['paddle.sqrt'],
'swish_f32': ['paddle.nn.Swish'],
'Tanh': ['paddle.nn.Tanh'],
'Softplus': ['paddle.nn.Softplus'],
'LeakyRelu': ['paddle.nn.LeakyReLU',
dict(alpha='negative_slope')],
'Softmax': ['paddle.nn.Softmax'],
'Floor': ['paddle.floor'],
'Erf': ['paddle.erf'],
'Square': ['paddle.square']
}
elementwise_ops = {
'Add': 'paddle.add',
'AddV2': 'paddle.add',
'RealDiv': 'paddle.divide',
'DivNoNan': 'paddle.divide',
'Sub': 'fluid.layers.elementwise_sub',
'Maximum': 'paddle.maximum',
'Minimum': 'paddle.minimum',
'LessEqual': 'paddle.less_equal',
'GreaterEqual': 'paddle.greater_equal',
'Greater': 'paddle.greater_than',
'NotEqual': 'paddle.not_equal',
'Equal': 'paddle.equal',
'Mul': 'paddle.multiply',
'FloorDiv': 'paddle.floor_divide',
'FloorMod': 'paddle.floor_mod',
'LogicalAnd': 'logical_and',
}
def __init__(self, decoder):
super(TFOpMapper, self).__init__()
self.decoder = decoder
self.graph = decoder.tf_graph
if not self.op_checker():
raise Exception("Model is not supported yet.")
self.params = dict()
self.nn_name2id = dict()
self.input_index = 0
self.inputs_info = dict()
self.paddle_graph = PaddleGraph(parent_layer=None, graph_type="dygraph", source_type="tf")
self.paddle_graph.outputs = self.graph.output_nodes
not_placeholder = list()
for name in self.graph.input_nodes:
if self.graph.get_node(
name).layer_type != "Placeholder" and self.graph.get_node(
name
).layer_type != "OneShotIterator" and self.graph.get_node(
name).layer_type != "IteratorV2":
not_placeholder.append(name)
for name in not_placeholder:
idx = self.graph.input_nodes.index(name)
del self.graph.input_nodes[idx]
print("Total nodes: {}".format(
sum([
isinstance(node, TFGraphNode)
for name, node in self.graph.node_map.items()
])))
print("Nodes converting ...")
for i, node_name in enumerate(self.graph.topo_sort):
sys.stderr.write("\rConverting node {} ... ".format(i + 1))
node = self.graph.get_node(node_name)
op = node.layer_type
if op in self.directly_map_ops:
self.directly_map(node)
elif op in self.elementwise_ops:
self.elementwise_map(node)
elif hasattr(self, op):
func = getattr(self, op)
func(node)
print("\nNodes converted.")
self.paddle_graph.set_name(self.graph.graph_name)
self.paddle_graph.set_parameters(self.params)
self.paddle_graph.set_inputs_info(self.inputs_info)
def op_checker(self):
unsupported_ops = set()
for node_name in self.graph.topo_sort:
node = self.graph.get_node(node_name)
op = node.layer_type
if not hasattr(self, op) and \
op not in self.directly_map_ops and \
op not in self.elementwise_ops:
unsupported_ops.add(op)
if len(unsupported_ops) == 0:
return True
else:
if len(unsupported_ops) > 0:
print("\n========= {} OPs are not supported yet ===========".format(
len(unsupported_ops)))
for op in unsupported_ops:
print("========== {} ============".format(op))
return False
def directly_map(self, node):
inputs = node.layer.input
assert len(inputs) == 1, 'directly_map error with multi inputs'
op_info = self.directly_map_ops[node.layer_type]
input = self.graph.get_input_node(node, 0)
paddle_op = op_info[0]
layer_attrs = dict()
if len(op_info) > 1:
attrs_name_map_dict = op_info[1]
for tf_attr_name, pd_attr_name in attrs_name_map_dict.items():
layer_attrs[pd_attr_name] = node.get_attr(tf_attr_name)
if paddle_op.startswith("paddle.nn"):
op_name = paddle_op[10:].lower()
op_name = name_generator(op_name, self.nn_name2id)
output_name = node.name
layer_outputs = [op_name, output_name]
self.paddle_graph.add_layer(
kernel=paddle_op,
inputs={"x": input.name},
outputs=layer_outputs,
**layer_attrs)
else:
self.paddle_graph.add_layer(
kernel=paddle_op,
inputs={"x": input.name},
outputs=[node.name],
**layer_attrs)
def elementwise_map(self, node):
op_type = self.elementwise_ops[node.layer_type]
x = self.graph.get_input_node(node, 0)
y = self.graph.get_input_node(node, 1)
x_shape = x.out_shapes[0]
y_shape = y.out_shapes[0]
layer_id = self.paddle_graph.add_layer(
kernel=op_type,
inputs={"x": x.name,
"y": y.name},
outputs=[node.name])
self.paddle_graph.layers[layer_id].input_shapes = {"x": x_shape, "y": y_shape}
def Placeholder(self, node):
shape = node.out_shapes[0]
assert len(shape) != 0, "Unknown shape of input nodes[{}].".format(
node.layer_name)
dtype = node.dtype
self.paddle_graph.add_layer(
kernel="paddle.to_tensor",
inputs={},
outputs=[node.name],
data="x{}".format(self.input_index))
self.inputs_info["x{}".format(self.input_index)] = [shape, node.dtype]
self.input_index += 1
def Const(self, node):
shape = node.out_shapes[0]
dtype = node.dtype
value = node.value
if len(shape) == 0:
assert value.size == 1, "Unexpected situation happend"
if value == float('inf'):
value = "float('inf')"
self.paddle_graph.add_layer(
"paddle.full",
inputs={},
outputs=[node.name],
dtype=string(dtype),
shape=[1],
fill_value=value)
return
self.params[node.name] = node.value
if 0 not in shape:
self.paddle_graph.add_layer(
"self.create_parameter",
inputs={},
outputs=[node.name],
shape=shape,
attr=string(node.name),
dtype=string(dtype),
default_initializer="paddle.nn.initializer.Constant(value=0.0)")
def Transpose(self, node):
input = self.graph.get_input_node(node, 0)
perm = self.graph.get_input_node(node, 1)
assert perm.layer_type == "Const", "Perm of transpose OP should be Const"
perm = perm.value.tolist()
self.paddle_graph.add_layer(
"paddle.transpose",
inputs={"x": input.name},
outputs=[node.name],
perm=perm)
def Where(self, node):
if len(node.layer.input) == 1:
cond = self.graph.get_input_node(node, 0)
self.paddle_graph.add_layer(
"paddle.nonzero",
inputs={"x": cond.name},
outputs=[node.name])
else:
cond = self.graph.get_input_node(node, 0)
x = self.graph.get_input_node(node, 1)
y = self.graph.get_input_node(node, 2)
self.paddle_graph.add_layer(
"paddle.where",
inputs={"condition": cond.name,
"x": x.name,
"y": y.name},
outputs=[node.name])
def Neg(self, node):
input = self.graph.get_input_node(node, 0)
self.paddle_graph.add_layer(
"paddle.scale",
inputs={"x": input.name},
outputs=[node.name],
scale=-1)
def Fill(self, node):
dims = self.graph.get_input_node(node, 0)
input_value = self.graph.get_input_node(node, 1)
inputs = dict()
layer_attrs = dict()
assert input_value.layer_type == "Const", "Value of fill OP should be Const"
if dims.layer_type == "Const":
layer_attrs["shape"] = dims.value.tolist()
else:
inputs["shape"] = dims.name
layer_attrs["dtype"] = string(input_value.dtype)
layer_attrs["fill_value"] = input_value.value
self.paddle_graph.add_layer(
"paddle.full",
inputs=inputs,
outputs=[node.name],
**layer_attrs)
def DepthToSpace(self, node):
input = self.graph.get_input_node(node, 0)
block_size = node.get_attr("block_size")
data_format = node.get_attr("data_format").decode()
if data_format == "NHWC":
n, h, w, c = input.out_shapes[0]
else:
n, c, h, w = input.out_shapes[0]
input_name = input.name
if data_format == "NHWC":
transpose_name = gen_name("depth_to_space", "transpose")
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
input_name = transpose_name
shape = [0, block_size * block_size, -1, h, w]
reshape_name = gen_name("depth_to_space", "reshape")
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": input_name},
outputs=[reshape_name],
shape=shape)
transpose_name = gen_name("depth_to_space", "transpose")
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": reshape_name},
outputs=[transpose_name],
perm=[0, 2, 1, 3, 4])
reshape_name = gen_name("depth_to_space", "reshape")
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": transpose_name},
outputs=[reshape_name],
shape=[0, c, h, w])
self.paddle_graph.add_layer(
kernel="fluid.layers.pixel_shuffle",
inputs={"x": reshape_name},
outputs=[node.name],
upscale_factor=block_size)
if data_format == "NHWC":
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 1])
def MaxPool(self, node):
input = self.graph.get_input_node(node, 0)
k_size = node.get_attr("ksize")
strides = node.get_attr("strides")
data_format = node.get_attr("data_format").decode()
pad_mode = node.get_attr("padding").decode()
input_name = input.name
if data_format == "NHWC":
transpose_name = gen_name("max_pool", "transpose")
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
strides = [strides[i] for i in [0, 3, 1, 2]]
k_size = [k_size[i] for i in [0, 3, 1, 2]]
input_name = transpose_name
op_name = name_generator("pool", self.nn_name2id)
output_name = node.name
layer_outputs = [op_name, output_name]
self.paddle_graph.add_layer(
kernel="paddle.nn.MaxPool2D",
inputs={"input": input_name},
outputs=layer_outputs,
kernel_size=k_size[2:4],
stride=strides[2:4],
padding=string(pad_mode))
if data_format == "NHWC":
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 1])
def Conv2D(self, node):
op_name = name_generator("conv", self.nn_name2id)
output_name = node.name
layer_outputs = [op_name, output_name]
input = self.graph.get_input_node(node, 0)
kernel = self.graph.get_input_node(node, 1)
k_size = kernel.out_shapes[0]
strides = node.get_attr("strides")
dilations = node.get_attr("dilations")
data_format = node.get_attr("data_format").decode()
pad_mode = node.get_attr("padding").decode()
if data_format == "NHWC":
n, h, w, c = input.out_shapes[0]
else:
n, c, h, w = input.out_shapes[0]
if kernel.layer_type == 'Const':
kernel_value = kernel.value
else:
kernel_value = self.decoder.infer_tensor(kernel, use_diff_inputs=False)
kernel_weight_name = op_name + ".weight"
self.params[kernel_weight_name] = numpy.transpose(kernel_value,
(3, 2, 0, 1))
input_name = input.name
if data_format == "NHWC":
strides = [strides[i] for i in [0, 3, 1, 2]]
dilations = [dilations[i] for i in [0, 3, 1, 2]]
transpose_name = gen_name("conv2d", "transpose")
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
input_name = transpose_name
if c == -1:
attr = {"shape": [0, k_size[2], 0, 0]}
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": input_name},
outputs=[input_name],
shape=[0, k_size[2], 0, 0])
self.paddle_graph.add_layer(
kernel="paddle.nn.Conv2D",
inputs={"input": input_name},
outputs=layer_outputs,
weight_attr=string(kernel_weight_name),
bias_attr=False,
in_channels=k_size[2],
out_channels=k_size[3],
kernel_size=k_size[0:2],
stride=strides[2:4],
dilation=dilations[2:4],
padding=string(pad_mode))
if data_format == "NHWC":
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 1])
def Conv3D(self, node):
op_name = name_generator("conv", self.nn_name2id)
output_name = node.name
layer_outputs = [op_name, output_name]
input = self.graph.get_input_node(node, 0)
kernel = self.graph.get_input_node(node, 1)
k_size = kernel.out_shapes[0]
strides = node.get_attr("strides")
dilations = node.get_attr("dilations")
data_format = node.get_attr("data_format").decode()
pad_mode = node.get_attr("padding").decode()
if data_format == "NDHWC":
n, d, h, w, c = input.out_shapes[0]
else:
n, c, d, h, w = input.out_shapes[0]
if kernel.layer_type == 'Const':
kernel_value = kernel.value
else:
kernel_value = self.decoder.infer_tensor(kernel, use_diff_inputs=False)
kernel_weight_name = op_name + ".weight"
self.params[kernel_weight_name] = numpy.transpose(kernel_value,
(4, 3, 0, 1, 2))
input_name = input.name
if data_format == "NDHWC":
strides = [strides[i] for i in [0, 4, 1, 2, 3]]
dilations = [dilations[i] for i in [0, 4, 1, 2, 3]]
transpose_name = gen_name("conv3d", "transpose")
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 4, 1, 2, 3])
input_name = transpose_name
if c == -1:
attr = {"shape": [0, k_size[2], 0, 0, 0]}
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": input_name},
outputs=[input_name],
shape=[0, k_size[2], 0, 0, 0])
self.paddle_graph.add_layer(
kernel="paddle.nn.Conv3D",
inputs={"input": input_name},
outputs=layer_outputs,
weight_attr=string(kernel_weight_name),
bias_attr=False,
in_channels=k_size[3],
out_channels=k_size[4],
kernel_size=k_size[0:3],
stride=strides[2:5],
dilation=dilations[2:5],
padding=string(pad_mode))
if data_format == "NDHWC":
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 4, 1])
def BiasAdd(self, node):
input = self.graph.get_input_node(node, 0)
bias = self.graph.get_input_node(node, 1)
self.paddle_graph.add_layer(
kernel="paddle.add",
inputs={"x": input.name,
"y": bias.name},
outputs=[node.name])
def FusedBatchNorm(self, node):
op_name = name_generator("bn", self.nn_name2id)
output_name = node.name
layer_outputs = [op_name, output_name]
input = self.graph.get_input_node(node, 0)
gamma = self.graph.get_input_node(node, 1)
beta = self.graph.get_input_node(node, 2)
moving_mean = self.graph.get_input_node(node, 3)
moving_var = self.graph.get_input_node(node, 4)
data_format = node.get_attr("data_format").decode()
assert gamma.layer_type == "Const"
assert beta.layer_type == "Const"
assert moving_mean.layer_type == "Const"
assert moving_var.layer_type == "Const"
input_name = input.name
if data_format == "NHWC":
transpose_name = gen_name("batch_norm", "transpose")
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
input_name = transpose_name
n, h, w, c = input.out_shapes[0]
else:
n, c, h, w = input.out_shapes[0]
self.params["{}_{}".format(node.name, gamma.name)] = self.params[gamma.name]
self.params["{}_{}".format(node.name, beta.name)] = self.params[beta.name]
self.params["{}_{}".format(node.name, moving_mean.name)] = self.params[moving_mean.name]
self.params["{}_{}".format(node.name, moving_var.name)] = self.params[moving_var.name]
self.paddle_graph.add_layer(
kernel="paddle.nn.BatchNorm",
inputs={"input": input_name},
outputs=layer_outputs,
num_channels=c,
epsilon=node.get_attr("epsilon"),
param_attr=string("{}_{}".format(node.name, gamma.name)),
bias_attr=string("{}_{}".format(node.name, beta.name)),
moving_mean_name=string("{}_{}".format(node.name, moving_mean.name)),
moving_variance_name=string("{}_{}".format(node.name, moving_var.name)),
is_test=True)
if data_format == "NHWC":
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 1])
def Mean(self, node):
input = self.graph.get_input_node(node, 0)
reduce_idx = self.graph.get_input_node(node, 1)
assert reduce_idx.layer_type == "Const", "Only support Const parameter[reduce_idx]"
dims = reduce_idx.value.tolist()
keep_dims = node.get_attr("keep_dims")
self.paddle_graph.add_layer(
kernel="paddle.mean",
inputs={"x": input.name},
outputs=[node.name],
axis=dims,
keepdim=keep_dims)
def Reshape(self, node):
input = self.graph.get_input_node(node, 0)
param = self.graph.get_input_node(node, 1)
input_name = input.name
if param.layer_type == "Const":
shape = param.value.tolist()
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": input_name},
outputs=[node.name],
shape=shape)
else:
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": input_name,
"shape": param.name},
outputs=[node.name])
if param.layer_type != "Const":
out_shape = numpy.array(node.out_shapes[0])
if (out_shape > 0).any():
out_shape[out_shape < 0] = 0
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": node.name},
outputs=[node.name],
shape=out_shape.tolist())
def Pad(self, node):
input = self.graph.get_input_node(node, 0)
paddings = self.graph.get_input_node(node, 1)
assert paddings.layer_type == "Const", "Padding should be Const"
paddings = paddings.value.flatten().tolist()
if len(input.out_shapes[0]) == 4:
if paddings[0] + paddings[1] + paddings[6] + paddings[7] == 0:
new_padding = paddings[2:6]
transpose_name = gen_name("pad", "transpose")
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.pad",
inputs={"x": transpose_name},
outputs=[node.name],
pad=new_padding)
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 1])
return
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.pad",
inputs={"x": input.name},
outputs=[node.name],
pad=paddings)
def MirrorPad(self, node):
op_name = name_generator("pad", self.nn_name2id)
output_name = node.name
layer_outputs = [op_name, output_name]
input = self.graph.get_input_node(node, 0)
paddings = self.graph.get_input_node(node, 1)
assert paddings.layer_type == "Const", "Padding should be Const"
paddings = np.flip(paddings.value, 0).flatten().tolist()
dim = int(len(paddings) / 2)
transpose_name = gen_name("pad", "transpose")
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
self.paddle_graph.add_layer(
kernel="paddle.nn.Pad{}D".format(dim),
inputs={"x": transpose_name},
outputs=layer_outputs,
pad=new_padding)
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 1])
def Squeeze(self, node):
input = self.graph.get_input_node(node, 0)
squeeze_dims = node.get_attr('squeeze_dims')
self.paddle_graph.add_layer(
kernel="paddle.squeeze",
inputs={"x": input.name},
outputs=[node.name],
axis=squeeze_dims)
def Shape(self, node):
input = self.graph.get_input_node(node, 0)
input_name = input.name
self.paddle_graph.add_layer(
kernel="paddle.shape",
inputs={"input": input_name},
outputs=[node.name])
def Size(self, node):
input = self.graph.get_input_node(node, 0)
input_name = input.name
self.paddle_graph.add_layer(
kernel="paddle.shape",
inputs={"input": input_name},
outputs=[node.name])
self.paddle_graph.add_layer(
kernel="paddle.prod",
inputs={"x": node.name},
outputs=[node.name])
def Ceil(self, node):
input = self.graph.get_input_node(node, 0)
self.paddle_graph.add_layer(
kernel="paddle.ceil",
inputs={"x": input.name},
outputs=[node.name])
def ArgMax(self, node):
input = self.graph.get_input_node(node, 0)
axis = self.graph.get_input_node(node, 1)
assert axis.layer_type == "Const", "ArgMax only support Const parameter"
axis = axis.value
self.paddle_graph.add_layer(
kernel="paddle.argmax",
inputs={"x": input.name},
outputs=[node.name],
axis=axis)
def TopKV2(self, node):
input = self.graph.get_input_node(node, 0)
k = self.graph.get_input_node(node, 1)
assert k.layer_type == "Const", "ArgMax only support Const parameter"
k = k.value
sort = node.get_attr('sorted')
self.paddle_graph.add_layer(
kernel="paddle.topk",
inputs={"x": input.name},
outputs=[node.name],
k=k,
sorted=sort)
def MatMul(self, node):
x = self.graph.get_input_node(node, 0)
y = self.graph.get_input_node(node, 1)
transpose_a = node.get_attr('transpose_a')
transpose_b = node.get_attr('transpose_b')
if transpose_a is None:
transpose_a = node.get_attr('adj_x')
if transpose_b is None:
transpose_b = node.get_attr('adj_y')
self.paddle_graph.add_layer(
kernel="paddle.matmul",
inputs={"x": x.name,
"y": y.name},
outputs=[node.name],
transpose_x=transpose_a,
transpose_y=transpose_b)
def BatchMatMul(self, node):
return self.MatMul(node)
def BatchMatMulV2(self, node):
return self.MatMul(node)
def DepthwiseConv2dNative(self, node):
op_name = name_generator("conv", self.nn_name2id)
output_name = node.name
layer_outputs = [op_name, output_name]
input = self.graph.get_input_node(node, 0)
kernel = self.graph.get_input_node(node, 1)
assert kernel.layer_type == "Const", "Kernel of DepthwiseConv2DNative should be Const"
in_shape = input.out_shapes[0]
k_size = kernel.out_shapes[0]
strides = node.get_attr("strides")
dilations = node.get_attr("dilations")
data_format = node.get_attr("data_format").decode()
pad_mode = node.get_attr("padding").decode()
kernel_weight_name = op_name + ".weight"
self.params[kernel_weight_name] = numpy.transpose(kernel.value,
(2, 3, 0, 1))
input_name = input.name
if data_format == "NHWC":
in_shape = [in_shape[i] for i in [0, 3, 1, 2]]
strides = [strides[i] for i in [0, 3, 1, 2]]
dilations = [dilations[i] for i in [0, 3, 1, 2]]
transpose_name = gen_name('depthwise_conv2d', 'transpose')
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
input_name = transpose_name
self.paddle_graph.add_layer(
kernel="paddle.nn.Conv2D",
inputs={"input": input_name},
outputs=layer_outputs,
weight_attr=string(kernel_weight_name),
bias_attr=False,
in_channels=in_shape[1],
out_channels=k_size[2],
kernel_size=k_size[0:2],
stride=strides[2:4],
dilation=dilations[2:4],
groups=k_size[3] * in_shape[1],
padding=string(pad_mode))
if data_format == "NHWC":
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 1])
def AvgPool(self, node):
input = self.graph.get_input_node(node, 0)
k_size = node.get_attr("ksize")
strides = node.get_attr("strides")
data_format = node.get_attr("data_format").decode()
pad_mode = node.get_attr("padding").decode()
input_name = input.name
if data_format == "NHWC":
transpose_name = gen_name("avg_pool", "transpose")
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
strides = [strides[i] for i in [0, 3, 1, 2]]
k_size = [k_size[i] for i in [0, 3, 1, 2]]
input_name = transpose_name
op_name = name_generator("pool", self.nn_name2id)
output_name = node.name
layer_outputs = [op_name, output_name]
# TODO(syf): The op has diff.
# self.paddle_graph.add_layer(
# kernel="paddle.nn.AvgPool2D",
# inputs={"input": input_name},
# outputs=layer_outputs,
# kernel_size=k_size[2:4],
# stride=strides[2:4],
# padding=string(pad_mode))
self.paddle_graph.add_layer(
kernel="fluid.layers.pool2d",
inputs={"input": input_name},
outputs=[node.name],
pool_size=k_size[2:4],
pool_type=string("avg"),
pool_stride=strides[2:4],
pool_padding=string(pad_mode))
if data_format == "NHWC":
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 1])
def Pack(self, node):
inputs_list = list()
for i in range(len(node.inputs)):
inputs_list.append(self.graph.get_input_node(node, i))
input_names = [i.name for i in inputs_list]
axis = node.get_attr("axis")
self.paddle_graph.add_layer(
kernel="paddle.stack",
inputs={"x": input_names},
outputs=[node.name],
axis=axis)
if len(node.out_shapes[0]) == 1:
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": node.name},
outputs=[node.name],
shape=[-1])
def Unpack(self, node):
input = self.graph.get_input_node(node, 0)
axis = node.get_attr("axis")
num = node.get_attr("num")
shape = input.out_shapes[0]
input_name = input.name
if len(shape) == 1:
if shape[0] > 0 and num == shape[0]:
self.paddle_graph.add_layer(
kernel="paddle.unsqueeze",
inputs={"x": input.name},
outputs=[node.name],
axis=[0])
input_name = node.name
axis = 1
else:
raise Exception("Unexpected situation happend in Unpack OP")
layer_outputs = ["{}_p{}".format(node.layer_name, i) for i in range(num)]
if len(layer_outputs) == 1:
layer_outputs[0] = "[{}]".format(node.layer_name)
self.paddle_graph.add_layer(
kernel="paddle.unstack",
inputs={"x": input_name},
outputs=layer_outputs,
axis=axis,
num=num)
def ConcatV2(self, node):
inputs_list = list()
for i in range(len(node.inputs) - 1):
inputs_list.append(self.graph.get_input_node(node, i))
axis = self.graph.get_input_node(node, -1)
assert axis.layer_type == "Const", "axis for ConcatV2 must be type Const"
axis = axis.value
if axis < 0:
axis += len(inputs_list[0].out_shapes[0])
input_names = [i.name for i in inputs_list]
self.paddle_graph.add_layer(
kernel="paddle.concat",
inputs={"x": input_names},
outputs=[node.name],
axis=axis)
def AddN(self, node):
inputs_list = list()
for i in range(len(node.inputs) - 1):
inputs_list.append(self.graph.get_input_node(node, i))
input_names = [i.name for i in inputs_list]
self.paddle_graph.add_layer(
kernel="paddle.add_n",
inputs={"inputs": input_names},
outputs=[node.name])
def StridedSlice(self, node):
input = self.graph.get_input_node(node, 0)
begin = self.graph.get_input_node(node, 1)
end = self.graph.get_input_node(node, 2)
strides = self.graph.get_input_node(node, 3)
if strides.layer_type == "Const":
strides = strides.value.tolist()
else:
strides = self.decoder.infer_tensor(strides)
if begin.layer_type == "Const":
begin = begin.value.tolist()
else:
begin = self.decoder.infer_tensor(begin)
if end.layer_type == "Const":
end = end.value.tolist()
else:
end = self.decoder.infer_tensor(end)
assert len(set(strides)) == 1 and strides[
0] == 1, "Only support strides be 1 in StridedSlice OP"
if len(begin) < len(input.out_shapes[0]):
begin = begin + [0] * (len(input.out_shapes[0]) - len(begin))
if len(end) < len(input.out_shapes[0]):
end = end + [0] * (len(input.out_shapes[0]) - len(end))
for i in range(len(end)):
if end[i] == 0:
end[i] = 999999
begin_mask = node.get_attr('begin_mask')
end_mask = node.get_attr('end_mask')
ellipsis_mask = node.get_attr('ellipsis_mask')
new_axis_mask = node.get_attr('new_axis_mask')
shrink_axis_mask = node.get_attr('shrink_axis_mask')
assert ellipsis_mask == 0, "(OP:{} Name:{})Only support ellipsis_mask be 0[now: {}] n StridedSlice OP".format(
node.layer_type, node.layer.name, ellipsis_mask)
# TODO codes without validation
# Use it carefully
new_begin = list()
new_end = list()
new_axes = list()
shrink_axes = list()
for i, item in enumerate(begin):
mask = (new_axis_mask >> i) & 1
if mask != 0:
new_axes.append(i)
continue
mask = (shrink_axis_mask >> i) & 1
if mask != 0:
shrink_axes.append(i)
mask = (begin_mask >> i) & 1
if mask != 0:
new_begin.append(0)
else:
new_begin.append(item)
mask = (end_mask >> i) & 1
if mask != 0:
new_end.append(999999)
else:
new_end.append(end[i])
if input.dtype == "bool":
self.paddle_graph.add_layer(
"paddle.cast",
inputs={"x": input.name},
outputs=[input.name],
dtype=string("int32"))
self.paddle_graph.add_layer(
kernel="paddle.slice",
inputs={"input": input.name},
outputs=[node.name],
axes=[i for i in range(len(new_begin))],
starts=new_begin,
ends=new_end)
if input.dtype == "bool":
self.paddle_graph.add_layer(
"paddle.cast",
inputs={"x": node.name},
outputs=[node.name],
dtype=string("bool"))
if len(new_axes) > 0:
self.paddle_graph.add_layer(
kernel="paddle.unsqueeze",
inputs={"x": node.name},
outputs=[node.name],
axis=new_axes)
if len(shrink_axes) > 0:
if len(input.out_shapes[0]) + len(new_axes) <= 1:
pass
else:
self.paddle_graph.add_layer(
kernel="paddle.squeeze",
inputs={"x": node.name},
outputs=[node.name],
axis=shrink_axes)
def Prod(self, node):
input = self.graph.get_input_node(node, 0)
reduction_indices = self.graph.get_input_node(node, 1)
assert reduction_indices.layer_type == "Const"
keep_dims = node.get_attr('keep_dims')
axis = reduction_indices.value
self.paddle_graph.add_layer(
kernel="paddle.prod",
inputs={"x": input.name},
outputs=[node.layer_name],
keepdim=keep_dims,
axis=axis)
def Split(self, node):
dim = self.graph.get_input_node(node, 0)
input = self.graph.get_input_node(node, 1)
assert dim.layer_type == "Const"
num_split = node.get_attr('num_split')
dim = dim.value
self.paddle_graph.add_layer(
kernel="paddle.split",
inputs={"x": input.name},
outputs=[
"{}_p{}".format(node.layer_name, i) for i in range(num_split)
],
num_or_sections=num_split,
axis=dim)
def Slice(self, node):
input = self.graph.get_input_node(node, 0)
begin = self.graph.get_input_node(node, 1)
size = self.graph.get_input_node(node, 2)
inputs = {"x": input.name}
attrs = {}
if begin.layer_type == "Const":
begin = begin.value.tolist()
attrs['offsets'] = begin
else:
# shape = begin.out_shapes[0]
# reshape_name = gen_name("slice", "reshape")
# self.paddle_graph.add_layer(
# kernel="fluid.layers.reshape",
# inputs={"x": begin.name},
# outputs=[reshape_name],
# shape=shape)
# inputs['offsets'] = reshape_name
begin = self.decoder.infer_tensor(begin, use_diff_inputs=False).tolist()
attrs['offsets'] = begin
if size.layer_type == "Const":
size = size.value.tolist()
attrs['shape'] = size
else:
shape = size.out_shapes[0]
reshape_name = gen_name("slice", "reshape")
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": size.name},
outputs=[reshape_name],
shape=shape)
inputs['shape'] = reshape_name
self.paddle_graph.add_layer(
kernel="paddle.crop",
inputs=inputs,
outputs=[node.name],
**attrs)
def ResizeNearestNeighbor(self, node):
input = self.graph.get_input_node(node, 0)
resize_shape = self.graph.get_input_node(node, 1)
data_format = "NHWC"
inputs = {"x": input.name}
attrs = {"align_corners": node.get_attr("align_corners"),
"mode": string("nearest"),
"align_mode": 1}
if resize_shape.layer_type == "Const":
resize_shape = resize_shape.value.tolist()
attrs["size"] = resize_shape
else:
shape = resize_shape.out_shapes[0]
reshape_name = gen_name("resize_nearest", "reshape")
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": resize_shape.name},
outputs=[reshape_name],
shape=shape)
inputs["size"] = reshape_name
if data_format == "NHWC":
transpose_name = gen_name("resize_nearest", "reshape")
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
inputs["x"] = transpose_name
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.interpolate",
inputs=inputs,
outputs=[node.name],
**attrs)
if data_format == "NHWC":
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 1])
def ResizeBilinear(self, node):
input = self.graph.get_input_node(node, 0)
resize_shape = self.graph.get_input_node(node, 1)
data_format = "NHWC"
inputs = {"x": input.name}
attrs = {"align_corners": node.get_attr("align_corners"),
"mode": string("bilinear"),
"align_mode": 1}
if resize_shape.layer_type == "Const":
resize_shape = resize_shape.value.tolist()
attrs["size"] = resize_shape
else:
shape = resize_shape.out_shapes[0]
reshape_name = gen_name("resize_bilinear", "reshape")
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": resize_shape.name},
outputs=[reshape_name],
shape=shape)
inputs["size"] = reshape_name
if data_format == "NHWC":
transpose_name = gen_name("resize_bilinear", "reshape")
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
inputs["x"] = transpose_name
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.interpolate",
inputs=inputs,
outputs=[node.name],
**attrs)
if data_format == "NHWC":
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 1])
def Cast(self, node):
input = self.graph.get_input_node(node, 0)
dtype = node.dtype
self.paddle_graph.add_layer(
kernel="paddle.cast",
inputs={"x": input.name},
outputs=[node.name],
dtype=string(dtype))
def Sum(self, node):
input = self.graph.get_input_node(node, 0)
reduce_idx = self.graph.get_input_node(node, 1)
assert reduce_idx.layer_type == "Const", "Only support Const parameter[reduce_idx]"
keep_dims = node.get_attr("keep_dims")
dim = reduce_idx.value.tolist()
self.paddle_graph.add_layer(
kernel="paddle.sum",
inputs={"x": input.name},
outputs=[node.name],
axis=dim,
keepdim=keep_dims)
def Max(self, node):
input = self.graph.get_input_node(node, 0)
reduce_idx = self.graph.get_input_node(node, 1)
assert reduce_idx.layer_type == "Const", "Only support Const parameter[reduce_idx]"
keep_dims = node.get_attr("keep_dims")
dim = reduce_idx.value.tolist()
self.paddle_graph.add_layer(
kernel="paddle.max",
inputs={"x": input.name},
outputs=[node.name],
axis=dim,
keepdim=keep_dims)
def RandomUniform(self, node):
shape = self.graph.get_input_node(node, 0)
if shape.layer_type == "Const":
shape = shape.value.tolist()
self.paddle_graph.add_layer(
kernel="paddle.uniform",
inputs={},
outputs=[node.name],
shape=shape,
min=0.0,
max=0.9999)
else:
self.paddle_graph.add_layer(
kernel="paddle.uniform",
inputs={'shape': shape.name},
outputs=[node.name],
min=0.0,
max=0.9999)
def Conv2DBackpropInput(self, node):
op_name = name_generator("conv", self.nn_name2id)
output_name = node.name
layer_outputs = [op_name, output_name]
out_shape = self.graph.get_input_node(node, 0)
kernel = self.graph.get_input_node(node, 1)
input = self.graph.get_input_node(node, 2)
assert kernel.layer_type == "Const", "Kernel of Conv2DBackpropInput should be Const"
if out_shape.layer_type == "Const":
out_shape = out_shape.value.tolist()
else:
out_shape = self.decoder.infer_tensor(out_shape,
out_shape=node.out_shapes[0])
in_shape = input.out_shapes[0]
if in_shape.count(-1) > 2:
in_shape = self.decoder.infer_tensor(input, use_diff_inputs=False).shape
k_size = kernel.out_shapes[0]
if k_size.count(-1) > 2:
k_size = self.decoder.infer_tensor(kernel, use_diff_inputs=False).shape
pad_mode = node.get_attr("padding").decode()
strides = node.get_attr("strides")
dilations = node.get_attr("dilations")
data_format = node.get_attr("data_format").decode()
kernel_name = op_name + ".weight"
self.params[kernel_name] = numpy.transpose(kernel.value, (3, 2, 0, 1))
input_name = input.name
if data_format == "NHWC":
in_shape = [in_shape[i] for i in [0, 3, 1, 2]]
strides = [strides[i] for i in [0, 3, 1, 2]]
dilations = [dilations[i] for i in [0, 3, 1, 2]]
transpose_name = gen_name("conv2dbackpropinput", "transpose")
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
input_name = transpose_name
# TODO(syf): The output_size is not set.
# self.paddle_graph.add_layer(
# kernel="paddle.nn.Conv2DTranspose",
# inputs={"input": input_name},
# outputs=layer_outputs,
# weight_attr=string(kernel_name),
# bias_attr=False,
# in_channels=k_size[3],
# out_channels=k_size[2],
# kernel_size=k_size[0:2],
# stride=strides[2:4],
# dilation=dilations[2:4],
# padding=string(pad_mode))
self.paddle_graph.add_layer(
"self.create_parameter",
inputs={},
outputs=["{}_{}".format(node.name, kernel_name).replace(".", "_")],
shape=self.params[kernel_name].shape,
attr=string(kernel_name))
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.conv2d_transpose",
inputs={"x": input_name,
"weight": "{}_{}".format(node.name, kernel_name).replace(".", "_")},
outputs=[node.name],
bias=None,
stride=strides[2:4],
dilation=dilations[2:4],
padding=string(pad_mode),
output_size=out_shape[1:3])
if data_format == "NHWC":
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 1])
def Tile(self, node):
input = self.graph.get_input_node(node, 0)
repeat_times = self.graph.get_input_node(node, 1)
inputs = {"x": input.name}
attr = dict()
in_shape = input.out_shapes[0]
if repeat_times.layer_type == "Const":
repeat_times = repeat_times.value.tolist()
attr["repeat_times"] = repeat_times
else:
inputs["repeat_times"] = repeat_times.name
self.paddle_graph.add_layer(
kernel="paddle.tile",
inputs=inputs,
outputs=[node.name],
**attr)
def Range(self, node):
start = self.graph.get_input_node(node, 0)
limit = self.graph.get_input_node(node, 1)
delta = self.graph.get_input_node(node, 2)
inputs = dict()
attr = dict()
dtype = 'int32'
if start.dtype.startswith('float'):
dtype = start.dtype
if start.layer_type == "Const":
attr["start"] = start.value
else:
inputs["start"] = start.name
if limit.dtype.startswith('float'):
dtype = limit.dtype
if limit.layer_type == "Const":
attr["end"] = limit.value
else:
inputs["end"] = limit.name
if delta.dtype.startswith('float'):
dtype = delta.dtype
if delta.layer_type == "Const":
attr["step"] = delta.value
else:
inputs["step"] = delta.name
node.set_dtype(dtype)
attr["dtype"] = string(node.dtype)
self.paddle_graph.add_layer(
kernel="paddle.arange",
inputs=inputs,
outputs=[node.name],
**attr)
def SquaredDifference(self, node):
x = self.graph.get_input_node(node, 0)
y = self.graph.get_input_node(node, 1)
inputs = {"x": x.name, "y": y.name}
x_shape = x.out_shapes[0]
y_shape = y.out_shapes[0]
layer_id = self.paddle_graph.add_layer(
"fluid.layers.elementwise_sub", inputs=inputs, outputs=[node.name])
self.paddle_graph.layers[layer_id].input_shapes = {"x": x_shape, "y": y_shape}
inputs = {"x": node.name, "y": node.name}
x_shape = node.out_shapes[0]
y_shape = node.out_shapes[0]
layer_id = self.paddle_graph.add_layer(
"paddle.multiply", inputs=inputs, outputs=[node.name])
self.paddle_graph.layers[layer_id].input_shapes = {"x": x_shape, "y": y_shape}
def OneHot(self, node):
input = self.graph.get_input_node(node, 0)
depth = self.graph.get_input_node(node, 1)
on_value = self.graph.get_input_node(node, 2)
off_value = self.graph.get_input_node(node, 3)
assert depth.layer_type == 'Const', 'Parameter depth should be Const in OneHot'
assert on_value.layer_type == 'Const', 'Parameter on_value should be Const in OneHot'
assert off_value.layer_type == 'Const', 'Parameter off_value should be Const in OneHot'
attr = {'depth': depth.value}
on_value = on_value.value
off_value = off_value.value
assert math.fabs(on_value -
1.0) < 1e-06, "on_value should be 1 in OneHot"
assert math.fabs(off_value -
0.0) < 1e-06, "off_value should be 0 in OneHot"
self.paddle_graph.add_layer(
"paddle.nn.functional.one_hot",
inputs={"x": input.name},
outputs=[node.name],
num_classes=depth.value)
def Pow(self, node):
x = self.graph.get_input_node(node, 0)
factor = self.graph.get_input_node(node, 1)
inputs = {"x": x.name}
attr = dict()
if factor.layer_type == 'Const':
attr["y"] = factor.value.tolist()
else:
inputs["y"] = factor.name
self.paddle_graph.add_layer(
"paddle.pow", inputs=inputs, outputs=[node.name], **attr)
def All(self, node):
input = self.graph.get_input_node(node, 0)
reduce_idx = self.graph.get_input_node(node, 1)
assert reduce_idx.layer_type == "Const", "Only support Const parameter[reduce_idx]"
attr = dict()
attr["axis"] = reduce_idx.value.tolist()
attr["keepdim"] = node.get_attr("keep_dims")
input_name = input.name
if input.dtype != "bool":
input_name = gen_name("all", "cast")
self.paddle_graph.add_layer(
"paddle.cast",
inputs={"x": input.name},
outputs=[input_name],
dtype=string("bool"))
self.paddle_graph.add_layer(
"paddle.all",
inputs={"x": input_name},
outputs=[node.name],
**attr)
node.layer.attr['dtype'].type = 10
def GatherV2(self, node):
embeddings = self.graph.get_input_node(node, 0)
index = self.graph.get_input_node(node, 1)
axis = self.graph.get_input_node(node, 2)
assert axis.layer_type == 'Const', "Only support Const parameter[axis]"
axis = axis.value
index_name = index.name
if len(index.out_shapes[0]) != 1:
reshape_name = gen_name("gather", "reshape")
index_name = reshape_name
self.paddle_graph.add_layer(
"paddle.reshape",
inputs={"x": index.name},
outputs=[reshape_name],
shape=[-1])
inputs = {'x': embeddings.name, 'index': index_name}
self.paddle_graph.add_layer(
"paddle.gather",
inputs=inputs,
outputs=[node.name],
axis=axis)
if len(index.out_shapes[0]) != 1:
out_shape = node.out_shapes[0]
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": node.name},
outputs=[node.name],
shape=out_shape)
def GatherNd(self, node):
x = self.graph.get_input_node(node, 0)
index = self.graph.get_input_node(node, 1)
inputs = {'x': x.name, 'index': index.name}
self.paddle_graph.add_layer(
"paddle.gather_nd",
inputs=inputs,
outputs=[node.name])
def ExpandDims(self, node):
x = self.graph.get_input_node(node, 0, copy=True)
y = self.graph.get_input_node(node, 1, copy=True)
inputs = {"x": x.name}
attr = dict()
if y.layer_type == 'Const':
dim = y.value.tolist()
if not isinstance(dim, list):
dim = [dim]
attr['axis'] = dim
else:
inputs['axis'] = y.name
self.paddle_graph.add_layer(
"paddle.unsqueeze",
inputs=inputs,
outputs=[node.name],
**attr)
......@@ -14,18 +14,6 @@ def detectionoutput_layer(inputs,
confidence_threshold=0.1,
input_shape=None,
name=None):
nms_param_str = nms_param
nms_param = {}
part = nms_param_str.split(',')
for s in part:
if s == '':
break
else:
name, obj = s.split(': ')
if name == 'top_k':
nms_param[name] = int(obj)
else:
nms_param[name] = float(obj)
if nms_param is None:
nms_param = {"nms_threshold": 0.3, "top_k": 10, "eta": 1.0}
mbox_conf_flatten = inputs[1]
......
......@@ -13,19 +13,21 @@
# limitations under the License.
import numbers
import copy
import numpy as np
from x2paddle.decoder.caffe_decoder import CaffeGraph
from x2paddle.core.op_mapper import OpMapper
from x2paddle.core.util import *
from x2paddle.op_mapper import caffe_shape
from x2paddle.op_mapper.caffe_custom_layer import *
from x2paddle.op_mapper.static.caffe2paddle import caffe_shape
from x2paddle.op_mapper.static.caffe2paddle.caffe_custom_layer import *
from x2paddle.core.program import PaddleGraph
class CaffeOpMapper(OpMapper):
directly_map_ops = {
'AbsVal': 'abs',
'Sigmoid': 'sigmoid',
'TanH': 'tanh',
'AbsVal': 'paddle.abs',
'Sigmoid': 'fluid.layers.sigmoid',
'TanH': 'paddle.tanh',
}
def __init__(self, decoder):
......@@ -34,6 +36,9 @@ class CaffeOpMapper(OpMapper):
self.weights = dict()
resolver = decoder.resolver
self.used_custom_layers = {}
self.paddle_graph = PaddleGraph(parent_layer=None, graph_type="static", source_type="caffe")
self.paddle_graph.inputs = self.graph.input_nodes
self.paddle_graph.outputs = self.graph.output_nodes
print("Total nodes: {}".format(len(self.graph.topo_sort)))
for node_name in self.graph.topo_sort:
......@@ -54,6 +59,9 @@ class CaffeOpMapper(OpMapper):
else:
raise Exception(
"The op {} in model is not supported yet.".format(op))
self.paddle_graph.set_parameters(self.weights)
self.paddle_graph.set_custom(self.used_custom_layers)
def op_checker(self):
unsupported_ops = set()
......@@ -181,34 +189,23 @@ class CaffeOpMapper(OpMapper):
def get_input_name(self, node):
if hasattr(node, "index"):
return node.layer_name + "[{}]".format(node.index)
return "{}_{}".format(node.layer_name, node.index)
else:
return node.layer_name
def Input(self, node):
shape = list(node.layer.input_param.shape[0].dim)[1:]
dtype = 'float32'
attr = {
'dtype': string(dtype),
'shape': shape,
'name': string(node.layer_name)
layer_attrs = {
"dtype": string(dtype),
"shape": [-1] + shape,
"name": string(node.layer_name)
}
node.fluid_code.add_layer(
"data", inputs=None, output=node, param_attr=attr)
def MemoryData(self, node):
# TODO(syf): Paddlepaddle can't fully support
shape = node.output_shape[0][1:]
dtype = 'float32'
attr = {
'dtype': string(dtype),
'shape': shape,
'name': string(node.layer_name)
}
node.fluid_code.add_layer(
"data", inputs=None, output=node.layer_name + '0', param_attr=attr)
node.fluid_code.add_note('{} = [{}]'.format(node.layer_name,
node.layer_name + '0'))
self.paddle_graph.add_layer(
kernel="fluid.data",
inputs={},
outputs=[node.layer_name],
**layer_attrs)
def Convolution(self, node):
data = node.data
......@@ -218,7 +215,7 @@ class CaffeOpMapper(OpMapper):
if data is None:
data = []
print(
'The parameter of {} (type is {}) is not set. So we set the parameters as 0'
"The parameter of {} (type is {}) is not set. So we set the parameters as 0"
.format(node.layer_name, node.layer_type))
input_c = node.input_shape[0][1]
output_c = channel
......@@ -233,9 +230,8 @@ class CaffeOpMapper(OpMapper):
self.weights[node.layer_name + '_bias'] = data[1]
assert len(node.inputs
) == 1, 'The count of Convolution node\'s input is not 1.'
input = self.graph.get_bottom_node(node, idx=0, copy=True)
attr = {
input = self.graph.get_input_node(node, idx=0, copy=True)
layer_attrs = {
'filter_size': kernel,
'num_filters': channel,
'stride': stride,
......@@ -247,9 +243,12 @@ class CaffeOpMapper(OpMapper):
'bias_attr': False
if len(data) == 1 else string(node.layer_name + '_bias'),
}
node.fluid_code.add_layer(
"conv2d", inputs=input, output=node, param_attr=attr)
self.paddle_graph.add_layer(
kernel="fluid.layers.conv2d",
inputs={"input": self.get_input_name(input)},
outputs=[node.layer_name],
**layer_attrs)
def Deconvolution(self, node):
data = node.data
params = node.layer.convolution_param
......@@ -273,8 +272,8 @@ class CaffeOpMapper(OpMapper):
self.weights[node.layer_name + '_bias'] = data[1]
assert len(node.inputs
) == 1, 'The count of Deconvolution node\'s input is not 1.'
input = self.graph.get_bottom_node(node, idx=0, copy=True)
attr = {
input = self.graph.get_input_node(node, idx=0, copy=True)
layer_attrs = {
'output_size': None,
'filter_size': kernel,
'num_filters': channel,
......@@ -287,8 +286,11 @@ class CaffeOpMapper(OpMapper):
'bias_attr': False
if len(data) == 1 else string(node.layer_name + '_bias')
}
node.fluid_code.add_layer(
"conv2d_transpose", inputs=input, output=node, param_attr=attr)
self.paddle_graph.add_layer(
kernel="fluid.layers.conv2d_transpose",
inputs={"input": self.get_input_name(input)},
outputs=[node.layer_name],
**layer_attrs)
def Pooling(self, node):
params = node.layer.pooling_param
......@@ -303,8 +305,8 @@ class CaffeOpMapper(OpMapper):
pool_type = 'avg'
assert len(
node.inputs) == 1, 'The count of Pooling node\'s input is not 1.'
input = self.graph.get_bottom_node(node, idx=0, copy=True)
attr = {
input = self.graph.get_input_node(node, idx=0, copy=True)
layer_attrs = {
'pool_size': kernel,
'pool_stride': stride,
'pool_padding': pad,
......@@ -314,8 +316,11 @@ class CaffeOpMapper(OpMapper):
'global_pooling': global_pool,
'name': string(node.layer_name)
}
node.fluid_code.add_layer(
"pool2d", inputs=input, output=node, param_attr=attr)
self.paddle_graph.add_layer(
kernel="fluid.layers.pool2d",
inputs={"input": self.get_input_name(input)},
outputs=[node.layer_name],
**layer_attrs)
def LRN(self, node):
assert len(node.inputs) == 1, 'The count of LRN node\'s input is not 1.'
......@@ -327,16 +332,19 @@ class CaffeOpMapper(OpMapper):
# just scales by alpha (as does Krizhevsky's paper).
# We'll account for that here.
alpha = params.alpha / float(params.local_size)
input = self.graph.get_bottom_node(node, idx=0, copy=True)
attr = {
input = self.graph.get_input_node(node, idx=0, copy=True)
layer_attrs = {
'n': params.local_size,
'k': params.k,
'alpha': alpha,
'beta': params.beta,
'name': string(node.layer_name)
}
node.fluid_code.add_layer(
"lrn", inputs=input, output=node, param_attr=attr)
self.paddle_graph.add_layer(
kernel="fluid.layers.lrn",
inputs={"input": self.get_input_name(input)},
outputs=[node.layer_name],
**layer_attrs)
def InnerProduct(self, node):
data = node.data
......@@ -372,8 +380,8 @@ class CaffeOpMapper(OpMapper):
#params = node.layer.inner_product_param
assert params.axis == 1
assert params.bias_term == True
input = self.graph.get_bottom_node(node, idx=0, copy=True)
attr = {
input = self.graph.get_input_node(node, idx=0, copy=True)
layer_attrs = {
'size': params.num_output,
'name': string(node.layer_name),
'act': None,
......@@ -381,26 +389,32 @@ class CaffeOpMapper(OpMapper):
'bias_attr': False
if len(data) == 1 else string(node.layer_name + '_bias')
}
node.fluid_code.add_layer(
"fc", inputs=input, output=node, param_attr=attr)
self.paddle_graph.add_layer(
kernel="fluid.layers.fc",
inputs={"input": self.get_input_name(input)},
outputs=[node.layer_name],
**layer_attrs)
def Softmax(self, node):
assert len(
node.inputs) == 1, 'The count of Softmax node\'s input is not 1.'
input = self.graph.get_bottom_node(node, idx=0, copy=True)
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.softmax_param
axis = params.axis
shape = node.input_shape[0]
dims = len(shape)
axis = axis + dims if axis < 0 else axis
attr = {'axis': axis, 'name': string(node.layer_name + '_softmax')}
node.fluid_code.add_layer(
"softmax", inputs=input, output=node, param_attr=attr)
layer_attrs = {'axis': axis, 'name': string(node.layer_name + '_softmax')}
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.softmax",
inputs={"x": self.get_input_name(input)},
outputs=[node.layer_name],
**layer_attrs)
def Slice(self, node):
assert len(
node.inputs) == 1, 'The count of Slice node\'s input is not 1.'
input = self.graph.get_bottom_node(node, idx=0, copy=True)
input = self.graph.get_input_node(node, idx=0, copy=True)
top_len = len(node.layer.top)
params = node.layer.slice_param
axis = params.axis
......@@ -408,30 +422,38 @@ class CaffeOpMapper(OpMapper):
if slice_dim != 1 and axis == 1:
axis = slice_dim
output_shape = node.output_shape
sections_list = []
for s in output_shape:
sections_list = list()
outputs_list = list()
for i, s in enumerate(output_shape):
sections_list.append(s[axis])
attr = {
outputs_list.append("{}_{}".format(node.layer_name, i))
layer_attrs = {
'num_or_sections': sections_list,
'dim': axis,
'name': string(node.layer_name)
}
node.fluid_code.add_layer(
"split", inputs=input, output=node.layer_name, param_attr=attr)
self.paddle_graph.add_layer(
kernel="fluid.layers.split",
inputs={"input": self.get_input_name(input)},
outputs=outputs_list,
**layer_attrs)
def Concat(self, node):
assert len(
node.inputs
) >= 1, 'The count of Concat node\'s input is not more than 1.'
inputs = []
inputs_list = []
for i in range(len(node.inputs)):
input = self.graph.get_bottom_node(node, idx=i, copy=True)
inputs.append(input)
input = self.graph.get_input_node(node, idx=i, copy=True)
inputs_list.append(self.get_input_name(input))
params = node.layer.concat_param
axis = params.axis
attr = {'axis': axis, 'name': string(node.layer_name)}
node.fluid_code.add_layer(
"concat", inputs=inputs, output=node, param_attr=attr)
layer_attrs = {'axis': axis, 'name': string(node.layer_name)}
self.paddle_graph.add_layer(
kernel="paddle.concat",
inputs={"x": inputs_list},
outputs=[node.layer_name],
**layer_attrs)
def ReLU(self, node):
"""
......@@ -441,22 +463,26 @@ class CaffeOpMapper(OpMapper):
"""
assert len(
node.inputs) == 1, 'The count of ReLU node\'s input is not 1.'
input = self.graph.get_bottom_node(node, idx=0, copy=True)
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.relu_param
if params.HasField('negative_slope') and params.negative_slope != 0:
negative_slope = float(params.negative_slope)
attr = {'alpha': negative_slope}
node.fluid_code.add_layer(
'leaky_relu', inputs=input, output=node, param_attr=attr)
self.paddle_graph.add_layer(
kernel="fluid.layers.leaky_relu",
inputs={"x": self.get_input_name(input)},
outputs=[node.layer_name],
alpha=negative_slope)
else:
node.fluid_code.add_layer('relu', inputs=input, output=node)
self.paddle_graph.add_layer(
kernel="fluid.layers.relu",
inputs={"x": self.get_input_name(input)},
outputs=[node.layer_name])
def PReLU(self, node):
assert len(
node.inputs) == 1, 'The count of PReLU node\'s input is not 1.'
input = self.graph.get_bottom_node(node, idx=0, copy=True)
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.prelu_param
mode_bool = params.channel_shared
if mode_bool:
......@@ -466,44 +492,40 @@ class CaffeOpMapper(OpMapper):
data = node.data
assert data is not None, 'The parameter of {} (type is {}) is not set. You need to use python package of caffe to set the default value.'.format(
node.layer_name, node.layer_type)
import paddle
pd_version = paddle.__version__
if pd_version.startswith("1.8.4") or pd_version.startswith("1.8.3"):
self.weights[node.layer_name + '_weights'] = data[0].reshape(1, -1)
else:
self.weights[node.layer_name + '_weights'] = data[0]
attr = {
self.weights[node.layer_name + '_weights'] = data[0]
layer_attrs = {
'mode': string(mode),
'param_attr': string(node.layer_name + '_weights'),
'name': string(node.layer_name)
}
node.fluid_code.add_layer(
"prelu", inputs=input, output=node, param_attr=attr)
self.paddle_graph.add_layer(
kernel="fluid.layers.prelu",
inputs={"x": self.get_input_name(input)},
outputs=[node.layer_name],
**layer_attrs)
def Accuracy(self, node):
assert len(
node.inputs) == 2, 'The count of Accuracy node\'s input is not 2.'
inputs = []
inputs[0] = None
inputs[1] = None
i = 0
for shape in node.input_shape:
inputs_dict = dict()
for i, shape in enumerate(node.input_shape):
if shape[1] == 1:
input = self.graph.get_bottom_node(node, idx=i, copy=True)
inputs[1] = input
input = self.graph.get_input_node(node, idx=i, copy=True)
inputs_dict["label"] = self.get_input_name(input)
else:
input = self.graph.get_bottom_node(node, idx=i, copy=True)
inputs[0] = input
i += 1
input = self.graph.get_input_node(node, idx=i, copy=True)
inputs_dict["input"] = self.get_input_name(input)
params = node.layer.accuracy_param
top_k = params.top_k
axis = params.axis
ignore_label = params.ignore_label
assert axis == 1, 'PaddlePaddle can not support the situation when the axis is not 1.'
assert not ignore_label >= 0, 'PaddlePaddle can not support the situation when the model has ignore label.'
attr = {'k': top_k}
node.fluid_code.add_layer(
"accuracy", inputs=inputs, output=node, param_attr=attr)
self.paddle_graph.add_layer(
kernel="fluid.layers.accuracy",
inputs=inputs_dict,
outputs=[node.layer_name],
k=top_k)
def Eltwise(self, node):
assert len(
......@@ -511,90 +533,79 @@ class CaffeOpMapper(OpMapper):
params = node.layer.eltwise_param
mode = params.operation
inputs = []
input0 = self.graph.get_bottom_node(node, idx=0, copy=True)
input0 = self.graph.get_input_node(node, idx=0, copy=True)
inputs.append(input0)
input1 = self.graph.get_bottom_node(node, idx=1, copy=True)
input1 = self.graph.get_input_node(node, idx=1, copy=True)
inputs.append(input1)
if mode == 0:
inputs_dict = {}
inputs_dict['x'] = inputs[0]
inputs_dict['y'] = inputs[1]
attr = {'act': None, 'name': string(node.layer_name)}
node.fluid_code.add_layer(
"elementwise_mul",
inputs_dict['x'] = self.get_input_name(inputs[0])
inputs_dict['y'] = self.get_input_name(inputs[1])
self.paddle_graph.add_layer(
kernel="fluid.layers.elementwise_mul",
inputs=inputs_dict,
output=node,
param_attr=attr)
outputs=[node.layer_name])
elif mode == 1:
if hasattr(params, 'coeff') and len(params.coeff) == 2:
coeff = params.coeff
input1_name = self.get_input_name(inputs[0])
attr = {
layer_attrs = {
'shape': [1],
'value': coeff[0],
'dtype': '{}.dtype'.format(input1_name)
}
node.fluid_code.add_layer(
"fill_constant",
inputs=None,
output=node.layer_name + '_const1',
param_attr=attr)
attr = {'act': None, 'name': string(node.layer_name + '_mul1')}
node.fluid_code.add_layer(
"elementwise_mul",
inputs=input1_name + ', ' + node.layer_name + '_const1',
output=node.layer_name + '_mul1',
param_attr=attr)
self.paddle_graph.add_layer(
kernel="fluid.layers.fill_constant",
inputs={},
outputs=["{}_const1".format(node.layer_name)],
**layer_attrs)
self.paddle_graph.add_layer(
kernel="fluid.layers.elementwise_mul",
inputs={"x": input1_name,
"y": "{}_const1".format(node.layer_name)},
outputs=["{}_mul1".format(node.layer_name)])
input2_name = self.get_input_name(inputs[1])
attr = {
layer_attrs = {
'shape': [1],
'value': coeff[1],
'dtype': '{}.dtype'.format(input2_name)
}
node.fluid_code.add_layer(
"fill_constant",
inputs=None,
output=node.layer_name + '_const2',
param_attr=attr)
attr = {'act': None, 'name': string(node.layer_name + '_mul2')}
node.fluid_code.add_layer(
"elementwise_mul",
inputs=input2_name + ', ' + node.layer_name + '_const2',
output=node.layer_name + '_mul2',
param_attr=attr)
attr = {'act': None, 'name': string(node.layer_name)}
node.fluid_code.add_layer(
"elementwise_add",
inputs='{}_mul1, {}_mul2'.format(node.layer_name,
node.layer_name),
output=node,
param_attr=attr)
self.paddle_graph.add_layer(
kernel="fluid.layers.fill_constant",
inputs={},
outputs=["{}_const2".format(node.layer_name)],
**layer_attrs)
self.paddle_graph.add_layer(
kernel="fluid.layers.elementwise_mul",
inputs={"x": input2_name,
"y": "{}_const2".format(node.layer_name)},
outputs=["{}_mul2".format(node.layer_name)])
self.paddle_graph.add_layer(
kernel="fluid.layers.elementwise_add",
inputs={"x": "{}_mul1".format(node.layer_name),
"y": "{}_mul2".format(node.layer_name)},
outputs=[node.layer_name])
else:
inputs_dict = {}
inputs_dict['x'] = inputs[0]
inputs_dict['y'] = inputs[1]
attr = {'act': None, 'name': string(node.layer_name)}
node.fluid_code.add_layer(
"elementwise_add",
inputs_dict['x'] = self.get_input_name(inputs[0])
inputs_dict['y'] = self.get_input_name(inputs[1])
self.paddle_graph.add_layer(
kernel="fluid.layers.elementwise_add",
inputs=inputs_dict,
output=node,
param_attr=attr)
outputs=[node.layer_name])
else:
inputs_dict = {}
inputs_dict['x'] = inputs[0]
inputs_dict['y'] = inputs[1]
attr = {'act': None, 'name': string(node.layer_name)}
node.fluid_code.add_layer(
"elementwise_max",
inputs=inputs_dict,
output=node,
param_attr=attr)
inputs_dict['x'] = self.get_input_name(inputs[0])
inputs_dict['y'] = self.get_input_name(inputs[1])
self.paddle_graph.add_layer(
kernel="fluid.layers.elementwise_max",
inputs=inputs_dict,
outputs=[node.layer_name])
def BatchNorm(self, node):
assert len(
node.inputs) == 1, 'The count of BatchNorm node\'s input is not 1.'
input = self.graph.get_bottom_node(node, idx=0, copy=True)
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.batch_norm_param
if hasattr(params, 'eps'):
eps = params.eps
......@@ -618,7 +629,7 @@ class CaffeOpMapper(OpMapper):
variance *= scaling_factor
self.weights[node.layer_name + '_mean'] = mean
self.weights[node.layer_name + '_variance'] = variance
attr = {
layer_attrs = {
'is_test': True,
'param_attr': None,
'bias_attr': None,
......@@ -627,8 +638,11 @@ class CaffeOpMapper(OpMapper):
'epsilon': eps,
'name': string(node.layer_name)
}
node.fluid_code.add_layer(
"batch_norm", inputs=input, output=node, param_attr=attr)
self.paddle_graph.add_layer(
kernel="fluid.layers.batch_norm",
inputs={"input": self.get_input_name(input)},
outputs=[node.layer_name],
**layer_attrs)
def Scale(self, node):
if node.data is None:
......@@ -655,82 +669,96 @@ class CaffeOpMapper(OpMapper):
# for two tensor, here resets axis to 1. Maybe there is a bug for unkown case.
axis = 1
bias_shape = node.input_shape[0][axis:axis + num_axes]
input0 = self.graph.get_bottom_node(node, idx=0, copy=True)
input1 = self.graph.get_bottom_node(node, idx=1, copy=True)
input0 = self.graph.get_input_node(node, idx=0, copy=True)
input1 = self.graph.get_input_node(node, idx=1, copy=True)
inputs_dict = {}
inputs_dict['x'] = input0
inputs_dict['y'] = input1
attr = {'axis': axis, 'name': string(node.layer_name + '_mul')}
node.fluid_code.add_layer(
"elementwise_mul",
inputs_dict['x'] = self.get_input_name(input0)
inputs_dict['y'] = self.get_input_name(input1)
self.paddle_graph.add_layer(
kernel="fluid.layers.elementwise_mul",
inputs=inputs_dict,
output=node.layer_name + '_mul',
param_attr=attr)
outputs=["{}_mul".format(node.layer_name)],
axis=axis)
else:
bias_shape = node.input_shape[0][axis:axis + num_axes]
input0 = self.graph.get_bottom_node(node, idx=0, copy=True)
input0 = self.graph.get_input_node(node, idx=0, copy=True)
input0_name = self.get_input_name(input0)
attr = {
self.paddle_graph.add_layer(
kernel="fluid.ParamAttr",
inputs={},
outputs=["{}_scale".format(node.layer_name)],
name = string("{}_scale".format(node.layer_name)))
layer_attrs = {
'dtype': '{}.dtype'.format(input0_name),
'shape': bias_shape,
'name': string(node.layer_name + '_cparam1'),
'attr': string(node.layer_name + '_scale'),
'is_bias': True,
'default_initializer': 'Constant(value=1.0)'
}
node.fluid_code.add_layer(
"create_parameter", inputs=None, output=node, param_attr=attr)
self.paddle_graph.add_layer(
kernel="fluid.layers.create_parameter",
inputs={"attr": node.layer_name + '_scale',},
outputs=["{}_cparam1".format(node.layer_name)],
**layer_attrs)
inputs_dict = {}
inputs_dict['x'] = input0
inputs_dict['y'] = node
attr = {'axis': axis, 'name': string(node.layer_name + '_mul')}
node.fluid_code.add_layer(
"elementwise_mul",
inputs_dict['x'] = self.get_input_name(input0)
inputs_dict['y'] = "{}_cparam1".format(node.layer_name)
self.paddle_graph.add_layer(
kernel="fluid.layers.elementwise_mul",
inputs=inputs_dict,
output=node.layer_name + '_mul',
param_attr=attr)
outputs=["{}_mul".format(node.layer_name)],
axis=axis)
scale_shape = bias_shape
input0_name = self.get_input_name(input0)
attr = {
self.paddle_graph.add_layer(
kernel="fluid.ParamAttr",
inputs={},
outputs=["{}_offset".format(node.layer_name)],
name = string("{}_offset".format(node.layer_name)))
layer_attrs = {
'dtype': '{}.dtype'.format(input0_name),
'shape': scale_shape,
'name': string(node.layer_name + '_cparam2'),
'attr': string(node.layer_name + '_offset'),
'is_bias': True,
'default_initializer': 'Constant(value=1.0)'
}
node.fluid_code.add_layer(
"create_parameter",
inputs=None,
output=node.layer_name + '_offset_param',
param_attr=attr)
attr = {'axis': axis, 'name': string(node.layer_name + '_add')}
node.fluid_code.add_layer(
"elementwise_add",
inputs='{}_mul, {}_offset_param'.format(node.layer_name,
node.layer_name),
output=node,
param_attr=attr)
self.paddle_graph.add_layer(
kernel="fluid.layers.create_parameter",
inputs={"attr": node.layer_name + '_offset'},
outputs=["{}_cparam2".format(node.layer_name)],
**layer_attrs)
inputs_dict = {}
inputs_dict['x'] = "{}_mul".format(node.layer_name)
inputs_dict['y'] = "{}_cparam2".format(node.layer_name)
self.paddle_graph.add_layer(
kernel="fluid.layers.elementwise_add",
inputs=inputs_dict,
outputs=[node.layer_name],
axis=axis)
def Reshape(self, node):
input = self.graph.get_bottom_node(node, idx=0, copy=True)
input = self.graph.get_input_node(node, idx=0, copy=True)
top_count = len(input.layer.top)
is_inplace = False if top_count == 1 else True
output_shape = node.output_shape[0]
attr = {
layer_attrs = {
'shape': output_shape,
'inplace': is_inplace,
'act': None,
'name': string(node.layer_name)
}
node.fluid_code.add_layer(
"reshape", inputs=input, output=node, param_attr=attr)
self.paddle_graph.add_layer(
kernel="fluid.layers.reshape",
inputs={"x": self.get_input_name(input)},
outputs=[node.layer_name],
**layer_attrs)
def ArgMax(self, node):
assert len(node.inputs) == 1 and len(
node.outputs
) == 1, 'The count of ArgMax node\'s input and output is not 1.'
input = self.graph.get_bottom_node(node, idx=0, copy=True)
input = self.graph.get_input_node(node, idx=0, copy=True)
input_shape = node.input_shape[0]
params = node.layer.argmax_param
out_max_val = params.out_max_val if hasattr(params,
......@@ -740,39 +768,35 @@ class CaffeOpMapper(OpMapper):
if axis < 0:
axis += len(input_shape)
if out_max_val is True:
attr = {'k': top_k, 'name': string(node.layer_name + '_topk')}
node.fluid_code.add_layer(
"topk",
inputs=input,
output='{}_topk_var, {}_index_var'.format(node.layer_name,
node.layer_name),
param_attr=attr)
attr = {'dtype': '{}_topk_var.dtype'.format(node.layer_name)}
node.fluid_code.add_layer(
"cast",
inputs='{}_index_var'.format(node.layer_name),
output='{}_index_var'.format(node.layer_name),
param_attr=attr)
attr = {'axis': axis, 'name': string(node.layer_name)}
node.fluid_code.add_layer(
"concat",
inputs='{}_topk_var, {}_index_var'.format(node.layer_name,
node.layer_name),
output=node,
param_attr=attr)
self.paddle_graph.add_layer(
kernel="fluid.layers.topk",
inputs={"input": self.get_input_name(input)},
outputs=["{}_topk_var".format(node.layer_name),
"{}_index_var".format(node.layer_name)],
k=top_k)
self.paddle_graph.add_layer(
kernel="paddle.cast",
inputs={"x": "{}_topk_var".format(node.layer_name)},
outputs=["{}_topk_var".format(node.layer_name)],
dtype="{}_topk_var.dtype".format(node.layer_name))
self.paddle_graph.add_layer(
kernel="paddle.concat",
inputs={"x": "[{}_topk_var, {}_index_var]".format(node.layer_name,
node.layer_name)},
outputs=[node.layer_name],
axis=axis)
else:
attr = {'k': top_k, 'name': string(node.layer_name)}
node.fluid_code.add_layer(
"topk",
inputs=input,
output='_, {}'.format(node.layer_name),
param_attr=attr)
self.paddle_graph.add_layer(
kernel="fluid.layers.topk",
inputs={"input": self.get_input_name(input)},
outputs=["_", node.layer_name],
k=top_k)
def Crop(self, node):
assert len(
node.inputs) == 2, 'The count of Crop node\'s input is not 2.'
input = self.graph.get_bottom_node(node, idx=0, copy=True)
example = self.graph.get_bottom_node(node, idx=1, copy=True)
input = self.graph.get_input_node(node, idx=0, copy=True)
example = self.graph.get_input_node(node, idx=1, copy=True)
params = node.layer.crop_param
axis = params.axis
input_shape = node.input_shape[0]
......@@ -785,48 +809,54 @@ class CaffeOpMapper(OpMapper):
) == len(offset), "invalid offset[%s] in crop layer" % (
str(offset))
offset_real = [0] * axis + offset
attr = {'offsets': list(offset_real), 'name': string(node.layer_name)}
node.fluid_code.add_layer(
"crop",
inputs={'x': input,
'shape': node.input_shape[1]},
output=node,
param_attr=attr)
layer_attrs = {"offsets": list(offset_real),
"shape": node.input_shape[1]}
self.paddle_graph.add_layer(
kernel="fluid.layers.crop_tensor",
inputs={"x": self.get_input_name(input)},
outputs=[node.layer_name],
**layer_attrs)
def Flatten(self, node):
assert len(
node.
inputs) == 1, 'The count of DetectionOutput node\'s input is not 1.'
input = self.graph.get_bottom_node(node, idx=0, copy=True)
shape = node.output_shape[0]
attr = {'shape': shape, 'name': string(node.layer_name)}
node.fluid_code.add_layer(
"reshape", inputs=input, output=node, param_attr=attr)
input = self.graph.get_input_node(node, idx=0, copy=True)
self.paddle_graph.add_layer(
kernel="fluid.layers.reshape",
inputs={"x": self.get_input_name(input)},
outputs=[node.layer_name],
shape = node.output_shape[0])
def Power(self, node):
assert len(
node.inputs) == 1, 'The count of Permute node\'s input is not 1.'
input = self.graph.get_bottom_node(node, idx=0, copy=True)
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.power_param
power = params.power
scale = params.scale
shift = params.shift
attr = {
layer_attrs = {
'scale': scale,
'bias': shift,
'bias_after_scale': True,
'name': string(node.layer_name + '_scale')
}
node.fluid_code.add_layer(
"scale", inputs=input, output=node, param_attr=attr)
attr = {'factor': power, 'name': string(node.layer_name)}
node.fluid_code.add_layer(
"pow", inputs=node, output=node, param_attr=attr)
self.paddle_graph.add_layer(
kernel="paddle.scale",
inputs={"x": self.get_input_name(input)},
outputs=[node.layer_name],
**layer_attrs)
self.paddle_graph.add_layer(
kernel="paddle.pow",
inputs={"x": node.layer_name},
outputs=[node.layer_name],
factor=power)
def Reduction(self, node):
assert len(
node.inputs) == 1, 'The count of Reduction node\'s input is not 1.'
input = self.graph.get_bottom_node(node, idx=0, copy=True)
input = self.graph.get_input_node(node, idx=0, copy=True)
params = node.layer.reduction_param
operation = params.operation
axis = params.axis
......@@ -838,46 +868,63 @@ class CaffeOpMapper(OpMapper):
axis += input_len + 1
dim = list(range(input_len))
if operation == 1: ## operation = SUM
attr = {
layer_attrs = {
'dim': dim[axis:],
'keep_dim': False,
'name': string(node.layer_name)
}
node.fluid_code.add_layer(
"reduce_sum", inputs=input, output=node, param_attr=attr)
self.paddle_graph.add_layer(
kernel="fluid.layers.reduce_sum",
inputs={"input": self.get_input_name(input)},
outputs=[node.layer_name],
**layer_attrs)
elif operation == 2: ## operation = ASUM
attr = {'name': string(node.layer_name + '_abs')}
node.fluid_code.add_layer(
"abs", inputs=input, output=node, param_attr=attr)
attr = {
self.paddle_graph.add_layer(
kernel="paddle.abs",
inputs={"x": self.get_input_name(input)},
outputs=[node.layer_name])
layer_attrs = {
'dim': dim[axis:],
'keep_dim': False,
'name': string(node.layer_name)
}
node.fluid_code.add_layer(
"reduce_sum", inputs=node, output=node, param_attr=attr)
self.paddle_graph.add_layer(
kernel="fluid.layers.reduce_sum",
inputs={"input": node.layer_name},
outputs=[node.layer_name],
**layer_attrs)
elif operation == 3: ## operation = SUMSQ
attr = {'factor': 2.0, 'name': string(node.layer_name + '_pow')}
node.fluid_code.add_layer(
"pow", inputs=input, output=node, param_attr=attr)
attr = {
self.paddle_graph.add_layer(
kernel="paddle.pow",
inputs={"x": self.get_input_name(input)},
outputs=[node.layer_name],
factor=2.0)
layer_attrs = {
'dim': dim[axis:],
'keep_dim': False,
'name': string(node.layer_name)
}
node.fluid_code.add_layer(
"reduce_sum", inputs=node, output=node, param_attr=attr)
self.paddle_graph.add_layer(
kernel="fluid.layers.reduce_sum",
inputs={"input": node.layer_name},
outputs=[node.layer_name],
**layer_attrs)
else: ## operation = MEAN
attr = {
layer_attrs = {
'dim': dim[axis:],
'keep_dim': False,
'name': string(node.layer_name)
}
node.fluid_code.add_layer(
"reduce_mean", inputs=node, output=node, param_attr=attr)
attr = {'scale': coeff}
node.fluid_code.add_layer(
"scale", inputs=node, output=node, param_attr=attr)
self.paddle_graph.add_layer(
kernel="fluid.layers.reduce_mean",
inputs={"input": node.layer_name},
outputs=[node.layer_name],
**layer_attrs)
self.paddle_graph.add_layer(
kernel="paddle.scale",
inputs={"x": node.layer_name},
outputs=[node.layer_name],
scale=coeff)
def deal_custom_layer(self, node):
op = node.layer_type
......@@ -892,31 +939,39 @@ class CaffeOpMapper(OpMapper):
weights_name = deal_weights(node)
for i in range(len(data)):
self.weights[weights_name[i]] = data[i]
inputs_node = []
inputs_list = []
for i in range(len(node.inputs)):
input = self.graph.get_bottom_node(node, idx=i, copy=True)
input = self.graph.get_input_node(node, idx=i, copy=True)
if i == 1 and op == 'DetectionOutput':
input = self.graph.get_bottom_node(node, idx=i, copy=True)
input = self.graph.get_input_node(node, idx=i, copy=True)
while input is not None \
and input.layer_type != 'Softmax' \
and input.layer_type != 'Sigmoid':
input = self.graph.get_bottom_node(input, idx=0, copy=True)
input = self.graph.get_input_node(input, idx=0, copy=True)
assert input is not None, 'This kind of DetectionOutput is not supported!'
input = self.graph.get_bottom_node(input, idx=0, copy=True)
inputs_node.append(input)
node.fluid_code.add_layer(
func.__code__.co_name,
inputs=inputs_node,
output=node,
param_attr=kwargs,
is_custom_layer=True)
input = self.graph.get_input_node(input, idx=0, copy=True)
inputs_list.append(self.get_input_name(input))
kwargs_tmp = copy.deepcopy(kwargs)
for k, v in kwargs_tmp.items():
if str(type(v)) == "<class 'caffe_pb2.NonMaximumSuppressionParameter'>":
kwargs[k] = dict()
kwargs[k]["nms_threshold"] = v.nms_threshold
kwargs[k]["top_k"] = v.top_k
kwargs[k]["eta"] = v.eta
self.paddle_graph.add_layer(
kernel="custom_layer:{}".format(op),
inputs={"inputs": inputs_list},
outputs=[node.layer_name],
**kwargs)
if op not in self.used_custom_layers:
self.used_custom_layers[op] = custom_code
def directly_map(self, node):
assert node.layer_type in self.directly_map_ops
op_info = self.directly_map_ops[node.layer_type]
input = self.graph.get_bottom_node(node, idx=0, copy=True)
attr = {'name': string(node.layer_name)}
node.fluid_code.add_layer(
op_info, inputs=input, output=node, param_attr=attr)
input = self.graph.get_input_node(node, idx=0, copy=True)
self.paddle_graph.add_layer(
kernel=op_info,
inputs={"x": self.get_input_name(input)},
outputs=[node.layer_name])
......@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from x2paddle.op_mapper.onnx2paddle.opset9 import OpSet9, custom_layers
from x2paddle.op_mapper.static.onnx2paddle.opset9 import OpSet9, custom_layers
from x2paddle.core.op_mapper import OpMapper
from x2paddle.decoder.onnx_decoder import ONNXGraph, ONNXGraphNode, ONNXGraphDataNode
......
......@@ -17,7 +17,7 @@ from x2paddle.core.graph import GraphNode
from x2paddle.core.fluid_code import Layer
from x2paddle.core.fluid_code import FluidCode
from x2paddle.core.util import string
from x2paddle.op_mapper.onnx2paddle.opset9.custom_layer import *
from x2paddle.op_mapper.static.onnx2paddle.opset9.custom_layer import *
from functools import reduce
import numpy as np
import onnx
......
# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"
# you may not use this file except in compliance with the License.
......@@ -12,7 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from x2paddle.decoder.tf_decoder import TFGraph
from x2paddle.decoder.tf_decoder import TFGraph, TFGraphNode
from x2paddle.core.program import PaddleGraph
from x2paddle.core.op_mapper import OpMapper
from x2paddle.core.util import *
from x2paddle import program
......@@ -66,26 +67,32 @@ class TFOpMapper(OpMapper):
'Square': ['square']
}
elementwise_ops = {
'Add': 'elementwise_add',
'AddV2': 'elementwise_add',
'RealDiv': 'elementwise_div',
'Sub': 'elementwise_sub',
'Maximum': 'elementwise_max',
'Minimum': 'elementwise_min',
'LessEqual': 'less_equal',
'GreaterEqual': 'greater_equal',
'Mul': 'elementwise_mul',
'FloorDiv': 'elementwise_floordiv'
'Add': 'paddle.add',
'AddV2': 'paddle.add',
'RealDiv': 'paddle.divide',
'DivNoNan': 'paddle.divide',
'Sub': 'fluid.layers.elementwise_sub',
'Maximum': 'paddle.maximum',
'Minimum': 'paddle.minimum',
'LessEqual': 'paddle.less_equal',
'GreaterEqual': 'paddle.greater_equal',
'Greater': 'paddle.greater_than',
'NotEqual': 'paddle.not_equal',
'Equal': 'paddle.equal',
'Mul': 'paddle.multiply',
'FloorDiv': 'paddle.floor_divide',
'FloorMod': 'paddle.floor_mod',
'LogicalAnd': 'logical_and',
}
def __init__(self, decoder):
super(TFOpMapper, self).__init__()
self.decoder = decoder
self.graph = decoder.tf_graph
self.weights = dict()
self.omit_nodes = list()
self.used_custom_layers = dict()
program.clear()
if not self.op_checker():
raise Exception("Model is not supported yet.")
self.params = dict()
self.paddle_graph = PaddleGraph(parent_layer=None, graph_type="static", source_type="tf")
not_placeholder = list()
for name in self.graph.input_nodes:
......@@ -99,41 +106,48 @@ class TFOpMapper(OpMapper):
idx = self.graph.input_nodes.index(name)
del self.graph.input_nodes[idx]
program.inputs = self.graph.input_nodes
program.outputs = self.graph.output_nodes
self.paddle_graph.inputs = self.graph.input_nodes
self.paddle_graph.outputs = self.graph.output_nodes
unsupported_ops = set()
sys.stderr.write("Total nodes: {}\n".format(len(self.graph.topo_sort)))
print("Total nodes: {}".format(
sum([
isinstance(node, TFGraphNode)
for name, node in self.graph.node_map.items()
])))
print("Nodes converting ...")
for i, node_name in enumerate(self.graph.topo_sort):
sys.stderr.write("\rConverting node {} ... ".format(i + 1))
node = self.graph.get_node(node_name)
op = node.layer_type
if op in self.directly_map_ops:
if len(unsupported_ops) > 0:
continue
self.directly_map(node)
elif op in self.elementwise_ops:
if len(unsupported_ops) > 0:
continue
self.elementwise_map(node)
elif hasattr(self, op):
if len(unsupported_ops) > 0:
continue
func = getattr(self, op)
try:
func(node)
except Exception as e:
unsupported_ops.add(op)
print("\n{}\n".format(traceback.format_exc()))
else:
func(node)
print("\nNodes converted.")
self.paddle_graph.set_name(self.graph.graph_name)
self.paddle_graph.set_parameters(self.params)
def op_checker(self):
unsupported_ops = set()
for node_name in self.graph.topo_sort:
node = self.graph.get_node(node_name)
op = node.layer_type
if not hasattr(self, op) and \
op not in self.directly_map_ops and \
op not in self.elementwise_ops:
unsupported_ops.add(op)
if len(unsupported_ops) > 0:
print("\n========= {} OPs are not supported yet ===========".format(
len(unsupported_ops)))
if len(unsupported_ops) == 0:
return True
else:
if len(unsupported_ops) > 0:
print("\n========= {} OPs are not supported yet ===========".format(
len(unsupported_ops)))
for op in unsupported_ops:
print("========== {} ============".format(op))
sys.exit(-1)
sys.stderr.write("\nDone!\n")
return False
def directly_map(self, node):
assert node.layer_type in self.directly_map_ops
......@@ -146,7 +160,7 @@ class TFOpMapper(OpMapper):
tf_param = node.get_attr(tf_param_name)
attr[pd_param_name] = tf_param
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.{}".format(op_info[0]),
inputs={"x": input.name},
outputs=[node.name],
......@@ -159,29 +173,19 @@ class TFOpMapper(OpMapper):
y = self.graph.get_node(node.layer.input[1])
x_shape = x.out_shapes[0]
y_shape = y.out_shapes[0]
layer_id = program.add_layer(
kernel="fluid.layers.{}".format(op_type),
inputs={"x": x.name,
"y": y.name},
outputs=[node.name])
program.layers[layer_id].input_shapes = {"x": x_shape, "y": y_shape}
def NotEqual(self, node):
x = self.graph.get_node(node.layer.input[0])
y = self.graph.get_node(node.layer.input[1])
program.add_layer(
kernel="fluid.layers.not_equal",
layer_id = self.paddle_graph.add_layer(
kernel=op_type,
inputs={"x": x.name,
"y": y.name},
outputs=[node.name])
self.paddle_graph.layers[layer_id].input_shapes = {"x": x_shape, "y": y_shape}
def Placeholder(self, node):
shape = node.out_shapes[0]
assert len(shape) != 0, "Unknown shape of input nodes[{}].".format(
node.layer_name)
dtype = node.dtype
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.data",
inputs={},
outputs=[node.name],
......@@ -199,7 +203,7 @@ class TFOpMapper(OpMapper):
shape = [1]
if value == float('inf'):
value = "float('inf')"
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.fill_constant",
inputs={},
outputs=[node.name],
......@@ -208,8 +212,8 @@ class TFOpMapper(OpMapper):
value=value)
return
program.parameters[node.name] = node.value
program.add_layer(
self.params[node.name] = node.value
self.paddle_graph.add_layer(
kernel="fluid.layers.create_parameter",
inputs={},
outputs=[node.name],
......@@ -224,7 +228,7 @@ class TFOpMapper(OpMapper):
assert perm.layer_type == "Const", "Perm of transpose OP should be Const"
perm = perm.value.tolist()
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.transpose",
inputs={"x": input.name},
outputs=[node.name],
......@@ -243,11 +247,17 @@ class TFOpMapper(OpMapper):
attr["dtype"] = string(input_value.dtype)
attr["value"] = input_value.value
program.add_layer(
self.paddle_graph.add_layer(
"fluid.layers.fill_constant",
inputs=inputs,
outputs=[node.name],
**attr)
if dims.layer_type != "Const":
self.paddle_graph.add_layer(
"paddle.reshape",
inputs={"x": node.name},
outputs=[node.name],
shape=node.out_shapes[0])
def DepthToSpace(self, node):
input = self.graph.get_node(node.layer.input[0])
......@@ -262,7 +272,7 @@ class TFOpMapper(OpMapper):
input_name = input.name
if data_format == "NHWC":
transpose_name = gen_name("depth_to_space", "transpose")
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
......@@ -271,38 +281,65 @@ class TFOpMapper(OpMapper):
shape = [0, block_size * block_size, -1, h, w]
reshape_name = gen_name("depth_to_space", "reshape")
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.reshape",
inputs={"x": input_name},
outputs=[reshape_name],
shape=shape)
transpose_name = gen_name("depth_to_space", "transpose")
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.transpose",
inputs={"x": reshape_name},
outputs=[transpose_name],
perm=[0, 2, 1, 3, 4])
reshape_name = gen_name("depth_to_space", "reshape")
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.reshape",
inputs={"x": transpose_name},
outputs=[reshape_name],
shape=[0, c, h, w])
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.pixel_shuffle",
inputs={"x": reshape_name},
outputs=[node.name],
upscale_factor=block_size)
if data_format == "NHWC":
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 1])
def Where(self, node):
if len(node.layer.input) == 1:
cond = self.graph.get_input_node(node, 0)
self.paddle_graph.add_layer(
"paddle.nonzero",
inputs={"x": cond.name},
outputs=[node.name])
else:
cond = self.graph.get_input_node(node, 0)
x = self.graph.get_input_node(node, 1)
y = self.graph.get_input_node(node, 2)
self.paddle_graph.add_layer(
"paddle.where",
inputs={"condition": cond.name,
"x": x.name,
"y": y.name},
outputs=[node.name])
def Neg(self, node):
input = self.graph.get_input_node(node, 0)
self.paddle_graph.add_layer(
"paddle.scale",
inputs={"x": input.name},
outputs=[node.name],
scale=-1)
def MaxPool(self, node):
input = self.graph.get_node(node.layer.input[0])
......@@ -315,7 +352,7 @@ class TFOpMapper(OpMapper):
input_name = input.name
if data_format == "NHWC":
transpose_name = gen_name("max_pool", "transpose")
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
......@@ -324,7 +361,7 @@ class TFOpMapper(OpMapper):
k_size = [k_size[i] for i in [0, 3, 1, 2]]
input_name = transpose_name
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.pool2d",
inputs={"input": input_name},
outputs=[node.name],
......@@ -334,7 +371,7 @@ class TFOpMapper(OpMapper):
pool_padding=string(pad_mode))
if data_format == "NHWC":
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.transpose",
inputs={"x": node.name},
outputs=[node.name],
......@@ -358,13 +395,13 @@ class TFOpMapper(OpMapper):
kernel_value = kernel.value
kernel_weight_name = kernel.name.replace('/', '_')
else:
kernel_value = self.decoder.infer_tensor(kernel)
kernel_value = self.decoder.infer_tensor(kernel, use_diff_inputs=False)
if kernel.layer_type == 'Split':
kernel_weight_name = "{}_{}_kernel".format(node.name,
kernel.name)
else:
kernel_weight_name = kernel.name.replace('/', '_')
program.parameters[kernel_weight_name] = numpy.transpose(kernel_value,
self.params[kernel_weight_name] = numpy.transpose(kernel_value,
(3, 2, 0, 1))
input_name = input.name
......@@ -372,7 +409,7 @@ class TFOpMapper(OpMapper):
strides = [strides[i] for i in [0, 3, 1, 2]]
dilations = [dilations[i] for i in [0, 3, 1, 2]]
transpose_name = gen_name("conv2d", "transpose")
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
......@@ -383,13 +420,13 @@ class TFOpMapper(OpMapper):
attr = {"shape": [0, k_size[2], 0, 0]}
node.fluid_code.add_layer(
"reshape", inputs=input, output=input, param_attr=attr)
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.reshape",
inputs={"x": input_name},
outputs=[input_name],
shape=[0, k_size[2], 0, 0])
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.conv2d",
inputs={"input": input_name},
outputs=[node.name],
......@@ -402,16 +439,93 @@ class TFOpMapper(OpMapper):
padding=string(pad_mode))
if data_format == "NHWC":
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 1])
def Conv3D(self, node):
input = self.graph.get_input_node(node, 0)
kernel = self.graph.get_input_node(node, 1)
k_size = kernel.out_shapes[0]
strides = node.get_attr("strides")
dilations = node.get_attr("dilations")
data_format = node.get_attr("data_format").decode()
pad_mode = node.get_attr("padding").decode()
if data_format == "NDHWC":
n, d, h, w, c = input.out_shapes[0]
else:
n, c, d, h, w = input.out_shapes[0]
if kernel.layer_type == 'Const':
kernel_value = kernel.value
kernel_weight_name = kernel.name.replace('/', '_')
self.paddle_graph.add_layer(
kernel="paddle.static.nn.create_parameter",
inputs={},
outputs=[kernel_weight_name],
shape=self.params[kernel_weight_name].shape,
dtype=string(str(self.params[kernel_weight_name].dtype)),
name=string(kernel_weight_name))
self.params[kernel_weight_name] = numpy.transpose(kernel_value,
(4, 3, 0, 1, 2))
else:
kernel_value = self.decoder.infer_tensor(kernel, use_diff_inputs=False)
if kernel.layer_type == 'Split':
kernel_weight_name = "{}_{}_kernel".format(node.name,
kernel.name)
else:
kernel_weight_name = kernel.name.replace('/', '_')
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": kernel_weight_name},
outputs=[kernel_weight_name],
perm=[4, 3, 0, 1, 2])
input_name = input.name
if data_format == "NDHWC":
strides = [strides[i] for i in [0, 4, 1, 2, 3]]
dilations = [dilations[i] for i in [0, 4, 1, 2, 3]]
transpose_name = gen_name("conv3d", "transpose")
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 4, 1, 2, 3])
input_name = transpose_name
if c == -1:
attr = {"shape": [0, k_size[2], 0, 0, 0]}
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": input_name},
outputs=[input_name],
shape=[0, k_size[2], 0, 0, 0])
self.paddle_graph.add_layer(
kernel="paddle.nn.functional.conv3d",
inputs={"x": input_name},
outputs=[node.name],
weight=kernel_weight_name,
bias=None,
stride=strides[2:5],
dilation=dilations[2:5],
padding=string(pad_mode))
if data_format == "NDHWC":
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 4, 1])
def BiasAdd(self, node):
input = self.graph.get_node(node.layer.input[0])
bias = self.graph.get_node(node.layer.input[1])
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.elementwise_add",
inputs={"x": input.name,
"y": bias.name},
......@@ -433,14 +547,14 @@ class TFOpMapper(OpMapper):
input_name = input.name
if data_format == "NHWC":
transpose_name = gen_name("batch_norm", "transpose")
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
input_name = transpose_name
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.batch_norm",
inputs={"input": input_name},
outputs=[node.name],
......@@ -452,7 +566,7 @@ class TFOpMapper(OpMapper):
is_test=True)
if data_format == "NHWC":
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.transpose",
inputs={"x": node.name},
outputs=[node.name],
......@@ -465,37 +579,29 @@ class TFOpMapper(OpMapper):
dims = reduce_idx.value.tolist()
keep_dims = node.get_attr("keep_dims")
program.add_layer(
kernel="fluid.layers.reduce_mean",
inputs={"input": input.name},
self.paddle_graph.add_layer(
kernel="paddle.mean",
inputs={"x": input.name},
outputs=[node.name],
dim=dims,
keep_dim=keep_dims)
axis=dims,
keepdim=keep_dims)
def Reshape(self, node):
input = self.graph.get_node(node.layer.input[0])
param = self.graph.get_node(node.layer.input[1])
input = self.graph.get_input_node(node, 0)
param = self.graph.get_input_node(node, 1)
input_name = input.name
if input.dtype == 'bool':
cast_name = gen_name('reshape', 'cast')
program.add_layer(
kernel="fluid.layers.cast",
inputs={"x": input_name},
outputs=[cast_name],
dtype="'int32'")
input_name = cast_name
if param.layer_type == "Const":
shape = param.value.tolist()
program.add_layer(
kernel="fluid.layers.reshape",
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": input_name},
outputs=[node.name],
shape=shape)
else:
program.add_layer(
kernel="fluid.layers.reshape",
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": input_name,
"shape": param.name},
outputs=[node.name])
......@@ -503,18 +609,53 @@ class TFOpMapper(OpMapper):
out_shape = numpy.array(node.out_shapes[0])
if (out_shape > 0).any():
out_shape[out_shape < 0] = 0
program.add_layer(
kernel="fluid.layers.reshape",
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": node.name},
outputs=[node.name],
shape=out_shape.tolist())
if input.dtype == 'bool':
program.add_layer(
kernel="fluid.layers.cast",
inputs={"x": node.name},
outputs=[node.name],
dtype="'bool'")
# input = self.graph.get_node(node.layer.input[0])
# param = self.graph.get_node(node.layer.input[1])
# input_name = input.name
# if input.dtype == 'bool':
# cast_name = gen_name('reshape', 'cast')
# self.paddle_graph.add_layer(
# kernel="fluid.layers.cast",
# inputs={"x": input_name},
# outputs=[cast_name],
# dtype="'int32'")
# input_name = cast_name
# if param.layer_type == "Const":
# shape = param.value.tolist()
# self.paddle_graph.add_layer(
# kernel="fluid.layers.reshape",
# inputs={"x": input_name},
# outputs=[node.name],
# shape=shape)
# else:
# self.paddle_graph.add_layer(
# kernel="fluid.layers.reshape",
# inputs={"x": input_name,
# "shape": param.name},
# outputs=[node.name])
# if param.layer_type != "Const":
# out_shape = numpy.array(node.out_shapes[0])
# if (out_shape > 0).any():
# out_shape[out_shape < 0] = 0
# self.paddle_graph.add_layer(
# kernel="fluid.layers.reshape",
# inputs={"x": node.name},
# outputs=[node.name],
# shape=out_shape.tolist())
# if input.dtype == 'bool':
# self.paddle_graph.add_layer(
# kernel="fluid.layers.cast",
# inputs={"x": node.name},
# outputs=[node.name],
# dtype="'bool'")
def Pad(self, node):
input = self.graph.get_node(node.layer.input[0])
......@@ -526,33 +667,59 @@ class TFOpMapper(OpMapper):
if paddings[0] + paddings[1] + paddings[6] + paddings[7] == 0:
new_padding = paddings[2:6]
transpose_name = gen_name("pad", "transpose")
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.pad2d",
inputs={"input": transpose_name},
outputs=[node.name],
paddings=new_padding)
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 1])
return
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.pad",
inputs={"x": input.name},
outputs=[node.name],
paddings=paddings)
def MirrorPad(self, node):
op_name = name_generator("pad", self.nn_name2id)
output_name = node.name
layer_outputs = [op_name, output_name]
input = self.graph.get_input_node(node, 0)
paddings = self.graph.get_input_node(node, 1)
assert paddings.layer_type == "Const", "Padding should be Const"
paddings = np.flip(paddings.value, 0).flatten().tolist()
dim = int(len(paddings) / 2)
transpose_name = gen_name("pad", "transpose")
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
self.paddle_graph.add_layer(
kernel="paddle.nn.Pad{}D".format(dim),
inputs={"x": transpose_name},
outputs=layer_outputs,
pad=new_padding)
self.paddle_graph.add_layer(
kernel="paddle.transpose",
inputs={"x": node.name},
outputs=[node.name],
perm=[0, 2, 3, 1])
def Squeeze(self, node):
input = self.graph.get_node(node.layer.input[0])
squeeze_dims = node.get_attr('squeeze_dims')
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.squeeze",
inputs={"input": input.name},
outputs=[node.name],
......@@ -561,38 +728,62 @@ class TFOpMapper(OpMapper):
def Softmax(self, node):
input = self.graph.get_node(node.layer.input[0])
axis = node.get_attr("axis")
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.softmax",
inputs={"input": input.name},
outputs=[node.name],
axis=axis)
def Shape(self, node):
input = self.graph.get_node(node.layer.input[0])
input = self.graph.get_input_node(node, 0)
input_name = input.name
if input.dtype == 'bool':
cast_name = gen_name('shape', 'cast')
program.add_layer(
kernel="fluid.layers.cast",
inputs={"x": input.name},
outputs=[cast_name],
dtype="'int32'")
input_name = cast_name
program.add_layer(
kernel="fluid.layers.shape",
self.paddle_graph.add_layer(
kernel="paddle.shape",
inputs={"input": input_name},
outputs=[node.name])
def Size(self, node):
input = self.graph.get_input_node(node, 0)
input_name = input.name
self.paddle_graph.add_layer(
kernel="paddle.shape",
inputs={"input": input_name},
outputs=[node.name])
self.paddle_graph.add_layer(
kernel="paddle.prod",
inputs={"x": node.name},
outputs=[node.name])
def Ceil(self, node):
input = self.graph.get_input_node(node, 0)
self.paddle_graph.add_layer(
kernel="paddle.ceil",
inputs={"x": input.name},
outputs=[node.name])
def ArgMax(self, node):
input = self.graph.get_node(node.layer.input[0])
axis = self.graph.get_node(node.layer.input[1])
assert axis.layer_type == "Const", "ArgMax only support Const parameter"
axis = axis.value
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.argmax",
inputs={"x": input.name},
outputs=[node.name],
axis=axis)
def TopKV2(self, node):
input = self.graph.get_input_node(node, 0)
k = self.graph.get_input_node(node, 1)
assert k.layer_type == "Const", "ArgMax only support Const parameter"
k = k.value
sort = node.get_attr('sorted')
self.paddle_graph.add_layer(
kernel="paddle.topk",
inputs={"x": input.name},
outputs=[node.name],
k=k,
sorted=sort)
def MatMul(self, node):
x = self.graph.get_node(node.layer.input[0])
......@@ -603,7 +794,7 @@ class TFOpMapper(OpMapper):
transpose_a = node.get_attr('adj_x')
if transpose_b is None:
transpose_b = node.get_attr('adj_y')
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.matmul",
inputs={"x": x.name,
"y": y.name},
......@@ -629,7 +820,7 @@ class TFOpMapper(OpMapper):
data_format = node.get_attr("data_format").decode()
pad_mode = node.get_attr("padding").decode()
program.parameters[kernel.layer_name.replace(
self.params[kernel.layer_name.replace(
'/', '_')] = numpy.transpose(kernel.value, (2, 3, 0, 1))
input_name = input.name
......@@ -638,14 +829,14 @@ class TFOpMapper(OpMapper):
strides = [strides[i] for i in [0, 3, 1, 2]]
dilations = [dilations[i] for i in [0, 3, 1, 2]]
transpose_name = gen_name('depthwise_conv2d', 'transpose')
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
input_name = transpose_name
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.conv2d",
inputs={"input": input_name},
outputs=[node.name],
......@@ -659,7 +850,7 @@ class TFOpMapper(OpMapper):
bias_attr=False)
if data_format == "NHWC":
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.transpose",
inputs={"x": node.name},
outputs=[node.name],
......@@ -676,7 +867,7 @@ class TFOpMapper(OpMapper):
input_name = input.name
if data_format == "NHWC":
transpose_name = gen_name("avg_pool", "transpose")
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
......@@ -685,7 +876,7 @@ class TFOpMapper(OpMapper):
k_size = [k_size[i] for i in [0, 3, 1, 2]]
input_name = transpose_name
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.pool2d",
inputs={"input": input_name},
outputs=[node.name],
......@@ -695,7 +886,7 @@ class TFOpMapper(OpMapper):
pool_padding=string(pad_mode))
if data_format == "NHWC":
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.transpose",
inputs={"x": node.name},
outputs=[node.name],
......@@ -705,13 +896,13 @@ class TFOpMapper(OpMapper):
inputs = [self.graph.get_node(name) for name in node.layer.input]
input_names = [i.name for i in inputs]
axis = node.get_attr("axis")
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.stack",
inputs={"x": input_names},
outputs=[node.name],
axis=axis)
if len(node.out_shapes[0]) == 1:
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.reshape",
inputs={"x": node.name},
outputs=[node.name],
......@@ -725,7 +916,7 @@ class TFOpMapper(OpMapper):
input_name = input.name
if len(shape) == 1:
if shape[0] > 0 and num == shape[0]:
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.unsqueeze",
inputs={"input": input.name},
outputs=[node.name],
......@@ -734,10 +925,13 @@ class TFOpMapper(OpMapper):
axis = 1
else:
raise Exception("Unexpected situation happend in Unpack OP")
program.add_layer(
layer_outputs = ["{}_p{}".format(node.layer_name, i) for i in range(num)]
if len(layer_outputs) == 1:
layer_outputs[0] = "[{}]".format(node.layer_name)
self.paddle_graph.add_layer(
kernel="fluid.layers.unstack",
inputs={"x": input_name},
outputs=["{}_p{}".format(node.layer_name, i) for i in range(num)],
outputs=layer_outputs,
axis=axis,
num=num)
......@@ -753,23 +947,34 @@ class TFOpMapper(OpMapper):
for i, ipt in enumerate(inputs):
if ipt.dtype == 'bool':
cast_name = gen_name('concat', 'cast')
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.cast",
inputs={"x": ipt.name},
outputs=[cast_name],
dtype="'int32'")
input_names[i] = cast_name
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.concat",
inputs={"input": input_names},
outputs=[node.name],
axis=axis)
if node.dtype == 'bool':
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.cast",
inputs={"x": node.name},
outputs=[node.name],
dtype="'bool'")
def AddN(self, node):
inputs_list = list()
for i in range(len(node.inputs) - 1):
inputs_list.append(self.graph.get_input_node(node, i))
input_names = [i.name for i in inputs_list]
self.paddle_graph.add_layer(
kernel="paddle.add_n",
inputs={"inputs": input_names},
outputs=[node.name])
def StridedSlice(self, node):
input = self.graph.get_node(node.layer.input[0])
......@@ -780,15 +985,15 @@ class TFOpMapper(OpMapper):
if strides.layer_type == "Const":
strides = strides.value.tolist()
else:
strides = self.decoder.infer_shape_tensor(strides)
strides = self.decoder.infer_tensor(strides)
if begin.layer_type == "Const":
begin = begin.value.tolist()
else:
begin = self.decoder.infer_shape_tensor(begin)
begin = self.decoder.infer_tensor(begin)
if end.layer_type == "Const":
end = end.value.tolist()
else:
end = self.decoder.infer_shape_tensor(end)
end = self.decoder.infer_tensor(end)
assert len(set(strides)) == 1 and strides[
0] == 1, "Only support strides be 1 in StridedSlice OP"
......@@ -838,7 +1043,7 @@ class TFOpMapper(OpMapper):
else:
new_end.append(end[i])
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.slice",
inputs={"input": input.name},
outputs=[node.name],
......@@ -846,7 +1051,7 @@ class TFOpMapper(OpMapper):
starts=new_begin,
ends=new_end)
if len(new_axes) > 0:
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.unsqueeze",
inputs={"input": node.name},
outputs=[node.name],
......@@ -855,11 +1060,25 @@ class TFOpMapper(OpMapper):
if len(input.out_shapes[0]) + len(new_axes) <= 1:
pass
else:
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.squeeze",
inputs={"input": node.name},
outputs=[node.name],
axes=shrink_axes)
def Prod(self, node):
input = self.graph.get_input_node(node, 0)
reduction_indices = self.graph.get_input_node(node, 1)
assert reduction_indices.layer_type == "Const"
keep_dims = node.get_attr('keep_dims')
axis = reduction_indices.value
self.paddle_graph.add_layer(
kernel="paddle.prod",
inputs={"x": input.name},
outputs=[node.layer_name],
keepdim=keep_dims,
axis=axis)
def Split(self, node):
dim = self.graph.get_node(node.layer.input[0])
......@@ -868,7 +1087,7 @@ class TFOpMapper(OpMapper):
num_split = node.get_attr('num_split')
dim = dim.value
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.split",
inputs={"input": input.name},
outputs=[
......@@ -896,7 +1115,7 @@ class TFOpMapper(OpMapper):
# outputs=[reshape_name],
# shape=shape)
# inputs['offsets'] = reshape_name
begin = self.decoder.infer_tensor(begin).tolist()
begin = self.decoder.infer_tensor(begin, use_diff_inputs=False).tolist()
attrs['offsets'] = begin
if size.layer_type == "Const":
size = size.value.tolist()
......@@ -929,7 +1148,7 @@ class TFOpMapper(OpMapper):
else:
shape = resize_shape.out_shapes[0]
reshape_name = gen_name("resize_nearest", "reshape")
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.reshape",
inputs={"x": resize_shape.name},
outputs=[reshape_name],
......@@ -938,21 +1157,21 @@ class TFOpMapper(OpMapper):
if data_format == "NHWC":
transpose_name = gen_name("resize_nearest", "reshape")
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
inputs["input"] = transpose_name
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.resize_nearest",
inputs=inputs,
outputs=[node.name],
**attrs)
if data_format == "NHWC":
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.transpose",
inputs={"x": node.name},
outputs=[node.name],
......@@ -971,7 +1190,7 @@ class TFOpMapper(OpMapper):
else:
shape = resize_shape.out_shapes[0]
reshape_name = gen_name("resize_bilinear", "reshape")
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.reshape",
inputs={"x": resize_shape.name},
outputs=[reshape_name],
......@@ -980,21 +1199,21 @@ class TFOpMapper(OpMapper):
if data_format == "NHWC":
transpose_name = gen_name("resize_bilinear", "reshape")
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
inputs["input"] = transpose_name
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.resize_bilinear",
inputs=inputs,
outputs=[node.name],
**attrs)
if data_format == "NHWC":
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.transpose",
inputs={"x": node.name},
outputs=[node.name],
......@@ -1003,7 +1222,7 @@ class TFOpMapper(OpMapper):
def Cast(self, node):
input = self.graph.get_node(node.layer.input[0])
dtype = node.dtype
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.cast",
inputs={"x": input.name},
outputs=[node.name],
......@@ -1016,7 +1235,7 @@ class TFOpMapper(OpMapper):
keep_dims = node.get_attr("keep_dims")
dim = reduce_idx.value.tolist()
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.reduce_sum",
inputs={"input": input.name},
outputs=[node.name],
......@@ -1029,7 +1248,7 @@ class TFOpMapper(OpMapper):
assert reduce_idx.layer_type == "Const", "Only support Const parameter[reduce_idx]"
keep_dims = node.get_attr("keep_dims")
dim = reduce_idx.value.tolist()
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.reduce_max",
inputs={"input": input.name},
outputs=[node.name],
......@@ -1040,7 +1259,7 @@ class TFOpMapper(OpMapper):
shape = self.graph.get_node(node.layer.input[0])
if shape.layer_type == "Const":
shape = shape.value.tolist()
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.uniform_random",
inputs={},
outputs=[node.name],
......@@ -1048,7 +1267,7 @@ class TFOpMapper(OpMapper):
min=0.0,
max=0.9999)
else:
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.uniform_random",
inputs={'shape': shape.name},
outputs=[node.name],
......@@ -1065,22 +1284,22 @@ class TFOpMapper(OpMapper):
if out_shape.layer_type == "Const":
out_shape = out_shape.value.tolist()
else:
out_shape = self.decoder.infer_shape_tensor(out_shape,
node.out_shapes[0])
out_shape = self.decoder.infer_tensor(out_shape,
out_shape=node.out_shapes[0])
in_shape = input.out_shapes[0]
if in_shape.count(-1) > 2:
in_shape = self.decoder.infer_tensor(input).shape
in_shape = self.decoder.infer_tensor(input, use_diff_inputs=False).shape
k_size = kernel.out_shapes[0]
if k_size.count(-1) > 2:
k_size = self.decoder.infer_tensor(kernel).shape
k_size = self.decoder.infer_tensor(input, use_diff_inputs=False).shape
pad_mode = node.get_attr("padding").decode()
strides = node.get_attr("strides")
dilations = node.get_attr("dilations")
data_format = node.get_attr("data_format").decode()
program.parameters[kernel.layer_name.replace(
self.params[kernel.layer_name.replace(
'/', '_')] = numpy.transpose(kernel.value, (3, 2, 0, 1))
input_name = input.name
......@@ -1089,14 +1308,14 @@ class TFOpMapper(OpMapper):
strides = [strides[i] for i in [0, 3, 1, 2]]
dilations = [dilations[i] for i in [0, 3, 1, 2]]
transpose_name = gen_name("conv2dbackpropinput", "transpose")
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.transpose",
inputs={"x": input.name},
outputs=[transpose_name],
perm=[0, 3, 1, 2])
input_name = transpose_name
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.conv2d_transpose",
inputs={"input": input_name},
outputs=[node.name],
......@@ -1110,7 +1329,7 @@ class TFOpMapper(OpMapper):
output_size=out_shape[1:3])
if data_format == "NHWC":
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.transpose",
inputs={"x": node.name},
outputs=[node.name],
......@@ -1118,20 +1337,27 @@ class TFOpMapper(OpMapper):
def Tile(self, node):
input = self.graph.get_node(node.layer.input[0])
expand_times = self.graph.get_node(node.layer.input[1])
repeat_times = self.graph.get_node(node.layer.input[1])
inputs = {"x": input.name}
attr = dict()
if expand_times.layer_type == "Const":
expand_times = expand_times.value.tolist()
attr["expand_times"] = expand_times
if repeat_times.layer_type == "Const":
repeat_times = repeat_times.value.tolist()
attr["repeat_times"] = repeat_times
else:
inputs["expand_times"] = expand_times.name
program.add_layer(
kernel="fluid.layers.expand",
inputs["repeat_times"] = repeat_times.name
self.paddle_graph.add_layer(
kernel="paddle.tile",
inputs=inputs,
outputs=[node.name],
**attr)
if not isinstance(repeat_times, list) and repeat_times.layer_type != "Const":
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": node.name},
outputs=[node.name],
shape=node.out_shapes[0])
def Range(self, node):
start = self.graph.get_node(node.layer.input[0])
......@@ -1162,11 +1388,19 @@ class TFOpMapper(OpMapper):
node.set_dtype(dtype)
attr["dtype"] = string(node.dtype)
program.add_layer(
kernel="fluid.layers.range",
self.paddle_graph.add_layer(
kernel="paddle.arange",
inputs=inputs,
outputs=[node.name],
**attr)
if start.layer_type != "Const" or \
limit.layer_type != "Const" or \
delta.layer_type != "Const":
self.paddle_graph.add_layer(
kernel="paddle.reshape",
inputs={"x": node.name},
outputs=[node.name],
shape=node.out_shapes[0])
def SquaredDifference(self, node):
x = self.graph.get_node(node.layer.input[0])
......@@ -1174,16 +1408,16 @@ class TFOpMapper(OpMapper):
inputs = {"x": x.name, "y": y.name}
x_shape = x.out_shapes[0]
y_shape = y.out_shapes[0]
layer_id = program.add_layer(
layer_id = self.paddle_graph.add_layer(
"fluid.layers.elementwise_sub", inputs=inputs, outputs=[node.name])
program.layers[layer_id].input_shapes = {"x": x_shape, "y": y_shape}
self.paddle_graph.layers[layer_id].input_shapes = {"x": x_shape, "y": y_shape}
inputs = {"x": node.name, "y": node.name}
x_shape = node.out_shapes[0]
y_shape = node.out_shapes[0]
layer_id = program.add_layer(
layer_id = self.paddle_graph.add_layer(
"fluid.layers.elementwise_mul", inputs=inputs, outputs=[node.name])
program.layers[layer_id].input_shapes = {"x": x_shape, "y": y_shape}
self.paddle_graph.layers[layer_id].input_shapes = {"x": x_shape, "y": y_shape}
def OneHot(self, node):
input = self.graph.get_node(node.layer.input[0])
......@@ -1202,7 +1436,7 @@ class TFOpMapper(OpMapper):
assert math.fabs(off_value -
0.0) < 1e-06, "off_value should be 0 in OneHot"
program.add_layer(
self.paddle_graph.add_layer(
"fluid.one_hot",
inputs={"input": input.name},
outputs=[node.name],
......@@ -1217,7 +1451,7 @@ class TFOpMapper(OpMapper):
attr["factor"] = factor.value.tolist()
else:
inputs["factor"] = factor.name
program.add_layer(
self.paddle_graph.add_layer(
"fluid.layers.pow", inputs=inputs, outputs=[node.name], **attr)
def All(self, node):
......@@ -1231,12 +1465,12 @@ class TFOpMapper(OpMapper):
input_name = input.name
if input.dtype != "bool":
input_name = gen_name("all", "cast")
program.add_layer(
self.paddle_graph.add_layer(
"fluid.layers.cast",
inputs={"x": input.name},
outputs=[input_name],
dtype=string("bool"))
program.add_layer(
self.paddle_graph.add_layer(
"fluid.layers.reduce_all",
inputs={"input": input_name},
outputs=[node.name],
......@@ -1249,30 +1483,39 @@ class TFOpMapper(OpMapper):
index = self.graph.get_node(node.layer.input[1])
axis = self.graph.get_node(node.layer.input[2])
assert axis.layer_type == 'Const', "Only support Const parameter[axis]"
axis = axis.value.tolist()
axis = axis.value
assert axis == 0, "Only support axis=0 in GatherV2 OP"
index_name = index.name
if len(index.out_shapes[0]) != 1:
reshape_name = gen_name("gather", "reshape")
index_name = reshape_name
program.add_layer(
self.paddle_graph.add_layer(
"fluid.layers.reshape",
inputs={"x": index.name},
outputs=[reshape_name],
shape=[-1])
inputs = {'input': embeddings.name, 'index': index_name}
program.add_layer(
self.paddle_graph.add_layer(
"fluid.layers.gather",
inputs=inputs,
outputs=[node.name],
overwrite=False)
if len(index.out_shapes[0]) != 1:
out_shape = node.out_shapes[0]
program.add_layer(
self.paddle_graph.add_layer(
kernel="fluid.layers.reshape",
inputs={"x": node.name},
outputs=[node.name],
shape=out_shape)
def GatherNd(self, node):
x = self.graph.get_input_node(node, 0)
index = self.graph.get_input_node(node, 1)
inputs = {'x': x.name, 'index': index.name}
self.paddle_graph.add_layer(
"paddle.gather_nd",
inputs=inputs,
outputs=[node.name])
def ExpandDims(self, node):
x = self.graph.get_node(node.layer.input[0], copy=True)
......@@ -1286,7 +1529,7 @@ class TFOpMapper(OpMapper):
attr['axes'] = dim
else:
inputs['axes'] = y.name
program.add_layer(
self.paddle_graph.add_layer(
"fluid.layers.unsqueeze",
inputs=inputs,
outputs=[node.name],
......
# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from x2paddle.decoder.caffe_decoder import CaffeGraph
from x2paddle.core.util import *
class CaffeOptimizer(object):
layers_with_act = ['Convolution', 'Deconvolution', 'InnerProduct']
activation_ops = ['ReLU', 'Sigmoid']
def __init__(self, mapper):
self.graph = mapper.graph
def merge_bn_scale(self):
for node_name in self.graph.topo_sort:
node = self.graph.get_node(node_name)
if node.layer_type == 'Scale':
parent_node = self.graph.get_bottom_node(node, idx=0)
if parent_node.layer_type == 'BatchNorm':
is_delete_node = True if len(
parent_node.outputs) == 1 else False
parent_fluid_layer = parent_node.fluid_code.layers[0]
input = parent_fluid_layer.inputs
parent_param_attr = parent_fluid_layer.param_attr
parent_param_attr['param_attr'] = string(node.layer_name +
'_scale')
parent_param_attr['bias_attr'] = string(node.layer_name +
'_offset')
if is_delete_node:
parent_node.fluid_code.clear()
node.fluid_code.clear()
node.fluid_code.add_layer(
"batch_norm",
inputs=input,
output=node,
param_attr=parent_param_attr)
def merge_op_activation(self):
for node_name in self.graph.topo_sort:
node = self.graph.get_node(node_name)
if node.layer_type in self.activation_ops:
parent_node = self.graph.get_bottom_node(node, idx=0)
if parent_node.layer_type in self.layers_with_act:
is_delete_node = True if len(
parent_node.outputs) == 1 else False
parent_fluid_layer = parent_node.fluid_code.layers[0]
input = parent_fluid_layer.inputs
parent_param_attr = parent_fluid_layer.param_attr
parent_param_attr['act'] = string(node.layer_type.lower())
op = parent_fluid_layer.op
if is_delete_node:
parent_node.fluid_code.clear()
node.fluid_code.clear()
node.fluid_code.add_layer(
op,
inputs=input,
output=node,
param_attr=parent_param_attr)
# 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.optimizer.code_optimizer.hierachical_tree import HierarchicalTree
\ No newline at end of file
# -*- coding:UTF-8 -*-
# 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.
import copy
import os.path as osp
from treelib import Tree
from queue import Queue
from x2paddle.optimizer.code_optimizer.layer_code_generator import gen_layer_code, rename_layers, NN_KERNEL_WITH_PARAMS, NN_KERNEL_NAME
from x2paddle.optimizer.code_optimizer.subgraphs_union import distinguish_sequential, get_inputs_outputs
from x2paddle.core.program import PaddleLayer
from x2paddle.optimizer.code_optimizer.parameter_tree import PamareterNode, PamareterTree
SEPARATOR_IN_SCOPE = "/"
class HierarchicalTree(Tree):
""" 定义层次树。
"""
def __init__(self, pd_graph):
super(HierarchicalTree, self).__init__()
self.pd_graph = pd_graph
self.script = pd_graph.script
self.create_node("Module", self.pd_graph.name) # create root
self._hierarchical_order = dict()
self.codes = list()
self.identifier_idx = dict()
self.param_tree = PamareterTree()
self.module_name2count = dict()
def insert(self, layer):
""" 往层次树中插入节点。
Args:
layer (PaddleLayer): 需要插入的节点。
"""
scope_name = layer.scope_name
if scope_name == "":
if layer.kernel == "prim.tuple" or layer.kernel == "prim.tuple_unpack":
layer_id = layer.id
layer_id_list = list()
for input_layer_id in self.pd_graph.edges_in[layer_id]:
layer_id_list.append(int(input_layer_id))
layer_id_list = list(set(layer_id_list))
layer_id_list.sort(reverse=True)
for input_layer_id in layer_id_list:
input_layer_id_str = str(input_layer_id)
if self.pd_graph.layers[input_layer_id_str].scope_name != "":
scope_name = self.pd_graph.layers[input_layer_id_str].scope_name
break
layer.scope_name = scope_name
else:
self.create_node(tag=layer.id,
identifier="no_scope_" + layer.id,
parent=self.pd_graph.name,
data=layer)
return
scopes = scope_name.split(SEPARATOR_IN_SCOPE)
for idx, scope in enumerate(scopes):
parent = SEPARATOR_IN_SCOPE.join(scopes[:idx])#.lower()
identifier = SEPARATOR_IN_SCOPE.join(scopes[:idx + 1])#.lower()
if self.contains(identifier):
if idx != len(scopes) - 1:
parent_node = self.parent(identifier)
self.move_node(identifier, parent_node.identifier)
continue
else:
if self.get_node(identifier).data is None:
data = layer
if identifier not in self.identifier_idx:
self.identifier_idx[identifier] = 0
else:
self.identifier_idx[identifier] += 1
identifier_name = identifier + SEPARATOR_IN_SCOPE + str(self.identifier_idx[identifier])
self.create_node(tag=scopes[idx],
identifier=identifier_name,
parent=identifier,
data=data)
data.scope_name = identifier_name
continue
else:
data = self[identifier].data
self[identifier].data = None
parent_node = self.parent(identifier)
self.move_node(identifier, parent_node.identifier)
if identifier not in self.identifier_idx:
self.identifier_idx[identifier] = 0
else:
self.identifier_idx[identifier] += 1
self.create_node(tag=scopes[idx],
identifier=identifier + SEPARATOR_IN_SCOPE + str(self.identifier_idx[identifier]),
parent=identifier,
data=data)
self.identifier_idx[identifier] += 1
data = layer
self.create_node(tag=scopes[idx],
identifier=identifier + SEPARATOR_IN_SCOPE + str(self.identifier_idx[identifier]),
parent=identifier,
data=data)
continue
if idx == 0 and not self.contains(identifier):
data = layer if idx == len(scopes) - 1 else None
self.create_node(tag=scopes[idx],
identifier=identifier,
parent=self.pd_graph.name,
data=data)
else:
if idx == len(scopes) - 1:
if parent == "":
childs = self.children(self.pd_graph.name)
parent = self.pd_graph.name
else:
childs = self.children(parent)
prefix = identifier
identifiers = list()
for child in childs:
child_identifier = child.identifier
if child_identifier.startswith(prefix) and child_identifier != prefix:
identifiers.append(child_identifier)
if len(identifiers) == 0:
identifier = prefix + "_0"
else:
identifier_ids = list()
for id_obj in identifiers:
identifier_ids.append(int(id_obj.split("_")[-1]))
identifier_ids.sort()
identifier = prefix + "_{}".format(identifier_ids[-1] + 1)
data = layer if idx == len(scopes) - 1 else None
self.create_node(tag=scopes[idx],
identifier=identifier,
parent=parent,
data=data)
def update_hierarchical_order(self):
""" 更新层次排序,使用一个字典存储该信息,
关键字为当前层次,值为节点名字。
"""
hierarchical_order = dict()
queue = Queue()
queue.put(item=(self.pd_graph.name, 0), block=False)
while not queue.empty():
node_name, cur_level = queue.get(block=False)
node_inst = self[node_name]
if cur_level not in hierarchical_order:
hierarchical_order[cur_level] = []
hierarchical_order[cur_level].append(node_name)
for successor_name in node_inst.successors(self.identifier):
queue.put(item=(successor_name, cur_level + 1), block=False)
self._hierarchical_order = hierarchical_order
def analyze_attrs_table(self, attrs_table):
""" 分析属性表格,哪些属性取值不一致。
"""
diff_attrs_column = list()
for column in list(attrs_table.columns):
elements = list(attrs_table.get(column))
base = elements[0]
for element in elements[1:]:
if isinstance(base, str) and "'" not in base:
break
if element != base:
diff_attrs_column.append(column)
break
return diff_attrs_column
def merge_node(self, sub_layers_list, attrs_table, node_name2sub_layers, module_name):
""" 将一个scope的节点合成一个Module(Class),并将对应的Class代码
放到code字符串中。
"""
def get_node_name(sub_layers):
for k, v in node_name2sub_layers.items():
if v == sub_layers:
node_name = k
break
return node_name
sub_layers = sub_layers_list[0]
node_name = get_node_name(sub_layers)
sub_layers, _, _ = rename_layers(sub_layers)
diff_attrs_column = self.analyze_attrs_table(attrs_table)
if module_name is None:
module_name = node_name.replace("/", "_") #node_name.split("/")[-1]
module_name = module_name[0].upper() + module_name[1:]
if module_name in self.module_name2count:
module_name = module_name + "_0"
code_str = gen_layer_code(self.pd_graph, sub_layers, module_name,
different_attrs=diff_attrs_column)
self.codes.append(code_str)
for sub_layers in sub_layers_list:
inputs, outputs = get_inputs_outputs(self.pd_graph, sub_layers)
inputs_dict = dict()
for i, input in enumerate(inputs):
inputs_dict["input_{}".format(i)] = input
if module_name in self.module_name2count:
self.module_name2count[module_name] += 1
else:
self.module_name2count[module_name] = 0
if module_name.lower() in NN_KERNEL_NAME.values():
mn = module_name.lower() + "__"
else:
mn = module_name.lower()
outputs = ["{}/{}".format(mn, self.module_name2count[module_name])] + outputs
node_name = get_node_name(sub_layers)
diff_attrs = dict()
for column in diff_attrs_column:
diff_attrs[column] = attrs_table.get(column).loc[node_name]
node_name_seg = node_name.split(SEPARATOR_IN_SCOPE)
node_name_seg[-1] = module_name.lower()
new_node_name = SEPARATOR_IN_SCOPE.join(node_name_seg)
new_layer = PaddleLayer(id=list(sub_layers.keys())[-1],
kernel="module",
inputs=inputs_dict,
outputs=outputs,
scope_name=new_node_name,
module=module_name,
**diff_attrs)
_, nn_param_nodes, _ = rename_layers(sub_layers, self.param_tree)
param_node = PamareterNode(old_name=outputs[0])
for node in nn_param_nodes:
param_node.add_child(node)
self.param_tree.add_node(param_node)
for i, (layer_id, layer) in enumerate(sub_layers.items()):
if i == len(sub_layers) - 1:
self.pd_graph.layers[layer_id] = new_layer
else:
self.pd_graph.layers.pop(layer_id)
self.pd_graph.build()
self[node_name].data = new_layer
def find_subgraph_diff(self, module_name2sub_layers, module_name2sub_identifiers, node_name2sub_layers, name):
""" 查找子图的diff,主要是输入参数的diff。
"""
sub_layers = module_name2sub_layers[name]
sub_identifiers = module_name2sub_identifiers[name]
new_sub_layers, new_sub_sequentials, sequentials2attrs_table = distinguish_sequential(self.pd_graph,
name,
sub_layers,
sub_identifiers,
node_name2sub_layers)
module_name2sub_layers.pop(name)
module_name2sub_identifiers.pop(name)
for k, v in new_sub_layers.items():
module_name2sub_layers[k] = v
module_name2sub_identifiers[k] = new_sub_sequentials[k]
return sequentials2attrs_table
def convert_subgraph_to_layer(self):
"""
1. 根据_hierarchical_order,从最深的层次开始将
子图合并成layer(即合成节点)。
2. 根据参数名新旧对应关系,更新参数名。
"""
depths = sorted(list(self._hierarchical_order.keys()), reverse=True)
all_name_old2new = dict()
for depth in depths[1:]:
# Module的名字与子图的对应关系
module_name2sub_layers = dict()
# Module的名字与子图中layer命名的对应关系
module_name2sub_identifiers = dict()
# 层次树中包含子树的节点,其节点名与子图对用关系
node_name2sub_layers = dict()
for node_name in self._hierarchical_order[depth]:
node_inst = self[node_name]
if node_inst.data is None:
sub_layers = dict()
sub_identifiers = dict()
for successor_name in node_inst.successors(self.identifier):
sub_layers[self[successor_name].data.id] = self[successor_name].data
sub_identifiers[self[successor_name].data.id] = self[successor_name].data.scope_name.split("/")[-1]
node_name2sub_layers[node_name] = sub_layers
node_name_segs = node_name.split("/")
# 获取Module的名字
module = self.script
is_largest_module = False # 当前module是否是最外层的Module
for name_id, name in enumerate(node_name_segs):
name = name.split("__")[0]
if not hasattr(module, name):
is_largest_module = True
break
module = getattr(module, name)
if is_largest_module:
if name_id == 0:
module_name = name
else:
module_name = "_".join(node_name_segs)
else:
module_name = module._get_name()
if module_name in module_name2sub_layers:
module_name2sub_layers[module_name].append(sub_layers)
module_name2sub_identifiers[module_name].append(sub_identifiers)
else:
module_name2sub_layers[module_name] = [sub_layers]
module_name2sub_identifiers[module_name] = [sub_identifiers]
module_names = list(module_name2sub_layers.keys())
for module_name in module_names:
sequentials2attrs_table = self.find_subgraph_diff(module_name2sub_layers,
module_name2sub_identifiers,
node_name2sub_layers,
module_name)
for name in sequentials2attrs_table.keys():
if name.startswith("Sequential"):
# 若Module的名字为Sequential,则以scope_name的名字来命名,在merge_node中实现
module_name = None
else:
module_name = name
self.merge_node(module_name2sub_layers[name],
sequentials2attrs_table[name],
node_name2sub_layers,
module_name)
def update_parameters(self):
""" 更新参数。
"""
self.param_tree.traverse()
full_old_name_list = copy.deepcopy(list(self.pd_graph.parameters.keys()))
for old_name, new_name in self.param_tree.old2new.items():
for full_old_name in full_old_name_list:
if full_old_name.startswith("{}.".format(old_name)):
full_new_name = full_old_name.replace("{}.".format(old_name), "{}.".format(new_name))
params = self.pd_graph.parameters.pop(full_old_name)
self.pd_graph.parameters[full_new_name] = params
if full_old_name == old_name:
full_new_name = full_old_name.replace(old_name, new_name)
params = self.pd_graph.parameters.pop(full_old_name)
self.pd_graph.parameters[full_new_name] = params
def save_source_files(self, save_dir):
def gen_main_code():
input_data_name = ', '.join(self.pd_graph.inputs)
run_func_list = list()
run_func_list.append("def main({}):".format(input_data_name))
run_func_list.append(" # 共{}个输入".format(len(self.pd_graph.inputs_info)))
for k, v in self.pd_graph.inputs_info.items():
run_func_list.append(" # {}: 形状为{},类型为{}。".format(k, v[0], v[1]))
run_func_list.extend(
[" paddle.disable_static()",
" params = paddle.load('{}/model.pdparams')".format(osp.abspath(save_dir)),
" model = {}()".format(self.pd_graph.name),
" model.set_dict(params)",
" model.eval()",
" out = model({})".format(input_data_name),
" return out"])
return "\n".join(run_func_list)
self.update_hierarchical_order()
self.convert_subgraph_to_layer()
self.update_parameters()
import_list = ["import paddle",
"import paddle.fluid as fluid",
"from paddle.fluid.initializer import Constant",
"from paddle.fluid.param_attr import ParamAttr",
"import math",
"from x2paddle.op_mapper.dygraph.pytorch2paddle " + \
"import pytorch_custom_layer as x2paddle_nn"
"\n",]
import_str = "\n".join(import_list)
if not osp.exists(save_dir):
os.makedirs(save_dir)
f = open(osp.join(save_dir, 'x2paddle_code.py'), 'w')
f.write(import_str)
for code in self.codes:
f.write(code)
f.write("\n")
run_func = gen_main_code()
f.write(run_func)
f.close()
# -*- coding:UTF-8 -*-
# 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.
import copy
from x2paddle.optimizer.code_optimizer.parameter_tree import PamareterNode
NN_KERNEL_NAME = {"paddle.nn.BatchNorm": "bn",
"paddle.nn.LayerNorm": "layernorm",
"paddle.nn.Conv2D": "conv",
"paddle.nn.Embedding": "embedding",
"paddle.nn.Linear": "linear",
"paddle.nn.Conv2DTranspose": "conv",
"paddle.nn.ReLU": "relu",
"paddle.nn.ReLU6": "relu",
"paddle.nn.Softmax": "softmax",
"paddle.nn.Softplus": "softplus",
"paddle.nn.Tanh": "tanh",
"paddle.nn.AvgPool2D": "pool",
"paddle.nn.MaxPool2D": "pool",
"paddle.nn.Pad1D": "pad",
"paddle.nn.Pad2D": "pad",
"paddle.nn.Pad3D": "pad",
"paddle.nn.Dropout": "dropout",
"paddle.nn.GELU": "gelu",
"paddle.nn.Hardtanh": "tanh",
"paddle.nn.LeakyReLU": "leakly_relu"}
NN_KERNEL_WITH_PARAMS = list(NN_KERNEL_NAME.keys())[:6]
def rename_layers(layers, param_tree=None):
""" 对子模块的输入输出等进行重命名。
"""
layers_cp = copy.deepcopy(layers)
name_dict = dict()
nn_param_nodes = list()
count = 0
nn_count_dict = dict()
module_count_dict = dict()
new_names = list()
for kernel in NN_KERNEL_NAME.keys():
nn_count_dict[kernel] = 0
def rename_sub_layers(sub_layers, count, is_block=False):
for layer_id, layer in sub_layers.items():
# 对输入重命名
for input_k, input_v in layer.inputs.items():
if input_v in name_dict:
layer.inputs[input_k] = name_dict[input_v]
else:
new_name = "x{}".format(count)
count += 1
layer.inputs[input_k] = new_name
name_dict[input_v] = new_name
# 对block重命名
for block in layer.blocks:
count = rename_sub_layers(block.layers,
count, is_block=True)
# 对输出重命名
if len(layer.outputs) == 0 and not is_block:
new_names.append("layer_id/{}".format(layer_id))
for i, output_v in enumerate(layer.outputs):
if output_v in name_dict:
layer.outputs[i] = name_dict[output_v]
if i == 0 and not is_block:
new_names.append(name_dict[output_v])
else:
if i == 0 and layer.kernel in NN_KERNEL_NAME.keys():
new_name = NN_KERNEL_NAME[layer.kernel] + str(nn_count_dict[layer.kernel])
param_node = PamareterNode(old_name=layer.outputs[0],
new_name=new_name)
nn_param_nodes.append(param_node)
if param_tree is not None:
param_tree.add_node(param_node)
layer.outputs[0] = new_name
nn_count_dict[layer.kernel] += 1
elif i == 0 and layer.kernel == "module":
old_name = layer.outputs[0].split("/")[0]
if old_name not in nn_count_dict:
nn_count_dict[old_name] = 0
else:
nn_count_dict[old_name] += 1
new_name = old_name + str(nn_count_dict[old_name])
if param_tree is not None:
param_node = param_tree.get_node(layer.outputs[0])
nn_param_nodes.append(param_node)
param_node.new_name = new_name
layer.outputs[0] = new_name
else:
old_name = layer.outputs[i]
new_name = "x{}".format(count)
count += 1
layer.outputs[i] = new_name
name_dict[output_v] = new_name
if layer.kernel == "self.create_parameter":
param_node = PamareterNode(old_name=old_name,
new_name=new_name)
nn_param_nodes.append(param_node)
if param_tree is not None:
param_tree.add_node(param_node)
if i == 0 and not is_block:
new_names.append(new_name)
# 对layer的attr进行重命名
for attr_k, attr_v in layer.attrs.items():
if isinstance(attr_v, str) and "'" not in attr_v \
and attr_v in name_dict:
layer.attrs[attr_k] = name_dict[attr_v]
return count
rename_sub_layers(layers_cp, count)
return layers_cp, nn_param_nodes, new_names
def gen_layer_code(graph, sub_layers, sub_layers_name, different_attrs=list()):
""" 根据sub_layers生成对应的Module代码。
Args:
graph (x2paddle.core.program.PaddleGraph): 整个Paddle图。
sub_layers (dict): 子图的id和其对应layer组成的字典。
sub_layers_name (str): 子图的名字。
different_attrs (list): 属性列表,这些属性表明在被调用时赋予不同值。
"""
def gen_codes(code_list, indent=0):
""" 根据code_list生成代码段。
Args:
code_list (list): 代码行组成的list。
indent (int): 每行空格的数量。
Returns:
str: 代码段。
"""
indent_blank = " " * indent
codes = []
for code_line in code_list:
if code_line.strip() == "":
codes.append('\n')
else:
codes.append(indent_blank + code_line + '\n')
return codes
def gen_head(inputs, different_attrs):
# 生成Layer的头部代码
head = gen_codes(["class {}(paddle.nn.Layer):".format(sub_layers_name)], indent=0)
# 生成init函数的头部代码
attrs_str = ", ".join(different_attrs)
init_func_head = \
gen_codes(["def __init__(self, {}):".format(attrs_str)], indent=1) + \
gen_codes(["super({}, self).__init__()".format(sub_layers_name)], indent=2)
# 生成forward函数的头部代码
input_data_name = ", ".join(inputs)
forward_func_head = \
gen_codes(["def forward(self, {}):".format(input_data_name)], indent=1)
return head, init_func_head, forward_func_head
init_func = []
forward_func = []
cur_outputs = list()
inputs = list()
outputs = list()
param_prefix_list = list()
input_id = 0
for layer_id, layer in sub_layers.items():
if layer_id not in graph.edges_out:
for index, output_name in enumerate(layer.outputs):
if layer.kernel.startswith("paddle.nn") and index == 0:
continue
if not output_name.startswith("x") or output_name in outputs \
or layer.kernel == "prim.assert":
continue
elif layer.kernel == "prim.if" or layer.kernel == "prim.loop":
if index != 0:
outputs.append(output_name)
elif output_name not in outputs:
outputs.append(output_name)
continue
for out_layer_id in graph.edges_out[layer_id]:
if out_layer_id not in sub_layers:
for index, output_name in enumerate(layer.outputs):
if layer.kernel.startswith("paddle.nn") and index == 0 and "functional" not in layer.kernel:
continue
if not output_name.startswith("x") or output_name in outputs \
or layer.kernel == "prim.assert":
continue
elif layer.kernel == "prim.if" or layer.kernel == "prim.loop":
if index != 0:
outputs.append(output_name)
else:
outputs.append(output_name)
no_output_count = 0
for i, (layer_id, layer) in enumerate(sub_layers.items()):
if ("paddle.nn" in layer.kernel and "functional" not in layer.kernel) or \
layer.kernel.startswith("custom_layer"):
line = "self.{}".format(layer.outputs[0])
if layer.kernel.startswith("custom_layer"):
line += "= x2paddle_nn.{}(".format(layer.kernel.split(":")[-1])
else:
line += " = {}(".format(layer.kernel)
for k, v in layer.attrs.items():
key_name = "{}_{}".format(layer.outputs[0], k)
if key_name in different_attrs:
line += "{}={}, ".format(k, key_name)
else:
line += "{}={}, ".format(k, v)
line = line.strip(", ")
line += ")"
init_func.extend(gen_codes([line], indent=2))
if len(layer.outputs) == 1:
line = layer.outputs[0]
elif len(layer.outputs) == 2:
line = layer.outputs[1]
else:
line = ','.join(layer.outputs[1:])
line += " = self.{}(".format(layer.outputs[0])
for k, v in layer.inputs.items():
if v not in cur_outputs and v not in inputs:
inputs.append(v)
line += "{}, ".format(v)
line = line.strip(", ")
line += ")"
forward_func.extend(gen_codes([line], indent=2))
if len(layer.outputs) == 1:
cur_outputs.append(layer.outputs[0])
else:
cur_outputs.extend(layer.outputs[1:])
elif "prim" in layer.kernel:
func_name = layer.kernel.replace(".", "_")
from x2paddle.op_mapper.dygraph.pytorch2paddle import prim2code
if hasattr(prim2code, func_name):
for k, v in layer.inputs.items():
if v not in cur_outputs and v not in inputs:
inputs.append(v)
func = getattr(prim2code, func_name)
func(
layer,
indent=2,
init_func=init_func,
forward_func=forward_func,
layer_id=layer_id,
different_attrs=different_attrs)
cur_outputs.extend(layer.outputs)
else:
raise Exception(
"The kind {} in paddle model is not supported yet.".
format(layer.kernel))
elif layer.kernel == "module":
line = "self.{} = {}(".format(layer.outputs[0], layer.attrs["module"])
layer.attrs.pop("module")
for k, v in layer.attrs.items():
key_name = "{}_{}".format(layer.outputs[0], k)
if key_name in different_attrs:
line += "{}={}, ".format(k, key_name)
else:
line += "{}={}, ".format(k, v)
line = line.strip(", ")
line += ")"
init_func.extend(gen_codes([line], indent=2))
if len(layer.outputs) == 2:
line = layer.outputs[1]
else:
line = ','.join(layer.outputs[1:])
line += " = self.{}(".format(layer.outputs[0])
for k, v in layer.inputs.items():
if v not in cur_outputs and v not in inputs:
inputs.append(v)
line += "{}, ".format(v)
line = line.strip(", ")
line += ")"
forward_func.extend(gen_codes([line], indent=2))
cur_outputs.extend(layer.outputs[1:])
else:
if layer.kernel == "paddle.to_tensor":
v = layer.attrs["data"]
if v not in cur_outputs and v not in inputs:
inputs.append(v)
if len(layer.outputs) == 1:
line = layer.outputs[0]
else:
line = ','.join(layer.outputs)
line += " = {}(".format(layer.kernel)
for k, v in layer.inputs.items():
if isinstance(v, list):
line += "{}=[{}], ".format(k, ", ".join(v))
for lv in v:
if lv not in cur_outputs and lv not in inputs:
inputs.append(lv)
else:
if v not in cur_outputs and v not in inputs:
inputs.append(v)
if k == "args":
line += v
else:
line += "{}={}, ".format(k, v)
for k, v in layer.attrs.items():
key_name = "{}_{}".format(layer.outputs[0], k)
if key_name in different_attrs:
line += "{}=self.{}, ".format(k, key_name)
init_func.extend(gen_codes(["self.{} = {}".format(key_name, key_name)], indent=2))
else:
line += "{}={}, ".format(k, v)
line = line.strip(", ")
line += ")"
if layer.kernel == "self.create_parameter":
init_func.extend(gen_codes(["self." + line], indent=2))
forward_func.extend(gen_codes(["{} = self.{}".format(layer.outputs[0],
layer.outputs[0])], indent=2))
else:
forward_func.extend(gen_codes([line], indent=2))
cur_outputs.extend(layer.outputs)
head, init_func_head, forward_func_head = gen_head(inputs, different_attrs)
output_data_name = ", ".join(outputs)
code_list = head + init_func_head + init_func + \
forward_func_head + forward_func + \
gen_codes(["return {}".format(output_data_name)], indent=2)
code_str = "".join(code_list)
return code_str
\ No newline at end of file
# -*- coding:UTF-8 -*-
# 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.
class PamareterNode(object):
def __init__(self, old_name=None, new_name=None):
self.old_name = old_name
self.new_name = new_name
self.childs = list()
def add_child(self, child):
self.childs.append(child)
def has_child(self):
if len(self.childs) == 0:
return False
else:
return True
class PamareterTree(object):
def __init__(self):
self.nodes = list()
self.old2new = dict()
def add_node(self, node):
self.nodes.append(node)
def traverse(self):
tmp = list()
def recurs(node, prefix_name):
for child in node.childs:
child_prefix_name = prefix_name + "." + child.new_name
if child.has_child():
recurs(child, child_prefix_name)
else:
self.old2new[child.old_name] = child_prefix_name[1:]
recurs(self.nodes[-1], "")
def get_node(self, old_name):
for node in self.nodes:
if node.old_name == old_name:
return node
\ No newline at end of file
# -*- coding:UTF-8 -*-
# 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.
import copy
import pandas as pd
from x2paddle.optimizer.code_optimizer.layer_code_generator import rename_layers
def construct_attrs_table(sub_layers_list, node_name2sub_layers):
""" 构造不同属性的表格。
"""
def get_node_name(sub_layers):
for k, v in node_name2sub_layers.items():
if v == sub_layers:
node_name = k
break
return node_name
sub_layers = sub_layers_list[0]
_, _, new_names = rename_layers(sub_layers)
table = list()
node_names = list()
for sub_layers in sub_layers_list:
attrs = dict()
node_names.append(get_node_name(sub_layers))
for i, (layer_id, layer) in enumerate(sub_layers.items()):
for k, v in layer.attrs.items():
attrs[new_names[i] + "_{}".format(k)] = v
table.append(attrs)
pd_table = pd.DataFrame(table, index=node_names)
return pd_table
def get_inputs_outputs(pd_graph, layers):
inputs = list()
outputs = list()
cur_outputs = list()
layer_ids = list(layers.keys())
for layer_id, layer in layers.items():
# 获取输出节点名字
if layer_id not in pd_graph.edges_out:
for index, output_name in enumerate(layer.outputs):
if not output_name.startswith("x") or output_name in outputs \
or layer.kernel == "prim.assert":
continue
elif layer.kernel == "prim.if" or layer.kernel == "prim.loop":
if index != 0:
outputs.append(output_name)
elif output_name not in outputs:
outputs.append(output_name)
else:
for out_layer_id in pd_graph.edges_out[layer_id]:
if out_layer_id not in layer_ids:
for index, output_name in enumerate(layer.outputs):
if not output_name.startswith("x") or output_name in outputs \
or layer.kernel == "prim.assert":
continue
elif layer.kernel == "prim.if" or layer.kernel == "prim.loop":
if index != 0:
outputs.append(output_name)
else:
outputs.append(output_name)
# 获取输入节点名字
for k, v in layer.inputs.items():
if v not in cur_outputs and v not in inputs:
inputs.append(v)
if ("paddle.nn" in layer.kernel and "functional" not in layer.kernel):
cur_outputs.extend(layer.outputs[1:])
else:
cur_outputs.extend(layer.outputs)
return inputs, outputs
def get_inputs_count(pd_graph, sub_layers):
input_ct2sub_layer_id = dict()
for i, sub_layer in enumerate(sub_layers):
inputs, outputs = get_inputs_outputs(pd_graph, sub_layer)
if len(inputs) not in input_ct2sub_layer_id:
input_ct2sub_layer_id[len(inputs)] = [i]
else:
input_ct2sub_layer_id[len(inputs)].append(i)
return input_ct2sub_layer_id
def distinguish_sequential(pd_graph, module_name, sub_layers, sub_identifiers, node_name2sub_layers):
""" 获取不同的layers组成的序列
"""
def distinguish_sequential_by_inputs(part_layers, part_identifiers, part_module_name):
new_sub_layers = dict()
new_sub_sequentials = dict()
sequentials2attrs_table = dict()
input_ct2sub_layer_id = get_inputs_count(pd_graph, part_layers)
if len(input_ct2sub_layer_id) == 1:
new_sub_layers["{}".format(part_module_name)] = part_layers
new_sub_sequentials["{}".format(part_module_name)] = part_identifiers
sequentials2attrs_table["{}".format(part_module_name)] = construct_attrs_table(part_layers, node_name2sub_layers)
else:
for i, (k, indexes) in enumerate(input_ct2sub_layer_id.items()):
new_sub_layers["{}__{}".format(part_module_name, i)] = list()
new_sub_sequentials["{}__{}".format(part_module_name, i)] = list()
for index in indexes:
new_sub_layers["{}__{}".format(part_module_name, i)].append(part_layers[index])
new_sub_sequentials["{}__{}".format(part_module_name, i)].append(part_identifiers[index])
sequentials2attrs_table["{}__{}".format(part_module_name, i)] = \
construct_attrs_table(new_sub_layers["{}__{}".format(part_module_name, i)], node_name2sub_layers)
return new_sub_layers, new_sub_sequentials, sequentials2attrs_table
new_sub_layers = dict()
new_sub_sequentials = dict()
sequentials2attrs_table = dict()
identifiers_str_list = list()
for identifiers in sub_identifiers:
identifiers_str_list.append(", ".join(list(identifiers.values())))
identifiers_str_set = list(set(identifiers_str_list))
if len(identifiers_str_set) == 1:
return distinguish_sequential_by_inputs(sub_layers, sub_identifiers, module_name)
else:
for i in range(len(identifiers_str_set)):
new_sub_layers["{}{}".format(module_name, i)] = list()
new_sub_sequentials["{}{}".format(module_name, i)] = list()
no_same_module_count = 0
for j, identifiers in enumerate(sub_identifiers):
identifiers_str = identifiers_str_list[j]
for i in range(len(identifiers_str_set)):
if identifiers_str_set[i] == identifiers_str:
is_diff = False
if identifiers_str_set[i].replace(", ", "").isdigit() or module_name == "ModuleList":
new_sub_layers["{}{}".format(module_name, len(identifiers_str_set) + no_same_module_count)] = [sub_layers[j]]
new_sub_sequentials["{}{}".format(module_name, len(identifiers_str_set) + no_same_module_count)] = [identifiers]
no_same_module_count += 1
else:
new_sub_layers["{}{}".format(module_name, i)].append(sub_layers[j])
new_sub_sequentials["{}{}".format(module_name, i)].append(identifiers)
break
new_new_sub_layers = dict()
new_new_sub_sequentials = dict()
for k, v in new_sub_layers.items():
part_sub_layers, part_sub_sequentials, part_sequentials2attrs_table = \
distinguish_sequential_by_inputs(v, new_sub_sequentials[k], k)
new_new_sub_layers.update(part_sub_layers)
new_new_sub_sequentials.update(part_sub_sequentials)
sequentials2attrs_table.update(part_sequentials2attrs_table)
return new_new_sub_layers, new_new_sub_sequentials, sequentials2attrs_table
\ No newline at end of file
# 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 .transpose_elimination import DygraphTransposeElimination
from .transpose_eliminate_pass import DygraphTransposeEliminatePass
\ No newline at end of file
# 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.optimizer.pass_ import Pass
from x2paddle.optimizer.elimination.dygraph import DygraphTransposeElimination
from x2paddle.optimizer.pass_manager import pass_register
@pass_register
class DygraphTransposeEliminatePass(Pass):
name = "transpose_eliminate_pass"
def __init__(self):
Pass.__init__(self)
def apply(self, graph):
fuser = DygraphTransposeElimination()
fuser.operate(graph)
# 用于注册
transpose_eliminate_pass = DygraphTransposeEliminatePass()
\ No newline at end of file
# 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.
import copy
import sys
import numpy as np
from x2paddle.optimizer.pattern_matcher import FuseBase
from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import *
class DygraphTransposeElimination(FuseBase):
def __init__(self):
super(DygraphTransposeElimination, self).__init__(graph_type="dygraph")
self.direct_layers = [
'paddle.nn.ReLU', 'paddle.nn.ReLU6', 'paddle.abs',
'paddle.nn.Sigmoid', 'paddle.exp', 'paddle.rsqrt',
'paddle.nn.Swish', 'paddle.nn.Tanh',
'paddle.nn.Softplus', 'paddle.nn.LeakyReLU',
'paddle.floor', 'paddle.erf', 'paddle.square'
]
self.elementwise_layers = [
'paddle.add', 'fluid.layers.elementwise_sub',
'paddle.multiply', 'paddle.divide'
]
self.reduce_layers = [
'paddle.mean', 'paddle.all',
'paddle.max', 'paddle.any',
'paddle.sum', 'paddle.prod'
]
def get_transpose_num(self, graph):
count = 0
for layer_id, layer in graph.layers.items():
if layer.kernel == "paddle.transpose":
count += 1
return count
def operate(self, graph):
total_layer_num = len(graph.layers)
scanned_layers = set()
optimized_transpose_layers = list()
optimized_reduce_layers = list()
optimized_concat_layers = list()
optimized_elementwise_layers = list()
def get_index(layer):
if layer.kernel.startswith("paddle.nn") and "functional" not in layer.kernel:
return 1
else:
return 0
def strip_transpose(_graph):
layers = copy.deepcopy(_graph.layers)
for layer_id, layer in layers.items():
if layer_id in scanned_layers:
continue
scanned_layers.add(layer_id)
percent = round(len(scanned_layers) / total_layer_num * 100, 2)
sys.stderr.write("\rOptimize Transpose Layers...{}%".format(
percent))
if layer.kernel != "paddle.transpose":
continue
if layer.attrs["perm"] != [0, 2, 3, 1]:
continue
transpose_layers = list()
propagate_layers = list()
reduce_layers = list()
concat_layers = list()
# 此elementwise_layers专用于存储shape(4) + shape(1)的形式layer
elementwise_layers = list()
can_be_optimized = True
for out in _graph.edges_out.get(layer_id, []):
if _graph.layers[out].kernel == "paddle.transpose":
if _graph.layers[out].attrs["perm"] != [0, 3, 1, 2]:
can_be_optimized = False
break
transpose_layers.append(out)
elif _graph.layers[out].kernel in self.elementwise_layers:
propagate_layers.append(out)
elif _graph.layers[out].kernel in self.direct_layers:
ouput_index = get_index(_graph.layers[out])
if _graph.layers[out].outputs[ouput_index] in _graph.outputs:
can_be_optimized = False
break
propagate_layers.append(out)
elif _graph.layers[out].kernel in self.reduce_layers:
ouput_index = get_index(_graph.layers[out])
if _graph.layers[out].outputs[ouput_index] in _graph.outputs:
can_be_optimized = False
break
if not _graph.layers[out].attrs.get('keepdim', False):
can_be_optimized = False
break
propagate_layers.append(out)
reduce_layers.append(out)
elif _graph.layers[out].kernel == "paddle.concat":
ouput_index = get_index(_graph.layers[out])
if _graph.layers[out].outputs[ouput_index] in _graph.outputs:
can_be_optimized = False
break
propagate_layers.append(out)
concat_layers.append(out)
else:
can_be_optimized = False
break
visited_layers = set()
while len(propagate_layers) > 0 and can_be_optimized:
current_id = propagate_layers.pop(0)
visited_layers.add(current_id)
for out in _graph.edges_out.get(current_id, []):
if _graph.layers[
out].kernel == "paddle.transpose":
if _graph.layers[out].attrs["perm"] != [0, 3, 1, 2]:
can_be_optimized = False
break
transpose_layers.append(out)
elif _graph.layers[
out].kernel in self.elementwise_layers:
output_index = get_index(_graph.layers[out])
if _graph.layers[out].outputs[output_index] in _graph.outputs:
can_be_optimized = False
break
if out not in visited_layers:
propagate_layers.append(out)
elif _graph.layers[out].kernel in self.direct_layers:
output_index = get_index(_graph.layers[out])
if _graph.layers[out].outputs[output_index] in _graph.outputs:
can_be_optimized = False
break
if out not in visited_layers:
propagate_layers.append(out)
elif _graph.layers[out].kernel in self.reduce_layers:
output_index = get_index(_graph.layers[out])
if _graph.layers[out].outputs[output_index] in _graph.outputs:
can_be_optimized = False
break
if not _graph.layers[out].attrs.get('keepdim',
False):
can_be_optimized = False
break
if out not in visited_layers:
propagate_layers.append(out)
reduce_layers.append(out)
elif _graph.layers[out].kernel == "paddle.concat":
output_index = get_index(_graph.layers[out])
if _graph.layers[out].outputs[output_index] in _graph.outputs:
can_be_optimized = False
break
if out not in visited_layers:
propagate_layers.append(out)
concat_layers.append(out)
else:
can_be_optimized = False
break
for ipt in _graph.edges_in.get(current_id, []):
if _graph.layers[
current_id].kernel in self.elementwise_layers:
try:
x_shape = _graph.layers[
current_id].input_shapes['x']
y_shape = _graph.layers[
current_id].input_shapes['y']
output_index = get_index(_graph.layers[ipt])
if _graph.layers[ipt].outputs[
output_index] == _graph.layers[current_id].inputs[
'x']:
if len(x_shape) <= 1:
elementwise_layers.append(current_id)
continue
elif _graph.layers[ipt].outputs[
output_index] == _graph.layers[current_id].inputs[
'y']:
if len(y_shape) <= 1:
elementwise_layers.append(current_id)
continue
else:
raise Exception(
"Unexcepted situation happend while optimizing transpose"
)
except Exception as e:
can_be_optimized = False
break
output_index = get_index(_graph.layers[ipt])
if _graph.layers[
ipt].kernel == "paddle.transpose":
if _graph.layers[ipt].attrs["perm"] != [0, 2, 3, 1]:
can_be_optimized = False
break
if ipt not in visited_layers:
transpose_layers.append(ipt)
elif _graph.layers[
ipt].kernel in self.elementwise_layers:
if _graph.layers[ipt].outputs[output_index] in _graph.outputs:
can_be_optimized = False
break
if ipt not in visited_layers:
propagate_layers.append(ipt)
elif _graph.layers[ipt].kernel in self.direct_layers:
if _graph.layers[ipt].outputs[output_index] in _graph.outputs:
can_be_optimized = False
break
if ipt not in visited_layers:
propagate_layers.append(ipt)
elif _graph.layers[ipt].kernel in self.reduce_layers:
if _graph.layers[ipt].outputs[output_index] in _graph.outputs:
can_be_optimized = False
break
if not _graph.layers[ipt].attrs.get('keepdim',
False):
can_be_optimized = False
break
if ipt not in visited_layers:
propagate_layers.append(ipt)
reduce_layers.append(ipt)
elif _graph.layers[ipt].kernel == "paddle.concat":
if _graph.layers[ipt].outputs[output_index] in _graph.outputs:
can_be_optimized = False
break
if ipt not in visited_layers:
propagate_layers.append(ipt)
concat_layers.append(ipt)
else:
can_be_optimized = False
break
if not can_be_optimized:
break
if not can_be_optimized:
continue
transpose_layers.append(layer_id)
transpose_layers = list(set(transpose_layers))
for l in transpose_layers:
output_index = get_index(graph.layers[l])
if graph.layers[l].outputs[output_index] in graph.outputs:
can_be_optimized = False
break
if not can_be_optimized:
continue
for l in transpose_layers:
_graph.del_layer(l)
optimized_transpose_layers.extend(transpose_layers)
optimized_reduce_layers.extend(reduce_layers)
optimized_concat_layers.extend(concat_layers)
optimized_elementwise_layers.extend(elementwise_layers)
return True
return False
before_transpose_num = self.get_transpose_num(graph)
opt_graph = copy.deepcopy(graph)
total_layer_num = len(opt_graph.layers)
while strip_transpose(opt_graph):
pass
for layer_id in list(set(optimized_transpose_layers)):
graph.del_layer(layer_id)
for layer_id in list(set(optimized_reduce_layers)):
dim = graph.layers[layer_id].attrs.get('axis', None)
if dim is not None:
for i in range(len(dim)):
dim[i] = [0, 2, 3, 1][dim[i]]
graph.layers[layer_id].attrs['axis'] = dim
for layer_id in list(set(optimized_concat_layers)):
axis = graph.layers[layer_id].attrs.get('axis', 0)
graph.layers[layer_id].attrs['axis'] = [0, 2, 3, 1][axis]
for layer_id in list(set(optimized_elementwise_layers)):
axis = graph.layers[layer_id].attrs.get('axis', -1)
graph.layers[layer_id].attrs['axis'] = [0, 2, 3, 1][axis]
if graph.layers[layer_id].kernel == "paddle.add":
graph.layers[layer_id].kernel = "fluid.layers.elementwise_add"
current_transpose_num = self.get_transpose_num(graph)
print(
"\nTranspose layers optimized, before: transpose_num={}, after: transpose_num={}".
format(before_transpose_num, current_transpose_num))
......@@ -12,17 +12,27 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from .adaptive_pool2d_fuser import AdaptivePool2dFuser
from .adaptive_pool2d_fuse_pass import AdaptivePool2dFusePass
from .batchnorm2d_fuser import BatchNorm2dFuser
from .batchnorm2d_fuse_pass import BatchNorm2dFusePass
from .constant_fuser import ConstantFuser
from .constant_fuse_pass import ConstantFusePass
from .dropout_fuser import DropoutFuser
from .dropout_fuse_pass import DropoutFusePass
from .fc_fuser import FcFuser
from .fc_fuse_pass import FcFusePass
from .interpolate_bilinear_fuser import InterpolateBilinearFuser
from .interpolate_bilinear_fuse_pass import InterpolateBilinearFusePass
from .reshape_fuser import ReshapeFuser
from .reshape_fuse_pass import ReshapeFusePass
from .adaptive_pool2d_fuser import DygraphAdaptivePool2dFuser
from .adaptive_pool2d_fuse_pass import DygraphAdaptivePool2dFusePass
from .batchnorm2d_fuser import DygraphBatchNorm2dFuser
from .batchnorm2d_fuse_pass import DygraphBatchNorm2dFusePass
from .bn_scale_fuser import DygraphBNScaleFuser
from .bn_scale_fuse_pass import DygraphBNScaleFusePass
from .constant_fuser import DygraphConstantFuser
from .constant_fuse_pass import DygraphConstantFusePass
from .conv2d_add_fuser import DygraphConv2DAddFuser
from .conv2d_add_fuse_pass import DygraphConv2DAddFusePass
from .dropout_fuser import DygraphDropoutFuser
from .dropout_fuse_pass import DygraphDropoutFusePass
from .fc_fuser import DygraphFcFuser
from .fc_fuse_pass import DygraphFcFusePass
from .interpolate_bilinear_fuser import DygraphInterpolateBilinearFuser
from .interpolate_bilinear_fuse_pass import DygraphInterpolateBilinearFusePass
from .prelu_fuser import DygraphPReLUFuser
from .prelu_fuse_pass import DygraphPReLUFusePass
from .reshape_fuser import DygraphReshapeFuser
from .reshape_fuse_pass import DygraphReshapeFusePass
from .tf_batchnorm_fuser import DygraphTFBatchNormFuser
from .tf_batchnorm_fuse_pass import DygraphTFBatchNormFusePass
from .trace_fc_fuser import TraceFcFuser
from .trace_fc_fuse_pass import TraceFcFusePass
# 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.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.dygraph import DygraphAdaptivePool2dFuser
from x2paddle.optimizer.pass_manager import pass_register
@pass_register
class DygraphAdaptivePool2dFusePass(Pass):
name = "dygraph_adaptive_pool2d_fuse_pass"
def __init__(self):
Pass.__init__(self)
def apply(self, graph):
fuser = DygraphAdaptivePool2dFuser()
fuser.operate(graph, match_kind="topo")
# 用于注册
adaptive_pool2d_fuse_pass = DygraphAdaptivePool2dFusePass()
......@@ -13,19 +13,22 @@
# limitations under the License.
import numpy as np
from x2paddle.optimizer.pytorch_optimizer.pattern_matcher import FuseBase
import copy
from x2paddle.optimizer.pattern_matcher import FuseBase
from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import *
class AdaptivePool2dFuser(FuseBase):
class DygraphAdaptivePool2dFuser(FuseBase):
def __init__(self):
super(AdaptivePool2dFuser, self).__init__(graph_type="dygraph")
super(DygraphAdaptivePool2dFuser, self).__init__(graph_type="dygraph")
self.patterns = list()
def build_pattern(self):
""" 描述需要替换的adaptive pool2d图结构。
adaptive pool2d层模式python实现代码示例:
x68 = fluid.layers.shape(input=x60)
模式一:
x68 = prim.shape(input=x60)
x69 = len(x68)
x70 = x69 <= 2
if x70 :
......@@ -38,57 +41,64 @@ class AdaptivePool2dFuser(FuseBase):
for _x79 in range(x77):
x80 = [6, 6][_x79]
x73.append(x80)
x81 = fluid.layers.adaptive_pool2d(input=x60, pool_size=x73, pool_type='avg')
x81 = paddle.nn.functional.adaptive_avg_pool2d(input=x60, pool_size=x73, pool_type='avg')
模式二:
x64 = x60.shape
x65 = len(x64)
x66 = x65 > 2
if x66 :
pass
else:
raise RaiseException('AssertionError: ')
x69 = self.pool2d3(x60)
"""
def gen_name(id):
return "x" + str(id)
self.pattern.add_layer(
"fluid.layers.shape",
# 模式一:
pattern = PaddleGraph(graph_type="dygraph")
pattern.add_layer(
"prim.shape",
inputs={'input': "pool-input-0"},
outputs=[gen_name(1)])
self.pattern.add_layer(
pattern.add_layer(
"prim.len", inputs={"input": gen_name(1)}, outputs=[gen_name(6)])
self.pattern.add_layer(
pattern.add_layer(
"prim.le", inputs={"x": gen_name(6)}, outputs=[gen_name(8)], y=2)
self.pattern.add_layer("prim.if", {'input': gen_name(8)}, [gen_name(9)])
if_layer = self.pattern.layers[list(self.pattern.layers.keys())[-1]]
pattern_block0 = PaddleGraph(if_layer, graph_type="dygraph")
pattern.add_layer("prim.if", {'input': gen_name(8)}, [gen_name(9)])
if_layer = pattern.layers[list(pattern.layers.keys())[-1]]
pattern_block0 = PaddleGraph(parent_layer=if_layer, graph_type="dygraph")
pattern_block0.add_layer(
"prim.exception",
inputs={},
outputs=[gen_name(9)],
input="Exception")
if_layer.add_block(pattern_block0)
pattern_block1 = PaddleGraph(if_layer, graph_type="dygraph")
pattern_block1 = PaddleGraph(parent_layer=if_layer, graph_type="dygraph")
if_layer.add_block(pattern_block1)
self.pattern.add_layer("prim.list", inputs={}, outputs=[gen_name(10)])
self.pattern.add_layer(
pattern.add_layer("prim.list", inputs={}, outputs=[gen_name(10)])
pattern.add_layer(
"prim.slice",
inputs={"input": gen_name(1), },
outputs=[gen_name(12)],
start=-1,
end=100,
step=1)
self.pattern.add_layer(
outputs=[gen_name(12)])
pattern.add_layer(
"prim.len", inputs={"input": gen_name(12)}, outputs=[gen_name(14)])
self.pattern.add_layer(
pattern.add_layer(
"prim.list",
inputs={"input1": gen_name(14)},
outputs=[gen_name(15)],
input0=2)
self.pattern.add_layer(
outputs=[gen_name(15)])
pattern.add_layer(
"prim.min", inputs={"input": gen_name(15)}, outputs=[gen_name(16)])
self.pattern.add_layer("prim.loop", {'input': gen_name(16)},
pattern.add_layer("prim.loop", {'input': gen_name(16)},
[gen_name(17), gen_name(18)])
loop_layer = self.pattern.layers[list(self.pattern.layers.keys())[-1]]
loop_layer = pattern.layers[list(pattern.layers.keys())[-1]]
pattern_block = PaddleGraph(loop_layer, graph_type="dygraph")
pattern_block.add_layer(
"prim.getitem",
inputs={"index": gen_name(18)},
outputs=[gen_name(19)],
list=[6, 6])
outputs=[gen_name(19)])
pattern_block.add_layer(
"prim.append",
inputs={"list": gen_name(10),
......@@ -97,14 +107,45 @@ class AdaptivePool2dFuser(FuseBase):
loop_layer.inputs["input-0"] = gen_name(10)
loop_layer.add_block(pattern_block)
pool_attrs = {'pool_type': string("avg")}
self.pattern.add_layer(
"fluid.layers.adaptive_pool2d",
pattern.add_layer(
"paddle.nn.functional.adaptive_avg_pool2d",
inputs={'input': "pool-input-0",
"pool_size": gen_name(10)},
outputs=[gen_name(21)],
**pool_attrs)
self.pattern.build(inputs={"input-0": "pool-input-0", })
pattern.build(inputs={"input-0": "pool-input-0", })
self.patterns.append(pattern)
# 模式二:
pattern = PaddleGraph(graph_type="dygraph")
pattern.add_layer(
"prim.shape",
inputs={'input': "pool-input-0"},
outputs=[gen_name(0)])
pattern.add_layer(
"prim.len", inputs={"input": gen_name(0)}, outputs=[gen_name(1)])
pattern.add_layer(
"prim.gt", inputs={"x": gen_name(1)}, outputs=[gen_name(2)], y=2)
pattern.add_layer("prim.if", {'input': gen_name(2)}, [gen_name(3)])
if_layer = pattern.layers[list(pattern.layers.keys())[-1]]
pattern_block0 = PaddleGraph(parent_layer=if_layer, graph_type="dygraph")
if_layer.add_block(pattern_block0)
pattern_block1 = PaddleGraph(parent_layer=if_layer, graph_type="dygraph")
pattern_block1.add_layer(
"prim.exception",
inputs={},
outputs=[gen_name(4)],
input="Exception")
if_layer.add_block(pattern_block1)
pattern.add_layer(
"paddle.nn.AdaptiveAvgPool2D",
inputs={"input": "pool-input-0"},
outputs=["pool1", gen_name(5)])
pattern.build(inputs={"input-0": "pool-input-0",
"input-1": "pool-input-0",})
self.patterns.append(pattern)
def insert_new_layer(self, graph, parameters, matches):
parameters = graph.parameters
new_layer = self.gen_new_layer(parameters, matches)
......@@ -114,20 +155,21 @@ class AdaptivePool2dFuser(FuseBase):
def gen_new_layer(self, parameters, matches):
layers_id = list(matches.keys())
layer = matches[layers_id[11]]
pool_size = layer.attrs["list"]
layer = matches[layers_id[0]]
input_name = layer.inputs["input"]
layer = matches[layers_id[-1]]
output_name = layer.outputs[0]
pool_type = layer.attrs["pool_type"]
attrs = dict()
attrs["pool_size"] = pool_size
attrs["pool_type"] = pool_type
new_layer = PaddleLayer(
layers_id[0],
"fluid.layers.adaptive_pool2d",
inputs={"input": input_name},
outputs=[output_name],
**attrs)
if matches[layers_id[-1]].kernel == "paddle.nn.functional.adaptive_avg_pool2d":
layer = matches[layers_id[11]]
pool_size = layer.attrs["list"]
layer = matches[layers_id[0]]
input_name = layer.inputs["input"]
layer = matches[layers_id[-1]]
output_name = layer.outputs[0]
attrs = dict()
attrs["output_size"] = pool_size
new_layer = PaddleLayer(
layers_id[0],
"paddle.nn.functional.adaptive_avg_pool2d",
inputs={"input": input_name},
outputs=[output_name],
**attrs)
else:
new_layer = copy.deepcopy(matches[layers_id[-1]])
return new_layer
......@@ -12,22 +12,22 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from x2paddle.optimizer.pytorch_optimizer.pass_ import Pass
from x2paddle.optimizer.pytorch_optimizer.fusion import BatchNorm2dFuser
from x2paddle.optimizer.pytorch_optimizer.pass_manager import pass_register
from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.dygraph import DygraphBatchNorm2dFuser
from x2paddle.optimizer.pass_manager import pass_register
@pass_register
class BatchNorm2dFusePass(Pass):
name = "batchnorm2d_fuse_pass"
class DygraphBatchNorm2dFusePass(Pass):
name = "dygraph_batchnorm2d_fuse_pass"
def __init__(self):
Pass.__init__(self)
def apply(self, graph):
fuser = BatchNorm2dFuser()
fuser = DygraphBatchNorm2dFuser()
fuser.operate(graph, match_kind="topo")
# 用于注册
batchnorm2d_fuse_pass = BatchNorm2dFusePass()
batchnorm2d_fuse_pass = DygraphBatchNorm2dFusePass()
......@@ -13,45 +13,45 @@
# limitations under the License.
import numpy as np
from x2paddle.optimizer.pytorch_optimizer.pattern_matcher import FuseBase
from x2paddle.optimizer.pattern_matcher import FuseBase
from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import *
class BatchNorm2dFuser(FuseBase):
class DygraphBatchNorm2dFuser(FuseBase):
def __init__(self):
super(BatchNorm2dFuser, self).__init__(graph_type="dygraph")
super(DygraphBatchNorm2dFuser, self).__init__(graph_type="dygraph")
def build_pattern(self):
""" 描述需要替换的batchnorm2d图结构。
batchnorm2d层模式python实现代码示例:
x336 = fluid.layers.shape(input=x334)
x336 = len(x336)
x337 = x336 != 4
if x337 :
x2011 = x2009.shape
x2011 = len(x2011)
x2012 = x2011 != 4
if x2012 :
raise RaiseException('Exception')
if False :
x351 = fluid.layers.shape(input=x334)
x352 = x351[0]
x353 = len(x351)
x354 = x353 - 2
x357 = x352
for _x356 in range(x354):
x358 = _x356 + 2
x359 = x351[x358]
x360 = x357 * x359
x355 = x360
x361 = x355 == 1
if x361 :
x2026 = x2009.shape
x2027 = x2026[0]
x2028 = len(x2026)
x2029 = x2028 - 2
x2032 = x2027
for _x2031 in range(x2029):
x2033 = _x2031 + 2
x2034 = x2026[x2033]
x2035 = x2032 * x2034
x2030 = x2035
x2036 = x2030 == 1
if x2036 :
raise RaiseException('Exception')
x364 = self.batchnorm7(x334)
x2039 = self.batchnorm50(x2009)
"""
def gen_name(id):
return "x" + str(id)
self.pattern.add_layer(
"fluid.layers.shape",
"prim.shape",
inputs={'input': "bn-input-0"},
outputs=[gen_name(0)])
self.pattern.add_layer(
......@@ -60,20 +60,20 @@ class BatchNorm2dFuser(FuseBase):
"prim.ne", inputs={"x": gen_name(0)}, outputs=[gen_name(1)], y=4)
self.pattern.add_layer("prim.if", {'input': gen_name(1)}, [gen_name(2)])
if_layer1 = self.pattern.layers[list(self.pattern.layers.keys())[-1]]
pattern_block0 = PaddleGraph(if_layer1, graph_type="dygraph")
pattern_block0 = PaddleGraph(parent_layer=if_layer1, graph_type="dygraph")
pattern_block0.add_layer(
"prim.exception",
inputs={},
outputs=[gen_name(3)],
input="Exception")
if_layer1.add_block(pattern_block0)
pattern_block1 = PaddleGraph(if_layer1, graph_type="dygraph")
pattern_block1 = PaddleGraph(parent_layer=if_layer1, graph_type="dygraph")
if_layer1.add_block(pattern_block1)
self.pattern.add_layer("prim.if", {}, [gen_name(4)], input=False)
if_layer2 = self.pattern.layers[list(self.pattern.layers.keys())[-1]]
pattern_block0 = PaddleGraph(if_layer2, graph_type="dygraph")
pattern_block0 = PaddleGraph(parent_layer=if_layer2, graph_type="dygraph")
pattern_block0.add_layer(
"fluid.layers.shape",
"prim.shape",
inputs={'input': "bn-input-0"},
outputs=[gen_name(5)])
pattern_block0.add_layer(
......@@ -93,7 +93,7 @@ class BatchNorm2dFuser(FuseBase):
outputs=[gen_name(8.1), gen_name(10)])
loop_layer = pattern_block0.layers[list(pattern_block0.layers.keys())[
-1]]
pattern_block0_block0 = PaddleGraph(loop_layer, graph_type="dygraph")
pattern_block0_block0 = PaddleGraph(parent_layer=loop_layer, graph_type="dygraph")
pattern_block0_block0.add_layer(
"prim.add", inputs={"x": gen_name(10)}, outputs=[gen_name(11)], y=2)
pattern_block0_block0.add_layer(
......@@ -119,27 +119,24 @@ class BatchNorm2dFuser(FuseBase):
"prim.if", inputs={"input": gen_name(14)}, outputs=[gen_name(15)])
if_layer21 = pattern_block0.layers[list(pattern_block0.layers.keys())[
-1]]
pattern_block0_block0 = PaddleGraph(if_layer21, graph_type="dygraph")
pattern_block0_block0 = PaddleGraph(parent_layer=if_layer21, graph_type="dygraph")
pattern_block0_block0.add_layer(
"prim.exception",
inputs={},
outputs=[gen_name(15)],
input="Exception")
if_layer21.add_block(pattern_block0_block0)
pattern_block0_block1 = PaddleGraph(if_layer21, graph_type="dygraph")
pattern_block0_block1 = PaddleGraph(parent_layer=if_layer21, graph_type="dygraph")
if_layer21.add_block(pattern_block0_block1)
if_layer2.add_block(pattern_block0)
pattern_block1 = PaddleGraph(if_layer2, graph_type="dygraph")
pattern_block1 = PaddleGraph(parent_layer=if_layer2, graph_type="dygraph")
if_layer2.add_block(pattern_block1)
if_layer2.inputs["input-0"] = "bn-input-0"
self.pattern.add_layer(
"paddle.nn.BatchNorm",
inputs={"input": "bn-input-0"},
outputs=[gen_name(16), gen_name(17)],
is_test=True,
num_channels=160,
momentum=0.1,
epsilon=0.001)
is_test=True)
self.pattern.build(inputs={"input-0": "bn-input-0"})
def insert_new_layer(self, graph, parameters, matches):
......@@ -148,9 +145,6 @@ class BatchNorm2dFuser(FuseBase):
graph.layers[new_layer_id] = new_layer
matches.pop(new_layer_id)
# for layer in matches.values():
# print(layer.outputs)
# print("-------")
def gen_new_layer(self, parameters, matches):
layers_id = list(matches.keys())
......
# 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.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.dygraph import DygraphBNScaleFuser
from x2paddle.optimizer.pass_manager import pass_register
@pass_register
class DygraphBNScaleFusePass(Pass):
name = "dygraph_bn_scale_fuse_pass"
def __init__(self):
Pass.__init__(self)
def apply(self, graph):
fuser = DygraphBNScaleFuser()
fuser.operate(graph, match_kind="topo")
# 用于注册
bn_scale_fuse_pass = DygraphBNScaleFusePass()
# 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.
import numpy as np
from x2paddle.optimizer.pattern_matcher import FuseBase
from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import *
class DygraphBNScaleFuser(FuseBase):
def __init__(self):
super(DygraphBNScaleFuser, self).__init__(graph_type="dygraph")
def build_pattern(self):
""" 描述需要替换的batchnorm2d图结构。
batchnorm2d层模式python实现代码示例:
bn_conv1 = self.batchnorm0(conv1)
scale_conv1_cparam1 = self.scale_conv1_cparam1
scale_conv1_mul = paddle.multiply(x=bn_conv1, y=scale_conv1_cparam1, axis=1)
scale_conv1_cparam2 = self.scale_conv1_cparam2
scale_conv1 = fluid.layers.elementwise_add(x=scale_conv1_mul, y=scale_conv1_cparam2, axis=1)
"""
def gen_name(id):
return "x" + str(id)
self.pattern.add_layer(
"paddle.nn.BatchNorm2D",
inputs={"input": "bn-input-0"},
outputs=[gen_name(0)])
self.pattern.add_layer(
"self.create_parameter",
inputs={},
outputs=[gen_name(1)])
inputs_dict = {}
inputs_dict['x'] = gen_name(0)
inputs_dict['y'] = gen_name(1)
self.pattern.add_layer(
"paddle.multiply",
inputs=inputs_dict,
outputs=[gen_name(2)])
self.pattern.add_layer(
"self.create_parameter",
inputs={},
outputs=[gen_name(3)])
inputs_dict = {}
inputs_dict['x'] = gen_name(2)
inputs_dict['y'] = gen_name(3)
self.pattern.add_layer(
"fluid.layers.elementwise_add",
inputs=inputs_dict,
outputs=[gen_name(4)])
self.pattern.build(inputs={"input-0": "bn-input-0"})
def insert_new_layer(self, graph, parameters, matches):
new_layer = self.gen_new_layer(parameters, matches)
new_layer_id = list(matches.keys())[0]
graph.layers[new_layer_id] = new_layer
matches.pop(new_layer_id)
def gen_new_layer(self, parameters, matches):
layers_id = list(matches.keys())
layer = matches[layers_id[0]]
layer_inputs = layer.inputs
bn_name = layer.outputs[0]
layer_attrs = layer.attrs
layer_attrs.pop("weight_attr")
layer_attrs.pop("bias_attr")
layer = matches[layers_id[4]]
layer_outputs = [bn_name] + layer.outputs
layer = matches[layers_id[1]]
data0_name = layer.outputs[0]
data0_numpy = parameters.pop(data0_name)
parameters["{}.weight".format(layer_outputs[0])] = data0_numpy
layer = matches[layers_id[3]]
data1_name = layer.outputs[0]
data1_numpy = parameters.pop(data1_name)
parameters["{}.bias".format(layer_outputs[0])] = data1_numpy
new_layer = PaddleLayer(
layers_id[0],
"paddle.nn.BatchNorm2D",
inputs=layer_inputs,
outputs=layer_outputs,
**layer_attrs)
return new_layer
\ No newline at end of file
......@@ -12,22 +12,22 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from x2paddle.optimizer.pytorch_optimizer.pass_ import Pass
from x2paddle.optimizer.pytorch_optimizer.fusion import ConstantFuser
from x2paddle.optimizer.pytorch_optimizer.pass_manager import pass_register
from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.dygraph import DygraphConstantFuser
from x2paddle.optimizer.pass_manager import pass_register
@pass_register
class ConstantFusePass(Pass):
name = "constant_fuse_pass"
class DygraphConstantFusePass(Pass):
name = "dygraph_constant_fuse_pass"
def __init__(self):
Pass.__init__(self)
def apply(self, graph):
fuser = ConstantFuser()
fuser = DygraphConstantFuser()
fuser.operate(graph, match_kind="topo")
# 用于注册
constant_fuse_pass = ConstantFuser()
constant_fuse_pass = DygraphConstantFuser()
......@@ -13,14 +13,14 @@
# limitations under the License.
import numpy as np
from x2paddle.optimizer.pytorch_optimizer.pattern_matcher import FuseBase
from x2paddle.optimizer.pattern_matcher import FuseBase
from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import *
class ConstantFuser(FuseBase):
class DygraphConstantFuser(FuseBase):
def __init__(self):
super(ConstantFuser, self).__init__(graph_type="dygraph")
super(DygraphConstantFuser, self).__init__(graph_type="dygraph")
def build_pattern(self):
""" 描述需要替换的constant图结构。
......
# 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.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.dygraph import DygraphConv2DAddFuser
from x2paddle.optimizer.pass_manager import pass_register
@pass_register
class DygraphConv2DAddFusePass(Pass):
name = "dygraph_conv2d_add_fuse_pass"
def __init__(self):
Pass.__init__(self)
def apply(self, graph):
fuser = DygraphConv2DAddFuser()
fuser.operate(graph, match_kind="edge")
# 用于注册
dygraph_conv2d_add_fuse_pass = DygraphConv2DAddFusePass()
\ No newline at end of file
# 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.
import copy
import numpy as np
from x2paddle.optimizer.pattern_matcher import FuseBase
from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import *
class DygraphConv2DAddFuser(FuseBase):
def __init__(self):
super(DygraphConv2DAddFuser, self).__init__(graph_type="dygraph")
self.patterns = list()
def build_pattern(self):
""" 描述需要替换的conv2d+add图结构。
conv2d+add层模式python实现代码示例:
模式一:
MobilenetV1_Logits_Conv2d_1c_1x1_biases = self.MobilenetV1_Logits_Conv2d_1c_1x1_biases
conv2d_transpose_14 = paddle.transpose(x=MobilenetV1_Logits_AvgPool_1a_AvgPool, perm=[0, 3, 1, 2])
MobilenetV1_Logits_Conv2d_1c_1x1_Conv2D = self.conv27(conv2d_transpose_14)
MobilenetV1_Logits_Conv2d_1c_1x1_Conv2D = paddle.transpose(x=MobilenetV1_Logits_Conv2d_1c_1x1_Conv2D, perm=[0, 2, 3, 1])
MobilenetV1_Logits_Conv2d_1c_1x1_BiasAdd = paddle.add(x=MobilenetV1_Logits_Conv2d_1c_1x1_Conv2D, y=MobilenetV1_Logits_Conv2d_1c_1x1_biases)
模式二:
MobilenetV1_Logits_Conv2d_1c_1x1_biases = self.MobilenetV1_Logits_Conv2d_1c_1x1_biases
MobilenetV1_Logits_Conv2d_1c_1x1_Conv2D = self.conv27(conv2d_transpose_14)
MobilenetV1_Logits_Conv2d_1c_1x1_BiasAdd = paddle.add(x=MobilenetV1_Logits_Conv2d_1c_1x1_Conv2D, y=MobilenetV1_Logits_Conv2d_1c_1x1_biases)
"""
def gen_name(id):
return "x" + str(id)
pattern = PaddleGraph(graph_type="dygraph")
pattern.add_layer(
"self.create_parameter",
inputs={},
outputs=[gen_name(0)])
pattern.add_layer(
kernel="paddle.transpose",
inputs={"x": "conv-input-0"},
outputs=[gen_name(1)],
perm=[0, 3, 1, 2])
pattern.add_layer(
kernel="paddle.nn.Conv2D",
inputs={"input": gen_name(1)},
outputs=[gen_name(2)])
pattern.add_layer(
kernel="paddle.transpose",
inputs={"x": gen_name(2)},
outputs=[gen_name(2)],
perm=[0, 2, 3, 1])
pattern.add_layer(
kernel="paddle.add",
inputs={"x": gen_name(2),
"y": gen_name(0)},
outputs=[gen_name(3)])
pattern.build(inputs={"input-0": "conv-input-0", })
self.patterns.append(pattern)
pattern = PaddleGraph(graph_type="dygraph")
pattern.add_layer(
"self.create_parameter",
inputs={},
outputs=[gen_name(0)])
pattern.add_layer(
kernel="paddle.nn.Conv2D",
inputs={"input": "conv-input-0"},
outputs=[gen_name(1)])
pattern.add_layer(
kernel="paddle.add",
inputs={"x": gen_name(1),
"y": gen_name(0)},
outputs=[gen_name(2)])
pattern.build(inputs={"input-0": "conv-input-0", })
self.patterns.append(pattern)
def insert_new_layer(self, graph, parameters, matches):
self.gen_new_layer(matches, graph)
matches_copy = copy.deepcopy(matches)
for layer_id, layer in matches_copy.items():
if layer.kernel not in ["self.create_parameter", "paddle.add"]:
matches.pop(layer_id)
def gen_new_layer(self, matches, graph):
is_transpose = False
for layer_id, layer in matches.items():
if layer.kernel == "self.create_parameter":
bias_name = layer.attrs["attr"]
if layer.kernel == "paddle.transpose":
is_transpose = True
if layer.kernel == "paddle.add":
output_name = layer.outputs[0]
if layer.kernel == "paddle.nn.Conv2D":
conv_id = layer_id
for layer_id, layer in matches.items():
if layer.kernel == "paddle.nn.functional.conv2d_transpose":
layer.bias = bias_name
if not is_transpose:
layer.outputs[0] = output_name
if layer.kernel == "paddle.nn.Conv2D":
layer.attrs["bias_attr"] = bias_name
if not is_transpose:
layer.outputs[1] = output_name
if layer.kernel == "paddle.transpose":
if conv_id in graph.edges_in[layer_id]:
layer.outputs[0] = output_name
......@@ -12,22 +12,22 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from x2paddle.optimizer.pytorch_optimizer.pass_ import Pass
from x2paddle.optimizer.pytorch_optimizer.fusion import DropoutFuser
from x2paddle.optimizer.pytorch_optimizer.pass_manager import pass_register
from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.dygraph import DygraphDropoutFuser
from x2paddle.optimizer.pass_manager import pass_register
@pass_register
class DropoutFusePass(Pass):
name = "dropout_fuse_pass"
class DygraphDropoutFusePass(Pass):
name = "dygraph_dropout_fuse_pass"
def __init__(self):
Pass.__init__(self)
def apply(self, graph):
fuser = DropoutFuser()
fuser = DygraphDropoutFuser()
fuser.operate(graph, match_kind="topo")
# 用于注册
dropout_fuse_pass = DropoutFuser()
dropout_fuse_pass = DygraphDropoutFuser()
......@@ -13,14 +13,14 @@
# limitations under the License.
import numpy as np
from x2paddle.optimizer.pytorch_optimizer.pattern_matcher import FuseBase
from x2paddle.optimizer.pattern_matcher import FuseBase
from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import *
class DropoutFuser(FuseBase):
class DygraphDropoutFuser(FuseBase):
def __init__(self):
super(DropoutFuser, self).__init__(graph_type="dygraph")
super(DygraphDropoutFuser, self).__init__(graph_type="dygraph")
def build_pattern(self):
""" 描述需要替换的constant图结构。
......
......@@ -12,22 +12,22 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from x2paddle.optimizer.pytorch_optimizer.pass_ import Pass
from x2paddle.optimizer.pytorch_optimizer.fusion import FcFuser
from x2paddle.optimizer.pytorch_optimizer.pass_manager import pass_register
from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.dygraph import DygraphFcFuser
from x2paddle.optimizer.pass_manager import pass_register
@pass_register
class FcFusePass(Pass):
name = "fc_fuse_pass"
class DygraphFcFusePass(Pass):
name = "dygraph_fc_fuse_pass"
def __init__(self):
Pass.__init__(self)
def apply(self, graph):
fuser = FcFuser()
fuser = DygraphFcFuser()
fuser.operate(graph, match_kind="topo")
# 用于注册
fc_fuse_pass = FcFusePass()
fc_fuse_pass = DygraphFcFusePass()
......@@ -13,15 +13,15 @@
# limitations under the License.
import numpy as np
from x2paddle.optimizer.pytorch_optimizer.pattern_matcher import FuseBase
from x2paddle.optimizer.pattern_matcher import FuseBase
from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import *
class FcFuser(FuseBase):
class DygraphFcFuser(FuseBase):
def __init__(self):
self.linear_index = 0
super(FcFuser, self).__init__(graph_type="dygraph")
super(DygraphFcFuser, self).__init__(graph_type="dygraph")
def build_pattern(self):
""" 描述需要替换的fc图结构。
......@@ -31,14 +31,14 @@ class FcFuser(FuseBase):
x134 = x133 == 2
if x134 :
classifier_6_weight = self.classifier_6_weight
x136 = fluid.layers.transpose(x=classifier_6_weight, perm=[1, 0])
x136 = paddle.transpose(x=classifier_6_weight, perm=[1, 0])
classifier_6_bias = self.classifier_6_bias
x137 = paddle.addmm(input=classifier_6_bias, x=x128, y=x136, beta=1, alpha=1)
x135 = x137
else:
classifier_6_weight = self.classifier_6_weight
x138 = fluid.layers.transpose(x=classifier_6_weight, perm=[1, 0])
x139 = fluid.layers.matmul(x=x128, y=x138)
x138 = paddle.transpose(x=classifier_6_weight, perm=[1, 0])
x139 = paddle.matmul(x=x128, y=x138)
classifier_6_bias = self.classifier_6_bias
x140 = x139 + 1 * classifier_6_bias
x135 = x140
......@@ -48,7 +48,7 @@ class FcFuser(FuseBase):
return "x" + str(id)
self.pattern.add_layer(
"fluid.layers.shape",
"prim.shape",
inputs={'input': "fc-input-0"},
outputs=[gen_name(2)])
self.pattern.add_layer(
......@@ -61,22 +61,20 @@ class FcFuser(FuseBase):
self.pattern.add_layer("prim.if", {'input': gen_name(3)}, [gen_name(4)])
self.pattern.outputs.append(gen_name(4))
if_layer1 = self.pattern.layers[list(self.pattern.layers.keys())[-1]]
pattern_block0 = PaddleGraph(if_layer1, graph_type="dygraph")
pattern_block0 = PaddleGraph(parent_layer=if_layer1, graph_type="dygraph")
pattern_block0.add_layer(
"fluid.dygraph.base.to_variable",
"self.create_parameter",
inputs={},
outputs=[gen_name(5)],
value="params[{}]".format(string(gen_name(5))))
outputs=[gen_name(5)])
pattern_block0.add_layer(
"fluid.layers.transpose",
"paddle.transpose",
inputs={"x": gen_name(5)},
outputs=[gen_name(6)],
perm=[1, 0])
pattern_block0.add_layer(
"fluid.dygraph.base.to_variable",
"self.create_parameter",
inputs={},
outputs=[gen_name(7)],
value="params[{}]".format(string(gen_name(7))))
outputs=[gen_name(7)])
pattern_block0.add_layer(
"paddle.addmm",
inputs={"input": gen_name(7),
......@@ -90,14 +88,13 @@ class FcFuser(FuseBase):
pattern_block0.add_layer(
"prim.equal", inputs={'input': gen_name(8)}, outputs=[gen_name(4)])
if_layer1.add_block(pattern_block0)
pattern_block1 = PaddleGraph(if_layer1, graph_type="dygraph")
pattern_block1 = PaddleGraph(parent_layer=if_layer1, graph_type="dygraph")
pattern_block1.add_layer(
"fluid.dygraph.base.to_variable",
"self.create_parameter",
inputs={},
outputs=[gen_name(5)],
value="params[{}]".format(string(gen_name(5))))
outputs=[gen_name(5)])
pattern_block1.add_layer(
"fluid.layers.transpose",
"paddle.transpose",
inputs={"x": gen_name(5)},
outputs=[gen_name(6)],
perm=[1, 0])
......@@ -108,10 +105,9 @@ class FcFuser(FuseBase):
outputs=[gen_name(9)])
if_layer1.inputs["input-1"] = "fc-input-0"
pattern_block1.add_layer(
"fluid.dygraph.base.to_variable",
"self.create_parameter",
inputs={},
outputs=[gen_name(12)],
value="params[{}]".format(string(gen_name(12))))
outputs=[gen_name(12)])
pattern_block1.add_layer(
"prim.add_",
inputs={"x": gen_name(9),
......@@ -137,9 +133,9 @@ class FcFuser(FuseBase):
layer = matches[layers_id[3]]
output_name = layer.outputs[0]
layer = matches[layers_id[4]]
weight_name = layer.attrs["value"][8:-2]
weight_name = layer.outputs[0]
layer = matches[layers_id[6]]
bias_name = layer.attrs["value"][8:-2]
bias_name = layer.outputs[0]
attrs = dict()
attrs["in_features"] = parameters[weight_name].shape[1]
attrs["out_features"] = parameters[weight_name].shape[0]
......
......@@ -12,22 +12,22 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from x2paddle.optimizer.pytorch_optimizer.pass_ import Pass
from x2paddle.optimizer.pytorch_optimizer.fusion import AdaptivePool2dFuser
from x2paddle.optimizer.pytorch_optimizer.pass_manager import pass_register
from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.dygraph import DygraphInterpolateBilinearFuser
from x2paddle.optimizer.pass_manager import pass_register
@pass_register
class AdaptivePool2dFusePass(Pass):
name = "adaptive_pool2d_fuse_pass"
class DygraphInterpolateBilinearFusePass(Pass):
name = "dygraph_interpolate_bilinear_fuse_pass"
def __init__(self):
Pass.__init__(self)
def apply(self, graph):
fuser = AdaptivePool2dFuser()
fuser = DygraphInterpolateBilinearFuser()
fuser.operate(graph, match_kind="topo")
# 用于注册
adaptive_pool2d_fuse_pass = AdaptivePool2dFusePass()
interpolate_bilinear_fuse_pass = DygraphInterpolateBilinearFusePass()
# 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.
import copy
import numpy as np
from x2paddle.optimizer.pattern_matcher import FuseBase
from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import *
class DygraphInterpolateBilinearFuser(FuseBase):
def __init__(self):
super(DygraphInterpolateBilinearFuser, self).__init__(graph_type="dygraph")
self.pattenrs = list()
def build_pattern(self):
""" 描述需要替换的双线性插值图结构。
interpolate_bilinear层模式python实现代码示例:
x2195 = x2181.shape
x2195 = len(x2195)
x2196 = x2195 - 2
x2197 = []
for _x2199 in range(x2196):
x2197.append(None)
x2200 = (x2181, x8, None, None)
...
x2267 = x2266 == 3
if x2267 :
raise RaiseException('Exception')
x2268 = None
else:
x2270 = x2181.shape
x2270 = len(x2270)
x2271 = x2270 == 4
if x2271 :
x2274 = x2197[0]
x2275 = x2197[1]
x2233_isinstance = isinstance(x2233, paddle.fluid.Variable)
if x2233_isinstance :
x2233 = x2233.numpy().tolist()
x2276 = paddle.nn.functional.interpolate(x=x2181, size=x2233, scale_factor=x2274, align_corners=False, align_mode=0, mode='bilinear')
x2272 = x2276
else:
x2277 = x2181.shape
x2277 = len(x2277)
x2278 = x2277 == 5
if x2278 :
raise RaiseException('Exception')
else:
raise RaiseException('Exception')
x2272 = None
x2268 = x2272
"""
def gen_name(id):
return "x" + str(id)
pattern = PaddleGraph(graph_type="dygraph")
pattern.add_layer(
"prim.shape",
inputs={"input": "interpolate-input-0"},
outputs=[gen_name(9)])
pattern.add_layer(
"prim.len",
inputs={"input": gen_name(9)},
outputs=[gen_name(9)])
pattern.add_layer(
"prim.sub",
inputs={"x": gen_name(9)},
outputs=[gen_name(10)],
y=2)
pattern.add_layer(
"prim.list", inputs={}, outputs=[gen_name(11)])
pattern.add_layer(
"prim.loop",
inputs={"input": gen_name(10)},
outputs=[gen_name(12.1), gen_name(12.2)])
loop_layer = pattern.layers[list(pattern.layers.keys())[
-1]]
pattern_block = PaddleGraph(loop_layer, graph_type="dygraph")
pattern_block.add_layer(
"prim.append",
inputs={"list": gen_name(11)},
outputs=[],
element=None)
loop_layer.inputs["input-0"] = gen_name(11)
loop_layer.add_block(pattern_block)
pattern.add_layer(
"prim.tuple",
inputs={
"input0": "interpolate-input-0",
"input1": "interpolate-input-4",
},
outputs=[gen_name(12)],
input2=None,
input3=None)
pattern.add_layer(
"prim.eq",
inputs={"x": "interpolate-input-2"},
outputs=[gen_name(10.1)],
y=3)
pattern.add_layer(
"prim.if",
inputs={"input": gen_name(10.1)},
outputs=[gen_name(14)])
if_layer1 = pattern.layers[list(pattern.layers.keys())[
-1]]
pattern_block = PaddleGraph(parent_layer=if_layer1, graph_type="dygraph")
pattern_block.add_layer(
"prim.exception",
inputs={},
outputs=[gen_name(15)],
input="Exception")
pattern_block.add_layer(
"prim.equal", inputs={}, outputs=[gen_name(14)], input=None)
if_layer1.add_block(pattern_block)
pattern_block = PaddleGraph(parent_layer=if_layer1, graph_type="dygraph")
pattern_block.add_layer(
"prim.shape",
inputs={"input": "interpolate-input-0"},
outputs=[gen_name(18)])
pattern_block.add_layer(
"prim.len",
inputs={"input": gen_name(18)},
outputs=[gen_name(18)])
pattern_block.add_layer(
"prim.eq",
inputs={"x": gen_name(18)},
outputs=[gen_name(19)],
y=4)
pattern_block.add_layer(
"prim.if",
inputs={"input": gen_name(19)},
outputs=[gen_name(20)])
if_layer2 = pattern_block.layers[list(pattern_block.layers.keys())[
-1]]
pattern_block_block = PaddleGraph(parent_layer=if_layer2, graph_type="dygraph")
pattern_block_block.add_layer(
"prim.getitem",
inputs={"list": gen_name(11)},
outputs=[gen_name(21)],
element=0)
pattern_block_block.add_layer(
"prim.getitem",
inputs={"list": gen_name(11)},
outputs=[gen_name(22)],
element=1)
pattern_block_block.add_layer(
"prim.isinstance",
inputs={"input": "interpolate-input-3"},
outputs=["interpolate-input-0_isinstance"],
cls="paddle.fluid.Variable")
pattern_block_block.add_layer(
"prim.if", {"input": "interpolate-input-0_isinstance"},
outputs=["interpolate-input-0_if1"])
if_layer_isinstance = pattern_block_block.layers[list(
pattern_block_block.layers.keys())[-1]]
pattern_block_block_block = PaddleGraph(
if_layer_isinstance, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.var2list",
inputs={"input": "interpolate-input-3"},
outputs=["interpolate-input-3"])
if_layer_isinstance.add_block(pattern_block_block_block)
pattern_block_block_block = PaddleGraph(
if_layer_isinstance, graph_type="dygraph")
if_layer_isinstance.add_block(pattern_block_block_block)
if_layer_isinstance.inputs["input-0"] = "interpolate-input-3"
pattern_block_block.add_layer(
"paddle.nn.functional.interpolate",
inputs={
"input": "interpolate-input-0",
"size": "interpolate-input-3",
"scale_factor": gen_name(21)
},
outputs=[gen_name(23)])
pattern_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(23)},
outputs=[gen_name(20)])
if_layer2.add_block(pattern_block_block)
pattern_block_block = PaddleGraph(if_layer2, graph_type="dygraph")
pattern_block_block.add_layer(
"prim.shape",
inputs={"input": "interpolate-input-0"},
outputs=[gen_name(24)])
pattern_block_block.add_layer(
"prim.len",
inputs={"input": gen_name(24)},
outputs=[gen_name(24)])
pattern_block_block.add_layer(
"prim.eq",
inputs={"x": gen_name(24)},
outputs=[gen_name(25)],
y=5)
pattern_block_block.add_layer(
"prim.if",
inputs={"input": gen_name(25)},
outputs=[gen_name(26)])
if_layer3 = pattern_block_block.layers[list(
pattern_block_block.layers.keys())[-1]]
pattern_block_block_block = PaddleGraph(
parent_layer=if_layer3, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.exception",
inputs={},
outputs=[gen_name(27)],
input="Exception")
if_layer3.add_block(pattern_block_block_block)
pattern_block_block_block = PaddleGraph(
parent_layer=if_layer3, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.exception",
inputs={},
outputs=[gen_name(28)],
input="Exception")
if_layer3.add_block(pattern_block_block_block)
pattern_block_block.add_layer(
"prim.equal", inputs={}, outputs=[gen_name(20)], input=None)
if_layer2.add_block(pattern_block_block)
if_layer2.inputs.update({
"input-0": "interpolate-input-0",
"input-1": "interpolate-input-3",
"input-2": "interpolate-input-3",
"input-3": gen_name(11),
"input-5": gen_name(11),
})
pattern_block.add_layer(
"prim.equal",
inputs={"input": gen_name(20)},
outputs=[gen_name(14)])
if_layer1.add_block(pattern_block)
if_layer1.inputs.update({
'input-2': 'interpolate-input-0',
'input-4': gen_name(11),
'input-6': gen_name(11),
'input-8': 'interpolate-input-0',
'input-9': 'interpolate-input-3',
'input-10': 'interpolate-input-0'
})
pattern.build(inputs={
"input-0": "interpolate-input-0",
"input-1": "interpolate-input-1",
"input-2": "interpolate-input-2",
"input-3": "interpolate-input-3",
"input-4": "interpolate-input-4"
})
self.patterns.append(pattern)
def insert_new_layer(self, graph, parameters, matches):
new_layer = self.gen_new_layer(parameters, matches)
global_layers = graph.get_global_layers()
new_matches = dict()
is_match = False
for layer_id, layer in global_layers.items():
if layer_id == list(matches.keys())[0] and not is_match:
new_matches[layer_id] = layer
is_match = True
if is_match:
new_matches[layer_id] = layer
if layer_id == list(matches.keys())[-1]:
break
new_layer_id = new_layer.layer_id
graph.layers[new_layer_id] = new_layer
new_matches.pop(new_layer_id)
matches.clear()
for layer_id, layer in new_matches.items():
matches[layer_id] = layer
def gen_new_layer(self, parameters, matches):
layers = list()
layers_id = list(matches.keys())
layer = matches[layers_id[6]]
size = layer.inputs["input1"]
layer = matches[layers_id[19]]
new_layer = copy.deepcopy(layer)
layer = matches[layers_id[9]]
new_layer.outputs[0] = layer.outputs[0]
new_layer.layer_id = layers_id[7]
new_layer.inputs.pop("scale_factor")
new_layer.inputs["size"] = size
return new_layer
# 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.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.dygraph import DygraphPReLUFuser
from x2paddle.optimizer.pass_manager import pass_register
@pass_register
class DygraphPReLUFusePass(Pass):
name = "dygraph_prelu_fuse_pass"
def __init__(self):
Pass.__init__(self)
def apply(self, graph):
fuser = DygraphPReLUFuser()
fuser.operate(graph, match_kind="edge")
# 用于注册
dygraph_prelu_fuse_pass = DygraphPReLUFusePass()
\ No newline at end of file
# 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.
import copy
import numpy as np
from collections import OrderedDict
from x2paddle.optimizer.pattern_matcher import FuseBase
from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import *
class DygraphPReLUFuser(FuseBase):
def __init__(self):
self.prelu_index = 0
super(DygraphPReLUFuser, self).__init__(graph_type="dygraph")
def build_pattern(self):
""" 描述需要替换的prelu图结构。
prelu层模式python实现代码示例:
conv2_alphas = self.conv2_alphas
conv2_mul_1_y = paddle.full(dtype='float32', shape=[1], fill_value=0.5)
conv2_Relu = self.relu1(conv2_Conv2D)
conv2_Abs = paddle.abs(x=conv2_Conv2D)
conv2_sub = fluid.layers.elementwise_sub(x=conv2_Conv2D, y=conv2_Abs)
conv2_mul = paddle.multiply(x=conv2_alphas, y=conv2_sub, axis=1)
conv2_mul_1 = paddle.multiply(x=conv2_mul, y=conv2_mul_1_y, axis=1)
conv2_add = paddle.add(x=conv2_Relu, y=conv2_mul_1)
"""
def gen_name(id):
return "x" + str(id)
self.pattern.add_layer(
"self.create_parameter",
inputs={},
outputs=[gen_name(0)])
self.pattern.add_layer(
"paddle.full",
inputs={},
outputs=[gen_name(1)],
shape=[1],
fill_value=0.5)
self.pattern.add_layer(
"paddle.nn.ReLU",
inputs={"x": "prelu-input-0"},
outputs=[gen_name(2)])
self.pattern.add_layer(
"paddle.abs",
inputs={"x": "prelu-input-0"},
outputs=[gen_name(3)])
self.pattern.add_layer(
"fluid.layers.elementwise_sub",
inputs={"x": "prelu-input-0",
"y": gen_name(3)},
outputs=[gen_name(4)])
self.pattern.add_layer(
"paddle.multiply",
inputs={"x": gen_name(0),
"y": gen_name(4)},
outputs=[gen_name(5)])
self.pattern.add_layer(
"paddle.multiply",
inputs={"x": gen_name(5),
"y": gen_name(1)},
outputs=[gen_name(6)])
self.pattern.add_layer(
"paddle.add",
inputs={"x": gen_name(2),
"y": gen_name(6)},
outputs=[gen_name(7)])
self.pattern.build(inputs={"input-0": "prelu-input-0", })
def insert_new_layer(self, graph, parameters, matches):
new_layers, last_layer_id = self.gen_new_layer(matches, parameters, graph)
matches_copy = copy.deepcopy(matches)
for layer_id, layer in matches_copy.items():
for i in range(3):
if layer_id == new_layers[i].id:
matches.pop(new_layers[i].id)
prefix_layers = OrderedDict()
mid_layers = OrderedDict()
suffix_layers = OrderedDict()
is_need_id = False
for layer_id, layer in graph.layers.items():
if is_need_id:
suffix_layers[layer_id] = layer
else:
if layer_id == last_layer_id:
for i in range(3):
mid_layers[new_layers[i].id] = new_layers[i]
is_need_id = True
prefix_layers[layer_id] = layer
prefix_layers.update(mid_layers)
prefix_layers.update(suffix_layers)
graph.layers = prefix_layers
def gen_new_layer(self, matches, parameters, graph):
layer_id_list = list(matches.keys())
layer_id_list.sort(key = int)
for layer_id, layer in matches.items():
if layer.kernel == "paddle.nn.ReLU":
input_name = layer.inputs["x"]
if layer.kernel == "self.create_parameter":
param_name = layer.outputs[0]
if layer.kernel == "paddle.add":
output_name = layer.outputs[0]
transpose0 = PaddleLayer(
id=layer_id_list[-1] + "_1",
kernel="paddle.transpose",
inputs={"x": input_name},
outputs=["{}_transpose_for_prelu".format(input_name)],
perm=[0, 3, 1, 2])
prelu_name = "merge_prelu{}".format(self.prelu_index)
self.prelu_index += 1
param = parameters[param_name]
c = param.shape[0]
prelu = PaddleLayer(id=layer_id_list[-1] + "_2",
kernel="paddle.nn.PReLU",
inputs={"input": "{}_transpose_for_prelu".format(input_name)},
outputs=[prelu_name, "{}_prelu".format(input_name)],
num_parameters=c,
weight_attr=string(param_name))
transpose1 = PaddleLayer(
id=layer_id_list[-1] + "_3",
kernel="paddle.transpose",
inputs={"x": "{}_prelu".format(input_name)},
outputs=[output_name],
perm=[0, 2, 3, 1])
return [transpose0, prelu, transpose1], layer_id_list[-1]
......@@ -12,22 +12,22 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from x2paddle.optimizer.pytorch_optimizer.pass_ import Pass
from x2paddle.optimizer.pytorch_optimizer.fusion import ReshapeFuser
from x2paddle.optimizer.pytorch_optimizer.pass_manager import pass_register
from x2paddle.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.dygraph import DygraphReshapeFuser
from x2paddle.optimizer.pass_manager import pass_register
@pass_register
class ReshapeFusePass(Pass):
name = "reshape_fuse_pass"
class DygraphReshapeFusePass(Pass):
name = "dygraph_reshape_fuse_pass"
def __init__(self):
Pass.__init__(self)
def apply(self, graph):
fuser = ReshapeFuser()
fuser = DygraphReshapeFuser()
fuser.operate(graph, match_kind="edge")
# 用于注册
reshape_fuse_pass = ReshapeFusePass()
reshape_fuse_pass = DygraphReshapeFusePass()
......@@ -13,14 +13,14 @@
# limitations under the License.
import numpy as np
from x2paddle.optimizer.pytorch_optimizer.pattern_matcher import FuseBase
from x2paddle.optimizer.pattern_matcher import FuseBase
from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import *
class ReshapeFuser(FuseBase):
class DygraphReshapeFuser(FuseBase):
def __init__(self):
super(ReshapeFuser, self).__init__(graph_type="dygraph")
super(DygraphReshapeFuser, self).__init__(graph_type="dygraph")
def build_pattern(self):
""" 描述需要替换的reshape图结构。
......
# 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.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.dygraph import DygraphTFBatchNormFuser
from x2paddle.optimizer.pass_manager import pass_register
@pass_register
class DygraphTFBatchNormFusePass(Pass):
name = "dygraph_tf_batchnorm_fuse_pass"
def __init__(self):
Pass.__init__(self)
def apply(self, graph):
fuser = DygraphTFBatchNormFuser()
fuser.operate(graph, match_kind="edge")
# 用于注册
dygraph_tf_batchnorm_fuse_pass = DygraphTFBatchNormFusePass()
\ No newline at end of file
# 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.
import copy
import numpy as np
from collections import OrderedDict
from x2paddle.optimizer.pattern_matcher import FuseBase
from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import *
class DygraphTFBatchNormFuser(FuseBase):
def __init__(self):
self.bn_index = 0
super(DygraphTFBatchNormFuser, self).__init__(graph_type="dygraph")
self.patterns = list()
def build_pattern(self):
""" 描述需要替换的batchnorm图结构。
batchnorm层模式python实现代码示例:
"""
def gen_name(id):
return "x" + str(id)
pattern = PaddleGraph(graph_type="dygraph")
pattern.add_layer(
"self.create_parameter",
inputs={},
outputs=[gen_name(0)])
pattern.add_layer(
"paddle.full",
inputs={},
outputs=[gen_name(1)],
shape=[1])
pattern.add_layer(
"paddle.add",
inputs={"x": gen_name(0), "y": gen_name(1)},
outputs=[gen_name(2)])
pattern.add_layer(
"paddle.rsqrt",
inputs={"x": gen_name(2)},
outputs=[gen_name(3)])
pattern.add_layer(
"self.create_parameter",
inputs={},
outputs=[gen_name(4)])
pattern.add_layer(
"paddle.multiply",
inputs={"x": gen_name(3), "y": gen_name(4)},
outputs=[gen_name(5)])
pattern.add_layer(
"self.create_parameter",
inputs={},
outputs=[gen_name(6)])
pattern.add_layer(
"paddle.multiply",
inputs={"x": gen_name(6), "y": gen_name(5)},
outputs=[gen_name(7)])
pattern.add_layer(
"self.create_parameter",
inputs={},
outputs=[gen_name(8)])
pattern.add_layer(
"fluid.layers.elementwise_sub",
inputs={"x": gen_name(8), "y": gen_name(7)},
outputs=[gen_name(9)])
pattern.add_layer(
"paddle.multiply",
inputs={"x": "bn-input-0", "y": gen_name(5)},
outputs=[gen_name(10)])
pattern.add_layer(
"paddle.add",
inputs={"x": gen_name(10), "y": gen_name(9)},
outputs=[gen_name(11)])
pattern.build(inputs={"input-0": "bn-input-0", })
self.patterns.append(pattern)
pattern = PaddleGraph(graph_type="dygraph")
pattern.add_layer(
"self.create_parameter",
inputs={},
outputs=[gen_name(0)])
pattern.add_layer(
"paddle.full",
inputs={},
outputs=[gen_name(1)],
shape=[1])
pattern.add_layer(
"paddle.add",
inputs={"x": gen_name(0), "y": gen_name(1)},
outputs=[gen_name(2)])
pattern.add_layer(
"paddle.rsqrt",
inputs={"x": gen_name(2)},
outputs=[gen_name(3)])
pattern.add_layer(
"self.create_parameter",
inputs={},
outputs=[gen_name(4)])
pattern.add_layer(
"paddle.multiply",
inputs={"x": gen_name(3), "y": gen_name(4)},
outputs=[gen_name(5)])
pattern.add_layer(
"paddle.multiply",
inputs={"x": "bn-input-0", "y": gen_name(5)},
outputs=[gen_name(10)])
pattern.add_layer(
"self.create_parameter",
inputs={},
outputs=[gen_name(6)])
pattern.add_layer(
"paddle.multiply",
inputs={"x": gen_name(6), "y": gen_name(5)},
outputs=[gen_name(7)])
pattern.add_layer(
"self.create_parameter",
inputs={},
outputs=[gen_name(8)])
pattern.add_layer(
"fluid.layers.elementwise_sub",
inputs={"x": gen_name(8), "y": gen_name(7)},
outputs=[gen_name(9)])
pattern.add_layer(
"paddle.add",
inputs={"x": gen_name(10), "y": gen_name(9)},
outputs=[gen_name(11)])
pattern.build(inputs={"input-0": "bn-input-0", })
self.patterns.append(pattern)
def insert_new_layer(self, graph, parameters, matches):
new_layers, last_layer_id = self.gen_new_layer(matches, parameters, graph)
matches_copy = copy.deepcopy(matches)
for layer_id, layer in matches_copy.items():
for i in range(3):
if layer_id == new_layers[i].id:
matches.pop(new_layers[i].id)
prefix_layers = OrderedDict()
mid_layers = OrderedDict()
suffix_layers = OrderedDict()
is_need_id = False
for layer_id, layer in graph.layers.items():
if is_need_id:
suffix_layers[layer_id] = layer
else:
if layer_id == last_layer_id:
for i in range(3):
mid_layers[new_layers[i].id] = new_layers[i]
is_need_id = True
prefix_layers[layer_id] = layer
prefix_layers.update(mid_layers)
prefix_layers.update(suffix_layers)
graph.layers = prefix_layers
def gen_new_layer(self, matches, parameters, graph):
layer_id_list = list(matches.keys())
layer_id_list.sort(key = int)
for layer_id, layer in matches.items():
if layer.kernel == "paddle.full":
full_layer = layer
out_layer_id = graph.edges_out[layer_id][0]
if matches[out_layer_id].kernel == "paddle.add":
var_layer_id = graph.edges_in[out_layer_id][0]
var_layer = matches[var_layer_id]
if layer.kernel == "paddle.rsqrt":
out_layer_id = graph.edges_out[layer_id][0]
if matches[out_layer_id].kernel == "paddle.multiply":
gamma_layer_id = graph.edges_in[out_layer_id][1]
gamma_layer = matches[gamma_layer_id]
if layer.kernel == "fluid.layers.elementwise_sub":
in_layer_id = graph.edges_in[layer_id][0]
beta_layer = matches[in_layer_id]
in_layer_id = graph.edges_in[layer_id][1]
in_layer_id = graph.edges_in[in_layer_id][0]
mean_layer = matches[in_layer_id]
out_layer_id = graph.edges_out[layer_id][0]
add_layer = matches[out_layer_id]
if layer.kernel == "paddle.multiply":
in_layer_id = graph.edges_in[layer_id][1]
mul_layer = matches[in_layer_id]
if mul_layer.kernel == "paddle.multiply":
in_layer_id = graph.edges_in[layer_id][0]
if in_layer_id not in matches:
input_name = layer.inputs["x"]
transpose0 = PaddleLayer(
id=layer_id_list[-1] + "_1",
kernel="paddle.transpose",
inputs={"x": input_name},
outputs=["{}_transpose_for_bn".format(input_name)],
perm=[0, 3, 1, 2])
bn_name = "merge_bn{}".format(self.bn_index)
self.bn_index += 1
params = parameters[gamma_layer.outputs[0]]
c = params.shape[0]
bn = PaddleLayer(
id=layer_id_list[-1] + "_2",
kernel="paddle.nn.BatchNorm",
inputs={"input": "{}_transpose_for_bn".format(input_name)},
outputs=[bn_name, "{}_bn".format(input_name)],
num_channels=c,
epsilon=full_layer.attrs["fill_value"],
param_attr=string(gamma_layer.outputs[0]),
bias_attr=string(beta_layer.outputs[0]),
moving_mean_name=string(mean_layer.outputs[0]),
moving_variance_name=string(var_layer.outputs[0]),
is_test=True)
transpose1 = PaddleLayer(
id=layer_id_list[-1] + "_3",
kernel="paddle.transpose",
inputs={"x": "{}_bn".format(input_name)},
outputs=add_layer.outputs,
perm=[0, 2, 3, 1])
return [transpose0, bn, transpose1], layer_id_list[-1]
# 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.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.dygraph import TraceFcFuser
from x2paddle.optimizer.pass_manager import pass_register
@pass_register
class TraceFcFusePass(Pass):
name = "trace_fc_fuse_pass"
def __init__(self):
Pass.__init__(self)
def apply(self, graph):
fuser = TraceFcFuser()
fuser.operate(graph, match_kind="topo")
# 用于注册
trace_fc_fuse_pass = TraceFcFusePass()
\ No newline at end of file
# 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.
import numpy as np
from x2paddle.optimizer.pattern_matcher import FuseBase
from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import *
class TraceFcFuser(FuseBase):
def __init__(self):
self.linear_index = 0
super(TraceFcFuser, self).__init__(graph_type="dygraph")
self.patterns = list()
def build_pattern(self):
""" 描述需要替换的fc图结构。
fc层模式python实现代码示例:
模式一:
encoder_layer_8_attention_self_key_weight = self.encoder_layer_8_attention_self_key_weight
x748 = paddle.transpose(x=encoder_layer_8_attention_self_key_weight, perm=[1, 0])
x749 = paddle.matmul(x=x732, y=x748)
encoder_layer_8_attention_self_key_bias = self.encoder_layer_8_attention_self_key_bias
x750 = x749 + 1 * encoder_layer_8_attention_self_key_bias
模式二:
x13 = self.x13
x14 = paddle.transpose(x=x13, perm=[1, 0])
x15 = self.x15
x16 = paddle.addmm(input=x15, x=x12, y=x14, beta=1, alpha=1)
"""
def gen_name(id):
return "x" + str(id)
pattern = PaddleGraph(graph_type="dygraph")
pattern.add_layer(
"self.create_parameter",
inputs={},
outputs=[gen_name(0)])
pattern.add_layer(
"fluid.layers.transpose",
inputs={"x": gen_name(0)},
outputs=[gen_name(1)],
perm=[1, 0])
pattern.add_layer(
"paddle.matmul",
inputs={"x": "fc-input-0",
"y": gen_name(1)},
outputs=[gen_name(2)])
pattern.add_layer(
"self.create_parameter",
inputs={},
outputs=[gen_name(3)])
pattern.add_layer(
"prim.add_",
inputs={"x": gen_name(2),
"y": gen_name(3)},
outputs=[gen_name(4)],
alpha=1)
pattern.build(inputs={"input-0": "fc-input-0"})
self.patterns.append(pattern)
pattern = PaddleGraph(graph_type="dygraph")
pattern.add_layer(
"self.create_parameter",
inputs={},
outputs=[gen_name(0)])
pattern.add_layer(
"paddle.transpose",
inputs={"x": gen_name(0)},
outputs=[gen_name(1)],
perm=[1, 0])
pattern.add_layer(
"self.create_parameter",
inputs={},
outputs=[gen_name(2)])
pattern.add_layer(
"paddle.addmm",
inputs={"input": gen_name(2),
"x": "fc-input-0",
"y": gen_name(1)},
outputs=[gen_name(4)],
alpha=1,
beta=1)
pattern.build(inputs={"input-0": "fc-input-0"})
self.patterns.append(pattern)
def insert_new_layer(self, graph, parameters, matches):
new_layer = self.gen_new_layer(parameters, matches)
new_layer_id = list(matches.keys())[0]
graph.layers[new_layer_id] = new_layer
matches.pop(new_layer_id)
def gen_new_layer(self, parameters, matches):
layers_id = list(matches.keys())
if len(layers_id) == 5:
layer = matches[layers_id[2]]
else:
layer = matches[layers_id[-1]]
input_name = layer.inputs["x"]
scope_name = layer.scope_name
layer = matches[layers_id[-1]]
output_name = layer.outputs[0]
layer = matches[layers_id[0]]
weight_name = layer.outputs[0]
layer = matches[layers_id[-2]]
bias_name = layer.outputs[0]
attrs = dict()
attrs["in_features"] = parameters[weight_name].shape[1]
attrs["out_features"] = parameters[weight_name].shape[0]
linear_name = "linear{}".format(self.linear_index)
self.linear_index += 1
parameters["{}.weight".format(linear_name)] = parameters[
weight_name].transpose((1, 0))
parameters["{}.bias".format(linear_name)] = np.squeeze(parameters[
bias_name])
new_layer = PaddleLayer(
layers_id[0],
"paddle.nn.Linear",
inputs={"input": input_name},
outputs=[linear_name, output_name],
scope_name=scope_name,
**attrs)
return new_layer
# 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 .bn_scale_fuser import Static_BNScaleFuser
from .bn_scale_fuse_pass import Static_BNScaleFusePass
\ No newline at end of file
# 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.optimizer.pass_ import Pass
from x2paddle.optimizer.fusion.static import Static_BNScaleFuser
from x2paddle.optimizer.pass_manager import pass_register
@pass_register
class Static_BNScaleFusePass(Pass):
name = "static_bn_scale_fuse_pass"
def __init__(self):
Pass.__init__(self)
def apply(self, graph):
fuser = Static_BNScaleFuser()
fuser.operate(graph, match_kind="topo")
# 用于注册
bn_scale_fuse_pass = Static_BNScaleFusePass()
# 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.
import numpy as np
from x2paddle.optimizer.pattern_matcher import FuseBase
from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import *
class Static_BNScaleFuser(FuseBase):
def __init__(self):
super(Static_BNScaleFuser, self).__init__(graph_type="dygraph")
def build_pattern(self):
""" 描述需要替换的batchnorm2d图结构。
batchnorm2d层模式python实现代码示例:
conv5_bn = fluid.layers.batch_norm(input=conv5, is_test=True, param_attr=None, bias_attr=None, moving_mean_name='conv5_bn_mean', moving_variance_name='conv5_bn_variance', epsilon=9.999999747378752e-06, name='conv5_bn')
conv5_scale_scale = fluid.ParamAttr(name='conv5_scale_scale')
conv5_scale_cparam1 = fluid.layers.create_parameter(attr=conv5_scale_scale, dtype=conv5_bn.dtype, shape=[256], name='conv5_scale_cparam1', is_bias=True, default_initializer=Constant(value=1.0))
conv5_scale_mul = fluid.layers.elementwise_mul(x=conv5_bn, y=conv5_scale_cparam1, axis=1)
conv5_scale_offset = fluid.ParamAttr(name='conv5_scale_offset')
conv5_scale_cparam2 = fluid.layers.create_parameter(attr=conv5_scale_offset, dtype=conv5_bn.dtype, shape=[256], name='conv5_scale_cparam2', is_bias=True, default_initializer=Constant(value=1.0))
conv5_scale = fluid.layers.elementwise_add(x=conv5_scale_mul, y=conv5_scale_cparam2, axis=1)
"""
def gen_name(id):
return "x" + str(id)
self.pattern.add_layer(
"fluid.layers.batch_norm",
inputs={"input": "bn-input-0"},
outputs=[gen_name(0)])
self.pattern.add_layer(
"fluid.ParamAttr",
inputs={},
outputs=[gen_name(1)])
self.pattern.add_layer(
"fluid.layers.create_parameter",
inputs={"attr": gen_name(1)},
outputs=[gen_name(2)])
inputs_dict = {}
inputs_dict['x'] = gen_name(0)
inputs_dict['y'] = gen_name(2)
self.pattern.add_layer(
"fluid.layers.elementwise_mul",
inputs=inputs_dict,
outputs=[gen_name(3)])
self.pattern.add_layer(
"fluid.ParamAttr",
inputs={},
outputs=[gen_name(4)])
self.pattern.add_layer(
"fluid.layers.create_parameter",
inputs={"attr": gen_name(4)},
outputs=[gen_name(5)])
inputs_dict = {}
inputs_dict['x'] = gen_name(3)
inputs_dict['y'] = gen_name(5)
self.pattern.add_layer(
"fluid.layers.elementwise_add",
inputs=inputs_dict,
outputs=[gen_name(6)])
self.pattern.build(inputs={"input-0": "bn-input-0"})
def insert_new_layer(self, graph, parameters, matches):
new_layer = self.gen_new_layer(parameters, matches)
new_layer_id = list(matches.keys())[0]
graph.layers[new_layer_id] = new_layer
matches.pop(new_layer_id)
def gen_new_layer(self, parameters, matches):
layers_id = list(matches.keys())
layer = matches[layers_id[0]]
layer_inputs = layer.inputs
layer_name = layer.outputs[0]
layer_attrs = layer.attrs
layer_attrs["param_attr"] = string("{}_scale".format(layer_name))
layer_attrs["bias_attr"] = string("{}_offset".format(layer_name))
layer = matches[layers_id[-1]]
layer_outputs = layer.outputs
layer = matches[layers_id[1]]
layer_name = layer.outputs[0]
scale_numpy = parameters.pop(layer_name)
parameters[layer_attrs["param_attr"][1: -1]] = scale_numpy
layer = matches[layers_id[4]]
layer_name = layer.outputs[0]
scale_numpy = parameters.pop(layer_name)
parameters[layer_attrs["bias_attr"][1: -1]] = scale_numpy
new_layer = PaddleLayer(
layers_id[0],
"fluid.layers.batch_norm",
inputs=layer_inputs,
outputs=layer_outputs,
**layer_attrs)
return new_layer
\ No newline at end of file
......@@ -12,22 +12,53 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from x2paddle.optimizer.pytorch_optimizer.fusion import *
from x2paddle.optimizer.pytorch_optimizer.pass_manager import PassManager
from x2paddle.optimizer.pass_manager import PassManager
from x2paddle.optimizer.fusion.dygraph import *
from x2paddle.optimizer.fusion.static import *
from x2paddle.optimizer.elimination.dygraph import *
class GraphOptimizer(object):
def __init__(self):
self.passes = [
"constant_fuse_pass", "batchnorm2d_fuse_pass",
"interpolate_bilinear_fuse_pass", "fc_fuse_pass",
"adaptive_pool2d_fuse_pass", "reshape_fuse_pass",
"dropout_fuse_pass"
]
def __init__(self, source_frame, paddle_type="dygraph", jit_type="trace"):
if source_frame == "pytorch":
if jit_type == "trace":
self.passes = ["dygraph_constant_fuse_pass",
"trace_fc_fuse_pass"]
else:
self.passes = [
"dygraph_constant_fuse_pass",
"dygraph_batchnorm2d_fuse_pass",
"dygraph_interpolate_bilinear_fuse_pass",
"dygraph_fc_fuse_pass",
"dygraph_adaptive_pool2d_fuse_pass",
"dygraph_reshape_fuse_pass",
"dygraph_dropout_fuse_pass"
]
elif source_frame == "caffe":
if paddle_type == "dygraph":
self.passes = ["dygraph_bn_scale_fuse_pass"]
else:
self.passes = ["static_bn_scale_fuse_pass"]
elif source_frame == "tf":
self.passes = [
"dygraph_conv2d_add_fuse_pass",
"dygraph_tf_batchnorm_fuse_pass",
"dygraph_prelu_fuse_pass",
"transpose_eliminate_pass"
]
else:
self.passes = []
def optimize(self, graph):
for pass_name in self.passes:
pass_ = PassManager.lookup(pass_name)()
pass_.apply(graph)
if pass_name.endswith("_eliminate_pass"):
pass_.apply(graph)
else:
while True:
before_len = len(graph.layers)
pass_.apply(graph)
after_len = len(graph.layers)
if before_len == after_len:
break
print("{} done!".format(pass_name))
return graph
# -*- coding:UTF-8 -*-
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"
......
# -*- coding:UTF-8 -*-
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"
......@@ -19,6 +20,7 @@ class PatternMatcher(object):
def __init__(self, pattern):
self.pattern = pattern
# matches的每个match是按照拓扑排序组成layer的dict
self.matches = list()
def operate(self, graph, match_kind="topo"):
......@@ -84,7 +86,11 @@ class PatternMatcher(object):
# 判断subgraph中的节点是否被外部图使用到(如若被使用到则无效)
if layer_id in graph.edges_out:
if pattern_layer_id not in pattern.edges_out:
if not set(pattern_layer.outputs).issubset(
if "paddle.nn" in layer.kernel and "functional" not in layer.kernel:
pattern_layer_opt = pattern_layer.outputs[1:]
else:
pattern_layer_opt = pattern_layer.outputs
if not set(pattern_layer_opt).issubset(
pattern.outputs):
# 若pattern当前layer的输出是pattern的输出,则是正确的
if pattern_index == 0 or is_subblock:
......@@ -96,7 +102,11 @@ class PatternMatcher(object):
if len(graph.edges_out[layer_id]) != len(
pattern.edges_out[pattern_layer_id]):
# 如果在每个节点edges_in相同的情况下,edges_out数目相同则说明无节点在subgraph外被用到
if not set(pattern_layer.outputs).issubset(
if "paddle.nn" in layer.kernel and "functional" not in layer.kernel:
pattern_layer_opt = pattern_layer.outputs[1:]
else:
pattern_layer_opt = pattern_layer.outputs
if not set(pattern_layer_opt).issubset(
pattern.outputs):
# 若pattern当前layer的输出是pattern的输出,则是正确的
if pattern_index == 0 or is_subblock:
......@@ -104,6 +114,7 @@ class PatternMatcher(object):
else:
subgraph_id2layers.pop(layer_id)
continue
# 当为控制流时的处理
if layer.kernel == "prim.if" or layer.kernel == "prim.loop":
if len(pattern_layer.blocks) != len(layer.blocks):
......@@ -154,7 +165,7 @@ class PatternMatcher(object):
if len(block.layers) > 0:
self.detect_patterns_by_topo(layer.blocks[j])
def detect_patterns_by_edge(self, graph, ignore_list_inputs=True):
def detect_patterns_by_edge(self, graph):
"""当遇见顺序没有强制规定的pattern时使用该方式
"""
......@@ -163,8 +174,8 @@ class PatternMatcher(object):
pattern_ids = list(pattern_id2layers.keys())
pattern_layer_id = pattern_ids[0]
subgraph_id2layers = dict()
graph_layers = dict(list(graph.layers.items())[start_index:])
layer_id = list(graph_layers.keys())[0]
layer_id = list(graph.layers.keys())[start_index]
graph_layers = graph.layers
def update(layer_id, pattern_layer_id):
layer = graph_layers[layer_id]
......@@ -172,15 +183,23 @@ class PatternMatcher(object):
if layer.kernel != pattern_layer.kernel:
return False
subgraph_id2layers[layer_id] = layer
for i, pattern_layer_id_in in enumerate(pattern.edges_in[
pattern_layer_id]):
if pattern_layer_id_in == -1 or ignore_list_inputs:
continue
layer_id_in = graph.edges_in[layer_id][i]
subgraph_ids = list(subgraph_id2layers.keys())
if layer_id_in not in subgraph_ids:
if pattern.edges_in.get(pattern_layer_id, 0) != 0:
if len(pattern.edges_in[pattern_layer_id]) != \
len(graph.edges_in[layer_id]):
return False
for i, pattern_layer_id_in in enumerate(pattern.edges_in[
pattern_layer_id]):
if pattern_layer_id_in == -1:
continue
if pattern_layer_id_in in pattern_ids:
new_layer_id_in = graph.edges_in[layer_id][i]
if new_layer_id_in in subgraph_id2layers:
continue
update(new_layer_id_in, pattern_layer_id_in)
if pattern.edges_out.get(pattern_layer_id, 0) != 0:
if layer_id not in graph.edges_out:
return False
if len(pattern.edges_out[pattern_layer_id]) != \
len(graph.edges_out[layer_id]):
return False
......@@ -188,17 +207,8 @@ class PatternMatcher(object):
pattern_layer_id]):
if pattern_layer_id_out in pattern_ids:
new_layer_id_out = graph.edges_out[layer_id][i]
for j, new_new_layer_id_in in enumerate(
graph.edges_in[new_layer_id_out]):
if new_new_layer_id_in not in subgraph_id2layers:
if ignore_list_inputs:
continue
new_new_pattern_layer_id_in = pattern.edges_in[
pattern_layer_id_out][j]
if new_new_pattern_layer_id_in == -1:
continue
update(new_new_layer_id_in,
new_new_pattern_layer_id_in)
if new_layer_id_out in subgraph_id2layers:
continue
update(new_layer_id_out, pattern_layer_id_out)
while len(subgraph_id2layers) != len(pattern_id2layers):
......@@ -258,6 +268,7 @@ def get_subgraph(prefix_layer_id, suffix_layer_id, graph):
class FuseBase(object):
def __init__(self, graph_type):
self.pattern = PaddleGraph(graph_type=graph_type)
self.patterns = list()
def operate(self, graph, match_kind="topo"):
parameters = graph.parameters
......@@ -267,16 +278,22 @@ class FuseBase(object):
first_layer_id = list(match.keys())[0]
subgraph = get_subgraph("", first_layer_id, graph)
self.insert_new_layer(subgraph, parameters, match)
self.delete_inter_layer(graph)
self.delete_match(graph)
graph.build()
def perform_pattern_matcher(self, graph, match_kind="topo"):
""" 执行模式匹配,找到匹配的子图。
"""
pattern_matcher = PatternMatcher(self.pattern)
self.matches = pattern_matcher.operate(graph, match_kind)
if len(self.patterns) > 0:
self.matches = list()
for pattern in self.patterns:
pattern_matcher = PatternMatcher(pattern)
self.matches.extend(pattern_matcher.operate(graph, match_kind))
else:
pattern_matcher = PatternMatcher(self.pattern)
self.matches = pattern_matcher.operate(graph, match_kind)
def delete_inter_layer(self, graph):
def delete_match(self, graph):
""" 删除不需要的中间layer及其对应参数。
"""
for match in self.matches:
......@@ -291,3 +308,4 @@ class FuseBase(object):
if layer_id in subgraph.layers:
# layer_id可能是属于子图的,此时删除父layer,即删除整个子图
subgraph.layers.pop(layer_id)
\ No newline at end of file
# 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.optimizer.pytorch_optimizer.pass_ import Pass
from x2paddle.optimizer.pytorch_optimizer.fusion import InterpolateBilinearFuser
from x2paddle.optimizer.pytorch_optimizer.pass_manager import pass_register
@pass_register
class InterpolateBilinearFusePass(Pass):
name = "interpolate_bilinear_fuse_pass"
def __init__(self):
Pass.__init__(self)
def apply(self, graph):
fuser = InterpolateBilinearFuser()
fuser.operate(graph, match_kind="topo")
# 用于注册
interpolate_bilinear_fuse_pass = InterpolateBilinearFusePass()
# 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.
import numpy as np
from x2paddle.optimizer.pytorch_optimizer.pattern_matcher import FuseBase
from x2paddle.core.program import PaddleGraph, PaddleLayer
from x2paddle.core.util import *
class InterpolateBilinearFuser(FuseBase):
def __init__(self):
super(InterpolateBilinearFuser, self).__init__(graph_type="dygraph")
import torch
torch_version = torch.__version__
torch_version_part = torch_version.split(".")
if int(torch_version_part[0]) == 1 and int(torch_version_part[1]) > 5:
self.version_gt_150 = True
else:
self.version_gt_150 = False
def build_pattern(self):
""" 描述需要替换的双线性插值图结构。
interpolate_bilinear层模式python实现代码示例:
x3016 = fluid.layers.shape(input=x3005)
x3016 = len(x3016)
x3017 = x3016 - 2
x3018 = []
for _x3020 in range(x3017):
x3018.append(None)
x3021 = (x3005, x8, None, None)
x3022 = fluid.layers.shape(input=x3005)
x3022 = len(x3022)
x3023 = x3022 == 3
if x3023 :
raise RaiseException('Exception')
x3024 = None
else:
x3026 = fluid.layers.shape(input=x3005)
x3026 = len(x3026)
x3027 = x3026 == 4
if x3027 :
x3044, x3045, x3046, x3047 = x3021
x3048 = x3045 is None
if x3048 :
x3051 = x3046 is None
x3049 = x3051
x3050 = x3045
else:
x3052 = x3045
x3049 = False
x3050 = x3052
if x3049 :
raise RaiseException('Exception')
x3055 = x3050 is not None
if x3055 :
x3058 = x3050
x3059 = x3046 is not None
x3056 = x3059
x3057 = x3058
else:
x3056 = False
x3057 = x3050
if x3056 :
raise RaiseException('Exception')
x3060 = None
x3061 = None
else:
x3060 = x3046
x3061 = x3057
x3063 = x3060 is not None
if x3063 :
x3065 = x3060
x3066 = len(x3065)
x3067 = x3066 != 2
if x3067 :
raise RaiseException('Exception')
x3064 = x3065
else:
x3064 = x3060
x3070 = x3061 is not None
if x3070 :
x3072 = x3061
x3071 = x3072
else:
x3071 = None
if x3070 :
x3073 = x3071
else:
x3074 = x3064 is not None
if x3074 :
x3076 = x3064
x3075 = x3076
else:
raise RaiseException('Exception')
x3075 = None
x3078 = x3047 is None
if x3078 :
x3080 = len(x3075)
x3081 = x3080 > 0
x3086 = 0
for x3083 in range(2147483647):
x3087 = x3075[x3086]
x3088 = math.floor(x3087)
x3089 = x3088 != x3087
if x3089 :
x3090 = False
x3091 = x3089
else:
x3090 = None
x3091 = None
if x3089 :
x3092 = x3090
x3093 = x3091
else:
x3092 = True
x3093 = x3089
x3094 = x3086 + 1
x3095 = x3094 < x3080
x3096 = x3095 and x3092
x3082 = x3093
x3083 = x3094
if x3082 :
import warnings
warnings.warn('The default behavior for interpolate/upsample with float scale_factor will change in 1.6.0 to align with other frameworks/libraries, and use scale_factor directly, instead of relying on the computed output size. If you wish to keep the old behavior, please set recompute_scale_factor=True. See the documentation of nn.Upsample for details. ', stacklevel=2)
x3099 = []
for _x3101 in range(2):
x3102 = _x3101 + 2
x3103 = fluid.layers.shape(x3044)[x3102]
x3104 = float(x3103)
x3105 = x3075[_x3101]
x3106 = x3104 * x3105
x3107 = math.floor(x3106)
x3099.append(x3107)
x3073 = x3099
x3108 = x3018[0]
x3109 = x3018[1]
x3073_isinstance = isinstance(x3073, paddle.fluid.Variable)
if x3073_isinstance :
x3073 = x3073.numpy().tolist()
assert x3108 == x3109, 'The x3108 must be x3109!'
x3110 = paddle.nn.functional.interpolate(x=x3005, size=x3073, scale_factor=x3108, align_corners=False, align_mode=0)
x3028 = x3110
else:
x3111 = fluid.layers.shape(input=x3005)
x3111 = len(x3111)
x3112 = x3111 == 5
if x3112 :
raise RaiseException('Exception')
else:
raise RaiseException('Exception')
x3028 = None
x3024 = x3028
"""
def gen_name(id):
return "x" + str(id)
if self.version_gt_150:
self.pattern.add_layer(
"fluid.layers.shape",
inputs={"input": "interpolate-input-0"},
outputs=[gen_name(9)])
self.pattern.add_layer(
"prim.len",
inputs={"input": gen_name(9)},
outputs=[gen_name(9)])
self.pattern.add_layer(
"prim.sub",
inputs={"x": gen_name(9)},
outputs=[gen_name(10)],
y=2)
self.pattern.add_layer(
"prim.list", inputs={}, outputs=[gen_name(11)])
self.pattern.add_layer(
"prim.loop",
inputs={"input": gen_name(10)},
outputs=[gen_name(12.1), gen_name(12.2)])
loop_layer = self.pattern.layers[list(self.pattern.layers.keys())[
-1]]
pattern_block = PaddleGraph(loop_layer, graph_type="dygraph")
pattern_block.add_layer(
"prim.append",
inputs={"list": gen_name(11)},
outputs=[],
element=None)
loop_layer.inputs["input-0"] = gen_name(11)
loop_layer.add_block(pattern_block)
self.pattern.add_layer(
"prim.tuple",
inputs={
"input0": "interpolate-input-0",
"input1": "interpolate-input-1",
},
outputs=[gen_name(13)],
input2=None,
input3=None)
self.pattern.add_layer(
"fluid.layers.shape",
inputs={"input": "interpolate-input-0"},
outputs=[gen_name(14)])
self.pattern.add_layer(
"prim.len",
inputs={"input": gen_name(14)},
outputs=[gen_name(14)])
self.pattern.add_layer(
"prim.eq",
inputs={"x": gen_name(14)},
outputs=[gen_name(15)],
y=3)
self.pattern.add_layer(
"prim.if",
inputs={"input": gen_name(15)},
outputs=[gen_name(16)])
if_layer1 = self.pattern.layers[list(self.pattern.layers.keys())[
-1]]
pattern_block = PaddleGraph(if_layer1, graph_type="dygraph")
pattern_block.add_layer(
"prim.exception",
inputs={},
outputs=[gen_name(17)],
input="Exception")
pattern_block.add_layer(
"prim.equal", inputs={}, outputs=[gen_name(16)], input=None)
if_layer1.add_block(pattern_block)
pattern_block = PaddleGraph(if_layer1, graph_type="dygraph")
pattern_block.add_layer(
"fluid.layers.shape",
inputs={"input": "interpolate-input-0"},
outputs=[gen_name(18)])
pattern_block.add_layer(
"prim.len",
inputs={"input": gen_name(18)},
outputs=[gen_name(18)])
pattern_block.add_layer(
"prim.eq",
inputs={"x": gen_name(18)},
outputs=[gen_name(19)],
y=4)
pattern_block.add_layer(
"prim.if",
inputs={"input": gen_name(19)},
outputs=[gen_name(20)])
if_layer2 = pattern_block.layers[list(pattern_block.layers.keys())[
-1]]
pattern_block_block = PaddleGraph(if_layer2, graph_type="dygraph")
pattern_block_block.add_layer(
"prim.tuple_unpack",
inputs={"input": gen_name(13)},
outputs=[
gen_name(34), gen_name(35), gen_name(36), gen_name(37)
])
pattern_block_block.add_layer(
"prim.is",
inputs={"x": gen_name(35)},
outputs=[gen_name(38)],
y=None)
pattern_block_block.add_layer(
"prim.if",
inputs={"input": gen_name(38)},
outputs=[gen_name(39), gen_name(40)])
if_layer3 = pattern_block_block.layers[list(
pattern_block_block.layers.keys())[-1]]
pattern_block_block_block = PaddleGraph(
if_layer3, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.is",
inputs={"x": gen_name(36)},
outputs=[gen_name(41)],
y=None)
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(41)},
outputs=[gen_name(39)])
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(35)},
outputs=[gen_name(40)])
if_layer3.add_block(pattern_block_block_block)
pattern_block_block_block = PaddleGraph(
if_layer3, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(35)},
outputs=[gen_name(42)])
pattern_block_block_block.add_layer(
"prim.equal", inputs={}, outputs=[gen_name(39)], input=False)
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(35)},
outputs=[gen_name(40)])
if_layer3.add_block(pattern_block_block_block)
if_layer3.inputs.update({
"input-0": gen_name(36),
'input-1': gen_name(35),
'input-2': gen_name(35),
})
pattern_block_block.add_layer(
"prim.if",
inputs={"input": gen_name(39)},
outputs=[gen_name(43)])
if_layer4 = pattern_block_block.layers[list(
pattern_block_block.layers.keys())[-1]]
pattern_block_block_block = PaddleGraph(
if_layer4, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.exception",
inputs={},
outputs=[gen_name(44)],
input="Exception")
if_layer4.add_block(pattern_block_block_block)
pattern_block_block_block = PaddleGraph(
if_layer4, graph_type="dygraph")
if_layer4.add_block(pattern_block_block_block)
pattern_block_block.add_layer(
"prim.isnot",
inputs={"x": gen_name(40)},
outputs=[gen_name(45)],
y=None)
pattern_block_block.add_layer(
"prim.if",
inputs={"input": gen_name(45)},
outputs=[gen_name(46), gen_name(47)])
if_layer5 = pattern_block_block.layers[list(
pattern_block_block.layers.keys())[-1]]
pattern_block_block_block = PaddleGraph(
if_layer5, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(40)},
outputs=[gen_name(48)])
pattern_block_block_block.add_layer(
"prim.isnot",
inputs={"x": gen_name(36)},
outputs=[gen_name(49)],
y=None)
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(49)},
outputs=[gen_name(46)])
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(48)},
outputs=[gen_name(47)])
if_layer5.add_block(pattern_block_block_block)
pattern_block_block_block = PaddleGraph(
if_layer5, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.equal", inputs={}, outputs=[gen_name(46)], input=False)
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(40)},
outputs=[gen_name(47)])
if_layer5.add_block(pattern_block_block_block)
if_layer5.inputs.update({
"input-0": gen_name(40),
"input-1": gen_name(36),
"input-3": gen_name(40)
})
pattern_block_block.add_layer(
"prim.if",
inputs={"input": gen_name(46)},
outputs=[gen_name(50), gen_name(51)])
if_layer6 = pattern_block_block.layers[list(
pattern_block_block.layers.keys())[-1]]
pattern_block_block_block = PaddleGraph(
if_layer6, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.exception",
inputs={},
outputs=[gen_name(52)],
input="Exception")
pattern_block_block_block.add_layer(
"prim.equal", inputs={}, outputs=[gen_name(50)], input=None)
pattern_block_block_block.add_layer(
"prim.equal", inputs={}, outputs=[gen_name(51)], input=None)
if_layer6.add_block(pattern_block_block_block)
pattern_block_block_block = PaddleGraph(
if_layer6, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(36)},
outputs=[gen_name(50)])
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(47)},
outputs=[gen_name(51)])
if_layer6.add_block(pattern_block_block_block)
if_layer6.inputs.update({
"input-0": gen_name(36),
"input-1": gen_name(47)
})
pattern_block_block.add_layer(
"prim.isnot",
inputs={"x": gen_name(50)},
outputs=[gen_name(53)],
y=None)
pattern_block_block.add_layer(
"prim.if",
inputs={"input": gen_name(53)},
outputs=[gen_name(54)])
if_layer7 = pattern_block_block.layers[list(
pattern_block_block.layers.keys())[-1]]
pattern_block_block_block = PaddleGraph(
if_layer7, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(50)},
outputs=[gen_name(55)])
pattern_block_block_block.add_layer(
"prim.len",
inputs={"input": gen_name(55)},
outputs=[gen_name(56)])
pattern_block_block_block.add_layer(
"prim.ne",
inputs={"x": gen_name(56)},
outputs=[gen_name(57)],
y=2)
pattern_block_block_block.add_layer(
"prim.if",
inputs={"input": gen_name(57)},
outputs=[gen_name(58)])
if_layer8 = pattern_block_block_block.layers[list(
pattern_block_block_block.layers.keys())[-1]]
pattern_block_block_block_block = PaddleGraph(
if_layer8, graph_type="dygraph")
pattern_block_block_block_block.add_layer(
"prim.exception",
inputs={},
outputs=[gen_name(59)],
input="Exception")
if_layer8.add_block(pattern_block_block_block_block)
pattern_block_block_block_block = PaddleGraph(
if_layer8, graph_type="dygraph")
if_layer8.add_block(pattern_block_block_block_block)
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(55)},
outputs=[gen_name(54)])
if_layer7.add_block(pattern_block_block_block)
pattern_block_block_block = PaddleGraph(
if_layer7, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(50)},
outputs=[gen_name(54)])
if_layer7.add_block(pattern_block_block_block)
if_layer7.inputs.update({
"input-0": gen_name(50),
"input-1": gen_name(50)
})
pattern_block_block.add_layer(
"prim.isnot",
inputs={"x": gen_name(51)},
outputs=[gen_name(60)],
y=None)
pattern_block_block.add_layer(
"prim.if",
inputs={"input": gen_name(60)},
outputs=[gen_name(61)])
if_layer9 = pattern_block_block.layers[list(
pattern_block_block.layers.keys())[-1]]
pattern_block_block_block = PaddleGraph(
if_layer9, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(51)},
outputs=[gen_name(62)])
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(62)},
outputs=[gen_name(61)])
if_layer9.add_block(pattern_block_block_block)
pattern_block_block_block = PaddleGraph(
if_layer9, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.isnot",
inputs={"x": gen_name(54)},
outputs=[gen_name(64)],
y=None)
pattern_block_block_block.add_layer(
"prim.if",
inputs={"input": gen_name(64)},
outputs=[gen_name(65)])
if_layer11 = pattern_block_block_block.layers[list(
pattern_block_block_block.layers.keys())[-1]]
pattern_block_block_block_block = PaddleGraph(
if_layer11, graph_type="dygraph")
pattern_block_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(54)},
outputs=[gen_name(66)])
pattern_block_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(66)},
outputs=[gen_name(65)])
if_layer11.add_block(pattern_block_block_block_block)
pattern_block_block_block_block = PaddleGraph(
if_layer11, graph_type="dygraph")
pattern_block_block_block_block.add_layer(
"prim.exception",
inputs={},
outputs=[gen_name(67)],
input="Exception")
pattern_block_block_block_block.add_layer(
"prim.equal", inputs={}, outputs=[gen_name(65)], input=None)
if_layer11.add_block(pattern_block_block_block_block)
if_layer11.inputs.update({"input-0": gen_name(54), })
pattern_block_block_block.add_layer(
"prim.is",
inputs={"x": gen_name(37)},
outputs=[gen_name(68)],
y=None)
pattern_block_block_block.add_layer(
"prim.if",
inputs={"input": gen_name(68)},
outputs=[gen_name(69)])
if_layer12 = pattern_block_block_block.layers[list(
pattern_block_block_block.layers.keys())[-1]]
pattern_block_block_block_block = PaddleGraph(
if_layer12, graph_type="dygraph")
pattern_block_block_block_block.add_layer(
"prim.len",
inputs={"input": gen_name(65)},
outputs=[gen_name(70)])
pattern_block_block_block_block.add_layer(
"prim.gt",
inputs={"x": gen_name(70)},
outputs=[gen_name(71)],
y=0)
pattern_block_block_block_block.add_layer(
"prim.equal", inputs={}, outputs=[gen_name(72)], input=0)
pattern_block_block_block_block.add_layer(
"prim.loop",
inputs={},
outputs=[gen_name(74), gen_name(75), gen_name(76.1)],
input=2147483647)
loop_layer = pattern_block_block_block_block.layers[list(
pattern_block_block_block_block.layers.keys())[-1]]
pattern_loop_block = PaddleGraph(loop_layer, graph_type="dygraph")
pattern_loop_block.add_layer(
"prim.getitem",
inputs={"list": gen_name(65),
"element": gen_name(72)},
outputs=[gen_name(74.1)])
pattern_loop_block.add_layer(
"prim.floor",
inputs={"input": gen_name(74.1)},
outputs=[gen_name(75.1)])
pattern_loop_block.add_layer(
"prim.ne",
inputs={"x": gen_name(75.1),
"y": gen_name(74.1)},
outputs=[gen_name(76)])
pattern_loop_block.add_layer(
"prim.if",
inputs={"input": gen_name(76)},
outputs=[gen_name(77)])
if_layer13 = pattern_loop_block.layers[list(
pattern_loop_block.layers.keys())[-1]]
pattern_loop_block_block = PaddleGraph(
if_layer13, graph_type="dygraph")
pattern_loop_block_block.add_layer(
"prim.equal", inputs={}, outputs=[gen_name(77)], input=False)
if_layer13.add_block(pattern_loop_block_block)
pattern_loop_block_block = PaddleGraph(
if_layer13, graph_type="dygraph")
pattern_loop_block_block.add_layer(
"prim.equal", inputs={}, outputs=[gen_name(77)], input=True)
if_layer13.add_block(pattern_loop_block_block)
pattern_loop_block.add_layer(
"prim.add",
inputs={"x": gen_name(72)},
outputs=[gen_name(81)],
y=1)
pattern_loop_block.add_layer(
"prim.lt",
inputs={"x": gen_name(81),
"y": gen_name(70)},
outputs=[gen_name(82)])
pattern_loop_block.add_layer(
"prim.and",
inputs={"x": gen_name(82),
"y": gen_name(77)},
outputs=[gen_name(83)])
pattern_loop_block.add_layer(
"prim.equal",
inputs={"input": gen_name(76)},
outputs=[gen_name(74)])
pattern_loop_block.add_layer(
"prim.equal",
inputs={"input": gen_name(81)},
outputs=[gen_name(75)])
loop_layer.add_block(pattern_loop_block)
loop_layer.inputs.update({
"input-0": gen_name(65),
"input-1": gen_name(72),
"input-2": gen_name(72),
"input-3": gen_name(70)
})
pattern_block_block_block_block.add_layer(
"prim.if",
inputs={"input": gen_name(74)},
outputs=[gen_name(84)])
if_layer15 = pattern_block_block_block_block.layers[list(
pattern_block_block_block_block.layers.keys())[-1]]
pattern_block_block_block_block_block = PaddleGraph(
if_layer15, graph_type="dygraph")
pattern_block_block_block_block_block.add_layer(
"prim.warnings",
inputs={},
outputs=[gen_name(85)],
stacklevel=2,
input="...")
if_layer15.add_block(pattern_block_block_block_block_block)
pattern_block_block_block_block_block = PaddleGraph(
if_layer15, graph_type="dygraph")
if_layer15.add_block(pattern_block_block_block_block_block)
if_layer12.add_block(pattern_block_block_block_block)
pattern_block_block_block_block = PaddleGraph(
if_layer12, graph_type="dygraph")
if_layer12.add_block(pattern_block_block_block_block)
if_layer12.inputs.update({
"input-0": gen_name(65),
"input-1": gen_name(65),
})
pattern_block_block_block.add_layer(
"prim.list", inputs={}, outputs=[gen_name(86)])
pattern_block_block_block.add_layer(
"prim.loop",
inputs={},
outputs=[gen_name(87), gen_name(88)],
input=2)
loop_layer = pattern_block_block_block.layers[list(
pattern_block_block_block.layers.keys())[-1]]
pattern_loop_block = PaddleGraph(loop_layer, graph_type="dygraph")
pattern_loop_block.add_layer(
"prim.add",
inputs={"x": gen_name(88)},
outputs=[gen_name(89)],
y=2)
pattern_loop_block.add_layer(
"prim.shape_dim",
inputs={"input": gen_name(34),
"dim": gen_name(89)},
outputs=[gen_name(90)])
pattern_loop_block.add_layer(
"prim.float",
inputs={"input": gen_name(90)},
outputs=[gen_name(91)])
pattern_loop_block.add_layer(
"prim.getitem",
inputs={"list": gen_name(65),
"element": gen_name(88)},
outputs=[gen_name(92)])
pattern_loop_block.add_layer(
"prim.mul",
inputs={"x": gen_name(91),
"y": gen_name(92)},
outputs=[gen_name(93)])
pattern_loop_block.add_layer(
"prim.floor",
inputs={"input": gen_name(93)},
outputs=[gen_name(94)])
pattern_loop_block.add_layer(
"prim.append",
inputs={"list": gen_name(86),
"element": gen_name(94)},
outputs=[])
loop_layer.add_block(pattern_loop_block)
loop_layer.inputs.update({
"input-0": gen_name(34),
"input-1": gen_name(65),
"input-2": gen_name(86)
})
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(86)},
outputs=[gen_name(61)])
if_layer9.add_block(pattern_block_block_block)
if_layer9.inputs.update({
"input-0": gen_name(51),
"input-1": gen_name(54),
"input-2": gen_name(54),
"input-3": gen_name(37),
"input-4": gen_name(34)
})
pattern_block_block.add_layer(
"prim.getitem",
inputs={"list": gen_name(11)},
outputs=[gen_name(95)],
element=0)
pattern_block_block.add_layer(
"prim.getitem",
inputs={"list": gen_name(11)},
outputs=[gen_name(96)],
element=1)
pattern_block_block.add_layer(
"prim.isinstance",
inputs={"input": gen_name(61)},
outputs=["interpolate-input-0_isinstance"],
cls="paddle.fluid.Variable")
pattern_block_block.add_layer(
"prim.if", {"input": "interpolate-input-0_isinstance"},
outputs=["interpolate-input-0_if1"])
if_layer_isinstance = pattern_block_block.layers[list(
pattern_block_block.layers.keys())[-1]]
pattern_block_block_block = PaddleGraph(
if_layer_isinstance, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.var2list",
inputs={"input": gen_name(61)},
outputs=[gen_name(61)])
if_layer_isinstance.add_block(pattern_block_block_block)
pattern_block_block_block = PaddleGraph(
if_layer_isinstance, graph_type="dygraph")
if_layer_isinstance.add_block(pattern_block_block_block)
if_layer_isinstance.inputs["input-0"] = gen_name(61)
pattern_block_block.add_layer(
"prim.assert",
inputs={"key": gen_name(95),
"value": gen_name(96)},
outputs=[gen_name(97) + "_assert"],
type="eq")
pattern_block_block.add_layer(
"paddle.nn.functional.interpolate",
inputs={
"input": "interpolate-input-0",
"size": gen_name(61),
"scale_factor": gen_name(95)
},
outputs=[gen_name(97)],
align_corners=False,
align_mode=0)
pattern_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(97)},
outputs=[gen_name(20)])
if_layer2.add_block(pattern_block_block)
pattern_block_block = PaddleGraph(if_layer2, graph_type="dygraph")
pattern_block_block.add_layer(
"fluid.layers.shape",
inputs={"input": "interpolate-input-0"},
outputs=[gen_name(98)])
pattern_block_block.add_layer(
"prim.len",
inputs={"input": gen_name(98)},
outputs=[gen_name(98)])
pattern_block_block.add_layer(
"prim.eq",
inputs={"x": gen_name(98)},
outputs=[gen_name(99)],
y=5)
pattern_block_block.add_layer(
"prim.if",
inputs={"input": gen_name(99)},
outputs=[gen_name(100)])
if_layer16 = pattern_block_block.layers[list(
pattern_block_block.layers.keys())[-1]]
pattern_block_block_block = PaddleGraph(
if_layer16, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.exception",
inputs={},
outputs=[gen_name(101)],
input="Exception")
if_layer16.add_block(pattern_block_block_block)
pattern_block_block_block = PaddleGraph(
if_layer16, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.exception",
inputs={},
outputs=[gen_name(102)],
input="Exception")
if_layer16.add_block(pattern_block_block_block)
pattern_block_block.add_layer(
"prim.equal", inputs={}, outputs=[gen_name(20)], input=None)
if_layer2.add_block(pattern_block_block)
if_layer2.inputs.update({
"input-0": gen_name(13),
"input-1": gen_name(13),
"input-2": "interpolate-input-0",
"input-3": gen_name(11),
"input-5": gen_name(11),
})
pattern_block.add_layer(
"prim.equal",
inputs={"input": gen_name(20)},
outputs=[gen_name(16)])
if_layer1.add_block(pattern_block)
if_layer1.inputs.update({
"input-2": "interpolate-input-0",
"input-4": gen_name(13),
"input-7": gen_name(11),
"input-9": gen_name(11),
"input-11": "interpolate-input-0",
"input-12": "interpolate-input-0",
})
self.pattern.build(inputs={
"input-0": "interpolate-input-0",
"input-1": "interpolate-input-1"
})
else:
self.pattern.add_layer(
"fluid.layers.shape",
inputs={"input": "interpolate-input-0"},
outputs=[gen_name(9)])
self.pattern.add_layer(
"prim.len",
inputs={"input": gen_name(9)},
outputs=[gen_name(9)])
self.pattern.add_layer(
"prim.sub",
inputs={"x": gen_name(9)},
outputs=[gen_name(10)],
y=2)
self.pattern.add_layer(
"prim.list", inputs={}, outputs=[gen_name(11)])
self.pattern.add_layer(
"prim.loop",
inputs={"input": gen_name(10)},
outputs=[gen_name(12.1), gen_name(12.2)])
loop_layer = self.pattern.layers[list(self.pattern.layers.keys())[
-1]]
pattern_block = PaddleGraph(loop_layer, graph_type="dygraph")
pattern_block.add_layer(
"prim.append",
inputs={"list": gen_name(11)},
outputs=[],
element=None)
loop_layer.inputs["input-0"] = gen_name(11)
loop_layer.add_block(pattern_block)
self.pattern.add_layer(
"prim.tuple",
inputs={
"input0": "interpolate-input-0",
"input1": "interpolate-input-1",
},
outputs=[gen_name(13)],
input2=None,
input3=None)
self.pattern.add_layer(
"fluid.layers.shape",
inputs={"input": "interpolate-input-0"},
outputs=[gen_name(14)])
self.pattern.add_layer(
"prim.len",
inputs={"input": gen_name(14)},
outputs=[gen_name(14)])
self.pattern.add_layer(
"prim.eq",
inputs={"x": gen_name(14)},
outputs=[gen_name(15)],
y=3)
self.pattern.add_layer(
"prim.if",
inputs={"input": gen_name(15)},
outputs=[gen_name(16)])
if_layer1 = self.pattern.layers[list(self.pattern.layers.keys())[
-1]]
pattern_block = PaddleGraph(if_layer1, graph_type="dygraph")
pattern_block.add_layer(
"prim.exception",
inputs={},
outputs=[gen_name(17)],
input="Exception")
pattern_block.add_layer(
"prim.equal", inputs={}, outputs=[gen_name(16)], input=None)
if_layer1.add_block(pattern_block)
pattern_block = PaddleGraph(if_layer1, graph_type="dygraph")
pattern_block.add_layer(
"fluid.layers.shape",
inputs={"input": "interpolate-input-0"},
outputs=[gen_name(18)])
pattern_block.add_layer(
"prim.len",
inputs={"input": gen_name(18)},
outputs=[gen_name(18)])
pattern_block.add_layer(
"prim.eq",
inputs={"x": gen_name(18)},
outputs=[gen_name(19)],
y=4)
pattern_block.add_layer(
"prim.if",
inputs={"input": gen_name(19)},
outputs=[gen_name(20)])
if_layer2 = pattern_block.layers[list(pattern_block.layers.keys())[
-1]]
pattern_block_block = PaddleGraph(if_layer2, graph_type="dygraph")
pattern_block_block.add_layer(
"prim.tuple_unpack",
inputs={"input": gen_name(13)},
outputs=[
gen_name(34), gen_name(35), gen_name(36), gen_name(37)
])
pattern_block_block.add_layer(
"prim.is",
inputs={"x": gen_name(35)},
outputs=[gen_name(38)],
y=None)
pattern_block_block.add_layer(
"prim.if",
inputs={"input": gen_name(38)},
outputs=[gen_name(39), gen_name(40)])
if_layer3 = pattern_block_block.layers[list(
pattern_block_block.layers.keys())[-1]]
pattern_block_block_block = PaddleGraph(
if_layer3, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.is",
inputs={"x": gen_name(36)},
outputs=[gen_name(41)],
y=None)
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(41)},
outputs=[gen_name(39)])
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(35)},
outputs=[gen_name(40)])
if_layer3.add_block(pattern_block_block_block)
pattern_block_block_block = PaddleGraph(
if_layer3, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(35)},
outputs=[gen_name(42)])
pattern_block_block_block.add_layer(
"prim.equal", inputs={}, outputs=[gen_name(39)], input=False)
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(35)},
outputs=[gen_name(40)])
if_layer3.add_block(pattern_block_block_block)
if_layer3.inputs.update({
"input-0": gen_name(36),
'input-1': gen_name(35),
'input-2': gen_name(35),
})
pattern_block_block.add_layer(
"prim.if",
inputs={"input": gen_name(39)},
outputs=[gen_name(43)])
if_layer4 = pattern_block_block.layers[list(
pattern_block_block.layers.keys())[-1]]
pattern_block_block_block = PaddleGraph(
if_layer4, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.exception",
inputs={},
outputs=[gen_name(44)],
input="Exception")
if_layer4.add_block(pattern_block_block_block)
pattern_block_block_block = PaddleGraph(
if_layer4, graph_type="dygraph")
if_layer4.add_block(pattern_block_block_block)
pattern_block_block.add_layer(
"prim.isnot",
inputs={"x": gen_name(40)},
outputs=[gen_name(45)],
y=None)
pattern_block_block.add_layer(
"prim.if",
inputs={"input": gen_name(45)},
outputs=[gen_name(46), gen_name(47)])
if_layer5 = pattern_block_block.layers[list(
pattern_block_block.layers.keys())[-1]]
pattern_block_block_block = PaddleGraph(
if_layer5, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(40)},
outputs=[gen_name(48)])
pattern_block_block_block.add_layer(
"prim.isnot",
inputs={"x": gen_name(36)},
outputs=[gen_name(49)],
y=None)
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(49)},
outputs=[gen_name(46)])
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(48)},
outputs=[gen_name(47)])
if_layer5.add_block(pattern_block_block_block)
pattern_block_block_block = PaddleGraph(
if_layer5, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.equal", inputs={}, outputs=[gen_name(46)], input=False)
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(40)},
outputs=[gen_name(47)])
if_layer5.add_block(pattern_block_block_block)
if_layer5.inputs.update({
"input-0": gen_name(40),
"input-1": gen_name(36),
"input-3": gen_name(40)
})
pattern_block_block.add_layer(
"prim.if",
inputs={"input": gen_name(46)},
outputs=[gen_name(50), gen_name(51)])
if_layer6 = pattern_block_block.layers[list(
pattern_block_block.layers.keys())[-1]]
pattern_block_block_block = PaddleGraph(
if_layer6, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.exception",
inputs={},
outputs=[gen_name(52)],
input="Exception")
pattern_block_block_block.add_layer(
"prim.equal", inputs={}, outputs=[gen_name(50)], input=None)
pattern_block_block_block.add_layer(
"prim.equal", inputs={}, outputs=[gen_name(51)], input=None)
if_layer6.add_block(pattern_block_block_block)
pattern_block_block_block = PaddleGraph(
if_layer6, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(36)},
outputs=[gen_name(50)])
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(47)},
outputs=[gen_name(51)])
if_layer6.add_block(pattern_block_block_block)
if_layer6.inputs.update({
"input-0": gen_name(36),
"input-1": gen_name(47)
})
pattern_block_block.add_layer(
"prim.isnot",
inputs={"x": gen_name(50)},
outputs=[gen_name(53)],
y=None)
pattern_block_block.add_layer(
"prim.if",
inputs={"input": gen_name(53)},
outputs=[gen_name(54)])
if_layer7 = pattern_block_block.layers[list(
pattern_block_block.layers.keys())[-1]]
pattern_block_block_block = PaddleGraph(
if_layer7, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(50)},
outputs=[gen_name(55)])
pattern_block_block_block.add_layer(
"prim.len",
inputs={"input": gen_name(55)},
outputs=[gen_name(56)])
pattern_block_block_block.add_layer(
"prim.ne",
inputs={"x": gen_name(56)},
outputs=[gen_name(57)],
y=2)
pattern_block_block_block.add_layer(
"prim.if",
inputs={"input": gen_name(57)},
outputs=[gen_name(58)])
if_layer8 = pattern_block_block_block.layers[list(
pattern_block_block_block.layers.keys())[-1]]
pattern_block_block_block_block = PaddleGraph(
if_layer8, graph_type="dygraph")
pattern_block_block_block_block.add_layer(
"prim.exception",
inputs={},
outputs=[gen_name(59)],
input="Exception")
if_layer8.add_block(pattern_block_block_block_block)
pattern_block_block_block_block = PaddleGraph(
if_layer8, graph_type="dygraph")
if_layer8.add_block(pattern_block_block_block_block)
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(55)},
outputs=[gen_name(54)])
if_layer7.add_block(pattern_block_block_block)
pattern_block_block_block = PaddleGraph(
if_layer7, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(50)},
outputs=[gen_name(54)])
if_layer7.add_block(pattern_block_block_block)
if_layer7.inputs.update({
"input-0": gen_name(50),
"input-1": gen_name(50)
})
pattern_block_block.add_layer(
"prim.isnot",
inputs={"x": gen_name(51)},
outputs=[gen_name(60)],
y=None)
pattern_block_block.add_layer(
"prim.if",
inputs={"input": gen_name(60)},
outputs=[gen_name(61)])
if_layer9 = pattern_block_block.layers[list(
pattern_block_block.layers.keys())[-1]]
pattern_block_block_block = PaddleGraph(
if_layer9, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(51)},
outputs=[gen_name(62)])
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(62)},
outputs=[gen_name(61)])
if_layer9.add_block(pattern_block_block_block)
pattern_block_block_block = PaddleGraph(
if_layer9, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.equal", inputs={}, outputs=[gen_name(61)], input=None)
if_layer9.add_block(pattern_block_block_block)
if_layer9.inputs.update({"input-0": gen_name(51)})
pattern_block_block.add_layer(
"prim.if",
inputs={"input": gen_name(60)},
outputs=[gen_name(63)])
if_layer10 = pattern_block_block.layers[list(
pattern_block_block.layers.keys())[-1]]
pattern_block_block_block = PaddleGraph(
if_layer10, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(61)},
outputs=[gen_name(63)])
if_layer10.add_block(pattern_block_block_block)
pattern_block_block_block = PaddleGraph(
if_layer10, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.isnot",
inputs={"x": gen_name(54)},
outputs=[gen_name(64)],
y=None)
pattern_block_block_block.add_layer(
"prim.if",
inputs={"input": gen_name(64)},
outputs=[gen_name(65)])
if_layer11 = pattern_block_block_block.layers[list(
pattern_block_block_block.layers.keys())[-1]]
pattern_block_block_block_block = PaddleGraph(
if_layer11, graph_type="dygraph")
pattern_block_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(54)},
outputs=[gen_name(66)])
pattern_block_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(66)},
outputs=[gen_name(65)])
if_layer11.add_block(pattern_block_block_block_block)
pattern_block_block_block_block = PaddleGraph(
if_layer11, graph_type="dygraph")
pattern_block_block_block_block.add_layer(
"prim.exception",
inputs={},
outputs=[gen_name(67)],
input="Exception")
pattern_block_block_block_block.add_layer(
"prim.equal", inputs={}, outputs=[gen_name(65)], input=None)
if_layer11.add_block(pattern_block_block_block_block)
if_layer11.inputs.update({"input-0": gen_name(54), })
pattern_block_block_block.add_layer(
"prim.is",
inputs={"x": gen_name(37)},
outputs=[gen_name(68)],
y=None)
pattern_block_block_block.add_layer(
"prim.if",
inputs={"input": gen_name(68)},
outputs=[gen_name(69)])
if_layer12 = pattern_block_block_block.layers[list(
pattern_block_block_block.layers.keys())[-1]]
pattern_block_block_block_block = PaddleGraph(
if_layer12, graph_type="dygraph")
pattern_block_block_block_block.add_layer(
"prim.len",
inputs={"input": gen_name(65)},
outputs=[gen_name(70)])
pattern_block_block_block_block.add_layer(
"prim.gt",
inputs={"x": gen_name(70)},
outputs=[gen_name(71)],
y=0)
pattern_block_block_block_block.add_layer(
"prim.equal", inputs={}, outputs=[gen_name(72)], input=0)
pattern_block_block_block_block.add_layer(
"prim.loop",
inputs={},
outputs=[gen_name(74), gen_name(75), gen_name(76.1)],
input=2147483647)
loop_layer = pattern_block_block_block_block.layers[list(
pattern_block_block_block_block.layers.keys())[-1]]
pattern_loop_block = PaddleGraph(loop_layer, graph_type="dygraph")
pattern_loop_block.add_layer(
"prim.getitem",
inputs={"list": gen_name(65),
"element": gen_name(72)},
outputs=[gen_name(74.1)])
pattern_loop_block.add_layer(
"prim.floor",
inputs={"input": gen_name(74.1)},
outputs=[gen_name(75.1)])
pattern_loop_block.add_layer(
"prim.ne",
inputs={"x": gen_name(75.1),
"y": gen_name(74.1)},
outputs=[gen_name(76)])
pattern_loop_block.add_layer(
"prim.if",
inputs={"input": gen_name(76)},
outputs=[gen_name(77), gen_name(78)])
if_layer13 = pattern_loop_block.layers[list(
pattern_loop_block.layers.keys())[-1]]
pattern_loop_block_block = PaddleGraph(
if_layer13, graph_type="dygraph")
pattern_loop_block_block.add_layer(
"prim.equal", inputs={}, outputs=[gen_name(77)], input=False)
pattern_loop_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(76)},
outputs=[gen_name(78)])
if_layer13.add_block(pattern_loop_block_block)
pattern_loop_block_block = PaddleGraph(
if_layer13, graph_type="dygraph")
pattern_loop_block_block.add_layer(
"prim.equal", inputs={}, outputs=[gen_name(77)], input=None)
pattern_loop_block_block.add_layer(
"prim.equal", inputs={}, outputs=[gen_name(78)], input=None)
if_layer13.add_block(pattern_loop_block_block)
if_layer13.inputs.update({"input-0": gen_name(76), })
pattern_loop_block.add_layer(
"prim.if",
inputs={"input": gen_name(76)},
outputs=[gen_name(79), gen_name(80)])
if_layer14 = pattern_loop_block.layers[list(
pattern_loop_block.layers.keys())[-1]]
pattern_loop_block_block = PaddleGraph(
if_layer14, graph_type="dygraph")
pattern_loop_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(77)},
outputs=[gen_name(79)])
pattern_loop_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(78)},
outputs=[gen_name(80)])
if_layer14.add_block(pattern_loop_block_block)
pattern_loop_block_block = PaddleGraph(
if_layer14, graph_type="dygraph")
pattern_loop_block_block.add_layer(
"prim.equal", inputs={}, outputs=[gen_name(79)], input=True)
pattern_loop_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(76)},
outputs=[gen_name(80)])
if_layer14.add_block(pattern_loop_block_block)
if_layer14.inputs.update({
"input-0": gen_name(77),
"input-1": gen_name(78),
"input-2": gen_name(76)
})
pattern_loop_block.add_layer(
"prim.add",
inputs={"x": gen_name(72)},
outputs=[gen_name(81)],
y=1)
pattern_loop_block.add_layer(
"prim.lt",
inputs={"x": gen_name(81),
"y": gen_name(70)},
outputs=[gen_name(82)])
pattern_loop_block.add_layer(
"prim.and",
inputs={"x": gen_name(82),
"y": gen_name(79)},
outputs=[gen_name(83)])
pattern_loop_block.add_layer(
"prim.equal",
inputs={"input": gen_name(80)},
outputs=[gen_name(74)])
pattern_loop_block.add_layer(
"prim.equal",
inputs={"input": gen_name(81)},
outputs=[gen_name(75)])
loop_layer.add_block(pattern_loop_block)
loop_layer.inputs.update({
"input-0": gen_name(65),
"input-1": gen_name(72),
"input-2": gen_name(72),
"input-3": gen_name(70)
})
pattern_block_block_block_block.add_layer(
"prim.if",
inputs={"input": gen_name(74)},
outputs=[gen_name(84)])
if_layer15 = pattern_block_block_block_block.layers[list(
pattern_block_block_block_block.layers.keys())[-1]]
pattern_block_block_block_block_block = PaddleGraph(
if_layer15, graph_type="dygraph")
pattern_block_block_block_block_block.add_layer(
"prim.warnings",
inputs={},
outputs=[gen_name(85)],
stacklevel=2,
input="...")
if_layer15.add_block(pattern_block_block_block_block_block)
pattern_block_block_block_block_block = PaddleGraph(
if_layer15, graph_type="dygraph")
if_layer15.add_block(pattern_block_block_block_block_block)
if_layer12.add_block(pattern_block_block_block_block)
pattern_block_block_block_block = PaddleGraph(
if_layer12, graph_type="dygraph")
if_layer12.add_block(pattern_block_block_block_block)
if_layer12.inputs.update({
"input-0": gen_name(65),
"input-1": gen_name(65),
})
pattern_block_block_block.add_layer(
"prim.list", inputs={}, outputs=[gen_name(86)])
pattern_block_block_block.add_layer(
"prim.loop",
inputs={},
outputs=[gen_name(87), gen_name(88)],
input=2)
loop_layer = pattern_block_block_block.layers[list(
pattern_block_block_block.layers.keys())[-1]]
pattern_loop_block = PaddleGraph(loop_layer, graph_type="dygraph")
pattern_loop_block.add_layer(
"prim.add",
inputs={"x": gen_name(88)},
outputs=[gen_name(89)],
y=2)
pattern_loop_block.add_layer(
"prim.shape_dim",
inputs={"input": gen_name(34),
"dim": gen_name(89)},
outputs=[gen_name(90)])
pattern_loop_block.add_layer(
"prim.float",
inputs={"input": gen_name(90)},
outputs=[gen_name(91)])
pattern_loop_block.add_layer(
"prim.getitem",
inputs={"list": gen_name(65),
"element": gen_name(88)},
outputs=[gen_name(92)])
pattern_loop_block.add_layer(
"prim.mul",
inputs={"x": gen_name(91),
"y": gen_name(92)},
outputs=[gen_name(93)])
pattern_loop_block.add_layer(
"prim.floor",
inputs={"input": gen_name(93)},
outputs=[gen_name(94)])
pattern_loop_block.add_layer(
"prim.append",
inputs={"list": gen_name(86),
"element": gen_name(94)},
outputs=[])
loop_layer.add_block(pattern_loop_block)
loop_layer.inputs.update({
"input-0": gen_name(34),
"input-1": gen_name(65),
"input-2": gen_name(86)
})
pattern_block_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(86)},
outputs=[gen_name(63)])
if_layer10.add_block(pattern_block_block_block)
if_layer10.inputs.update({
"input-0": gen_name(61),
"input-1": gen_name(54),
"input-2": gen_name(54),
"input-3": gen_name(37),
"input-4": gen_name(34)
})
pattern_block_block.add_layer(
"prim.getitem",
inputs={"list": gen_name(11)},
outputs=[gen_name(95)],
element=0)
pattern_block_block.add_layer(
"prim.getitem",
inputs={"list": gen_name(11)},
outputs=[gen_name(96)],
element=1)
pattern_block_block.add_layer(
"prim.isinstance",
inputs={"input": gen_name(63)},
outputs=["interpolate-input-0_isinstance"],
cls="paddle.fluid.Variable")
pattern_block_block.add_layer(
"prim.if", {"input": "interpolate-input-0_isinstance"},
outputs=["interpolate-input-0_if1"])
if_layer_isinstance = pattern_block_block.layers[list(
pattern_block_block.layers.keys())[-1]]
pattern_block_block_block = PaddleGraph(
if_layer_isinstance, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.var2list",
inputs={"input": gen_name(63)},
outputs=[gen_name(63)])
if_layer_isinstance.add_block(pattern_block_block_block)
pattern_block_block_block = PaddleGraph(
if_layer_isinstance, graph_type="dygraph")
if_layer_isinstance.add_block(pattern_block_block_block)
if_layer_isinstance.inputs["input-0"] = gen_name(63)
pattern_block_block.add_layer(
"prim.assert",
inputs={"key": gen_name(95),
"value": gen_name(96)},
outputs=[gen_name(97) + "_assert"],
type="eq")
pattern_block_block.add_layer(
"paddle.nn.functional.interpolate",
inputs={
"input": "interpolate-input-0",
"size": gen_name(63),
"scale_factor": gen_name(95)
},
outputs=[gen_name(97)],
align_corners=False,
align_mode=0)
pattern_block_block.add_layer(
"prim.equal",
inputs={"input": gen_name(97)},
outputs=[gen_name(20)])
if_layer2.add_block(pattern_block_block)
pattern_block_block = PaddleGraph(if_layer2, graph_type="dygraph")
pattern_block_block.add_layer(
"fluid.layers.shape",
inputs={"input": "interpolate-input-0"},
outputs=[gen_name(98)])
pattern_block_block.add_layer(
"prim.len",
inputs={"input": gen_name(98)},
outputs=[gen_name(98)])
pattern_block_block.add_layer(
"prim.eq",
inputs={"x": gen_name(98)},
outputs=[gen_name(99)],
y=5)
pattern_block_block.add_layer(
"prim.if",
inputs={"input": gen_name(99)},
outputs=[gen_name(100)])
if_layer16 = pattern_block_block.layers[list(
pattern_block_block.layers.keys())[-1]]
pattern_block_block_block = PaddleGraph(
if_layer16, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.exception",
inputs={},
outputs=[gen_name(101)],
input="Exception")
if_layer16.add_block(pattern_block_block_block)
pattern_block_block_block = PaddleGraph(
if_layer16, graph_type="dygraph")
pattern_block_block_block.add_layer(
"prim.exception",
inputs={},
outputs=[gen_name(102)],
input="Exception")
if_layer16.add_block(pattern_block_block_block)
pattern_block_block.add_layer(
"prim.equal", inputs={}, outputs=[gen_name(20)], input=None)
if_layer2.add_block(pattern_block_block)
if_layer2.inputs.update({
"input-0": gen_name(13),
"input-1": gen_name(13),
"input-2": "interpolate-input-0",
"input-3": gen_name(11),
"input-5": gen_name(11),
})
pattern_block.add_layer(
"prim.equal",
inputs={"input": gen_name(20)},
outputs=[gen_name(16)])
if_layer1.add_block(pattern_block)
if_layer1.inputs.update({
"input-2": "interpolate-input-0",
"input-4": gen_name(13),
"input-7": gen_name(11),
"input-9": gen_name(11),
"input-11": "interpolate-input-0",
"input-12": "interpolate-input-0",
})
self.pattern.build(inputs={
"input-0": "interpolate-input-0",
"input-1": "interpolate-input-1"
})
def insert_new_layer(self, graph, parameters, matches):
new_layers = self.gen_new_layer(parameters, matches)
new_layer_id = list(matches.keys())[0]
graph.layers[new_layer_id] = new_layers[0]
matches.pop(new_layer_id)
new_layer_id = list(matches.keys())[0]
graph.layers[new_layer_id] = new_layers[1]
block_layer = new_layers[1].blocks[0].layers.pop(
list(new_layers[1].blocks[0].layers.keys())[-1])
new_layers[1].blocks[0].layers[new_layer_id + ".0.0"] = block_layer
matches.pop(new_layer_id)
new_layer_id = list(matches.keys())[0]
graph.layers[new_layer_id] = new_layers[2]
matches.pop(new_layer_id)
def gen_new_layer(self, parameters, matches):
layers = list()
layers_id = list(matches.keys())
layer = matches[layers_id[6]]
size = layer.inputs["input1"]
layer = matches[layers_id[92]]
layer.inputs["input"] = size
layers.append(layer)
layer = matches[layers_id[93]]
block_layer = layer.blocks[0].layers[list(layer.blocks[0].layers.keys())
[0]]
block_layer.inputs["input"] = size
block_layer.outputs[0] = size
layer.inputs["input-0"] = size
layers.append(layer)
layer = matches[layers_id[-1]]
outputs = layer.outputs
layer = matches[layers_id[96]]
layer.inputs.pop("scale_factor")
layer.inputs["size"] = size
layer.outputs = outputs
layers.append(layer)
return layers
......@@ -6,11 +6,6 @@ class BiasOpt:
self.conv_layers = [
'fluid.layers.conv2d', 'fluid.layers.conv2d_transpose'
]
self.act_layers = [
'fluid.layers.relu', 'fluid.layers.relu6', 'fluid.layers.sigmoid',
'fluid.layers.exp', 'fluid.layers.tanh', 'fluid.layers.softplus',
'fluid.layers.leaky_relu'
]
def run(self, graph):
print("Optimize: BiasOpt...")
......
......@@ -118,6 +118,6 @@ class PReLUOpt:
graph.layers[transpose0.id] = transpose0
graph.layers[prelu.id] = prelu
graph.layers[transpose1.id] = transpose1
graph.parameters[alpha.outputs[0]] = np.expand_dims(graph.parameters[alpha.outputs[0]], 0)
graph.build()
first_axis = graph.parameters[alpha.outputs[0]].shape[0]
graph.parameters[alpha.outputs[0]] = np.reshape(graph.parameters[alpha.outputs[0]], (1, first_axis, 1, 1))
graph.build()
\ No newline at end of file
......@@ -21,7 +21,6 @@ class TransposeOpt:
'fluid.layers.elementwise_add', 'fluid.layers.elementwise_sub',
'fluid.layers.elementwise_mul', 'fluid.layers.elementwise_div'
]
# self.reduce_layers = []
self.reduce_layers = [
'fluid.layers.reduce_mean', 'fluid.layers.reduce_all',
'fluid.layers.reduce_max', 'fluid.layers.reduce_any',
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册