C# 操作TensorFlow SavedModel C#如何加载和使用TensorFlow训练好的模型文件

2次阅读

tensorflow.net 当前(v2.14+)不支持直接加载 savedmodel,loadsavedmodel() 抛 notimplementedexception;正确做法是传入含 saved_model.pb 和 variables/ 的目录路径,并通过 python 查 signature 后按签名张量名调用。

C# 操作TensorFlow SavedModel C#如何加载和使用TensorFlow训练好的模型文件

TensorFlow.NET 加载 SavedModel 会直接报错“NotImplementedException”

因为 TensorFlow.NET 当前(v2.14+)对 SavedModel 的原生支持仍不完整,LoadSavedModel() 函数只是声明了,但底层没实现——调用就崩。这不是你模型导出有问题,是库本身卡在关键路径上。

实操建议:

  • 改用 TensorFlowSharp?不行,它已停止维护,且不支持 TF 2.x 的 SavedModel 格式
  • 真正可行的路只有一条:把 SavedModel 转成 .pb 冻结图(frozen graph),再用 TensorFlow.NETsession.LoadFromSavedModel() 替代方案——即 Session.LoadMetaGraph() + Session.Restore(),但这要求你有 .meta + .index + .data 三件套
  • 更稳的选择:用 Python 启一个轻量服务(比如 flask + tf.keras.models.load_model()),C# 通过 http 调用;或者用 ML.NET 做中间桥接(前提是模型结构能被 ML.NET 导入)

SavedModel 目录里一文件,C# 到底该读哪个路径?

别碰 variables/assets/ 单独路径——TensorFlow.NETLoadSavedModel() 期望的是整个目录的**父路径**,且该路径下必须包含 saved_model.pb(或 saved_model.pbtxt)和 variables/ 子目录。

常见错误现象:

  • 传入 "./mymodel/variables" → 报 Invalid argument: Expected model file at .../variables/saved_model.pb
  • 传入 "./mymodel/saved_model.pb"(文件路径)→ 报 DirectoryNotFoundException
  • 路径末尾带斜杠或不带斜杠,行为不一致;建议统一用 Path.GetFullPath() 规范化

正确写法示例:

string modelPath = Path.GetFullPath(@"..modelsmy_tf2_model"); // 指向含 saved_model.pb 的目录 var session = Session.LoadFromSavedModel(modelPath); // 注意:此行目前会抛 NotImplementedException

输入输出张量名对不上,session.GetOutput() 返回空或 shape 不匹配

TF 2.x 的 SavedModel 默认用的是“signature def”,不是原始 tensor 名。C# 侧看不到 serving_default 这类 signature,直接按 "input:0" 硬写大概率失败。

必须先查签名:

  • 用 Python 快速确认:from tensorflow.saved_model import load; m = load("path"); list(m.signatures.keys()),通常返回 ['serving_default']
  • 再看输入输出:m.signatures['serving_default'].structured_input_signature
  • C# 中不能跳过这步——你得把 signature 里的 input_1:0output_1:0 这类名字抄下来,而不是猜
  • Session.Run() 时,feed dict 的 key 必须是 signature 中的 tensor name(含冒号),例如 "serving_default_input_1:0",不是 "input_1"

为什么不用 ML.NET 直接加载 SavedModel

ML.NETTensorFlowModelScorer 确实支持 SavedModel,但它只认 TF 1.x 风格的模型(即含 .meta 文件的 checkpoint),对 TF 2.x 的纯 SavedModel(只有 saved_model.pb + variables/)支持有限,容易在 LoadTensorFlowModel() 时抛 InvalidOperationException: Could not find SavedModel bundle

如果你的模型是 Keras 训练的,更现实的做法是:

  • 导出时加 signatures 参数,确保 signature 名明确、输入输出 tensor 名不含动态前缀
  • 在 C# 中放弃“全自动加载”,改用 TensorFlow.NET 手动构造 Graph + Session,并显式指定 placeholder 和 fetch node
  • 接受一个事实:C# 生态对 TF 2.x 模型的原生支持仍是补丁状态,绕不开 Python 辅助验证和转换

最常被忽略的一点:TF 版本锁死。C# 项目引用的 TensorFlow.NET 必须与训练环境的 TensorFlow 主版本一致(比如 TF 2.12 训练 → C# 必须用 TensorFlow.NET v2.12.x),否则 saved_model.pb 解析会静默失败,连错误都不报全。

text=ZqhQzanResources