保存为.keras格式后无法加载ResNet50迁移学习模型求助
模型保存后加载失败问题排查
操作流程
- 加载预训练ResNet50并冻结层
pretrained = tf.keras.applications.ResNet50(include_top = False, input_shape = (224,224,3), pooling = 'avg', classes = 525, weights = 'imagenet' ) for layer in pretrained.layers: # 设置层不参与训练 layer.trainable = False
- 构建自定义Sequential模型
model = keras.Sequential() model.add(pretrained) model.add(keras.layers.Dense(512, activation = 'relu', name = 'capa_1')) model.add(keras.layers.Dense(525, activation = 'softmax', name = 'capa_de_salida'))
- 训练模型(最终准确率达90%)
opt = keras.optimizers.Adam(learning_rate = 5.5e-05) model.compile(optimizer = opt, loss = 'categorical_crossentropy', metrics = ['accuracy']) history = model.fit(train_dataset, epochs = 10, validation_data = val_dor)
保存与加载报错
保存模型后执行加载操作失败:
path_model = './ResNet50_trans_learning_final.keras' model.save(path_model) modelo2 = tf.keras.models.load_model(path_model, compile=False)
报错详情
-------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In[102], line 5 1 model.save('ResNet50_trans_learning_final.keras') 3 path_model = './ResNet50_trans_learning_final.keras' ----> 5 modelo2 = tf.keras.models.load_model(path_model, compile=False) 6 # 问题出在flatten层,无法读取 File /usr/local/lib/python3.11/dist-packages/keras/src/saving/saving_api.py:176, in load_model(filepath, custom_objects, compile, safe_mode) 173 is_keras_zip = True 175 if is_keras_zip: --> 176 return saving_lib.load_model( 177 filepath, 178 custom_objects=custom_objects, 179 compile=compile, 180 safe_mode=safe_mode, 181 ) 182 if str(filepath).endswith((".h5", ".hdf5")): 183 return legacy_h5_format.load_model_from_hdf5(filepath) File /usr/local/lib/python3.11/dist-packages/keras/src/saving/saving_lib.py:155, in load_model(filepath, custom_objects, compile, safe_mode) 153 # 从归档中的配置文件构建模型 154 with ObjectSharingScope(): --> 155 model = deserialize_keras_object( 156 config_dict, custom_objects, safe_mode=safe_mode 157 ) 159 all_filenames = zf.namelist() 160 if _VARS_FNAME + ".h5" in all_filenames: File /usr/local/lib/python3.11/dist-packages/keras/src/saving/serialization_lib.py:711, in deserialize_keras_object(config, custom_objects, safe_mode, **kwargs) 709 with custom_obj_scope, safe_mode_scope: 710 try: --> 711 instance = cls.from_config(inner_config) 712 except TypeError as e: 713 raise TypeError( 714 f"{cls}无法正确反序列化,请确保所有Python对象组件(如自定义层、损失函数等)都已正确注册。" (...) 719 f"配置={config}。遇到的异常:{e}" 720 ) File /usr/local/lib/python3.11/dist-packages/keras/src/models/sequential.py:336, in Sequential.from_config(cls, config, custom_objects) 331 else: 332 layer = serialization_lib.deserialize_keras_object( 333 layer_config, 334 custom_objects=custom_objects, 335 ) --> 336 model.add(layer) 337 if ( 338 not model._functional 339 and build_input_shape 340 and isinstance(build_input_shape, (tuple, list)) 341 ): 342 model.build(build_input_shape) File /usr/local/lib/python3.11/dist-packages/keras/src/models/sequential.py:117, in Sequential.add(self, layer, rebuild) 115 self._layers.append(layer) 116 if rebuild: --> 117 self._maybe_rebuild() 118 else: 119 self.built = False File /usr/local/lib/python3.11/dist-packages/keras/src/models/sequential.py:136, in Sequential._maybe_rebuild(self) 134 if isinstance(self._layers[0], InputLayer) and len(self._layers) > 1: 135 input_shape = self._layers[0].batch_shape --> 136 self.build(input_shape) File /usr/local/lib/python3.11/dist-packages/keras/src/layers/layer.py:224, in Layer.__new__.<locals>.build_wrapper(*args, **kwargs) 221 @wraps(original_build_method) 222 def build_wrapper(*args, **kwargs): 223 with backend.name_scope(obj.name, caller=obj): --> 224 original_build_method(*args, **kwargs) 225 # 记录构建配置 226 signature = inspect.signature(original_build_method) File /usr/local/lib/python3.11/dist-packages/keras/src/models/sequential.py:177, in Sequential.build(self, input_shape) 175 for layer in self._layers[1:]: 176 try: --> 177 x = layer(x) 178 except NotImplementedError: 179 # 形状推断未实现时可能发生 180 # TODO:考虑还原已处理层的入站节点 181 return File /usr/local/lib/python3.11/dist-packages/keras/src/utils/traceback_utils.py:123, in filter_traceback.<locals>.error_handler(*args, **kwargs) 120 filtered_tb = _process_traceback_frames(e.__traceback__) 121 # 要获取完整堆栈跟踪,请调用: 122 # `keras.config.disable_traceback_filtering()` --> 123 raise e.with_traceback(filtered_tb) from None 124 finally: 125 del filtered_tb File /usr/local/lib/python3.11/dist-packages/keras/src/layers/input_spec.py:202, in assert_input_compatibility(input_spec, inputs, layer_name) 200 if spec.min_ndim is not None: 201 if ndim is not None and ndim < spec.min_ndim: --> 202 raise ValueError( 203 f'层"{layer_name}"的输入0与该层不兼容:期望最小维度={spec.min_ndim},实际找到维度={ndim}。接收的完整形状:{shape}' 204 ) 209 # 检查数据类型 210 if spec.dtype is not None: ValueError: 层"capa_de_salida"的输入0与该层不兼容:期望最小维度=2,实际找到维度=1。接收的完整形状:(512,)
使用环境
基于TensorFlow 2.16.1的Docker容器:
sudo docker run -it --rm -v ./:/tf/notebooks -p 8888:8888 --runtime=nvidia tensorflow/tensorflow:latest-gpu-jupyter
问题分析与解决办法
问题原因
报错核心是输出层capa_de_salida期望接收2维输入(格式为(批量大小, 特征数)),但模型加载时形状推断异常,实际传入了1维的(512,)张量。这是因为Sequential模型序列化时,没有完整保存输入形状的上下文信息,导致重建时无法正确推断各层的输入维度。
解决办法
1. 构建模型时显式添加输入层
在预训练模型前添加InputLayer,确保模型输入形状被明确记录:
model = keras.Sequential() model.add(keras.layers.Input(shape=(224,224,3))) # 显式定义输入形状 model.add(pretrained) model.add(keras.layers.Dense(512, activation = 'relu', name = 'capa_1')) model.add(keras.layers.Dense(525, activation = 'softmax', name = 'capa_de_salida'))
重新训练并保存模型后,加载时就能正确推断各层维度。
2. 加载模型时关闭安全模式
TensorFlow 2.16默认开启safe_mode=True的严格形状检查,尝试关闭该模式加载:
modelo2 = tf.keras.models.load_model(path_model, compile=False, safe_mode=False)
3. 改用Functional API构建模型
Functional API的序列化逻辑更稳定,能避免Sequential模型的形状推断问题:
inputs = keras.Input(shape=(224,224,3)) x = pretrained(inputs) x = keras.layers.Dense(512, activation='relu', name='capa_1')(x) outputs = keras.layers.Dense(525, activation='softmax', name='capa_de_salida')(x) model = keras.Model(inputs=inputs, outputs=outputs)
用此方式构建的模型,保存和加载过程不会出现维度不匹配问题。
内容的提问来源于stack exchange,提问作者Lesim Use
相关产品推荐
相关产品推荐

