提交 cf689f17 编写于 作者: J jiangjiajun

add tensor infer function

上级 b5fe13be
import sys
import math
val1 = map(float, open(sys.argv[1]).read().strip().split('\n'))
val2 = map(float, open(sys.argv[2]).read().strip().split('\n'))
if len(val1) != len(val2):
raise Exception("Not Same Length")
max_diff = 0
avg_diff = 0
for i in range(len(val1)):
diff = math.fabs(val1[i] - val2[i])
if diff > max_diff:
max_diff = diff
avg_diff += diff
avg_diff /= len(val1)
print("max_diff: {}\tavg_diff: {}".format(max_diff, avg_diff))
# coding:utf-8
import sys
sys.path.append("..")
from paddle_resnet_v1_101.mymodel import KitModel
import paddle.fluid as fluid
import numpy
use_cuda = True
def model_initialize():
# 构建模型结构,并初始化参数
result = KitModel()
if use_cuda:
exe = fluid.Executor(fluid.CUDAPlace(0))
else:
exe = fluid.Executor(fluid.CPUPlace())
exe.run(fluid.default_startup_program())
# 根据save_var.list列表,加载模型参数
var_list = list()
global_block = fluid.default_main_program().global_block()
with open('../paddle_resnet_v1_101/save_var.list') as f:
for line in f:
try:
# 过滤部分不需要加载的参数(OP配置参数)
var = global_block.var(line.strip())
var_list.append(var)
except:
pass
fluid.io.load_vars(exe, '../paddle_resnet_v1_101', vars=var_list)
prog = fluid.default_main_program()
return exe, prog, result
def test_case(exe, prog, result):
# 测试随机数据输入
numpy.random.seed(13)
img_data = numpy.random.rand(1000, 224, 224, 3)
# tf中输入为NHWC,PaddlePaddle则为NCHW,需transpose
img_data = numpy.transpose(img_data, (0, 3, 1, 2))
# input_0为输入数据的张量名,张量名和数据类型须与my_model.py中定义一致
for i in range(0, 50):
r, = exe.run(
fluid.default_main_program(),
feed={
'input_0':
numpy.array(img_data[i * 20:i * 20 + 20], dtype='float32')
},
fetch_list=[result])
r = r.flatten()
files = open('fluid_resnet_v1_101.result', 'a+')
for i in range(0, r.shape[0]):
files.write(str(r[i]) + '\n')
files.close()
# 调用save_inference_model可将模型结构(当前以代码形式保存)和参数均序列化保存
# 保存后的模型可使用load_inference_model加载
# http://www.paddlepaddle.org/documentation/docs/zh/1.2/api_cn/api_guides/low_level/inference.html#api-guide-inference
# fluid.io.save_inference_model("./paddle_model", ["input_0"], [result], exe)
if __name__ == "__main__":
exe, prog, result = model_initialize()
test_case(exe, prog, result)
# coding:utf-8
import sys
sys.path.append("..")
from paddle_resnet_v1_50.mymodel import KitModel
import paddle.fluid as fluid
import numpy
use_cuda = True
def model_initialize():
# 构建模型结构,并初始化参数
result = KitModel()
if use_cuda:
exe = fluid.Executor(fluid.CUDAPlace(0))
else:
exe = fluid.Executor(fluid.CPUPlace())
exe.run(fluid.default_startup_program())
# 根据save_var.list列表,加载模型参数
var_list = list()
global_block = fluid.default_main_program().global_block()
with open('../paddle_resnet_v1_50/save_var.list') as f:
for line in f:
try:
# 过滤部分不需要加载的参数(OP配置参数)
var = global_block.var(line.strip())
var_list.append(var)
except:
pass
fluid.io.load_vars(exe, '../paddle_resnet_v1_50', vars=var_list)
prog = fluid.default_main_program()
return exe, prog, result
def test_case(exe, prog, result):
# 测试随机数据输入
numpy.random.seed(13)
img_data = numpy.random.rand(1000, 224, 224, 3)
# tf中输入为NHWC,PaddlePaddle则为NCHW,需transpose
img_data = numpy.transpose(img_data, (0, 3, 1, 2))
# input_0为输入数据的张量名,张量名和数据类型须与my_model.py中定义一致
for i in range(0, 50):
r, = exe.run(
fluid.default_main_program(),
feed={
'input_0':
numpy.array(img_data[i * 20:i * 20 + 20], dtype='float32')
},
fetch_list=[result])
r = r.flatten()
files = open('fluid_resnet_v1_50.result', 'a+')
for i in range(0, r.shape[0]):
files.write(str(r[i]) + '\n')
files.close()
# 调用save_inference_model可将模型结构(当前以代码形式保存)和参数均序列化保存
# 保存后的模型可使用load_inference_model加载
# http://www.paddlepaddle.org/documentation/docs/zh/1.2/api_cn/api_guides/low_level/inference.html#api-guide-inference
# fluid.io.save_inference_model("./paddle_model", ["input_0"], [result], exe)
if __name__ == "__main__":
exe, prog, result = model_initialize()
test_case(exe, prog, result)
rm -rf fluid_vgg_19.result
python vgg_19_infer.py
echo "paddle fluid vgg_19 model"
python diff.py fluid_vgg_19.result tf_vgg_19.result
rm -rf fluid_vgg_16.result
python vgg_16_infer.py
echo "paddle fluid vgg_16 model"
python diff.py fluid_vgg_16.result tf_vgg_16.result
rm -rf fluid_resnet_v1_50.result
python resnet_v1_50_infer.py
echo "paddle fluid resnet_v1_50 model"
python diff.py fluid_resnet_v1_50.result tf_resnet_v1_50.result
rm -rf fluid_resnet_v1_101.result
python resnet_v1_101_infer.py
echo "paddle fluid resnet_v1_101 model"
python diff.py fluid_resnet_v1_101.result tf_resnet_v1_101.result
# coding:utf-8
import sys
sys.path.append("..")
from paddle_vgg_16.mymodel import KitModel
import paddle.fluid as fluid
import numpy
use_cuda = True
def model_initialize():
# 构建模型结构,并初始化参数
result = KitModel()
if use_cuda:
exe = fluid.Executor(fluid.CUDAPlace(0))
else:
exe = fluid.Executor(fluid.CPUPlace())
exe.run(fluid.default_startup_program())
# 根据save_var.list列表,加载模型参数
var_list = list()
global_block = fluid.default_main_program().global_block()
with open('../paddle_vgg_16/save_var.list') as f:
for line in f:
try:
# 过滤部分不需要加载的参数(OP配置参数)
var = global_block.var(line.strip())
var_list.append(var)
except:
pass
fluid.io.load_vars(exe, '../paddle_vgg_16', vars=var_list)
prog = fluid.default_main_program()
return exe, prog, result
def test_case(exe, prog, result):
# 测试随机数据输入
numpy.random.seed(13)
img_data = numpy.random.rand(1000, 224, 224, 3)
# tf中输入为NHWC,PaddlePaddle则为NCHW,需transpose
img_data = numpy.transpose(img_data, (0, 3, 1, 2))
# input_0为输入数据的张量名,张量名和数据类型须与my_model.py中定义一致
for i in range(0, 50):
r, = exe.run(
fluid.default_main_program(),
feed={
'input_0':
numpy.array(img_data[i * 20:i * 20 + 20], dtype='float32')
},
fetch_list=[result])
r = r.flatten()
files = open('fluid_vgg_16.result', 'a+')
for i in range(0, r.shape[0]):
files.write(str(r[i]) + '\n')
files.close()
# 调用save_inference_model可将模型结构(当前以代码形式保存)和参数均序列化保存
# 保存后的模型可使用load_inference_model加载
# http://www.paddlepaddle.org/documentation/docs/zh/1.2/api_cn/api_guides/low_level/inference.html#api-guide-inference
# fluid.io.save_inference_model("./paddle_model", ["input_0"], [result], exe)
if __name__ == "__main__":
exe, prog, result = model_initialize()
test_case(exe, prog, result)
# coding:utf-8
import sys
sys.path.append("..")
from paddle_vgg_19.mymodel import KitModel
import paddle.fluid as fluid
import numpy
use_cuda = True
def model_initialize():
# 构建模型结构,并初始化参数
result = KitModel()
if use_cuda:
exe = fluid.Executor(fluid.CUDAPlace(0))
else:
exe = fluid.Executor(fluid.CPUPlace())
exe.run(fluid.default_startup_program())
# 根据save_var.list列表,加载模型参数
var_list = list()
global_block = fluid.default_main_program().global_block()
with open('../paddle_vgg_19/save_var.list') as f:
for line in f:
try:
# 过滤部分不需要加载的参数(OP配置参数)
var = global_block.var(line.strip())
var_list.append(var)
except:
pass
fluid.io.load_vars(exe, '../paddle_vgg_19', vars=var_list)
prog = fluid.default_main_program()
return exe, prog, result
def test_case(exe, prog, result):
# 测试随机数据输入
numpy.random.seed(13)
img_data = numpy.random.rand(1000, 224, 224, 3)
# tf中输入为NHWC,PaddlePaddle则为NCHW,需transpose
img_data = numpy.transpose(img_data, (0, 3, 1, 2))
# input_0为输入数据的张量名,张量名和数据类型须与my_model.py中定义一致
for i in range(0, 50):
r, = exe.run(
fluid.default_main_program(),
feed={
'input_0':
numpy.array(img_data[i * 20:i * 20 + 20], dtype='float32')
},
fetch_list=[result])
r = r.flatten()
files = open('fluid_vgg_19.result', 'a+')
for i in range(0, r.shape[0]):
files.write(str(r[i]) + '\n')
files.close()
# 调用save_inference_model可将模型结构(当前以代码形式保存)和参数均序列化保存
# 保存后的模型可使用load_inference_model加载
# http://www.paddlepaddle.org/documentation/docs/zh/1.2/api_cn/api_guides/low_level/inference.html#api-guide-inference
# fluid.io.save_inference_model("./paddle_model", ["input_0"], [result], exe)
if __name__ == "__main__":
exe, prog, result = model_initialize()
test_case(exe, prog, result)
from tensorflow.contrib.slim.nets import inception
from tensorflow.contrib.slim.nets import vgg as vgg
from tensorflow.contrib.slim.nets import resnet_v1 as resnet_v1
import tensorflow.contrib.slim as slim
import tensorflow as tf
from six import text_type as _text_type
def inception_v3(ckpt_file):
def get_tuned_variables():
CHECKPOINT_EXCLUDE_SCOPES = 'InceptionV3/Logits,InceptionV3/AuxLogits'
exclusions = [
scope.strip() for scope in CHECKPOINT_EXCLUDE_SCOPES.split(',')
]
variables_to_restore = []
for var in slim.get_model_variables():
excluded = False
for exclusion in exclusions:
if var.op.name.startswith(exclusion):
excluded = True
break
if not excluded:
variables_to_restore.append(var)
return variables_to_restore
img_size = inception.inception_v3.default_image_size
img = tf.placeholder(
tf.float32, shape=[None, img_size, img_size, 3], name='inputs')
with slim.arg_scope(inception.inception_v3_arg_scope()):
logits, _ = inception.inception_v3(
img, num_classes=1000, is_training=False)
sess = tf.Session()
init = tf.global_variables_initializer()
sess.run(init)
load_model = tf.contrib.slim.assign_from_checkpoint_fn(
ckpt_file, get_tuned_variables(), ignore_missing_vars=True)
load_model(sess)
return sess
def resnet_v1_50(ckpt_file):
img_size = resnet_v1.resnet_v1.default_image_size
img = tf.placeholder(
tf.float32, shape=[None, img_size, img_size, 3], name='inputs')
with slim.arg_scope(resnet_v1.resnet_arg_scope()):
net, endpoint = resnet_v1.resnet_v1_50(
img, num_classes=1000, is_training=False)
sess = tf.Session()
load_model = tf.contrib.slim.assign_from_checkpoint_fn(
ckpt_file, tf.contrib.slim.get_model_variables("resnet_v1_50"))
load_model(sess)
return sess
def resnet_v1_101(ckpt_file):
img_size = resnet_v1.resnet_v1.default_image_size
img = tf.placeholder(
tf.float32, shape=[None, img_size, img_size, 3], name='inputs')
with slim.arg_scope(resnet_v1.resnet_arg_scope()):
net, endpoint = resnet_v1.resnet_v1_101(
img, num_classes=1000, is_training=False)
sess = tf.Session()
sess.run(tf.global_variables_initializer())
load_model = tf.contrib.slim.assign_from_checkpoint_fn(
ckpt_file, tf.contrib.slim.get_model_variables("resnet_v1_101"))
load_model(sess)
return sess
def vgg_16(ckpt_file):
img_size = vgg.vgg_16.default_image_size
inputs = tf.placeholder(
tf.float32, shape=[None, img_size, img_size, 3], name="inputs")
logits, endpoint = vgg.vgg_16(inputs, num_classes=1000, is_training=False)
sess = tf.Session()
load_model = tf.contrib.slim.assign_from_checkpoint_fn(
ckpt_file, tf.contrib.slim.get_model_variables("vgg_16"))
load_model(sess)
return sess
def vgg_19(ckpt_file):
img_size = vgg.vgg_19.default_image_size
inputs = tf.placeholder(
tf.float32, shape=[None, img_size, img_size, 3], name="inputs")
logits, endpoint = vgg.vgg_19(inputs, num_classes=1000, is_training=False)
sess = tf.Session()
load_model = tf.contrib.slim.assign_from_checkpoint_fn(
ckpt_file, tf.contrib.slim.get_model_variables("vgg_19"))
load_model(sess)
return sess
def save_checkpoint(sess, save_dir):
saver = tf.train.Saver()
saver.save(sess, save_dir + "/model")
def get_parser():
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"--model",
"-m",
type=_text_type,
default=None,
help="inception_v3/resnet_v1_50/resnet_v1_101/vgg_16/vgg_19")
parser.add_argument(
"--ckpt_file",
"-c",
type=_text_type,
default=None,
help="parameters ckpt file")
parser.add_argument(
"--save_dir", "-s", type=_text_type, default=None, help="model path")
return parser
if __name__ == "__main__":
parser = get_parser()
args = parser.parse_args()
sess = None
if args.model is None or args.save_dir is None or args.ckpt_file is None:
raise Exception("--model, --ckpt_file and --save_dir are needed")
if args.model == "inception_v3":
sess = inception_v3(args.ckpt_file)
elif args.model == "resnet_v1_50":
sess = resnet_v1_50(args.ckpt_file)
elif args.model == "resnet_v1_101":
sess = resnet_v1_101(args.ckpt_file)
elif args.model == "vgg_16":
sess = vgg_16(args.ckpt_file)
elif args.model == "vgg_19":
sess = vgg_19(args.ckpt_file)
else:
raise Exception(
"Only support inception_v3/resnet_v1_50/resnet_v1_101/vgg_16/vgg_19"
)
save_checkpoint(sess, args.save_dir)
export CUDA_VISIBLE_DEVICES=-1
wget http://download.tensorflow.org/models/resnet_v1_101_2016_08_28.tar.gz
tar xzvf resnet_v1_101_2016_08_28.tar.gz
python export_to_checkpoint.py --model resnet_v1_101 --ckpt_file resnet_v1_101.ckpt --save_dir resnet_v1_101_checkpoint
rm resnet_v1_101_2016_08_28.tar.gz resnet_v1_101.ckpt
tf2fluid --meta_file resnet_v1_101_checkpoint/model.meta \
--ckpt_dir resnet_v1_101_checkpoint \
--in_nodes inputs \
--input_shape None,224,224,3 \
--output_nodes resnet_v1_101/predictions/Softmax \
--save_dir paddle_resnet_v1_101
export CUDA_VISIBLE_DEVICES=-1
wget http://download.tensorflow.org/models/resnet_v1_50_2016_08_28.tar.gz
tar xzvf resnet_v1_50_2016_08_28.tar.gz
python export_to_checkpoint.py --model resnet_v1_50 --ckpt_file resnet_v1_50.ckpt --save_dir resnet_v1_50_checkpoint
rm resnet_v1_50_2016_08_28.tar.gz resnet_v1_50.ckpt
tf2fluid --meta_file resnet_v1_50_checkpoint/model.meta \
--ckpt_dir resnet_v1_50_checkpoint \
--in_nodes inputs \
--input_shape None,224,224,3 \
--output_nodes resnet_v1_50/predictions/Softmax \
--save_dir paddle_resnet_v1_50
export CUDA_VISIBLE_DEVICES=-1
wget http://download.tensorflow.org/models/vgg_16_2016_08_28.tar.gz
tar xzvf vgg_16_2016_08_28.tar.gz
python export_to_checkpoint.py --model vgg_16 --ckpt_file vgg_16.ckpt --save_dir vgg_16_checkpoint
rm vgg_16_2016_08_28.tar.gz vgg_16.ckpt
tf2fluid --meta_file vgg_16_checkpoint/model.meta \
--ckpt_dir vgg_16_checkpoint \
--in_nodes inputs \
--input_shape None,224,224,3 \
--output_nodes vgg_16/fc8/squeezed \
--save_dir paddle_vgg_16
export CUDA_VISIBLE_DEVICES=-1
wget http://download.tensorflow.org/models/vgg_19_2016_08_28.tar.gz
tar xzvf vgg_19_2016_08_28.tar.gz
python export_to_checkpoint.py --model vgg_19 --ckpt_file vgg_19.ckpt --save_dir vgg_19_checkpoint
rm vgg_19_2016_08_28.tar.gz vgg_19.ckpt
tf2fluid --meta_file vgg_19_checkpoint/model.meta \
--ckpt_dir vgg_19_checkpoint \
--in_nodes inputs \
--input_shape None,224,224,3 \
--output_nodes vgg_19/fc8/squeezed \
--save_dir paddle_vgg_19
from __future__ import absolute_import
from setuptools import setup, find_packages
from io import open
setup(
name='tensorflow2fluid',
version='0.0.1',
description='Translate TensorFlow Model to PaddlePaddle',
url='http://paddlepaddle.org',
author = 'PaddlePaddle Development Group',
author_email='paddle-dev@baidu.com',
license='Apache 2',
packages=find_packages(),
install_requires=[],
entry_points={
'console_scripts': [
'tf2fluid = src.convert:_main',
],
},
)
# 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 paddle_emitter import PaddleEmitter
from tensorflow_parser import TensorflowCkptParser
from tensorflow_parser import TensorflowPbParser
from six import text_type as _text_type
from utils import *
import argparse
import sys
import logging
import os
logging.basicConfig(level=logging.DEBUG)
def _get_parser():
parser = argparse.ArgumentParser()
parser.add_argument("--meta_file", "-m", type=_text_type, default=None, help="meta file path for checkpoint format")
parser.add_argument("--ckpt_dir", "-c", type=_text_type, default=None, help="checkpoint directory")
parser.add_argument("--pb_file", "-p", type=_text_type, default=None, help="pb model file path")
parser.add_argument("--in_nodes", "-i", type=_text_type, nargs="+", default=None, help="input nodes name")
parser.add_argument("--input_shape", "-is", type=_text_type, nargs="+", default=None, help="input tensor shape")
parser.add_argument("--output_nodes", "-o", type=_text_type, nargs="+", default=None, help="output nodes name")
parser.add_argument("--save_dir", "-s", type=_text_type, default=None, help="path to save transformed paddle model")
parser.add_argument("--version", "-v", action="version", version="tensorflow2fluid version=0.0.1 Release @2019.01.28")
parser.add_argument("--meta_file", "-m", type=_text_type,
default=None, help="meta file path for checkpoint format")
parser.add_argument("--ckpt_dir", "-c", type=_text_type,
default=None, help="checkpoint directory")
parser.add_argument("--pb_file", "-p", type=_text_type,
default=None, help="pb model file path")
parser.add_argument("--in_nodes", "-i", type=_text_type, nargs="+",
default=None, help="input nodes name")
parser.add_argument("--input_shape", "-is", type=_text_type, nargs="+",
default=None, help="input tensor shape")
parser.add_argument("--output_nodes", "-o", type=_text_type, nargs="+",
default=None, help="output nodes name")
parser.add_argument("--save_dir", "-s", type=_text_type,
default=None, help="path to save transformed paddle model")
parser.add_argument("--input_format", "-sf", type=_text_type,
default=None, help="input data format(NHWC/NCHW or OTHER)")
parser.add_argument("--use_cuda", "-u", type=_text_type,
default="True", help="True for use gpu")
return parser
def _convert(args):
if args.meta_file is None and args.pb_file is None:
raise Exception("Need to define --meta_file or --pb_file")
if args.input_format is None:
raise Exception("Input format need to be defined(NHWC, NCHW or OTHER)")
assert args.use_cuda == "True" or args.use_cuda == "False"
if args.use_cuda == "False":
os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
if args.input_format == "NHWC":
input_format = NHWC
elif args.input_format == "NCHW":
input_format = NCHW
elif args.input_format == "OTHER":
input_format = OTHER
else:
raise Exception("Can not identify input format(NHWC/NCHW/OTHER)")
assert args.in_nodes is not None
assert args.output_nodes is not None
assert args.input_shape is not None
assert args.save_dir is not None
if os.path.exists(args.save_dir):
sys.stderr.write("save_dir already exists, change to a new path\n")
return
if not os.path.exists(args.save_dir):
os.makedirs(args.save_dir)
input_shape = list()
......@@ -43,19 +81,21 @@ def _convert(args):
input_shape.append(items)
sys.stderr.write("\nLoading tensorflow model......\n")
logging.info("Loading tensorflow model...")
if args.meta_file is not None:
parser = TensorflowCkptParser(args.meta_file, args.ckpt_dir, args.output_nodes, input_shape, args.in_nodes)
parser = TensorflowCkptParser(args.meta_file, args.ckpt_dir,
args.output_nodes, input_shape, args.in_nodes, input_format)
else:
parser = TensorflowPbParser(args.pb_file, args.output_nodes, input_shape, args.in_nodes)
sys.stderr.write("Tensorflow model loaded!\n")
parser = TensorflowPbParser(args.pb_file, args.output_nodes,
input_shape, args.in_nodes, input_format)
logging.info("Tensorflow model loaded!")
emitter = PaddleEmitter(parser, args.save_dir)
emitter.run()
open(args.save_dir+"/__init__.py", "w").close()
def _main():
os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
parser = _get_parser()
args = parser.parse_args()
_convert(args)
......
......@@ -12,16 +12,21 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from name_generator import NameGenerator
from utils import *
import collections
class GraphNode(object):
def __init__(self, layer):
def __init__(self, layer, layer_name=None):
self.inputs = list()
self.outputs = list()
self.layer = layer
self.ref_name = None
self.output_name = None
if layer_name is not None:
self.layer_name = layer_name
else:
self.layer_name = layer.name
def __hash__(self):
return hash(self.layer.name)
......@@ -34,14 +39,14 @@ class GraphNode(object):
class Graph(object):
def __init__(self, model):
self.node_map = dict()
self.node_map = collections.OrderedDict()
self.input_nodes = list()
self.output_nodes = list()
self.topological_sort = list()
self.model = model
self.name_generator = NameGenerator()
def build(self):
def build(self, input_format):
self._make_input_nodes()
self._make_output_nodes()
self._get_topological_sort()
......@@ -78,9 +83,26 @@ class Graph(object):
for node_name in self.topological_sort:
node = self.node_map[node_name]
ref_name = self.name_generator.get_name(node)
if node.layer_type == 'split' or node.layer_type == 'splitv':
index = '0'
if len(node_name.split(':')) == 2:
index = node_name.split(':')[-1]
ref_name += '[{}]'.format(index)
self.node_map[node.layer.name].ref_name = ref_name
self.node_map[node.layer.name].output_name = ref_name.split('[')[0]
for node_name, node in self.node_map.items():
ref_name = self.name_generator.get_name(node)
if node.layer_type == 'split' or node.layer_type == 'splitv':
index = '0'
if len(node_name.split(':')) == 2:
index = node_name.split(':')[-1]
ref_name += '[{}]'.format(index)
self.node_map[node_name].ref_name = ref_name
self.node_map[node_name].output_name = ref_name.split('[')[0]
def get_node(self, name):
if name not in self.node_map:
raise Exception("Graph doesn't have node [%s]." % name)
......@@ -88,9 +110,8 @@ class Graph(object):
return self.node_map[name]
def _make_connection(self, src, dst):
if src.layer_name == dst.layer_name or src.layer_name not in self.node_map or dst.layer_name not in self.node_map:
if src.layer_name == dst.layer_name or src.layer_name not in \
self.node_map or dst.layer_name not in self.node_map:
raise Exception('Warning: Node not exist or there is a self-loop')
if src not in self.node_map[dst.layer_name].inputs:
self.node_map[dst.layer_name].inputs.append(src)
if dst not in self.node_map[src.layer_name].outputs:
self.node_map[src.layer_name].outputs.append(dst)
......@@ -14,21 +14,35 @@
from graph import GraphNode, Graph
from tensorflow.core.framework import attr_value_pb2
from utils import *
class TensorflowGraphNode(GraphNode):
def __init__(self, layer):
super(TensorflowGraphNode, self).__init__(layer)
dtype_map = {1: "float32", 3: "int32", 9: "int64"}
def __init__(self, layer, input_format, layer_name=None):
super(TensorflowGraphNode, self).__init__(layer, layer_name)
self.codes = list()
self.data_format = 'NCHW'
self.code = FluidCode()
self.ref_as_const = 0
self.data_format = input_format
@property
def layer_type(self):
return self.layer.op.lower()
@property
def layer_name(self):
return self.layer.name
def shape_dim_size(self):
shape = self.layer.attr['_output_shapes']
return len(shape.list.shape[0].dim)
@property
def dtype(self):
dtype = self.get_attr("dtype")
if dtype in self.dtype_map:
dtype = self.dtype_map[dtype]
else:
raise Exception("Unknow dtype: {}".format(dtype))
return dtype
def get_attr(self, name, default_value=None):
if name in self.layer.attr:
......@@ -36,33 +50,62 @@ class TensorflowGraphNode(GraphNode):
field = attr.WhichOneof('value')
val = getattr(attr, field) if field else default_value
if isinstance(val, attr_value_pb2.AttrValue.ListValue):
return list(val.ListFields()[0][1])
result = list(val.ListFields()[0][1])
for i in range(len(result)):
if isinstance(result[i], int):
result[i] = int(result[i])
try:
if isinstance(result[i], long):
result[i] = int(result[i])
except:
pass
return result
else:
return val.decode('utf-8') if isinstance(val, bytes) else val
return val if isinstance(val, bytes) else val
else:
return default_value
def clear_code(self):
self.code.clear()
class TensorflowGraph(Graph):
useless_type = [
'identity',
'placeholderwithdefault',
'switch',
'merge'
]
def __init__(self, tf_graph):
super(TensorflowGraph, self).__init__(tf_graph)
self.tf_graph = tf_graph
def build(self):
def build(self, input_format):
skip_node = set(['const'])
for i, layer in enumerate(self.tf_graph.node):
self.node_map[layer.name] = TensorflowGraphNode(layer)
self.node_map[layer.name] = TensorflowGraphNode(layer, input_format)
for i, layer in enumerate(self.tf_graph.node):
if layer.op.lower() in skip_node:
continue
for pred in layer.input:
if pred not in self.node_map and pred.split(
':')[0] in self.node_map:
node = self.node_map[pred.split(':')[0]]
if node.layer_type == "switch":
self._make_connection(node, self.node_map[layer.name])
pred_node = self.node_map[pred.split(':')[0]]
if pred_node.layer_type == "switch":
self._make_connection(pred_node,
self.node_map[layer.name])
elif pred_node.layer_type == "split" or \
pred_node.layer_type == "splitv":
self.node_map[pred] = TensorflowGraphNode(
pred_node.layer, input_format, pred)
self._make_connection(self.node_map[pred],
self.node_map[layer.name])
self._make_connection(pred_node, self.node_map[pred])
else:
raise Exception("Need to fix here")
raise Exception("Unsupported situation(name:[{}], \
OP[{}])".format(node.layer_name, node.layer_type))
elif pred in self.node_map:
self._make_connection(self.node_map[pred],
......@@ -70,38 +113,26 @@ class TensorflowGraph(Graph):
else:
raise Exception("input: {} not in node_map".format(pred))
super(TensorflowGraph, self).build()
super(TensorflowGraph, self).build(input_format)
self._remove_useless_nodes()
self._check_dataformat()
self._process_useless_nodes()
self._check_dataformat(input_format)
def _check_dataformat(self):
ss = list()
for i in range(0, len(self.topological_sort)):
def _check_dataformat(self, input_format):
for i in range(len(self.topological_sort)):
current_node = self.node_map[self.topological_sort[i]]
if 'data_format' in current_node.layer.attr:
if 'data_format'.encode() in current_node.layer.attr:
s = current_node.layer.attr['data_format'].s
if s != 'NHWC' and s != 'NCHW':
if s != NHWC and s != NCHW:
raise Exception('Unkown dataformat {}'.format(s))
ss.append(s)
if len(set(ss)) > 1:
raise Exception("Two type of dataformat exist in this model")
if len(set(ss)) == 0:
return
self.set_data_format(current_node, s)
for k, v in self.node_map.items():
self.node_map[k].data_format = ss[0]
def _remove_useless_nodes(self):
useless_type = set(
['identity', 'placeholderwithdefault', 'switch', 'merge'])
def _process_useless_nodes(self):
remove_index = list()
for i in range(0, len(self.topological_sort)):
for i in range(len(self.topological_sort)):
name = self.topological_sort[i]
current_node = self.node_map[name]
if current_node.layer_type in useless_type:
if current_node.layer_type in self.useless_type:
input = current_node.inputs[0]
for node in current_node.outputs:
for k in range(0, len(node.inputs)):
......@@ -118,5 +149,15 @@ class TensorflowGraph(Graph):
remove_index.append(i)
remove_index.sort(reverse=True)
for i in range(0, len(remove_index)):
for i in range(len(remove_index)):
del self.topological_sort[remove_index[i]]
def set_data_format(self, node, data_format):
assert data_format == 'NHWC'.encode() or data_format == 'NCHW'.encode()
if node.data_format == data_format:
return
node.data_format = data_format
if len(node.outputs) == 0:
return
for output in node.outputs:
self.set_data_format(output, data_format)
......@@ -12,11 +12,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import tensorflow
import tensorflow as tf
from tensorflow_graph import TensorflowGraph
from tensorflow.python.framework import tensor_util
from tensorflow.python.tools import strip_unused_lib
from tensorflow.python.framework import dtypes
import numpy
class TensorflowCkptParser(object):
def __init__(self,
......@@ -24,24 +25,25 @@ class TensorflowCkptParser(object):
checkpoint_file,
dest_nodes,
input_shape=None,
in_nodes=None):
in_nodes=None,
input_format="NCHW".encode()):
graph_def = None
self.weights = None
with tensorflow.Session() as sess:
sess = tf.Session()
if meta_file is None:
raise Exception("meta_file must be provided")
new_saver = tensorflow.train.import_meta_graph(meta_file)
new_saver = tf.train.import_meta_graph(meta_file)
if checkpoint_file is not None:
self.weights = dict()
new_saver.restore(
sess, tensorflow.train.latest_checkpoint(checkpoint_file))
for var in tensorflow.global_variables():
sess, tf.train.latest_checkpoint(checkpoint_file))
for var in tf.global_variables():
value = var.eval(sess)
self.weights[var.name.split(':')[0]] = value
graph_def, ver = tensorflow.get_default_graph()._as_graph_def(
self.infer = ModelInfer(sess)
graph_def, ver = tf.get_default_graph()._as_graph_def(
add_shapes=True)
# self.sess = sess
if in_nodes is not None and input_shape is not None:
graph_def = strip_unused_lib.strip_unused(
......@@ -50,23 +52,34 @@ class TensorflowCkptParser(object):
output_node_names=dest_nodes,
placeholder_type_enum=dtypes.float32.as_datatype_enum)
for node in graph_def.node:
if node.name in in_nodes:
index = in_nodes.index(node.name)
shape = [tf.Dimension(x) for x in input_shape[index]]
shape_proto = tf.TensorShape(shape).as_proto()
node.attr['_output_shapes'].list.shape.pop()
node.attr['_output_shapes'].list.shape.extend([shape_proto])
self.infer.gen_sample_data(node.name, input_shape[index])
self.tf_graph = TensorflowGraph(graph_def)
else:
raise Exception('in_nodes and output_nodes need be provided')
self.tf_graph.build()
self.tf_graph.build(input_format)
class TensorflowPbParser(object):
def __init__(self, pb_file, dest_nodes, input_shape=None, in_nodes=None):
with open(pb_file) as f:
def __init__(self, pb_file, dest_nodes, input_shape=None,
in_nodes=None, input_format="NCHW".encode()):
with open(pb_file, 'rb') as f:
serialized = f.read()
tensorflow.reset_default_graph()
original_graph_def = tensorflow.GraphDef()
tf.reset_default_graph()
original_graph_def = tf.GraphDef()
original_graph_def.ParseFromString(serialized)
# tensorflow.import_graph_def(origin_graph_def, name="")
# self.sess = tensorflow.Session(graph=tf.get_default_graph())
# self.sess.run(tensorflow.global_variables_initializer())
sess = tf.Session(graph=tf.get_default_graph())
sess.run(tf.global_variables_initializer())
self.infer = ModelInfer(sess)
original_graph_def = strip_unused_lib.strip_unused(
input_graph_def=original_graph_def,
......@@ -74,7 +87,7 @@ class TensorflowPbParser(object):
output_node_names=dest_nodes,
placeholder_type_enum=dtypes.float32.as_datatype_enum)
graph_def = tensorflow.GraphDef()
graph_def = tf.GraphDef()
graph_def.ParseFromString(original_graph_def.SerializeToString())
in_type_list = dict()
for node in graph_def.node:
......@@ -89,23 +102,23 @@ class TensorflowPbParser(object):
for i in range(len(input_shape)):
if in_type_list[in_nodes[i]] == 1 or in_type_list[
in_nodes[i]] == 0:
dtype = tensorflow.float32
x = tensorflow.placeholder(dtype, shape=input_shape[i])
dtype = tf.float32
x = tf.placeholder(dtype, shape=input_shape[i])
elif in_type_list[in_nodes[i]] == 3:
dtype = tensorflow.int32
x = tensorflow.placehoder(dtype, shape=input_shape[i])
dtype = tf.int32
x = tf.placehoder(dtype, shape=input_shape[i])
else:
raise Exception(
"Unexpected dtype for input, only support float32 and int32 now"
)
raise Exception("Unexpected dtype for input, only support " \
"float32 and int32 now")
input_map[in_nodes[i] + ":0"] = x
self.infer.gen_sample_data(x.name, input_shape[i])
tensorflow.import_graph_def(graph_def, name="", input_map=input_map)
graph_def = tensorflow.get_default_graph()._as_graph_def(
tf.import_graph_def(graph_def, name="", input_map=input_map)
graph_def = tf.get_default_graph()._as_graph_def(
add_shapes=True)[0]
node = graph_def.node[0]
self.tf_graph = TensorflowGraph(graph_def)
self.tf_graph.build()
self.tf_graph.build(input_format)
self.weights = dict()
for node in graph_def.node:
......@@ -116,3 +129,136 @@ class TensorflowPbParser(object):
self.weights[node.name] = weight
except:
continue
class ModelInfer(object):
""" Trick method for tensorflow2fluid
There are some Operators in PaddlePaddle not support
tensor as parameter, like reshape/transpose, Because these
parameters should be fixed in PaddlePaddle. So we
provide 'ModelInfer' here to solove this problem.
"""
def __init__(self, sess):
self.sess = sess
self.inputs_sample_data = dict()
def gen_sample_data(self, tensor_name, shape):
self.inputs_sample_data[tensor_name] = list()
if shape[0] is None or shape[0] < 0:
for i in range(1, 4):
data = numpy.random.random_sample([i] + shape[1:])
self.inputs_sample_data[tensor_name].append(data)
else:
for i in range(1, 4):
data = numpy.random.random_sample(shape)
self.inputs_sample_data[tensor_name].append(data)
def get_shape_tensor(self, layer, output_shape=None):
""" return value of shape parameter
return value of shape parameter which are tensor type
in tensorflow model
"""
tensor_name = layer.name
if len(tensor_name.split(':')) < 2:
tensor_name = tensor_name + ':0'
output_tensor = self.sess.graph.get_tensor_by_name(tensor_name)
tensor_values = []
for i in range(0, 3):
inputs_tensors = dict()
for name, values in self.inputs_sample_data.items():
if len(name.split(':')) < 2:
name = name + ':0'
tensor = self.sess.graph.get_tensor_by_name(name)
inputs_tensors[tensor] = values[i]
r, = self.sess.run([output_tensor], inputs_tensors)
tensor_values.append(r.flatten())
compare01 = (tensor_values[0] == tensor_values[1])
compare12 = (tensor_values[1] == tensor_values[2])
if compare01.all() and compare12.all():
return tensor_values[0]
if (compare01 == compare12).all():
index = numpy.argwhere(compare01==False).flatten()
if index.shape[0] != 1:
raise Exception("There's not only one unstable dimension")
tensor_values[0][index[0]] = -1
index = numpy.argwhere(tensor_values[0] < 0).flatten()
if index.shape[0] > 2:
raise Exception("There's more than two values less than zero")
if index.shape[0] == 2:
if output_shape is None:
raise Exception("Need output_shape parameter, " \
"get_shape_tensor(tensor_name, output_shape)")
tensor_values[0][index[1]] = output_shape[index[1]]
return tensor_values[0]
else:
raise Exception("Can not infer a stable shape tensor value")
def get_tensor_shape(self, layer):
shape = layer.attr['_output_shapes'].list.shape[0]
shape = numpy.array([dim.size for dim in shape.dim])
if numpy.argwhere(shape<0).shape[0] <= 1:
return shape
tensor_name = layer.name
if len(tensor_name.split(':')) < 2:
tensor_name = tensor_name + ':0'
output_tensor = self.sess.graph.get_tensor_by_name(tensor_name)
shapes = []
for i in range(0, 3):
inputs_tensors = dict()
for name, values in self.inputs_sample_data.items():
if len(name.split(':')) < 2:
name = name + ':0'
tensor = self.sess.graph.get_tensor_by_name(name)
inputs_tensors[tensor] = values[i]
r, = self.sess.run([output_tensor], inputs_tensors)
shapes.append(numpy.array(r.shape))
compare01 = (shapes[0] == shapes[1])
compare12 = (shapes[1] == shapes[2])
if compare01.all() and compare12.all():
return shapes[0]
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]
else:
raise Exception("Can not infer a stable tensor shape, failed!")
def get_const_tensor_value(self, layer):
tensor_name = layer.name
if len(tensor_name.split(':')) < 2:
tensor_name = tensor_name + ':0'
output_tensor = self.sess.graph.get_tensor_by_name(tensor_name)
result = []
for i in range(0, 3):
inputs_tensors = dict()
for name, values in self.inputs_sample_data.items():
if len(name.split(':')) < 2:
name = name + ':0'
tensor = self.sess.graph.get_tensor_by_name(name)
inputs_tensors[tensor] = values[i]
r, = self.sess.run([output_tensor], inputs_tensors)
result.append(r)
compare01 = (result[0] == result[1])
compare12 = (result[1] == result[2])
if compare01.all() and compare12.all():
return result[0]
else:
raise Exception("Can not infer a stable constant tensor value")
from paddle_emitter import PaddleEmitter
from tensorflow_parser import TensorflowCkptParser
from tensorflow_parser import TensorflowPbParser
class Transformer(object):
def __init__(self, meta_file, ckpt_file, out_nodes, in_shape, in_nodes, save_dir):
self.parser = TensorflowCkptParser(meta_file, ckpt_file, out_nodes,
in_shape, in_nodes)
self.emitter = PaddleEmitter(self.parser, save_dir)
def transform_code(self):
codes = self.emitter.run()
def run(self):
self.transform_code()
class PbTransformer(object):
def __init__(self, pb_file, out_nodes, in_shape, in_nodes, save_dir):
self.parser = TensorflowPbParser(pb_file, out_nodes, in_shape, in_nodes)
self.emitter = PaddleEmitter(self.parser, save_dir)
node = self.parser.tf_graph.tf_graph.node[0]
def transform_code(self):
codes = self.emitter.run()
def run(self):
self.transform_code()
# 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.
NHWC = 'NHWC'.encode()
NCHW = 'NCHW'.encode()
OTHER = 'OTHER'.encode()
SAME = 'SAME'.encode()
VALID = 'VALID'.encode()
class NameGenerator(object):
def __init__(self):
self.param_index = 0
self.input_index = 0
self.net_index = 0
self.const_index = 0
self.names = dict()
def get_name(self, node):
ref_name = None
op_name = node.layer_type
if node.layer.name in self.names:
return self.names[node.layer.name]
if op_name == "variablev2":
ref_name = "param_" + str(self.param_index)
self.param_index += 1
elif op_name == "placeholder":
ref_name = "input_" + str(self.input_index)
self.input_index += 1
elif op_name == "const":
ref_name = "const_" + str(self.const_index)
self.const_index += 1
elif op_name.lower() == "identity":
ref_name = self.names[node.layer.input[0]]
else:
ref_name = "net_" + str(self.net_index)
self.net_index += 1
self.names[node.layer.name] = ref_name
return ref_name
class LayerCode(object):
def __init__(self):
self.op = None
self.param_attr = dict()
self.input = None
self.output = None
self.str_code = None
def get_str_code(self):
if self.str_code is not None:
return self.str_code
layer_code0 = ""
if self.output is not None:
layer_code0 = layer_code0 + self.output + " = "
layer_code0 += "layers."
layer_code1 = self.op + "("
if self.input is not None:
layer_code1 = layer_code1 + self.input + ", "
layer_code2 = ""
for k, v in self.param_attr.items():
layer_code2 = layer_code2 + k + "=" + "{}".format(v) + ", "
layer_code2 = layer_code2.strip(", ")
layer_code = (layer_code0 + layer_code1 + layer_code2).strip(", ") + ")"
return layer_code
class FluidCode(object):
def __init__(self):
self.codes = list()
def add_layer(self, op, input, output, param_attr=None):
if param_attr is None:
param_attr = dict()
layer_code = LayerCode()
layer_code.op = op
layer_code.input = input
layer_code.output = output
layer_code.param_attr = param_attr
self.codes.append(layer_code)
def add_str(self, str_code):
layer_code = LayerCode()
layer_code.str_code = str_code
self.codes.append(layer_code)
def clear(self):
self.codes = list()
def gen_codes(self):
res = list()
if len(self.codes) == 0:
return []
for code in self.codes:
if isinstance(code, LayerCode):
res.append(code.get_str_code())
else:
raise Exception("Unexcept situation!")
return res
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册