I can't convert a simple Keras model to CoreML with coremltools
~/anaconda3/lib/python3.7/site-packages/coremltools/converters/keras/_keras2_converter.py in _convert(model, input_names, output_names, image_input_names, input_name_shape_dict, 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, custom_objects, input_shapes, output_shapes, respect_trainable, use_float_arraytype)
326 # Build network graph to represent Keras model
327 graph = _topology2.NetGraph(model)
--> 328 graph.build()
329
330 # The graph should be finalized before executing this~/anaconda3/lib/python3.7/site-packages/coremltools/converters/keras/_topology2.py in build(self, is_top_level)
738
739 # tag input layers and and output layers
--> 740 self.make_input_layers()
741 self.make_output_layers()
742~/anaconda3/lib/python3.7/site-packages/coremltools/converters/keras/_topology2.py in make_input_layers(self)
167 for l in self.layer_list:
168 kl = self.keras_layer_map[l]
--> 169 if isinstance(kl, InputLayer) and kl.input == ts:
170 self.input_layers.append(l)
171 elif len(in_nodes) <= 1:~/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/framework/ops.py in __bool__(self)
763TypeError.
764 """
--> 765 self._disallow_bool_casting()
766
767 def __nonzero__(self):~/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/framework/ops.py in _disallow_bool_casting(self)
532 else:
533 # Default: V1-style Graph execution.
--> 534 self._disallow_in_graph_mode("using atf.Tensoras a Pythonbool")
535
536 def _disallow_iteration(self):~/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/framework/ops.py in _disallow_in_graph_mode(self, task)
521 raise errors.OperatorNotAllowedInGraphError(
522 "{} is not allowed in Graph execution. Use Eager execution or decorate"
--> 523 " this function with @tf.function.".format(task))
524
525 def _disallow_bool_casting(self):OperatorNotAllowedInGraphError: using a
tf.Tensoras a Pythonboolis not allowed in Graph execution. Use Eager execution or decorate this function with @tf.function.
inp = keras.layers.Input(shape=(420, 420, 3))
conv = keras.layers.Conv2D(32, 3, activation='relu')(inp)
keras_model = keras.models.Model(inputs=[inp], outputs=conv)
model = coremltools.converters.keras.convert(
keras_model,
input_name_shape_dict={
keras_model.input.name: [None, 420, 420, 3]
},
input_names=[keras_model.input.name],
output_names=[keras_model.output.name]
)
If I try to use tf.compat.v1.disable_eager_execution(), I get this:
~/anaconda3/lib/python3.7/site-packages/coremltools/converters/keras/_keras2_converter.py in _convert(model, input_names, output_names, image_input_names, input_name_shape_dict, 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, custom_objects, input_shapes, output_shapes, respect_trainable, use_float_arraytype)
494 if converter_func:
495 converter_func(builder, layer, input_names, output_names,
--> 496 keras_layer, respect_trainable)
497 else:
498 if _is_activation_layer(keras_layer):~/anaconda3/lib/python3.7/site-packages/coremltools/converters/keras/_layers2.py in convert_convolution(builder, layer, input_names, output_names, keras_layer, respect_train)
357
358 # Get the weights from _keras.
--> 359 weightList = keras_layer.get_weights()
360
361 # Dimensions and weights~/anaconda3/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py in eager_fn_wrapper(args, *kwargs)
103 _SYMBOLIC_SCOPE.value = False
104 with context.eager_mode():
--> 105 out = func(args, *kwargs)
106 finally:
107 _SYMBOLIC_SCOPE.value = prev_value~/anaconda3/lib/python3.7/site-packages/keras/engine/base_layer.py in get_weights(self)
1136 """
1137 params = self.weights
-> 1138 return K.batch_get_value(params)
1139
1140 def get_config(self):~/anaconda3/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py in batch_get_value(ops)
2937 A list of Numpy arrays.
2938 """
-> 2939 return tf_keras_backend.batch_get_value(ops)
2940
2941~/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/keras/backend.py in batch_get_value(tensors)
3294 """
3295 if context.executing_eagerly():
-> 3296 return [x.numpy() for x in tensors]
3297 elif ops.inside_function(): # pylint: disable=protected-access
3298 raise RuntimeError('Cannot get value inside Tensorflow graph function.')~/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/keras/backend.py in
(.0)
3294 """
3295 if context.executing_eagerly():
-> 3296 return [x.numpy() for x in tensors]
3297 elif ops.inside_function(): # pylint: disable=protected-access
3298 raise RuntimeError('Cannot get value inside Tensorflow graph function.')~/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/ops/resource_variable_ops.py in numpy(self)
575 def numpy(self):
576 if context.executing_eagerly():
--> 577 return self.read_value().numpy()
578 raise NotImplementedError(
579 "numpy() is only available when eager execution is enabled.")~/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/ops/resource_variable_ops.py in read_value(self)
628 # Ensure we read the variable in the same device as the handle.
629 with ops.device(self._handle.device):
--> 630 value = self._read_variable_op()
631 # Return an identity so it can get placed on whatever device the context
632 # specifies instead of the device where the variable is.~/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/ops/resource_variable_ops.py in _read_variable_op(self)
606 variable_accessed(self)
607 result = gen_resource_variable_ops.read_variable_op(self._handle,
--> 608 self._dtype)
609 _maybe_set_handle_data(self._dtype, self._handle, result)
610~/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/ops/gen_resource_variable_ops.py in read_variable_op(resource, dtype, name)
573 try:
574 return read_variable_op_eager_fallback(
--> 575 resource, dtype=dtype, name=name, ctx=_ctx)
576 except _core._SymbolicException:
577 pass # Add nodes to the TensorFlow graph.~/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/ops/gen_resource_variable_ops.py in read_variable_op_eager_fallback(resource, dtype, name, ctx)
611 _attrs = ("dtype", dtype)
612 _result = _execute.execute(b"ReadVariableOp", 1, inputs=_inputs_flat,
--> 613 attrs=_attrs, ctx=_ctx, name=name)
614 _execute.record_gradient(
615 "ReadVariableOp", _inputs_flat, _attrs, _result, name)~/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/eager/execute.py in quick_execute(op_name, num_outputs, inputs, attrs, ctx, name)
74 "Inputs to eager execution function cannot be Keras symbolic "
75 "tensors, but found {}".format(keras_symbolic_tensors))
---> 76 raise e
77 # pylint: enable=protected-access
78 return tensors~/anaconda3/lib/python3.7/site-packages/tensorflow_core/python/eager/execute.py in quick_execute(op_name, num_outputs, inputs, attrs, ctx, name)
59 tensors = pywrap_tensorflow.TFE_Py_Execute(ctx._handle, device_name,
60 op_name, inputs, attrs,
---> 61 num_outputs)
62 except core._NotOkStatusException as e:
63 if name is not None:TypeError: An op outside of the function building code is being passed
a "Graph" tensor. It is possible to have Graph tensors
leak out of the function building context by including a
tf.init_scope in your function building code.
For example, the following function will fail:
@tf.function
def has_init_scope():
my_constant = tf.constant(1.)
with tf.init_scope():
added = my_constant * 2
The graph tensor has name: conv2d_1/kernel:0
This appears to be a TF2.0 native issue. If TF1.x (e.g. 1.14) is used instead, the code appears to run fine. (Although this is pretty inconvenient and definitely not a good long term solution for version compatibility with other libraries)