@@ -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
326326def _resize_bilinear ():
@@ -383,7 +383,7 @@ def _impl(inputs, attr, params):
383383def _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 )
0 commit comments