加载PennyLane+TensorFlow Keras混合量子模型报错:未知KerasLayer层
混合量子-经典Keras模型加载失败问题解决
问题描述
用TensorFlow构建了包含经典卷积层和量子输出层的混合模型,能正常保存为.h5或.keras格式,但执行model = keras.models.load_model('MODEL_PATH')加载时,抛出如下错误:
ValueError: Unknown layer: 'KerasLayer'. Please ensure you are using a "keras.utils.custom_object_scope" and that this object is included in the scope.
完整错误日志:
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': ...}, {}, ...]}".
问题原因
这不是TensorFlow对量子集成支持不完善,而是自定义层加载时的标准问题:你的量子输出层是通过KerasLayer(通常来自TensorFlow Quantum或其他量子ML框架)实现的,这类非原生Keras层属于自定义对象,Keras在加载模型时无法自动识别,必须显式告知加载器该层的定义。
解决方法
方法1:加载时指定custom_objects参数
首先导入你的KerasLayer类(根据你使用的量子框架调整导入路径,比如TensorFlow Quantum的KerasLayer来自tensorflow_quantum.keras.layers),然后在load_model中传入custom_objects参数:
# 导入对应的KerasLayer import tensorflow_quantum as tfq from tensorflow import keras # 加载模型时指定自定义对象 loaded_model = keras.models.load_model( './models/hybrid3232.keras', custom_objects={'KerasLayer': tfq.keras.layers.KerasLayer} )
方法2:使用custom_object_scope上下文管理器
如果模型中有多个自定义对象,或者需要在更大范围内使用该层定义,可以用上下文管理器包裹加载代码:
import tensorflow_quantum as tfq from tensorflow import keras from tensorflow.keras.utils import custom_object_scope with custom_object_scope({'KerasLayer': tfq.keras.layers.KerasLayer}): loaded_model = keras.models.load_model('./models/hybrid3232.keras')
注意事项
- 确保加载模型时使用的量子框架版本和保存模型时一致,版本不匹配可能导致层定义不兼容
- 如果你的
KerasLayer是自己封装的自定义子类,需要导入你自己定义的那个类,而不是框架原生的KerasLayer
内容的提问来源于stack exchange,提问作者Ryan Wang
相关产品推荐
相关产品推荐

