CoreML Conversion of TensorFlow Keras NN fails on Iris Data set

On tf version 2.11.0.

I have tried to follow on a fairly standard NN example in order to convert to a CoreML model. However, I cannot get this to work and I'm not clear where it is going wrong. It would seem to be a fairly standard task - a toy example - and I can't see why the conversion would fail.

Any help would be appreciated. I have tried the different approaches listed below, but it seems the conversion should just work.

I have also tried running the same code pinned to: tensorflow==2.6.2 scikit-learn==0.19.2 pandas==1.1.1

And get a different sequence of errors.

The Python code I used mostly comes form this example: https://lnwatson.co.uk/posts/intro_to_nn/

import pandas as pd
import numpy as np
import tensorflow as tf 
import torch
from sklearn.model_selection import train_test_split
from tensorflow import keras

import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '1' 

np.bool = np.bool_
np.int = np.int_

print("tf version", tf.__version__)

csv_url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data'
col_names = ['Sepal_Length','Sepal_Width','Petal_Length','Petal_Width','Class']
df =  pd.read_csv(csv_url, names = col_names)

labels = df.pop('Class')
labels = pd.get_dummies(labels)

X = df.values
y = labels.values
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.05)
X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=0.2)

model = keras.Sequential()
model.add(keras.layers.Dense(16, activation='relu', input_shape=(4,)))
model.add(keras.layers.Dense(3, activation='softmax'))
model.summary()

model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(X_train, y_train,
          batch_size=12,
          epochs=200,
          validation_data=(X_val, y_val))

import coremltools as ct

# Pass in `tf.keras.Model` to the Unified Conversion API
mlmodel = ct.convert(model, convert_to="mlprogram")
# mlmodel = ct.convert(model, source="tensorflow")
# mlmodel = ct.convert(model, convert_to="neuralnetwork")

# mlmodel = ct.convert(
#     model,
#     source="tensorflow",
# 	inputs=[ct.TensorType(name="input")],
#  	outputs=[ct.TensorType(name="output")],
#     minimum_deployment_target=ct.target.iOS14,
# )

When using either of these 3:

mlmodel = ct.convert(model, convert_to="mlprogram")
mlmodel = ct.convert(model, source="tensorflow")
mlmodel = ct.convert(model, convert_to="neuralnetwork")

I get:



mlmodel2 = ct.convert(model, source="tensorflow")

ValueError: Const node 'sequential_5/dense_10/MatMul/ReadVariableOp' cannot have no value



ERROR:root:sequential_5/dense_11/BiasAdd/ReadVariableOp:0
ERROR:root:[ 0.34652767 0.16202268 -0.3554725 ]
Running TensorFlow Graph Passes: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 5/5 [00:00<00:00, 28.76 passes/s]
Converting Frontend ==> MIL Ops:  8%|█████████████████                                                                                              | 1/12 [00:00<00:00, 16710.37 ops/s]
---------------------------------------------------------------------------
ValueError                Traceback (most recent call last)
File ~/Documents/CoreML Basic Models/NN_Keras_Iris.py:142
  130 import coremltools as ct
  131 # Pass in `tf.keras.Model` to the Unified Conversion API
  132 # mlmodel = ct.convert(model, convert_to="mlprogram")
  133 
  (...)
  140 
  141 # ct.convert(mymodel(), source="tensorflow")
--> 142 mlmodel2 = ct.convert(model, source="tensorflow")
  144 mlmodel = ct.convert(
  145   model,
  146   source="tensorflow",
  (...)
  153   minimum_deployment_target=ct.target.iOS14,
  154 )


....

File ~/opt/anaconda3/envs/coreml_env/lib/python3.8/site-packages/coremltools/converters/mil/frontend/tensorflow/ops.py:430, in Const(context, node)
  427 @register_tf_op
  428 def Const(context, node):
  429   if node.value is None:
--> 430     raise ValueError("Const node '{}' cannot have no value".format(node.name))
  431   mode = get_const_mode(node.value.val)
  432   x = mb.const(val=node.value.val, mode=mode, name=node.name)

ValueError: Const node 'sequential_5/dense_10/MatMul/ReadVariableOp' cannot have no value

Second Approach:

A different approach I tried was specifying the inout type TensorType.

However, when specifying the input and outputs I get a different error. I have tried variations on this initialiser but all produce the same error.

The variations revolve around adding input_shape, dtype=np.float32

mlmodel = ct.convert(
    model,
    source="tensorflow",
	inputs=[ct.TensorType(name="input")],
 	outputs=[ct.TensorType(name="output")],
    minimum_deployment_target=ct.target.iOS14,
)

t

File ~/opt/anaconda3/envs/coreml_env/lib/python3.8/site-packages/coremltools/converters/mil/frontend/tensorflow/load.py:106, in <listcomp>(.0)
  104 logging.debug(msg.format(outputs))
  105 outputs = outputs if isinstance(outputs, list) else [outputs]
--> 106 outputs = [i.split(":")[0] for i in outputs]
  107 if _get_version(tf.__version__) < _StrictVersion("1.13.1"):
  108   return tf.graph_util.extract_sub_graph(graph_def, outputs)

AttributeError: 'TensorType' object has no attribute 'split'