未验证 提交 853731b8 编写于 作者: J Jason 提交者: GitHub

Merge pull request #294 from mamingjie-China/develop

remove infer when converting TF model
......@@ -95,8 +95,9 @@ class TFOpMapperNHWC(OpMapper):
func = getattr(self, op)
try:
func(node)
except:
except Exception as e:
unsupported_ops.add(op)
print(e)
else:
unsupported_ops.add(op)
if len(unsupported_ops) > 0:
......@@ -147,89 +148,7 @@ class TFOpMapperNHWC(OpMapper):
op_type = self.elementwise_ops[node.layer_type]
x = self.graph.get_node(node.layer.input[0], copy=True)
y = self.graph.get_node(node.layer.input[1], copy=True)
x_shape = x.out_shapes[0]
y_shape = y.out_shapes[0]
if len(x_shape) == 0:
x_shape = [1]
if len(y_shape) == 0:
y_shape = [1]
# incomplement broadcasting support for paddle
x_input = x
y_input = y
if len(x_shape) < len(y_shape):
unrevertable_ops = [
"elementwise_sub", "elementwise_div", "elementwise_floordiv",
"elementwise_mod", "elementwise_pow"
]
if op_type not in unrevertable_ops:
x_input = y
y_input = x
x_shape = y.out_shapes[0]
if len(x_shape) == 0:
x_shape = [1]
y_shape = x.out_shapes[0]
if len(y_shape) == 0:
y_shape = [1]
else:
raise Exception("Unexpected situation happend")
if len(x_shape) == 4 and len(y_shape) == 1:
inputs = {"x": x_input, "y": y_input}
node.fluid_code.add_layer(op_type, inputs=inputs, output=node)
return
is_sub_seq = True
for i in range(len(y_shape)):
index = -1 * i - 1
if y_shape[index] != x_shape[index]:
is_sub_seq = False
if not is_sub_seq:
x_expand_times = [1] * len(x_shape)
y_expand_times = [1] * len(y_shape)
x_need_expand = False
y_need_expand = False
for i in range(len(y_shape)):
index = -1 * i - 1
if y_shape[index] != x_shape[index]:
if y_shape[index] == 1:
y_expand_times[index] = x_shape[index]
y_need_expand = True
elif x_shape[index] == 1:
x_expand_times[index] = y_shape[index]
x_need_expand = True
else:
raise Exception("Unexpected situation happend")
if x_need_expand:
attr = {"expand_times": x_expand_times}
node.fluid_code.add_layer(
"expand", inputs=x_input, output="x_tmp", param_attr=attr)
x_input = "x_tmp"
if y_need_expand:
attr = {"expand_times": y_expand_times}
node.fluid_code.add_layer(
"expand", inputs=y_input, output="y_tmp", param_attr=attr)
y_input = "y_tmp"
if len(x_shape) == 4 and len(y_shape) == 4:
node.fluid_code.add_layer(
"transpose",
inputs=x_input,
output=x_input,
param_attr={'perm': [0, 3, 1, 2]})
node.fluid_code.add_layer(
"transpose",
inputs=y_input,
output=y_input,
param_attr={'perm': [0, 3, 1, 2]})
inputs = {"x": x_input, "y": y_input}
node.fluid_code.add_layer(
op_type, inputs=inputs, output=node, param_attr=None)
node.fluid_code.add_layer(
"transpose",
inputs=node,
output=node,
param_attr={'perm': [0, 2, 3, 1]})
else:
inputs = {"x": x_input, "y": y_input}
inputs = {"x": x, "y": y}
node.fluid_code.add_layer(
op_type, inputs=inputs, output=node, param_attr=None)
......@@ -286,10 +205,6 @@ class TFOpMapperNHWC(OpMapper):
def MaxPool(self, node):
input = self.graph.get_node(node.layer.input[0], copy=True)
in_shape = input.out_shapes[0]
if in_shape.count(-1) > 2:
in_shape = self.decoder.infer_tensor(input).shape
k_size = node.get_attr("ksize")
strides = node.get_attr("strides")
data_format = node.get_attr("data_format").decode()
......@@ -300,7 +215,6 @@ class TFOpMapperNHWC(OpMapper):
attr = {"perm": [0, 3, 1, 2]}
node.fluid_code.add_layer(
"transpose", inputs=input, output=node, param_attr=attr)
in_shape = [in_shape[i] for i in [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 = node
......@@ -322,15 +236,8 @@ class TFOpMapperNHWC(OpMapper):
def Conv2D(self, node):
input = self.graph.get_node(node.layer.input[0], copy=True)
kernel = self.graph.get_node(node.layer.input[1], copy=True)
self.add_omit_nodes(kernel.layer_name, node.layer_name)
in_shape = input.out_shapes[0]
if in_shape.count(-1) > 2:
in_shape = self.decoder.infer_tensor(input).shape
k_size = kernel.out_shapes[0]
if k_size.count(-1) > 2:
k_size = self.decoder.infer_tensor(kernel).shape
strides = node.get_attr("strides")
dilations = node.get_attr("dilations")
data_format = node.get_attr("data_format").decode()
......@@ -338,14 +245,12 @@ class TFOpMapperNHWC(OpMapper):
channel_first = data_format == "NCHW"
if kernel.layer_type == 'Const':
self.add_omit_nodes(kernel.layer_name, node.layer_name)
kernel_value = kernel.value
else:
kernel_value = self.decoder.infer_tensor(kernel)
self.weights[kernel.layer_name.replace('/', '_')] = numpy.transpose(
kernel_value, (3, 2, 0, 1))
if not channel_first:
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]]
attr = {"perm": [0, 3, 1, 2]}
......@@ -366,7 +271,6 @@ class TFOpMapperNHWC(OpMapper):
if hasattr(node, 'dilation') and attr['dilation'] == [1, 1]:
if len(node.dilation) == 1:
attr['dilation'] = [1, node.dilation[0]]
node.fluid_code.add_layer(
"conv2d", inputs=input, output=node, param_attr=attr)
if not channel_first:
......@@ -429,12 +333,7 @@ class TFOpMapperNHWC(OpMapper):
self.add_omit_nodes(kernel.layer_name, node.layer_name)
in_shape = input.out_shapes[0]
if in_shape.count(-1) > 2:
in_shape = self.decoder.infer_tensor(input).shape
k_size = kernel.out_shapes[0]
if k_size.count(-1) > 2:
k_size = self.decoder.infer_tensor(kernel).shape
strides = node.get_attr("strides")
dilations = node.get_attr("dilations")
data_format = node.get_attr("data_format").decode()
......@@ -475,61 +374,25 @@ class TFOpMapperNHWC(OpMapper):
def Reshape(self, node):
input = self.graph.get_node(node.layer.input[0], copy=True)
param = self.graph.get_node(node.layer.input[1], copy=True)
is_variable = False
if param.layer_type == "Const":
attr = {"shape": param.value.tolist()}
self.add_omit_nodes(param.layer_name, node.layer_name)
shape = param.value.tolist()
else:
# Here is a trick method to solove tensor parameter in tensorflow
shape = self.decoder.infer_shape_tensor(param, node.out_shapes[0])
if shape.count(-1) <= 1:
attr = {"shape": shape}
self.add_omit_nodes(param.layer_name, node.layer_name)
else:
assert len(param.out_shapes[
0]) == 1, "Unexpected situation of shape parameter"
attr = {"shape": [-1]}
shape = param
inputs = {"x": input, "shape": shape}
node.fluid_code.add_layer(
"reshape",
inputs=param,
output="shape_param",
param_attr=attr)
attr = {"num_or_sections": param.out_shapes[0][0], "dim": 0}
node.fluid_code.add_layer(
"split", inputs="shape_param", output=node, param_attr=attr)
new_param = "["
for i in range(param.out_shapes[0][0]):
new_param += (node.layer_name + "[{}]".format(i) + ", ")
new_param = new_param.strip(", ") + "]"
attr = {"shape": new_param}
is_variable = True
# to change [192, -1]->[-1, 192], allways put -1 in the first dimension
# optimization for Paddle-Lite
in_shape = input.out_shapes[0]
if not is_variable and in_shape.count(-1) < 1:
total_size = 1
for i in range(len(in_shape)):
total_size *= in_shape[i]
for i in range(len(attr["shape"])):
if attr["shape"][i] == 0:
attr["shape"][i] = in_shape[i]
if attr["shape"][i] != -1:
total_size /= attr["shape"][i]
if attr["shape"].count(-1) > 0:
index = attr["shape"].index(-1)
attr["shape"][index] = int(total_size)
attr["shape"][0] = -1
node.fluid_code.add_layer(
"reshape", inputs=input, output=node, param_attr=attr)
"reshape", inputs=inputs, output=node, param_attr=None)
if param.layer_type != "Const":
out_shape = numpy.array(node.out_shapes[0])
if (out_shape > 0).any():
out_shape[out_shape < 0] = 0
attr = {'shape': out_shape.tolist()}
node.fluid_code.add_layer(
"reshape", inputs=node, output=node, param_attr=attr)
def AvgPool(self, node):
input = self.graph.get_node(node.layer.input[0], copy=True)
in_shape = input.out_shapes[0]
if in_shape.count(-1) > 2:
in_shape = self.decoder.infer_tensor(input).shape
k_size = node.get_attr("ksize")
strides = node.get_attr("strides")
data_format = node.get_attr("data_format").decode()
......@@ -537,7 +400,6 @@ class TFOpMapperNHWC(OpMapper):
channel_first = data_format == "NCHW"
if not channel_first:
in_shape = [in_shape[i] for i in [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]]
attr = {"perm": [0, 3, 1, 2]}
......@@ -586,7 +448,6 @@ class TFOpMapperNHWC(OpMapper):
axis = axis.value
if axis < 0:
axis += len(inputs[0].out_shapes[0])
attr = {"axis": axis}
node.fluid_code.add_layer(
"concat", inputs=inputs, output=node, param_attr=attr)
......@@ -594,25 +455,38 @@ class TFOpMapperNHWC(OpMapper):
def Tile(self, node):
input = self.graph.get_node(node.layer.input[0], copy=True)
expand_times = self.graph.get_node(node.layer.input[1], copy=True)
self.add_omit_nodes(expand_times.layer_name, node.layer_name)
if expand_times.layer_type == "Const":
self.add_omit_nodes(expand_times.layer_name, node.layer_name)
expand_times = expand_times.value.tolist()
else:
expand_times = self.decoder.infer_shape_tensor(expand_times)
for i in range(len(expand_times)):
if expand_times[i] < 0:
expand_times[i] = 1
attr = {"expand_times": expand_times}
expand_times = expand_times
inputs = {"x": input, "expand_times": expand_times}
node.fluid_code.add_layer(
"expand", inputs=input, output=node, param_attr=attr)
"expand", inputs=inputs, output=node, param_attr=None)
def Pack(self, node):
inputs = [
self.graph.get_node(
name, copy=True) for name in node.layer.input
]
reshape_shape = list()
for input_node in inputs:
k_size = input_node.out_shapes[0]
if len(k_size) and k_size[-1] != -1:
reshape_shape = [0] * len(k_size)
reshape_shape[-1] = k_size[-1]
break
if len(reshape_shape):
for i, input_node in enumerate(inputs):
node.fluid_code.add_layer(
"reshape",
inputs=input_node,
output='tmp_{}'.format(i),
param_attr={"shape": reshape_shape})
axis = node.get_attr("axis")
attr = {"axis": axis}
if len(reshape_shape):
inputs = ['tmp_{}'.format(i) for i in range(len(inputs))]
node.fluid_code.add_layer(
"stack", inputs=inputs, output=node, param_attr=attr)
......@@ -656,21 +530,17 @@ class TFOpMapperNHWC(OpMapper):
start = self.graph.get_node(node.layer.input[0], copy=True)
limit = self.graph.get_node(node.layer.input[1], copy=True)
delta = self.graph.get_node(node.layer.input[2], copy=True)
self.add_omit_nodes(start.layer_name, node.layer_name)
self.add_omit_nodes(limit.layer_name, node.layer_name)
self.add_omit_nodes(delta.layer_name, node.layer_name)
if start.layer_type == "Const":
self.add_omit_nodes(start.layer_name, node.layer_name)
start = start.value
else:
start = self.decoder.infer_tensor(start)
if limit.layer_type == "Const":
self.add_omit_nodes(limit.layer_name, node.layer_name)
limit = limit.value
else:
limit = self.decoder.infer_tensor(limit)
if delta.layer_type == "Const":
self.add_omit_nodes(delta.layer_name, node.layer_name)
delta = delta.value
else:
delta = self.decoder.infer_tensor(delta)
dtype = node.dtype
inputs = {
"start": start,
......@@ -802,31 +672,27 @@ class TFOpMapperNHWC(OpMapper):
input = self.graph.get_node(node.layer.input[0], copy=True)
begin = self.graph.get_node(node.layer.input[1], copy=True)
size = self.graph.get_node(node.layer.input[2], copy=True)
self.add_omit_nodes(begin.layer_name, node.layer_name)
self.add_omit_nodes(size.layer_name, node.layer_name)
if begin.layer_type == "Const":
self.add_omit_nodes(begin.layer_name, node.layer_name)
begin = begin.value.tolist()
else:
begin = self.decoder.infer_tensor(begin).tolist()
if size.layer_type == "const":
begin = begin
shape = begin.out_shapes[0]
attr = {"shape": shape}
node.fluid_code.add_layer(
"reshape", inputs=begin, output=begin, param_attr=attr)
if size.layer_type == "Const":
self.add_omit_nodes(size.layer_name, node.layer_name)
size = size.value.tolist()
else:
size = self.decoder.infer_tensor(size).tolist()
for i in range(len(size)):
if size[i] < 0:
size[i] = 99999999
else:
size[i] = size[i] + begin[i]
attr = {
"axes": [i for i in range(len(size))],
"starts": begin,
"ends": size
}
size = size
shape = size.out_shapes[0]
attr = {"shape": shape}
node.fluid_code.add_layer(
"slice", inputs=input, output=node, param_attr=attr)
"reshape", inputs=size, output=size, param_attr=attr)
inputs = {"x": input, "offsets": begin, "shape": size}
node.fluid_code.add_layer(
"crop_tensor", inputs=inputs, output=node, param_attr=None)
def Conv2DBackpropInput(self, node):
out_shape = self.graph.get_node(node.layer.input[0], copy=True)
......@@ -834,15 +700,12 @@ class TFOpMapperNHWC(OpMapper):
input = self.graph.get_node(node.layer.input[2], copy=True)
assert kernel.layer_type == "Const", "Kernel of Conv2DBackpropInput should be Const"
assert out_shape.layer_type == "Const", "Out_shape of Conv2DBackpropInput should be Const"
self.add_omit_nodes(kernel.layer_name, node.layer_name)
self.add_omit_nodes(out_shape.layer_name, node.layer_name)
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])
self.add_omit_nodes(out_shape.layer_name, node.layer_name)
in_shape = input.out_shapes[0]
if in_shape.count(-1) > 2:
......@@ -946,19 +809,27 @@ class TFOpMapperNHWC(OpMapper):
def ResizeNearestNeighbor(self, node):
input = self.graph.get_node(node.layer.input[0], copy=True)
resize_shape = self.graph.get_node(node.layer.input[1], copy=True)
self.add_omit_nodes(resize_shape.layer_name, node.layer_name)
if resize_shape.layer_type == "Const":
self.add_omit_nodes(resize_shape.layer_name, node.layer_name)
resize_shape = resize_shape.value.tolist()
else:
resize_shape = self.decoder.infer_shape_tensor(resize_shape,
node.out_shapes[0])
resize_shape = resize_shape
shape = resize_shape.out_shapes[0]
attr = {"shape": shape}
node.fluid_code.add_layer(
"reshape",
inputs=resize_shape,
output=resize_shape,
param_attr=attr)
align_corners = node.get_attr("align_corners")
attr = {"perm": [0, 3, 1, 2]}
node.fluid_code.add_layer(
"transpose", inputs=input, output=node, param_attr=attr)
attr = {"align_corners": align_corners, "out_shape": resize_shape}
inputs = {"input": node, "out_shape": resize_shape}
attr = {"align_corners": align_corners}
node.fluid_code.add_layer(
"resize_nearest", inputs=node, output=node, param_attr=attr)
"resize_nearest", inputs=inputs, output=node, param_attr=attr)
attr = {"perm": [0, 2, 3, 1]}
node.fluid_code.add_layer(
"transpose", inputs=node, output=node, param_attr=attr)
......@@ -966,23 +837,29 @@ class TFOpMapperNHWC(OpMapper):
def ResizeBilinear(self, node):
input = self.graph.get_node(node.layer.input[0], copy=True)
resize_shape = self.graph.get_node(node.layer.input[1], copy=True)
self.add_omit_nodes(resize_shape.layer_name, node.layer_name)
if resize_shape.layer_type == "Const":
self.add_omit_nodes(resize_shape.layer_name, node.layer_name)
resize_shape = resize_shape.value.tolist()
else:
resize_shape = self.decoder.infer_shape_tensor(resize_shape,
node.out_shapes[0])
shape = resize_shape.out_shapes[0]
attr = {"shape": shape}
node.fluid_code.add_layer(
"reshape",
inputs=resize_shape,
output=resize_shape,
param_attr=attr)
align_corners = node.get_attr("align_corners")
attr = {"perm": [0, 3, 1, 2]}
node.fluid_code.add_layer(
"transpose", inputs=input, output=node, param_attr=attr)
inputs = {"input": node, "out_shape": resize_shape}
attr = {
#"out_shape": resize_shape,
"align_corners": align_corners,
"out_shape": resize_shape,
"align_mode": 1
}
node.fluid_code.add_layer(
"resize_bilinear", inputs=node, output=node, param_attr=attr)
"resize_bilinear", inputs=inputs, output=node, param_attr=attr)
attr = {"perm": [0, 2, 3, 1]}
node.fluid_code.add_layer(
"transpose", inputs=node, output=node, param_attr=attr)
......@@ -996,23 +873,15 @@ class TFOpMapperNHWC(OpMapper):
def RandomUniform(self, node):
shape = self.graph.get_node(node.layer.input[0], copy=True)
self.add_omit_nodes(shape.layer_name, node.layer_name)
if shape.layer_type == "Const":
self.add_omit_nodes(shape.layer_name, node.layer_name)
shape = shape.value.tolist()
else:
shape = self.decoder.infer_shape_tensor(shape)
attr = {"shape": shape, "min": 0.0, "max": 0.9999}
shape = shape
attr = {"min": 0.0, "max": 0.9999}
if shape[0] < 0:
input = self.batch_node
node.fluid_code.add_layer(
"uniform_random_batch_size_like",
inputs=input,
output=node,
param_attr=attr)
else:
node.fluid_code.add_layer(
"uniform_random", inputs=None, output=node, param_attr=attr)
"uniform_random", inputs=shape, output=node, param_attr=attr)
def SquaredDifference(self, node):
x = self.graph.get_node(node.layer.input[0], copy=True)
......@@ -1028,11 +897,11 @@ class TFOpMapperNHWC(OpMapper):
x = self.graph.get_node(node.layer.input[0], copy=True)
y = self.graph.get_node(node.layer.input[1], copy=True)
if y.layer_type == 'Const':
dim = y.value.tolist()
else:
dim = self.decoder.infer_tensor(y)
self.add_omit_nodes(y.layer_name, node.layer_name)
dim = y.value.tolist()
attr = {'axes': [dim]}
else:
attr = {'axes': y}
node.fluid_code.add_layer(
"unsqueeze", inputs=x, output=node, param_attr=attr)
......
......@@ -236,26 +236,18 @@ class TFOptimizer(object):
def remove_transpose(self):
graph_copy = cp.deepcopy(self.graph)
nhwc_insensitive_ops = [
'Relu', 'Relu6', 'Abs', 'Sigmoid', 'Exp', 'Rsqrt', 'swish_f32',
'LeakyRelu', 'Cast', 'Tanh'
]
elementwise_ops = [
'Sub', 'Add', 'RealDiv', 'Maximum', 'Mul', 'FloorDiv',
'GreaterEqual'
]
optimize_ops = [
'Conv2D', 'MaxPool', 'FusedBatchNorm', 'DepthwiseConv2dNative',
'AvgPool', 'Pad', 'Conv2DBackpropInput', 'ResizeNearestNeighbor',
'ResizeBilinear', "Placeholder"
'GreateerEqual'
]
can_be_optimized_ops = [
'Conv2D', 'MaxPool', 'FusedBatchNorm', 'DepthwiseConv2dNative',
'AvgPool', 'Pad', 'Conv2DBackpropInput', 'ResizeNearestNeighbor',
'ResizeBilinear', "Placeholder", 'Relu', 'Relu6', 'Abs', 'Sigmoid',
'Exp', 'Rsqrt', 'swish_f32', 'LeakyRelu', 'Cast', 'Tanh'
'Placeholder', 'Relu', 'Relu6', 'Abs', 'Sigmoid', 'Exp', 'Rsqrt',
'swish_f32', 'LeakyRelu', 'Cast', 'Tanh'
]
# These ops may have one more Variable input
can_be_optimized_special_ops = ['ResizeBilinear']
for node_name in self.graph.topo_sort:
node = graph_copy.get_node(node_name)
if node is None:
......@@ -278,9 +270,10 @@ class TFOptimizer(object):
0].param_attr["perm"] != [0, 3, 1, 2]:
can_be_removed = False
break
elif out_node.layer_type in elementwise_ops:
elif out_node.layer_type in elementwise_ops or out_node.layer_type in can_be_optimized_special_ops:
can_be_removed = False
break
if can_be_removed and len(node.fluid_code.layers) > 1:
true_node = self.graph.get_node(node_name)
if true_node.layer_type == "Placeholder":
......@@ -298,6 +291,7 @@ class TFOptimizer(object):
-2].output = true_node.fluid_code.layers[-1].output
node.removed = True
del true_node.fluid_code.layers[-1]
for out_name in output_names:
out_node = self.graph.get_node(out_name)
out_node.fluid_code.layers[
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册