Keras训练正常的模型保存后加载出现Graph disconnected错误如何解决
Keras模型训练正常、保存后加载报Graph disconnected错误解决方案
错误根源
报错的核心原因是你手动遍历子模型层调用时,保留了原各个子模型自带的输入层节点,同时直接修改层的_name私有属性破坏了Keras内部的依赖记录。训练时动态图模式下可以正常运行,但保存序列化时计算图依赖没有正确记录,加载时校验失败。具体来说报错里提到的InputLucaSchifoso就是model_LucaSchifoso自带的输入层,该节点没有和你自定义的全局输入层input_layer建立正确的连接,加载时找不到该节点的上游输入,因此报计算图断开错误。
解决方法
- 方案一:权重加载法(无需修改训练代码,可快速解决问题)
不需要直接加载整个保存的模型文件,先完全复现训练时的模型构建代码,得到和训练时结构完全一致的空白模型,再单独加载权重即可:
# 复制训练时的模型构建代码,得到结构完全一致的空白modellone modellone = build_your_model() # 仅加载保存的权重 modellone.load_weights("best/variables/variables")
- 方案二:重构模型构建逻辑(彻底解决序列化问题,方便后续保存加载)
- 不要直接遍历子模型的每层逐个调用,也不要手动修改层的
_name私有属性,改为先截断子模型到需要的输出层,再整体调用截断后的子模型,自动规避子模型输入层残留的问题:
layers_dict = {} extra_out = {} input_layer = tfk.layers.Input(shape=input_shape, name="input_layer") for model_name in preprocessing_function_dict: # 预处理层 proc_out = tfk.layers.Lambda( preprocessing_function_dict[model_name], name="lambda_" + model_name )(input_layer) if model_name == "LucaSchifoso": # 截断子模型到第10层输出,自动丢弃原输入层 sub_model = tfk.Model( inputs=model_dict[model_name].input, outputs=model_dict[model_name].layers[10].output, name=f"sub_{model_name}" ) luca_out = sub_model(proc_out) # 后续自定义处理 extra_out["LucaSchifoso"] = tfkl.Flatten(name='flatten_LucaSchifoso1')( tfkl.MaxPooling2D(name='maxpool_LucaSchifoso1', pool_size = (3, 3))(luca_out) ) else: # 其他模型截断到第2层输出 sub_model = tfk.Model( inputs=model_dict[model_name].input, outputs=model_dict[model_name].layers[2].output, name=f"sub_{model_name}" ) layers_dict[model_name] = sub_model(proc_out) # 拼接层 concatenate_layer = tfkl.Concatenate()([ layers_dict["InceptionV3"], layers_dict["MobileNetV2"], extra_out["LucaSchifoso"], layers_dict["Resnet50"] ])
- 尽量避免使用Lambda层封装预处理逻辑,改为实现自定义可序列化层,重写
get_config方法,保证序列化时依赖不会丢失。 - 子模型加载时直接指定
name参数,让Keras自动给子模型所有层添加前缀,无需手动修改层名避免冲突。
- 方案三:加载时指定自定义对象
如果用到了自定义层、自定义损失或者Lambda层,加载时在custom_objects参数中传入对应的对象即可:
model = tf.keras.models.load_model('best', custom_objects={ # 传入你用到的自定义层、预处理函数等 })
内容的提问来源于stack exchange,提问作者Axelitama
相关产品推荐
相关产品推荐

