apple / coremltools

Core ML tools contain supporting tools for Core ML model conversion, editing, and validation.
https://coremltools.readme.io
BSD 3-Clause "New" or "Revised" License
4.42k stars 640 forks source link

Problem converting Tenserflow model to CoreML #1953

Open aargar1 opened 1 year ago

aargar1 commented 1 year ago

🐞Describing the bug

When trying to convert @yoeo's Guesslang model, I received a ValueError: Failed to import metagraph, check error log for more info.

Stack Trace

12 frames /usr/local/lib/python3.10/dist-packages/coremltools/converters/_converters_entry.py in convert(model, source, inputs, outputs, classifier_config, minimum_deployment_target, convert_to, compute_precision, skip_model_load, compute_units, package_dir, debug, pass_pipeline) 490 specification_version = _set_default_specification_version(exact_target) 491 --> 492 mlmodel = mil_convert( 493 model, 494 convert_from=exact_source,

/usr/local/lib/python3.10/dist-packages/coremltools/converters/mil/converter.py in mil_convert(model, convert_from, convert_to, compute_units, kwargs) 186 See coremltools.converters.convert 187 """ --> 188 return _mil_convert(model, convert_from, convert_to, ConverterRegistry, MLModel, compute_units, kwargs) 189 190

/usr/local/lib/python3.10/dist-packages/coremltools/converters/mil/converter.py in _mil_convert(model, convert_from, convert_to, registry, modelClass, compute_units, **kwargs) 210 kwargs["weights_dir"] = weights_dir.name 211 --> 212 proto, mil_program = mil_convert_to_proto( 213 model, 214 convert_from,

/usr/local/lib/python3.10/dist-packages/coremltools/converters/mil/converter.py in mil_convert_to_proto(model, convert_from, convert_to, converter_registry, main_pipeline, kwargs) 283 284 frontend_converter = frontend_converter_type() --> 285 prog = frontend_converter(model, kwargs) 286 PipelineManager.apply_pipeline(prog, frontend_pipeline) 287

/usr/local/lib/python3.10/dist-packages/coremltools/converters/mil/converter.py in call(self, *args, *kwargs) 96 97 tf2_loader = TF2Loader(args, **kwargs) ---> 98 return tf2_loader.load() 99 100

/usr/local/lib/python3.10/dist-packages/coremltools/converters/mil/frontend/tensorflow/load.py in load(self) 59 outputs = self.kwargs.get("outputs", None) 60 output_names = get_output_names(outputs) ---> 61 self._graph_def = self._graph_def_from_model(output_names) 62 63 if self._graph_def is not None and len(self._graph_def.node) == 0:

/usr/local/lib/python3.10/dist-packages/coremltools/converters/mil/frontend/tensorflow2/load.py in _graph_def_from_model(self, output_names) 131 def _graph_def_from_model(self, output_names=None): 132 """Overwrites TFLoader._graph_def_from_model()""" --> 133 cfs, graph_def = self._get_concrete_functions_and_graph_def() 134 if isinstance(self.model, _tf.keras.Model) and self.kwargs.get("outputs", None) is None: 135 # For the keras model, check if the outputs is provided by the user.

/usr/local/lib/python3.10/dist-packages/coremltools/converters/mil/frontend/tensorflow2/load.py in _get_concrete_functions_and_graph_def(self) 125 raise NotImplementedError(msg.format(self.model)) 126 --> 127 graph_def = self._graph_def_from_concrete_fn(cfs) 128 129 return cfs, graph_def

/usr/local/lib/python3.10/dist-packages/coremltools/converters/mil/frontend/tensorflow2/load.py in _graph_def_from_concrete_fn(self, cfs) 326 327 if _get_version(_tf.version) >= _StrictVersion("2.2.0"): --> 328 frozen_fn = _convert_variables_to_constants_v2(cfs[0], lower_control_flow=False, aggressive_inlining=True) 329 else: 330 frozen_fn = _convert_variables_to_constants_v2(cfs[0], lower_control_flow=False)

/usr/local/lib/python3.10/dist-packages/tensorflow/python/framework/convert_to_constants.py in convert_variables_to_constants_v2(func, lower_control_flow, aggressive_inlining) 1168 """ 1169 -> 1170 converter_data = _FunctionConverterDataInEager( 1171 func=func, 1172 lower_control_flow=lower_control_flow,

/usr/local/lib/python3.10/dist-packages/tensorflow/python/framework/convert_to_constants.py in init(self, func, lower_control_flow, aggressive_inlining, variable_names_allowlist, variable_names_denylist) 831 self._func = func 832 # Inline the graph in order to remove functions when possible. --> 833 graph_def = _run_inline_graph_optimization(func, lower_control_flow, 834 aggressive_inlining) 835 super(_FunctionConverterData, self).init(

/usr/local/lib/python3.10/dist-packages/tensorflow/python/framework/convert_to_constants.py in _run_inline_graph_optimization(func, lower_control_flow, aggressive_inlining) 1066 rewrite_options.function_optimization =\ 1067 rewriter_config_pb2.RewriterConfig.AGGRESSIVE -> 1068 return tf_optimizer.OptimizeGraph(config, meta_graph) 1069 1070

/usr/local/lib/python3.10/dist-packages/tensorflow/python/grappler/tf_optimizer.py in OptimizeGraph(config_proto, metagraph, verbose, graph_id, cluster, strip_default_attributes) 63 cluster = gcluster.Cluster() 64 try: ---> 65 out_graph = tf_opt.TF_OptimizeGraph(cluster.tf_cluster, 66 config_proto.SerializeToString(), 67 metagraph.SerializeToString(),

ValueError: Failed to import metagraph, check error log for more info.

## To Reproduce
- Please add a minimal code example that can reproduce the error when running it.

Paste Python code snippet here, complete with any required import statements.

import tensorflow as tf import coremltools as ct

model = tf.saved_model.load("./savedmodel") mfunc = model.signatures['serving_default'] ctmodel = ct.convert([mfunc], "tensorflow") ctmodel.save("ctmodel")



- If the model conversion succeeds, but there is a numerical mismatch in predictions, please include the code used for comparisons.

## System environment (please complete the following information):
 - coremltools version: 6.3.0
 - OS (e.g. MacOS version or Linux type): macOS Ventura (also tested on Google Colab (Debian Linux))
 - Any other relevant version information (e.g. PyTorch or TensorFlow version): 2.12.0

## Additional context
As per #1794, which concerned the same model, I tried converting only a single concrete function.
junpeiz commented 1 year ago

Hey @aargar1, Thank you for reporting this issue!

As there are security concerns to load arbitrary models (I am not allowed to load your "./savedmodel"), could you provide a simple code snippet to construct the TF model and reproduce the issue? Thanks!

aargar1 commented 1 year ago

I do not know how to do that... (I am an app dev, not an ML engineer by education). There are two options. One is that the savedmodel is just the Guesslang model from @yoeo, which is OSS. The other option is if you could load it into something like Google Colab.

junpeiz commented 1 year ago

Hi @aargar1 , it's due to that your TensorFlow package version is incompatible with the version which was used to generate the Guesslang model (especially when the model was generated by TF<=2.2.0 while you use TF>2.2.0 when you do conversion). So it triggered an error in tf_opt.TF_OptimizeGraph which is a TF internal error that coremltools cannot touch.

Could you check with the model author about the TF version used when save that model, and then try to use the same (or at least closer) version of the tensorflow package and re-run the conversion? Thanks!

aargar1 commented 1 year ago

The Guesslang author used 2.5.0 while I am using 2.12.0; however when I use Tensorflow 2.12.0 to load the model itself and use it within TF, everything works fine. Unfortunately, TF 2.5.0 cannot be installed using the Python version that I am using, and I am having a hard time trying to get some other Python version. Any advice?