通过 C API 访问 tensorflow 2.0 SavedModel 的输入和输出张量

jav*_*vor 2 c c-api tensorflow tensorflow-serving tensorflow2.0

我无法从加载了 C_API 的 tensorflow 2.0 SavedModel 运行推理,因为我无法按名称访问输入和输出操作。

我通过 TF_LoadSessionFromSavedModel(...) 成功加载了会话:

#include <tensorflow/c/c_api>

...

TF_Status* status = TF_NewStatus();
TF_Graph*  graph  = TF_NewGraph();
TF_Buffer* r_opts = TF_NewBufferFromString("",0);
TF_Buffer* meta_g = TF_NewBuffer();

TF_SessionOptions* opts = TF_NewSessionOptions();
const char* tags[] = {"serve"};

TF_Session* session = TF_LoadSessionFromSavedModel(opts, r_opts, "saved_model/tf2_model", tags, 1, graph, meta_g, status);

if ( TF_GetCode(status) != TF_OK ) exit(-1); //does not happen
Run Code Online (Sandbox Code Playgroud)

但是,尝试使用以下方法设置输入和输出张量时出现错误:

TF_Operation* inputOp  = TF_GraphOperationByName(graph, "input"); //works with "serving_default_input"
TF_Operation* outputOp = TF_GraphOperationByName(graph, "prediction"); //does not work
Run Code Online (Sandbox Code Playgroud)

我作为参数传递的名称被分配给保存模型的输入和输出 keras 层,但不在加载的graph. 运行saved_model_cli(继TF SavedModel教程这里)显示,随着这些名字的男高音下存在的SignatureDef serving_default,所以我想,我需要实例serving_default为一个图(即根据签名创建一个图形),但我找不到使用 C API 执行此操作的方法。

请注意,tensorflows 的 C_API测试使用 C++ tensorflow/core/ 功能从元图中加载签名定义映射并使用它来查找输入和输出操作名称,但我想避免对 C++ 的依赖。

另请注意,按名称访问操作适用于冻结的 .pb 图形,但此格式已被弃用。

在此先感谢您的任何想法和提示!

Ber*_*san 6

目前(截至 2020 年 5 月)Tensorflow C API 尚未正式支持 SavedModel ( tensorflow 2.0 ) 格式,尽管它们可能很快会发布该功能。

无论如何,您可以使用导出模型时定义的默认SignatureDefs,并使用saved_model_cli工具查找输入和输出张量的名称

假设您使用以下方法保存了模型

model.save('/path/to/model/folder')
Run Code Online (Sandbox Code Playgroud)

然后你打开一个bash并做

cd /python/folder/bin/
saved_model_cli show --dir /path/to/model/folder --tag_set serve --signature_def serving_default
Run Code Online (Sandbox Code Playgroud)

(实际位置saved_model_cli不同,但在bin/文件夹下使用anaconda时默认安装)

默认情况下它会产生类似的东西:

serving_default
The given SavedModel SignatureDef contains the following input(s):
  inputs['graph_input'] tensor_info:
      dtype: DT_DOUBLE
      shape: (-1, 28, 28)
      name: serving_default_graph_input:0
The given SavedModel SignatureDef contains the following output(s):
  outputs['graph_output'] tensor_info:
      dtype: DT_FLOAT
      shape: (-1, 10)
      name: StatefulPartitionedCall:0
Method name is: tensorflow/serving/predict
Run Code Online (Sandbox Code Playgroud)

在这种情况下,serving_default_graph_input是输入张量名称,StatefulPartitionedCall是输出张量名称。然后,您可以使用TF_GraphOperationByName().

通过对 Tensorflow 2 的 C API 支持,您将能够使用一组定义的 SignatureDefs 保存模型,然后加载所需的concrete_function(),而不必担心张量名称。然而,这种当前的方法应该仍然有效。