Skip to content

Support for BERT's hub.KerasLayer preprocessors and encoders #5734

Open
@thibaut-d

Description

@thibaut-d

System information

  • TensorFlow.js version: 3.9.0
  • tfjs-react-native version: 0.7.0

Current behavior/state.

I'm trying to make a pilot project to see how we can use BERT in React Native with TensorFlow.js.

The code is public: https://github.com/thibaut-d/Bert-in-React-Native-with-TensorFlow.js

I train the following model:

# Preprocessing
bert_preprocess_model = hub.KerasLayer('https://tfhub.dev/tensorflow/bert_en_uncased_preprocess/3')

# Bert encoder
bert_model = hub.KerasLayer('https://tfhub.dev/tensorflow/small_bert/bert_en_uncased_L-2_H-128_A-2/2')

# Model
def build_model():

  # Input
  text_input = tf.keras.layers.Input(shape=(), dtype=tf.string, name='text')

  # Preprocessing 
  preprocessing_layer = hub.KerasLayer(tfhub_handle_preprocess, name='preprocessing')

  # Encoder
  encoder_inputs = preprocessing_layer(text_input)
  encoder = hub.KerasLayer(tfhub_handle_encoder, trainable=True, name='BERT_encoder')

  # Encoder's output
  outputs = encoder(encoder_inputs)
  net = outputs['pooled_output']
  net = tf.keras.layers.Dropout(0.1)(net)

  # Classifier
  regression = tf.keras.layers.Dense(1, name='regression', activation=None)(net)
  classifier = tf.keras.layers.Dense(1, name='classifier', activation='sigmoid')(net)

  # Final output
  outputs = {'regression': regression, 'classifier': classifier}

  # Return the model
  return tf.keras.Model(text_input, outputs)

I do not include the Python code for training and testing, as it is quite classic.

I save it to different formats:

# Save to Tensorflow SavedModel
model.save("./formats/tf_savedmodel",save_format='tf')

WARNING:absl:Found untraced functions such as restored_function_body, restored_function_body, restored_function_body, restored_function_body, restored_function_body while saving (showing 5 of 165). These functions will not be directly callable after loading.

# Save to HDF5
model.save('./formats/tf_hdf5/model.h5',save_format='h5')

No warning

Then I try different exports:

# Keras HDF5 --> tfjs_layers_model
!tensorflowjs_converter --input_format keras --output_format tfjs_layers_model ./formats/tf_hdf5/model.h5 ./formats/tfjs_layers_model_from_keras_hdf5

No warning

# Keras HDF5 --> tfjs_graph_model
!tensorflowjs_converter --input_format keras --output_format tfjs_graph_model ./formats/tf_hdf5/model.h5 ./formats/tfjs_graph_model_from_keras_hdf5

I get the error message:

Traceback (most recent call last):
  File "C:\Users\thiba\anaconda3\envs\bert\lib\runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "C:\Users\thiba\anaconda3\envs\bert\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\Users\thiba\anaconda3\envs\bert\Scripts\tensorflowjs_converter.exe\__main__.py", line 7, in <module>
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\tensorflowjs\converters\converter.py", line 813, in pip_main
    main([' '.join(sys.argv[1:])])
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\tensorflowjs\converters\converter.py", line 817, in main
    convert(argv[0].split(' '))
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\tensorflowjs\converters\converter.py", line 803, in convert
    _dispatch_converter(input_format, output_format, args, quantization_dtype_map,
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\tensorflowjs\converters\converter.py", line 504, in _dispatch_converter
    dispatch_keras_h5_to_tfjs_graph_model_conversion(
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\tensorflowjs\converters\converter.py", line 140, in dispatch_keras_h5_to_tfjs_graph_model_conversion
    model = tf.keras.models.load_model(h5_path, compile=False)
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\keras\saving\save.py", line 200, in load_model
    return hdf5_format.load_model_from_hdf5(filepath, custom_objects,
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\keras\saving\hdf5_format.py", line 180, in load_model_from_hdf5
    model = model_config_lib.model_from_config(model_config,
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\keras\saving\model_config.py", line 52, in model_from_config
    return deserialize(config, custom_objects=custom_objects)
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\keras\layers\serialization.py", line 208, in deserialize
    return generic_utils.deserialize_keras_object(
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\keras\utils\generic_utils.py", line 674, in deserialize_keras_object
    deserialized_obj = cls.from_config(
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\keras\engine\functional.py", line 662, in from_config
    input_tensors, output_tensors, created_layers = reconstruct_from_config(
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\keras\engine\functional.py", line 1273, in reconstruct_from_config
    process_layer(layer_data)
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\keras\engine\functional.py", line 1255, in process_layer
    layer = deserialize_layer(layer_data, custom_objects=custom_objects)
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\keras\layers\serialization.py", line 208, in deserialize
    return generic_utils.deserialize_keras_object(
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\keras\utils\generic_utils.py", line 659, in deserialize_keras_object
    (cls, cls_config) = class_and_config_for_serialized_keras_object(
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\keras\utils\generic_utils.py", line 556, in class_and_config_for_serialized_keras_object
    raise ValueError(
ValueError: Unknown layer: KerasLayer. Please ensure this object is passed to the `custom_objects` argument. See https://www.tensorflow.org/guide/keras/save_and_serialize#registering_the_custom_object for details.

I also tried to export form tf savedmodel, despite the warning:

# tf_saved_model --> tfjs_graph_model
!tensorflowjs_converter --input_format tf_saved_model --output_format=tfjs_graph_model ./formats/tf_savedmodel ./formats/tfjs_graph_model_from_tf_saved_model
2021-10-17 21:13:22.786947: I tensorflow/core/platform/cpu_feature_guard.cc:142] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX AVX2
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
2021-10-17 21:13:23.483860: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1510] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 1789 MB memory:  -> device: 0, name: NVIDIA GeForce GTX 1050, pci bus id: 0000:01:00.0, compute capability: 6.1
Traceback (most recent call last):
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\tensorflow\python\framework\ops.py", line 3962, in _get_op_def
    return self._op_def_cache[type]
KeyError: 'CaseFoldUTF8'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\tensorflow\python\saved_model\load.py", line 902, in load_internal
    loader = loader_cls(object_graph_proto, saved_model_proto, export_dir,
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\tensorflow\python\saved_model\load.py", line 137, in __init__
    function_deserialization.load_function_def_library(
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\tensorflow\python\saved_model\function_deserialization.py", line 388, in load_function_def_library
    func_graph = function_def_lib.function_def_to_graph(copy)
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\tensorflow\python\framework\function_def_to_graph.py", line 63, in function_def_to_graph
    graph_def, nested_to_flat_tensor_name = function_def_to_graph_def(
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\tensorflow\python\framework\function_def_to_graph.py", line 228, in function_def_to_graph_def
    op_def = default_graph._get_op_def(node_def.op)  # pylint: disable=protected-access
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\tensorflow\python\framework\ops.py", line 3966, in _get_op_def
    pywrap_tf_session.TF_GraphGetOpDef(self._c_graph, compat.as_bytes(type),
tensorflow.python.framework.errors_impl.NotFoundError: Op type not registered 'CaseFoldUTF8' in binary running on IDEAPAD. Make sure the Op and Kernel are registered in the binary running in this process. Note that if you are loading a saved graph which used ops from tf.contrib, accessing (e.g.) `tf.contrib.resampler` should be done before importing the graph, as contrib ops are lazily registered when the module is first accessed.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\thiba\anaconda3\envs\bert\lib\runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "C:\Users\thiba\anaconda3\envs\bert\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\Users\thiba\anaconda3\envs\bert\Scripts\tensorflowjs_converter.exe\__main__.py", line 7, in <module>
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\tensorflowjs\converters\converter.py", line 813, in pip_main
    main([' '.join(sys.argv[1:])])
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\tensorflowjs\converters\converter.py", line 817, in main
    convert(argv[0].split(' '))
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\tensorflowjs\converters\converter.py", line 803, in convert
    _dispatch_converter(input_format, output_format, args, quantization_dtype_map,
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\tensorflowjs\converters\converter.py", line 523, in _dispatch_converter
    tf_saved_model_conversion_v2.convert_tf_saved_model(
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\tensorflowjs\converters\tf_saved_model_conversion_v2.py", line 599, in convert_tf_saved_model
    model = _load_model(saved_model_dir, saved_model_tags)
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\tensorflowjs\converters\tf_saved_model_conversion_v2.py", line 536, in _load_model
    model = load(saved_model_dir, saved_model_tags)
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\tensorflow\python\saved_model\load.py", line 864, in load
    result = load_internal(export_dir, tags, options)["root"]
  File "C:\Users\thiba\anaconda3\envs\bert\lib\site-packages\tensorflow\python\saved_model\load.py", line 905, in load_internal
    raise FileNotFoundError(
FileNotFoundError: Op type not registered 'CaseFoldUTF8' in binary running on IDEAPAD. Make sure the Op and Kernel are registered in the binary running in this process. Note that if you are loading a saved graph which used ops from tf.contrib, accessing (e.g.) `tf.contrib.resampler` should be done before importing the graph, as contrib ops are lazily registered when the module is first accessed.
 If trying to load on a different device from the computational device, consider using setting the `experimental_io_device` option on tf.saved_model.LoadOptions to the io_device such as '/job:localhost'.

Since exporting to keras HDF5 and converting to tfjs_layers did not raise warning or errors, I tried to run it in React Native.

TensforFlow.js successfully loads, with backend: rn-webgl.

But when I load the model with:

const modelJson = require('./model/model.json');
const m1 = require('./model/group1-shard1of5.bin');
const m2 = require('./model/group1-shard2of5.bin');
const m3 = require('./model/group1-shard3of5.bin');
const m4 = require('./model/group1-shard4of5.bin');
const m5 = require('./model/group1-shard5of5.bin');

 const model = await tf.loadLayersModel(bundleResourceIO(modelJson, [m1,m2,m3,m4,m5]))

I get the following message:

[Error: Unknown layer: KerasLayer. This may be due to one of the following reasons:
1. The layer is defined in Python, in which case it needs to be ported to TensorFlow.js or your JavaScript code.
2. The custom layer is defined in JavaScript, but is not registered properly with tf.serialization.registerClass().]

So ?

My bet is that all these errors are linked to the fact that one or both of the hub.KerasLayer are not supported.

# Preprocessing
bert_preprocess_model = hub.KerasLayer('https://tfhub.dev/tensorflow/bert_en_uncased_preprocess/3')

# Bert encoder
bert_model = hub.KerasLayer('https://tfhub.dev/tensorflow/small_bert/bert_en_uncased_L-2_H-128_A-2/2')

Is there something I can do to load these layers?

Does another similar model support it?

The current option I see is to rely on HuggingFace transformers library on the Python side and to implement from scratch the preprocessing in JavaScript. Is it the only option?

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions