如何将Keras模型导出为.pbtxt文件 解决TF2.2+Keras2.3环境转换报错
TF2.2+Keras2.3环境下pbtxt模型保存适配方案
报错根因
该Input 0 of node ... AssignSubVariableOp incompatible with expected resource错误为指定版本组合的原生兼容问题:
- 按要求使用独立安装的
keras.applications.DenseNet121时,模型内部BatchNorm、卷积层的变量,是基于独立Keras的资源管理逻辑创建的Resource类型节点 - 参考教程使用的
convert_variables_to_constants_v2接口在TF2.2版本中,无法正确识别独立Keras创建的Resource类型变量,会错误地把普通float值传入要求Resource类型输入的节点端口,触发图导入时的类型校验失败。
适配操作流程(严格保留要求的DenseNet导入方式)
1. 前置环境兼容配置
在模型构建前,完成Keras后端与当前TF图的绑定,避免资源管理脱节:
import tensorflow as tf # 关闭eager模式,匹配Keras2.3对静态图的兼容要求 tf.compat.v1.disable_eager_execution() # 严格按要求保留该DenseNet导入,禁止替换为tf.keras对应接口 from keras.applications import DenseNet121 from keras.models import Sequential from keras.layers import Dense from keras import backend as K # 绑定Keras后端会话到当前TF静态图 K.set_session(tf.compat.v1.Session())
2. 模型构建修正
在原有模型结构基础上,补充全局池化层匹配低版本下的维度推导逻辑,不改变模型预测行为:
opt = tf.keras.optimizers.Adam(learning_rate=1e-4) # 替换为你实际使用的优化器配置 densenet_wrapper = DenseNet121(weights='imagenet', include_top=False, input_shape=(224, 224, 3)) def build_model(): model = Sequential() model.add(densenet_wrapper) # 补充全局平均池化,消除低版本下4维特征图到Dense层的维度推导错误 model.add(tf.keras.layers.GlobalAveragePooling2D()) model.add(Dense(5, activation=tf.keras.activations.relu)) model.add(Dense(1, activation="linear")) model.compile(loss='mse', optimizer=opt, metrics=['mse', 'acc']) print(model.summary()) return model model = build_model()
3. 低版本兼容的模型冻结与pbtxt保存逻辑
替换原教程中易触发类型不匹配的tf.function转换逻辑,使用TF2.2兼容的图冻结接口:
import os # 提前创建模型保存目录 save_dir = './pbtxt_save_dir' os.makedirs(save_dir, exist_ok=True) output_pb_name = 'frozen_graph.pbtxt' # 获取当前会话的图定义,以及模型的输出节点名称 sess = K.get_session() output_node_name = model.output.op.name # 使用TF2.2原生的常量转换接口,冻结所有变量 from tensorflow.python.framework import graph_util frozen_graph_def = graph_util.convert_variables_to_constants( sess=sess, input_graph_def=sess.graph.as_graph_def(), output_node_names=[output_node_name] ) # 写入文本格式的pbtxt文件 tf.io.write_graph( graph_or_graph_def=frozen_graph_def, logdir=save_dir, name=output_pb_name, as_text=True )
校验注意事项
- 保存完成后,可打开pbtxt文件确认输入节点维度为
[None, 224, 224, 3],输出节点为线性激活层的对应Op,无缺失的Resource类型节点 - 禁止中途将独立Keras的DenseNet121替换为tf.keras对应接口,否则会触发图重复初始化,再次出现Resource类型不匹配的报错
- 若运行时出现图节点重复报错,可在脚本最开头增加Keras会话重置操作:
K.clear_session()
内容的提问来源于stack exchange,提问作者busman
相关产品推荐
相关产品推荐

