Iva*_*kov 4 c++ python model keras tensorflow
我有一个使用 Tensorflow 2 和 Keras 定义的大模型。该模型在 Python 中运行良好。现在,我想将它导入到 C++ 项目中。
在我的 C++ 项目中,我使用TF_GraphImportGraphDef
函数。*.pb
如果我使用以下代码准备文件,效果很好:
with open('load_model.pb', 'wb') as f:
f.write(tf.compat.v1.get_default_graph().as_graph_def().SerializeToString())
Run Code Online (Sandbox Code Playgroud)
我已经在使用 Tensorflow 1 (使用 tf.compat.v1.* 函数)编写的简单网络上尝试了此代码。效果很好。
现在我想将我的大模型(开头提到的,使用 Tensorflow 2 编写的)导出到 C++ 项目中。为此,我需要从模型中获取一个Graph
or对象。GraphDef
问题是:如何做到这一点?我没有找到任何属性或函数来获取它。
我还尝试使用来tf.saved_model.save(model, 'model')
保存整个模型。它生成一个包含不同文件的目录,包括saved_model.pb
file. 不幸的是,当我尝试使用TF_GraphImportGraphDef
函数在 C++ 中加载此文件时,程序抛出异常。
生成的协议缓冲区文件tf.saved_model.save
不包含GraphDef
消息,而是包含SavedModel
. 您可以在 Python 中遍历它SavedModel
以获取其中的嵌入图,但这不会立即作为冻结图工作,因此正确处理可能会很困难。相反,C++ API 现在包含一个LoadSavedModel
调用,允许您从目录加载整个保存的模型。它应该看起来像这样:
#include <iostream>
#include <...> // Add necessary TF include directives
using namespace std;
using namespace tensorflow;
int main()
{
// Path to saved model directory
const string export_dir = "...";
// Load model
Status s;
SavedModelBundle bundle;
SessionOptions session_options;
RunOptions run_options;
s = LoadSavedModel(session_options, run_options, export_dir,
// default "serve" tag set by tf.saved_model.save
{"serve"}, &bundle));
if (!.ok())
{
cerr << "Could not load model: " << s.error_message() << endl;
return -1;
}
// Model is loaded
// ...
return 0;
}
Run Code Online (Sandbox Code Playgroud)
从这里开始,您可以做不同的事情。也许您会最舒服地使用 将该保存的模型转换为冻结图FreezeSavedModel
,这应该允许您执行与之前执行的操作几乎相同的操作:
GraphDef frozen_graph_def;
std::unordered_set<string> inputs;
std::unordered_set<string> outputs;
s = FreezeSavedModel(bundle, &frozen_graph_def,
&inputs, &outputs));
if (!s.ok())
{
cerr << "Could not freeze model: " << s.error_message() << endl;
return -1;
}
Run Code Online (Sandbox Code Playgroud)
否则,您可以直接使用保存的模型对象:
// Default "serving_default" signature name set by tf.saved_model_save
const SignatureDef& signature_def = bundle.GetSignatures().at("serving_default");
// Get input and output names (different from layer names)
// Key is input and output layer names
const string input_name = signature_def.inputs().at("my_input").name();
const string output_name = signature_def.inputs().at("my_output").name();
// Run model
Tensor input = ...;
std::vector<Tensor> outputs;
s = bundle.session->Run({{input_name, input}}, {output_name}, {}, &outputs));
if (!s.ok())
{
cerr << "Error running model: " << s.error_message() << endl;
return -1;
}
// Get result
Tensor& output = outputs[0];
Run Code Online (Sandbox Code Playgroud)