Skip to content

Commit de8da06

Browse files
committed
Fix for stack(unstack(data)) != data
1 parent e406740 commit de8da06

2 files changed

Lines changed: 29 additions & 4 deletions

File tree

nnvm/python/nnvm/frontend/tensorflow.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ def __call__(self, inputs, attrs, *args):
3636
self._ignores.append('_node_name')
3737
self._ignores.append('is_training')
3838
self._ignores.append('_target_layout')
39+
self._ignores.append('_input_0d_mismatch')
3940
# Retain the names
4041
try:
4142
attrs['name'] = attrs['_node_name']
@@ -319,8 +320,7 @@ def _impl(inputs, attr, params):
319320
dim_input = inputs.pop(1)
320321
axis = params[dim_input.list_output_names()[0]]
321322
params.pop(dim_input.list_output_names()[0])
322-
return AttrCvt(op_name="expand_dims", ignores=['Tdim'],
323-
extras={'axis': axis.asnumpy()[0]})(inputs, attr)
323+
return _expand_dims_0d_aware(inputs[0], attr, axis=axis.asnumpy()[0])
324324
return _impl
325325

326326
def _resize_bilinear():
@@ -383,7 +383,7 @@ def _impl(inputs, attr, params):
383383
def _pack():
384384
def _impl(inputs, attr, params):
385385
axis = int(attr["axis"])
386-
inputs_reshaped = [_sym.expand_dims(i, axis=axis, num_newaxis=1) for i in inputs]
386+
inputs_reshaped = [_expand_dims_0d_aware(i, attr, axis=axis, num_newaxis=1) for i in inputs]
387387
return _sym.concatenate(*inputs_reshaped, axis=axis, name=attr["_node_name"])
388388

389389
return _impl
@@ -838,6 +838,13 @@ def _impl(inputs, attr, params):
838838
return _sym.Group([_sym.squeeze(split_item, axis=axis) for split_item in splitted])
839839
return _impl
840840

841+
def _expand_dims_0d_aware(data, attr, axis, num_newaxis=1):
842+
if data in attr['_input_0d_mismatch']:
843+
return data if num_newaxis == 1 else \
844+
_sym.expand_dims(data, axis=axis, num_newaxis=num_newaxis-1)
845+
846+
return _sym.expand_dims(data, axis=axis, num_newaxis=num_newaxis)
847+
841848
# compatible operators that do NOT require any conversion.
842849
_identity_list = []
843850

@@ -1103,6 +1110,7 @@ def __init__(self):
11031110
self._output_shapes = {}
11041111
self._num_param = 0
11051112
self._num_rnn_layer = False
1113+
self._outputs_are_0d = {}
11061114

11071115
def from_tensorflow(self, graph, layout="NHWC", shape=None, outputs=None):
11081116
"""Construct nnvm nodes from tensorflow graph definition - GraphDef.
@@ -1158,6 +1166,7 @@ def from_tensorflow(self, graph, layout="NHWC", shape=None, outputs=None):
11581166
# Operator name 'Const' is treated as a parameter to build NNVM params dict.
11591167

11601168
input_shapes = {}
1169+
input_0d_mismatch = set()
11611170
attr = self._parse_attr(node.attr)
11621171

11631172
#Variable converted to Const will not have only value attr
@@ -1177,6 +1186,9 @@ def from_tensorflow(self, graph, layout="NHWC", shape=None, outputs=None):
11771186
else:
11781187
raise NotImplementedError( \
11791188
"Please freeze the graph with add_shapes=True")
1189+
self._outputs_are_0d[node.name] = [ \
1190+
not shape if isinstance(shape, list) else False \
1191+
for shape in self._output_shapes[node.name]]
11801192

11811193
if node.op == "Placeholder":
11821194
self._nodes[node.name] = _sym.Variable(name=node.name,
@@ -1222,10 +1234,16 @@ def from_tensorflow(self, graph, layout="NHWC", shape=None, outputs=None):
12221234
in_sym = in_sym[tensor_slot]
12231235
input_shape = self._output_shapes[node_name][tensor_slot]
12241236
else:
1237+
tensor_slot = 0
12251238
input_shape = self._output_shapes[node_name][0]
12261239
inputs.append(in_sym)
12271240
input_shapes[in_sym] = [input_shape]
1241+
# This means the node is 1d in NVM and 0d in TF.
1242+
# See `_expand_dims_0d_aware`.
1243+
if self._outputs_are_0d[node_name][tensor_slot] and input_shape:
1244+
input_0d_mismatch.add(in_sym)
12281245
attr['_input_shapes'] = input_shapes
1246+
attr['_input_0d_mismatch'] = input_0d_mismatch
12291247

12301248
inputs = self._fix_extranodes(node.op, attr, inputs)
12311249
op = self._convert_operator(node.op, inputs, attr, graph)

nnvm/tests/python/frontend/tensorflow/test_forward.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,13 +559,20 @@ def test_forward_split():
559559
# -------
560560

561561
def _test_unstack(ip_shape, axis, dtype):
562+
np_data = np.random.uniform(-5, 5, size=ip_shape).astype(dtype)
563+
562564
tf.reset_default_graph()
563565
in_data = tf.placeholder(dtype, ip_shape, name="in_data")
564566
tf.unstack(in_data, axis=axis)
565-
np_data = np.random.uniform(-5, 5, size=ip_shape).astype(dtype)
566567

567568
compare_tf_with_tvm([np_data], ['in_data:0'], [f'unstack:{n}' for n in range(ip_shape[axis])])
568569

570+
tf.reset_default_graph()
571+
in_data = tf.placeholder(dtype, ip_shape, name="in_data")
572+
tf.stack(tf.unstack(in_data, axis=axis), axis=axis)
573+
574+
compare_tf_with_tvm([np_data], ['in_data:0'], 'stack:0')
575+
569576
def test_forward_unstack():
570577
'''test unstack layer'''
571578
_test_unstack((6,), 0, 'int32')

0 commit comments

Comments
 (0)