I'm creating a hybrid model consisting of classical convolutional layers and a quantum output using Tensorflow. I can save the model in either .h5 or .keras format, but when I load them with code model = keras.models.load_model('MODEL_PATH')
they give
ValueError: Unknown layer: 'KerasLayer'. Please ensure you are using a "keras.utils.custom_object_scope" and that this object is included in the scope. See https://www.tensorflow.org/guide/keras/save_and_serialize#registering_the_custom_object for details.
The full error log is here:
ValueError Traceback (most recent call last)
/Users/raheyo/Research/SpookyEngine/model.ipynb Cell 30 line 1
----> 1 loadedHybrid = keras.models.load_model('./models/hybrid3232.keras')
File /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/keras/src/saving/saving_api.py:230, in load_model(filepath, custom_objects, compile, safe_mode, **kwargs)
225 if kwargs:
226 raise ValueError(
227 "The following argument(s) are not supported "
228 f"with the native Keras format: {list(kwargs.keys())}"
229 )
--> 230 return saving_lib.load_model(
231 filepath,
232 custom_objects=custom_objects,
233 compile=compile,
234 safe_mode=safe_mode,
235 )
237 # Legacy case.
238 return legacy_sm_saving_lib.load_model(
239 filepath, custom_objects=custom_objects, compile=compile, **kwargs
240 )
File /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/keras/src/saving/saving_lib.py:275, in load_model(filepath, custom_objects, compile, safe_mode)
272 asset_store.close()
274 except Exception as e:
--> 275 raise e
276 else:
277 return model
File /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/keras/src/saving/saving_lib.py:240, in load_model(filepath, custom_objects, compile, safe_mode)
238 # Construct the model from the configuration file in the archive.
239 with ObjectSharingScope():
--> 240 model = deserialize_keras_object(
241 config_dict, custom_objects, safe_mode=safe_mode
242 )
244 all_filenames = zf.namelist()
245 if _VARS_FNAME + ".h5" in all_filenames:
File /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/keras/src/saving/serialization_lib.py:704, in deserialize_keras_object(config, custom_objects, safe_mode, **kwargs)
702 safe_mode_scope = SafeModeScope(safe_mode)
703 with custom_obj_scope, safe_mode_scope:
--> 704 instance = cls.from_config(inner_config)
705 build_config = config.get("build_config", None)
706 if build_config:
File /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/keras/src/engine/sequential.py:473, in Sequential.from_config(cls, config, custom_objects)
471 for layer_config in layer_configs:
472 use_legacy_format = "module" not in layer_config
--> 473 layer = layer_module.deserialize(
474 layer_config,
475 custom_objects=custom_objects,
476 use_legacy_format=use_legacy_format,
477 )
478 model.add(layer)
480 if (
481 not model.inputs
482 and build_input_shape
483 and isinstance(build_input_shape, (tuple, list))
484 ):
File /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/keras/src/layers/serialization.py:269, in deserialize(config, custom_objects, use_legacy_format)
265 raise ValueError(
266 f"Cannot deserialize empty config. Received: config={config}"
267 )
268 if use_legacy_format:
--> 269 return legacy_serialization.deserialize_keras_object(
270 config,
271 module_objects=LOCAL.ALL_OBJECTS,
272 custom_objects=custom_objects,
273 printable_module_name="layer",
274 )
276 return serialization_lib.deserialize_keras_object(
277 config,
278 module_objects=LOCAL.ALL_OBJECTS,
279 custom_objects=custom_objects,
280 printable_module_name="layer",
281 )
File /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/keras/src/saving/legacy/serialization.py:480, in deserialize_keras_object(identifier, module_objects, custom_objects, printable_module_name)
477 if isinstance(identifier, dict):
478 # In this case we are dealing with a Keras config dictionary.
479 config = identifier
--> 480 (cls, cls_config) = class_and_config_for_serialized_keras_object(
481 config, module_objects, custom_objects, printable_module_name
482 )
484 # If this object has already been loaded (i.e. it's shared between
485 # multiple objects), return the already-loaded object.
486 shared_object_id = config.get(SHARED_OBJECT_KEY)
File /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/keras/src/saving/legacy/serialization.py:365, in class_and_config_for_serialized_keras_object(config, module_objects, custom_objects, printable_module_name)
361 cls = object_registration.get_registered_object(
362 class_name, custom_objects, module_objects
363 )
364 if cls is None:
--> 365 raise ValueError(
366 f"Unknown {printable_module_name}: '{class_name}'. "
367 "Please ensure you are using a `keras.utils.custom_object_scope` "
368 "and that this object is included in the scope. See "
369 "https://www.tensorflow.org/guide/keras/save_and_serialize"
370 "#registering_the_custom_object for details."
371 )
373 cls_config = config["config"]
374 # Check if `cls_config` is a list. If it is a list, return the class and the
375 # associated class configs for recursively deserialization. This case will
376 # happen on the old version of sequential model (e.g. `keras_version` ==
377 # "2.0.6"), which is serialized in a different structure, for example
378 # "{'class_name': 'Sequential',
379 # 'config': [{'class_name': 'Embedding', 'config': ...}, {}, ...]}".
Is it that tensorflow doesn't fully support quantum integration yet? Or I did something wrong? Thanks!
I posted an alternative solution over here: https://quantumcomputing.stackexchange.com/q/34920/25997
But essentially, I had no way to work around the traditional
model.save(MODEL_PATH)
method, but I usedmodel.save_weights(WEIGHTS_PATH)
instead to save the model and load it back up later. See this official Tensorflow Doc for more details.