tensorflow: Cannot convert model containing categorical_column_with_vocabulary_list op

System information

  • OS Platform and Distribution (e.g., Linux Ubuntu 16.04):CentOS
  • TensorFlow installed from (source or binary): binary
  • TensorFlow version (or github SHA if from source): 2.2.0rc0

Command used to run the converter or code if you’re using the Python API If possible, please share a link to Colab/Jupyter/any notebook.

import tensorflow as tf
import os

model_dir = "models/feature_column_example"
category = tf.constant(["A", "B", "A", "C", "C", "A"])
label = tf.constant([1, 0, 1, 0, 0, 0])

ds = tf.data.Dataset.from_tensor_slices(({"category": category}, label))
ds = ds.batch(2)

fc_category = tf.feature_column.indicator_column(
    tf.feature_column.categorical_column_with_vocabulary_list(
        "category", vocabulary_list=["A", "B", "C"]
    )
)
feature_layer = tf.keras.layers.DenseFeatures([fc_category])

model = tf.keras.Sequential(
    [
        feature_layer,
        tf.keras.layers.Dense(10, activation="relu"),
        tf.keras.layers.Dense(1, activation="sigmoid"),
    ]
)
model.compile(
    optimizer="adam", loss="binary_crossentropy", metrics=["accuracy"]
)

model.fit(ds, epochs=2)
converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.allow_custom_ops = True
# converter.experimental_new_converter = True
# converter.experimental_new_quantizer = True

# Convert the model.
tflite_model = converter.convert()
open(os.path.join(model_dir, "output.tflite"), "wb").write(tflite_model)

The output from the converter invocation

Cannot convert a Tensor of dtype resource to a NumPy array.

Also, please include a link to the saved model or GraphDef

saved_model_cli show --dir models/feature_column_example/ --tag_set serve --signature_def serving_default

The given SavedModel SignatureDef contains the following input(s):
  inputs['category'] tensor_info:
      dtype: DT_STRING
      shape: (-1, 1)
      name: serving_default_category:0
The given SavedModel SignatureDef contains the following output(s):
  outputs['output_1'] tensor_info:
      dtype: DT_FLOAT
      shape: (-1, 1)
      name: StatefulPartitionedCall_7:0
Method name is: tensorflow/serving/predict

Failure details Cannot convert a Tensor of dtype resource to a NumPy array.

According to my analysis, this might be caused by some HashTable Ops, which create table handles. And my additional question is: whether tfliteconverter could convert model contains ops of initialize hashtableV2 and LookupTableImportV2? Thank you.

Any other info / logs: Full logs

Traceback (most recent call last):
  File "feature_column_example.py", line 62, in <module>
    export_keras_hashtable_model()
  File "feature_column_example.py", line 58, in export_keras_hashtable_model
    tflite_model = converter.convert()
  File "/root/tf2.2/lib/python3.6/site-packages/tensorflow/lite/python/lite.py", line 464, in convert
    self._funcs[0], lower_control_flow=False))
  File "/root/tf2.2/lib/python3.6/site-packages/tensorflow/python/framework/convert_to_constants.py", line 706, in convert_variables_to_constants_v2_as_graph
    func, lower_control_flow, aggressive_inlining)
  File "/root/tf2.2/lib/python3.6/site-packages/tensorflow/python/framework/convert_to_constants.py", line 457, in _convert_variables_to_constants_v2_impl
    tensor_data = _get_tensor_data(func)
  File "/root/tf2.2/lib/python3.6/site-packages/tensorflow/python/framework/convert_to_constants.py", line 217, in _get_tensor_data
    data = val_tensor.numpy()
  File "/root/tf2.2/lib/python3.6/site-packages/tensorflow/python/framework/ops.py", line 961, in numpy
    maybe_arr = self._numpy()  # pylint: disable=protected-access
  File "/root/tf2.2/lib/python3.6/site-packages/tensorflow/python/framework/ops.py", line 929, in _numpy
    six.raise_from(core._status_to_exception(e.code, e.message), None)
  File "<string>", line 3, in raise_from
tensorflow.python.framework.errors_impl.InvalidArgumentError: Cannot convert a Tensor of dtype resource to a NumPy array.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 18 (11 by maintainers)

Most upvoted comments

EMBEDDING_LOOKUP is already supported via TensorFlow Lite builtin ops. And the experimental hashtable op kernels are existing under the following directory: https://github.com/tensorflow/tensorflow/tree/master/tensorflow/lite/experimental/kernels. In order to enable them in Python, here is the example code.

with tf.Session() as sess:
    int64_values = tf.constant([1, 2, 3], dtype=tf.int64)
    string_values = tf.constant(['bar', 'foo', 'baz'], dtype=tf.string)
    int64_to_string_initializer = tf.lookup.KeyValueTensorInitializer(
        int64_values, string_values)
    string_to_int64_initializer = tf.lookup.KeyValueTensorInitializer(
        string_values, int64_values)
    int64_to_string_table = tf.lookup.StaticHashTable(
        int64_to_string_initializer, '7')
    string_to_int64_table = tf.lookup.StaticHashTable(
        string_to_int64_initializer, 4)

    with tf.control_dependencies([tf.initializers.tables_initializer()]):
      input_int64_tensor = tf.placeholder(tf.int64, shape=[1])
      input_string_tensor = tf.placeholder(tf.string, shape=[1])
      out_string_tensor = int64_to_string_table.lookup(input_int64_tensor)
      out_int64_tensor = string_to_int64_table.lookup(input_string_tensor)

    graph_def = tf.get_default_graph().as_graph_def()
    tf.io.write_graph(graph_def, '/tmp/', 'hashtable.pbtxt')

  converter = tf.lite.TFLiteConverter(graph_def,
                                      [input_int64_tensor, input_string_tensor],
                                      [out_string_tensor, out_int64_tensor])

  supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS]
  converter.target_spec.supported_ops = supported_ops
  converter.allow_custom_ops = True
  tflite_model = converter.convert()

  # Initialize interpreter with HashTableV2 custom ops.
  model_interpreter = interpreter_wrapper.InterpreterWithCustomOps(
      model_content=tflite_model, custom_op_registerers=['AddHashtableOps'])

  input_details = model_interpreter.get_input_details()
  output_details = model_interpreter.get_output_details()
  print('Input details: ', input_details)
  print('Output details: ', output_details)

  model_interpreter.allocate_tensors()
  model_interpreter.reset_all_variables()
  model_interpreter.set_tensor(input_details[0]['index'],
                               np.array([2], dtype=np.int64))
  model_interpreter.set_tensor(input_details[1]['index'],
                               np.array(['foo'], dtype=np.string_))
  model_interpreter.invoke()

  for out in output_details:
    result = model_interpreter.get_tensor(out['index'])  # Expect no errors.
    print('Result tensor: ', out['name'], result.shape, result)

The AddHashtableOps Python module exists in here: https://github.com/tensorflow/tensorflow/blob/master/tensorflow/lite/experimental/kernels/BUILD#L177

If you want to make your own custom ops, please check out https://www.tensorflow.org/lite/guide/ops_custom.

For the below error at the conversion, currently, we are trying to fix it soon hopefully. I will leave a comment when it is fixed in the nightly build.

Cannot convert a Tensor of dtype resource to a NumPy array.

Was able to reproduce the issue with TF v2.2.0-rc1 and TF-nightly. Please find the attached gist. Thanks!