tensorflow 2.x 默认不推荐、也不原生支持生成传统 frozen_graph.pb,应使用 tf.saved_model.save() 导出 savedmodel 目录(含 saved_model.pb 和 variables/);若强制需单个 .pb,则须回退兼容模式手动冻结图并转常量,易出错且丧失元数据支持。

什么是TensorFlow的“固化模型”(SavedModel vs frozen pb)
直接说结论:TensorFlow 2.x 默认不推荐、也不原生支持生成传统意义上的 frozen_graph.pb(即用 freeze_graph 工具导出的旧式单文件pb)。你真正该用的是 tf.saved_model.save() 导出的 SavedModel 格式——它本质是包含 variables/、assets/ 和 saved_model.pb 的目录,不是单个 .pb 文件。
如果你明确需要单个 .pb(比如部署到某些嵌入式推理引擎或旧版TensorRT),那必须手动“冻结”:把变量转为常量,再序列化图结构。这在 TF 2.x 中需回退到兼容模式,且容易出错。
TF 2.x 正确导出 SavedModel(推荐做法)
这是当前标准流程,兼容 eager mode,支持签名、多输入输出、自定义函数:
-
model必须是tf.keras.Model实例,或带@tf.function装饰的可调用对象 - 导出前建议先用
model(tf.zeros(...))触发一次前向,确保所有子图已构建 - 调用
tf.saved_model.save(model, "path/to/saved_model_dir")即可 - 导出后目录下会生成
saved_model.pb(图定义)和variables/(权重),这才是现代部署的基准格式
示例:
import tensorflow as tf <p>model = tf.keras.Sequential([tf.keras.layers.Dense(10, input_shape=(5,))]) model(tf.zeros((1, 5))) # warm up tf.saved_model.save(model, "my_model") </p>
非要生成 frozen_graph.pb?得绕回 TF 1.x 兼容路径
TF 2.x 中没有 freeze_graph.freeze_graph,必须显式启用 v1 行为,并手动提取图和变量:
- 必须用
tf.compat.v1模块,禁用 eager execution:tf.compat.v1.disable_eager_execution() - 模型需是
tf.compat.v1.Session下构建的图(Keras model 需先用model._set_inputs()或转为 ConcreteFunction) - 核心步骤:获取
ConcreteFunction→ 调用concrete_function.graph.as_graph_def()→ 用tf.graph_util.convert_variables_to_constants_v2冻结 - 冻结后得到的
graph_def才能用tf.io.write_graph(..., format="binary")写成 .pb
常见报错:ValueError: Cannot convert a partially defined TensorShape —— 多因输入 shape 未完全指定,务必在构建 concrete function 时传入完整 shape 示例。
冻结后的 pb 文件到底能不能直接 load?
不能直接用 tf.keras.models.load_model() 加载 frozen pb;它不含 Keras 层信息,只是纯计算图。
- 加载方式只能是:
tf.compat.v1.Graph().as_default()+tf.import_graph_def() - 必须手动查找输入/输出 tensor 名(如
"serving_default_input:0"),名字取决于导出时的 signature - 没有自动 shape 推断,
tensor.shape可能为None,需靠tensor.set_shape()补全 - 性能上,frozen pb 比 SavedModel 略快(少变量加载开销),但丢失了版本兼容、元数据、asset 支持等关键能力
真正容易被忽略的一点:很多所谓“pb 部署文档”默认你用的是 TF 1.x 图模式,而 TF 2.x 用户若没关 eager mode、没设 concrete function 输入 shape、没处理好 name scope,导出来的 pb 极大概率在下游解析时报 Not found: Op type not registered 或 tensor name mismatch。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











