tensorflow模型静态导出供c++调用需用tf.saved_model.save()生成savedmodel,显式定义带tf.tensorspec的concrete function并指定signatures;c++加载时须版本严格匹配、路径规范、输入shape/dtype与signature完全一致。

TensorFlow 模型静态导出给 C++ 调用,核心是用 tf.saved_model.save() 生成 SavedModel 格式,并确保图结构冻结、输入输出签名明确——否则 C++ 的 tensorflow::SavedModelBundle::LoadSavedModel() 会报 Invalid argument: Input xxx is not in graph 或找不到 signature。
导出前必须显式定义 concrete function 并指定 input_signature
动态图(Eager)默认不带固定输入形状和类型,C++ 加载时无法推断 tensor shape,直接导出会丢失输入约束。必须用 @tf.function + get_concrete_function() 提前固化图结构。
- 输入 tensor 必须带
tf.TensorSpec,例如input_signature=[tf.TensorSpec(shape=[None, 224, 224, 3], dtype=tf.float32)];None表示 batch 维度可变,但其余维度必须固定 - 避免在
@tf.function内部使用 Python 值(如if x.numpy() > 0),这会导致图构建失败或 fallback 到 eager 模式 - 若模型含状态(如 BatchNorm、LSTM),需确保
training=False被作为参数传入,否则导出的图仍含训练 op,C++ 加载后推理结果异常
导出时用 tf.saved_model.save() 并指定 signatures
tf.saved_model.save() 是唯一支持 C++ 加载的导出方式;model.save('path', save_format='h5') 或 tf.keras.models.save_model(..., save_format='tf')(无 signatures)均不可用于 C++。
- 必须通过
signatures参数传入 concrete function,例如:signatures={'serving_default': call_fn.get_concrete_function(...)} - signature key 名称要与 C++ 中
GetSession()->Run()指定的input_tensor_names/output_tensor_names匹配,常见用'serving_default'或自定义名如'predict' - 导出路径不能含中文、空格或特殊字符,C++ 的
LoadSavedModel()在 Windows 下对路径敏感,建议全英文+下划线
C++ 加载时注意 runtime 版本与 saved_model 兼容性
TensorFlow C++ API 对 SavedModel 格式有严格版本约束:1.x 导出的模型无法被 2.x C++ 库加载,反之亦然;且 minor 版本差异(如 2.12 vs 2.13)也可能因 op 注册变动导致 Not found: Op type not registered 'StatefulPartitionedCall'。
- Python 端导出时,用
tf.__version__确认版本,C++ 端链接的libtensorflow_cc.so(Linux)或tensorflow.lib(Windows)必须完全一致 - 检查导出目录下是否有
saved_model.pb和variables/子目录,缺一不可;若只有assets/和variables/,说明没生成 protobuf 图文件,是导出调用错误 - C++ 中调用
LoadSavedModel()后,务必检查返回的Status,不要跳过 error check,常见失败原因包括权限不足(Linux 下 variables/ 目录不可读)、CUDA 环境未初始化(启用了 GPU 但 C++ 未调用tensorflow::InitGoogleTensorFlow())
最易忽略的是 concrete function 的 input_signature 与 C++ 输入 tensor 的 shape/dtype 完全对齐——哪怕 batch 维度是 [1, ...] 而 signature 写了 [None, ...],C++ 侧也必须按 [1, ...] 分配内存并填充,否则 SegFault 或数值错乱。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











