FaceBoxes-tensorflow
FaceBoxes-tensorflow copied to clipboard
Converting to tf-coreml
I'm trying to find out endpoints of model like is done here: https://github.com/tf-coreml/tf-coreml/blob/master/examples/ssd_example.ipynb
Cause using default input/output node names produce error:
input_tensor_shapes {'image_tensor:0': [1, 256, 256, 3]}
output_tensor_names ['boxes:0', 'scores:0', 'num_boxes:0']
Loading the TF graph...
Graph Loaded.
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-15-3268ebb54f92> in <module>
18 mlmodel_path=coreml_model_file,
19 input_name_shape_dict=input_tensor_shapes,
---> 20 output_feature_names=output_tensor_names)
/usr/local/lib/python3.6/site-packages/tfcoreml/_tf_coreml_converter.py in convert(tf_model_path, mlmodel_path, output_feature_names, input_name_shape_dict, image_input_names, is_bgr, red_bias, green_bias, blue_bias, gray_bias, image_scale, class_labels, predicted_feature_name, predicted_probabilities_output, add_custom_layers, custom_conversion_functions)
584 predicted_probabilities_output=predicted_probabilities_output,
585 add_custom_layers=add_custom_layers,
--> 586 custom_conversion_functions=custom_conversion_functions)
/usr/local/lib/python3.6/site-packages/tfcoreml/_tf_coreml_converter.py in _convert_pb_to_mlmodel(tf_model_path, mlmodel_path, output_feature_names, input_name_shape_dict, image_input_names, is_bgr, red_bias, green_bias, blue_bias, gray_bias, image_scale, class_labels, predicted_feature_name, predicted_probabilities_output, add_custom_layers, custom_conversion_functions)
165 print('Graph Loaded.')
166 # Sort the ops in topological order and check whether the graph has cycles, if yes, error out
--> 167 OPS = _topological_sort_ops(OPS)
168
169 SHAPE_DICT = {} #Tensor name --> shape ({str: list})
/usr/local/lib/python3.6/site-packages/tfcoreml/_tf_graph_transform.py in _topological_sort_ops(ops)
192 node = _get_unvisited_child(G, stack[-1], not_visited)
193 if node != -1:
--> 194 _push_stack(stack, node, in_stack)
195 else:
196 node = stack.pop()
/usr/local/lib/python3.6/site-packages/tfcoreml/_tf_graph_transform.py in _push_stack(stack, node, in_stack)
36 stack.append(node)
37 if node in in_stack:
---> 38 raise ValueError('Graph has cycles.')
39 else:
40 in_stack[node] = True
ValueError: Graph has cycles.
On graph last block before nms is preprocessing, but I'm not sure what is output_tensor_names should be used.
I have tried to print node dimensions:
with tf.Graph().as_default() as graph:
tf.import_graph_def(original_gdef, name='')
for op in graph.get_operations():
if 'postprocessing' in op.name:
print('-'*60)
print('str(op.name)', str(op.name))
print('len(op.values())', len(op.values()))
try:
for i in range(len(op.values())):
print('op.values()[i].get_shape().as_list()', op.values()[i].get_shape().as_list())
except:
for i in range(len(op.values())):
print('op.values()[i].get_shape()', op.values()[i].get_shape())
Output:
------------------------------------------------------------
str(op.name) postprocessing/Shape
len(op.values()) 1
op.values()[i].get_shape().as_list() [3]
------------------------------------------------------------
str(op.name) postprocessing/strided_slice/stack
len(op.values()) 1
op.values()[i].get_shape().as_list() [1]
------------------------------------------------------------
str(op.name) postprocessing/strided_slice/stack_1
len(op.values()) 1
op.values()[i].get_shape().as_list() [1]
------------------------------------------------------------
str(op.name) postprocessing/strided_slice/stack_2
len(op.values()) 1
op.values()[i].get_shape().as_list() [1]
------------------------------------------------------------
str(op.name) postprocessing/strided_slice
len(op.values()) 1
op.values()[i].get_shape().as_list() []
------------------------------------------------------------
str(op.name) postprocessing/Shape_1
len(op.values()) 1
op.values()[i].get_shape().as_list() [3]
------------------------------------------------------------
str(op.name) postprocessing/strided_slice_1/stack
len(op.values()) 1
op.values()[i].get_shape().as_list() [1]
------------------------------------------------------------
str(op.name) postprocessing/strided_slice_1/stack_1
len(op.values()) 1
op.values()[i].get_shape().as_list() [1]
------------------------------------------------------------
str(op.name) postprocessing/strided_slice_1/stack_2
len(op.values()) 1
op.values()[i].get_shape().as_list() [1]
------------------------------------------------------------
str(op.name) postprocessing/strided_slice_1
len(op.values()) 1
op.values()[i].get_shape().as_list() []
------------------------------------------------------------
str(op.name) postprocessing/ExpandDims/dim
len(op.values()) 1
op.values()[i].get_shape().as_list() []
------------------------------------------------------------
str(op.name) postprocessing/ExpandDims
len(op.values()) 1
op.values()[i].get_shape().as_list() [1, 1364, 4]
------------------------------------------------------------
str(op.name) postprocessing/Tile/multiples/1
len(op.values()) 1
op.values()[i].get_shape().as_list() []
------------------------------------------------------------
str(op.name) postprocessing/Tile/multiples/2
len(op.values()) 1
op.values()[i].get_shape().as_list() []
------------------------------------------------------------
str(op.name) postprocessing/Tile/multiples
len(op.values()) 1
op.values()[i].get_shape().as_list() [3]
------------------------------------------------------------
str(op.name) postprocessing/Tile
len(op.values()) 1
op.values()[i].get_shape().as_list() [None, 1364, 4]
------------------------------------------------------------
str(op.name) postprocessing/Reshape/shape
len(op.values()) 1
op.values()[i].get_shape().as_list() [2]
------------------------------------------------------------
str(op.name) postprocessing/Reshape
len(op.values()) 1
op.values()[i].get_shape().as_list() [None, 4]
------------------------------------------------------------
str(op.name) postprocessing/Reshape_1/shape
len(op.values()) 1
op.values()[i].get_shape().as_list() [2]
------------------------------------------------------------
str(op.name) postprocessing/Reshape_1
len(op.values()) 1
op.values()[i].get_shape().as_list() [None, 4]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/unstack
len(op.values()) 4
op.values()[i].get_shape().as_list() [None]
op.values()[i].get_shape().as_list() [None]
op.values()[i].get_shape().as_list() [None]
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/to_center_coordinates/sub
len(op.values()) 1
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/to_center_coordinates/sub_1
len(op.values()) 1
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/to_center_coordinates/mul/x
len(op.values()) 1
op.values()[i].get_shape().as_list() []
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/to_center_coordinates/mul
len(op.values()) 1
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/to_center_coordinates/add
len(op.values()) 1
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/to_center_coordinates/mul_1/x
len(op.values()) 1
op.values()[i].get_shape().as_list() []
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/to_center_coordinates/mul_1
len(op.values()) 1
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/to_center_coordinates/add_1
len(op.values()) 1
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/unstack_1
len(op.values()) 4
op.values()[i].get_shape().as_list() [None]
op.values()[i].get_shape().as_list() [None]
op.values()[i].get_shape().as_list() [None]
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/truediv/y
len(op.values()) 1
op.values()[i].get_shape().as_list() []
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/truediv
len(op.values()) 1
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/truediv_1/y
len(op.values()) 1
op.values()[i].get_shape().as_list() []
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/truediv_1
len(op.values()) 1
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/truediv_2/y
len(op.values()) 1
op.values()[i].get_shape().as_list() []
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/truediv_2
len(op.values()) 1
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/truediv_3/y
len(op.values()) 1
op.values()[i].get_shape().as_list() []
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/truediv_3
len(op.values()) 1
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/Exp
len(op.values()) 1
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/mul
len(op.values()) 1
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/Exp_1
len(op.values()) 1
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/mul_1
len(op.values()) 1
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/mul_2
len(op.values()) 1
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/add
len(op.values()) 1
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/mul_3
len(op.values()) 1
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/add_1
len(op.values()) 1
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/to_minmax_coordinates/mul/x
len(op.values()) 1
op.values()[i].get_shape().as_list() []
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/to_minmax_coordinates/mul
len(op.values()) 1
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/to_minmax_coordinates/sub
len(op.values()) 1
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/to_minmax_coordinates/mul_1/x
len(op.values()) 1
op.values()[i].get_shape().as_list() []
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/to_minmax_coordinates/mul_1
len(op.values()) 1
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/to_minmax_coordinates/sub_1
len(op.values()) 1
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/to_minmax_coordinates/mul_2/x
len(op.values()) 1
op.values()[i].get_shape().as_list() []
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/to_minmax_coordinates/mul_2
len(op.values()) 1
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/to_minmax_coordinates/add
len(op.values()) 1
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/to_minmax_coordinates/mul_3/x
len(op.values()) 1
op.values()[i].get_shape().as_list() []
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/to_minmax_coordinates/mul_3
len(op.values()) 1
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/to_minmax_coordinates/add_1
len(op.values()) 1
op.values()[i].get_shape().as_list() [None]
------------------------------------------------------------
str(op.name) postprocessing/decode_predictions/stack
len(op.values()) 1
op.values()[i].get_shape().as_list() [None, 4]
------------------------------------------------------------
str(op.name) postprocessing/Reshape_2/shape/2
len(op.values()) 1
op.values()[i].get_shape().as_list() []
------------------------------------------------------------
str(op.name) postprocessing/Reshape_2/shape
len(op.values()) 1
op.values()[i].get_shape().as_list() [3]
------------------------------------------------------------
str(op.name) postprocessing/Reshape_2
len(op.values()) 1
op.values()[i].get_shape().as_list() [None, None, 4]
------------------------------------------------------------
str(op.name) postprocessing/clip_by_value/Minimum/y
len(op.values()) 1
op.values()[i].get_shape().as_list() []
------------------------------------------------------------
str(op.name) postprocessing/clip_by_value/Minimum
len(op.values()) 1
op.values()[i].get_shape().as_list() [None, None, 4]
------------------------------------------------------------
str(op.name) postprocessing/clip_by_value/y
len(op.values()) 1
op.values()[i].get_shape().as_list() []
------------------------------------------------------------
str(op.name) postprocessing/clip_by_value
len(op.values()) 1
op.values()[i].get_shape().as_list() [None, None, 4]
------------------------------------------------------------
str(op.name) postprocessing/truediv
len(op.values()) 1
op.values()[i].get_shape().as_list() [None, None, 4]
------------------------------------------------------------
str(op.name) postprocessing/clip_by_value_1/Minimum/y
len(op.values()) 1
op.values()[i].get_shape().as_list() []
------------------------------------------------------------
str(op.name) postprocessing/clip_by_value_1/Minimum
len(op.values()) 1
op.values()[i].get_shape().as_list() [None, None, 4]
------------------------------------------------------------
str(op.name) postprocessing/clip_by_value_1/y
len(op.values()) 1
op.values()[i].get_shape().as_list() []
------------------------------------------------------------
str(op.name) postprocessing/clip_by_value_1
len(op.values()) 1
op.values()[i].get_shape().as_list() [None, None, 4]
------------------------------------------------------------
str(op.name) postprocessing/Softmax
len(op.values()) 1
op.values()[i].get_shape().as_list() [None, None, 2]
------------------------------------------------------------
str(op.name) postprocessing/strided_slice_2/stack
len(op.values()) 1
op.values()[i].get_shape().as_list() [3]
------------------------------------------------------------
str(op.name) postprocessing/strided_slice_2/stack_1
len(op.values()) 1
op.values()[i].get_shape().as_list() [3]
------------------------------------------------------------
str(op.name) postprocessing/strided_slice_2/stack_2
len(op.values()) 1
op.values()[i].get_shape().as_list() [3]
------------------------------------------------------------
str(op.name) postprocessing/strided_slice_2
len(op.values()) 1
op.values()[i].get_shape().as_list() [None, None]
But I can't find out any meaningfull node name:
These looks like bboxes:
str(op.name) postprocessing/Tile
len(op.values()) 1
op.values()[i].get_shape().as_list() [None, 1364, 4]
str(op.name) postprocessing/ExpandDims
len(op.values()) 1
op.values()[i].get_shape().as_list() [1, 1364, 4]
Is it true that for 256x256 image we have 1364 bboxes?
With same approach I found node:
------------------------------------------------------------
str(op.name) postprocessing/Softmax
len(op.values()) 1
op.values()[i].get_shape().as_list() [None, None, 2]
But not sure why it have shape [None, None, 2]?
Also here is postprocessing scope:
https://github.com/TropComplique/FaceBoxes-tensorflow/blob/545ec4f4f3c55c3592ee189ed56a11a3fd017194/src/detector.py#L70
It should have output boxes with [batch_size, num_anchors, 4] shape and scores with [batch_size, num_anchors] shape.
I have ended with layers after prediction_layers scope, looks like it's maximum that tf-coreml can support in terms of operations.
I can't figure out how to get tensor names in tensorboard, so I have added print to get tensor names and the run python save.py:
for i in range(len(box_encodings)):
print('DEBUG: box_encodings[i]', box_encodings[i])
for i in range(len(class_predictions_with_background)):
print('DEBUG: class_predictions_with_background[i]', class_predictions_with_background[i])
Here in the code: https://github.com/TropComplique/FaceBoxes-tensorflow/blob/545ec4f4f3c55c3592ee189ed56a11a3fd017194/src/detector.py#L284
# V1: after feature extractor
# [None, None, None, 128], [None, None, None, 256], [None, None, None, 256]
# output_node_names = ['inception3/concat', 'conv3_2/Relu', 'conv4_2/Relu']
# V2: real netwrok outputs
# ValueError: Graph has cycles.
# output_node_names = ['boxes', 'scores', 'num_boxes']
# V3: before NMS
# NotImplementedError: Unsupported Ops of type: Unpack,Pack
# [batch_size, num_anchors, 4], [batch_size, num_anchors]
# output_node_names = ['postprocessing/clip_by_value_1', 'postprocessing/strided_slice_2']
# V4: after reshaping scope
# AssertionError: Reshape: Currently only supported if target shape is rank 2, 3 or 4
# output_node_names = ['reshaping/concat', 'reshaping/concat_1']
# V5: after prediction_layers scope
output_node_names = ['prediction_layers/box_encoding_predictor_0/BiasAdd',
'prediction_layers/box_encoding_predictor_1/BiasAdd',
'prediction_layers/box_encoding_predictor_2/BiasAdd',
'prediction_layers/class_predictor_0/BiasAdd',
'prediction_layers/class_predictor_1/BiasAdd',
'prediction_layers/class_predictor_2/BiasAdd']
For 256x256 input image shapes of output tensors are:
------------------------------------------------------------
str(op.name) image_tensor
len(op.values()) 1
op.values()[i].get_shape().as_list() [None, 256, 256, 3]
------------------------------------------------------------
str(op.name) prediction_layers/box_encoding_predictor_0/BiasAdd
len(op.values()) 1
op.values()[i].get_shape().as_list() [None, 8, 8, 84]
------------------------------------------------------------
str(op.name) prediction_layers/class_predictor_0/BiasAdd
len(op.values()) 1
op.values()[i].get_shape().as_list() [None, 8, 8, 42]
------------------------------------------------------------
str(op.name) prediction_layers/box_encoding_predictor_1/BiasAdd
len(op.values()) 1
op.values()[i].get_shape().as_list() [None, 4, 4, 4]
------------------------------------------------------------
str(op.name) prediction_layers/class_predictor_1/BiasAdd
len(op.values()) 1
op.values()[i].get_shape().as_list() [None, 4, 4, 2]
------------------------------------------------------------
str(op.name) prediction_layers/box_encoding_predictor_2/BiasAdd
len(op.values()) 1
op.values()[i].get_shape().as_list() [None, 2, 2, 4]
------------------------------------------------------------
str(op.name) prediction_layers/class_predictor_2/BiasAdd
len(op.values()) 1
op.values()[i].get_shape().as_list() [None, 2, 2, 2]