导入一个简单的 Tensorflow frozen_model.pb 文件并在 C++ 中进行预测

Posted

技术标签:

【中文标题】导入一个简单的 Tensorflow frozen_model.pb 文件并在 C++ 中进行预测【英文标题】:Import a simple Tensorflow frozen_model.pb file and make prediction in C++ 【发布时间】:2017-07-19 13:05:25 【问题描述】:

我正在尝试将从 Tensorflow Python 导出的图形导入到 Tensorflow C++ 中。我已经成功地将图形重新导入 Python。我现在唯一想要的是用 C++ 编写相同的代码,但我不确定 C++ api 函数和那里的用法,因为 Tensorflow 网站上的文档不够好。

这是我目前找到的 C++ 代码。

C++:

namespace tf = tensorflow;

tf::Session* session;

tf::Status status = tf::NewSession(tf::SessionOptions(), &session);
checkStatus(status);

tf::GraphDef graph_def;
status = ReadBinaryProto(tf::Env::Default(), "./models/frozen_model.pb", &graph_def);
checkStatus(status);

status = session->Create(graph_def);
checkStatus(status);

tf::Tensor x(tf::DT_FLOAT, tf::TensorShape());
tf::Tensor y(tf::DT_FLOAT, tf::TensorShape());

x.scalar<float>()() = 23.0;
y.scalar<float>()() = 19.0;

std::vector<std::pair<tf::string, tf::Tensor>> input_tensors = "x", x, "y", y;
std::vector<string> vNames; // vector of names for required graph nodes
vNames.push_back("prefix/input_neurons:0");
vNames.push_back("prefix/prediction_restore:0");
std::vector<tf::Tensor> output_tensors;

status = session->Run(, vNames,  , &output_tensors);
checkStatus(status);

tf::Tensor output = output_tensors[0];
std::cout << "Success: " << output.scalar<float>() << "!" << std::endl;
session->Close();
return 0;

我对上面当前 c++ 代码的问题是它说它找不到任何名为 prefix/input_neurons:0 的操作。虽然图中有一个操作,因为当我在 Python 代码中导入此图时(如下所示),它工作得非常好。

这是成功导入图表的 Python 代码。

Python:(工作得很好)

def load_graph(frozen_graph_filename):
    # We load the protobuf file from the disk and parse it to retrieve the 
    # unserialized graph_def
    with tf.gfile.GFile(frozen_graph_filename, "rb") as f:
        graph_def = tf.GraphDef()
        graph_def.ParseFromString(f.read())

    # Then, we can use again a convenient built-in function to import a graph_def into the 
    # current default Graph
    with tf.Graph().as_default() as graph:
        tf.import_graph_def(
            graph_def, 
            input_map=None, 
            return_elements=None, 
            name="prefix", 
            op_dict=None, 
            producer_op_list=None
        )
    return graph

# We use our "load_graph" function
graph = load_graph("./models/frozen_model.pb")

# We can verify that we can access the list of operations in the graph
for op in graph.get_operations():
    print(op.name)     # <--- printing the operations snapshot below
    # prefix/Placeholder/inputs_placeholder
    # ...
    # prefix/Accuracy/predictions

# We access the input and output nodes
x = graph.get_tensor_by_name('prefix/input_neurons:0')
y = graph.get_tensor_by_name('prefix/prediction_restore:0')

# We launch a Session
with tf.Session(graph=graph) as sess:

    test_features = [[0.377745556,0.009904444,0.063231111,0.009904444,0.003734444,0.002914444,0.008633333,0.000471111,0.009642222,0.05406,0.050163333,7e-05,0.006528889,0.000314444,0.00649,0.043956667,0.016816667,0.001644444,0.016906667,0.00204,0.027342222,0.13864]]
        # compute the predicted output for test_x
    pred_y = sess.run( y, feed_dict=x: test_features )
    print(pred_y)

更新

我可以从 python 脚本打印操作。这是屏幕截图。

这是我得到的错误。

【问题讨论】:

你能显示确切的错误吗? (如果我的回答没有解决问题) 【参考方案1】:

参见Run function reference:在 C++ 中,输入首先是输入字典,然后是输出节点,然后是需要运行的其他操作,然后是输出向量(可选地带有额外的参数,但看起来你没有不需要它们)。这个调用应该有效:

status = session->Run("prefix/input_neurons:0", x, "prefix/prediction_restore:0", , &output_tensors);

如果您想将x 设置为与python 中相同的值(很可能有一种方法可以在不复制数据的情况下执行此操作,但我不知道如何),您可以在调用Run() 之前执行此操作:

std::vector<float> test_features = 0.377745556,0.009904444,0.063231111,0.009904444,0.003734444,0.002914444,0.008633333,0.000471111,0.009642222,0.05406,0.050163333,7e-05,0.006528889,0.000314444,0.00649,0.043956667,0.016816667,0.001644444,0.016906667,0.00204,0.027342222,0.13864;
int n_features = test_features.size();
x= tf::Tensor(tf::DT_FLOAT, tf::TensorShape(1,n_features));
auto x_mapped = x.tensor<float, 2>();

for (int i = 0; i< n_features; i++)

    x_mapped(0, i) = test_features[i];

告诉我这个更好吗!

【讨论】:

您好,感谢您的示例,您的代码 sn-p 仍然出现相同的错误。您可以在问题中看到错误快照。我已经更新了。 我认为现在的基本问题是“prefix/input_neurons:0”没有从图中导入。我不知道如何在 c++ 中打印操作,但如果我在 python 中打印图形的操作,这些操作就在那里 您确定从您的图表中导入了任何内容吗?您是否尝试过运行不需要任何 feed_dict 的其他张量(例如,已知名称的权重)? 我不确定是否导入了图表中的任何内容,更好的方法是打印导入图表的操作,我不确定如何在 c++ 中执行此操作。你可以看到我用 python 打印它,我还附上了它的截图。我没试过。我不知道该怎么做,因为我完全是新手。 当我打印 graph_def.node_size() 时,这等于 21。这是正确的,因为如果您计算上面屏幕截图中的节点数,它们是 21。但是如果我尝试通过 @ 获取参考987654327@ 为节点。我收到一个奇怪的错误

以上是关于导入一个简单的 Tensorflow frozen_model.pb 文件并在 C++ 中进行预测的主要内容,如果未能解决你的问题,请参考以下文章

如何使用来自 Google AutoML 视觉分类的 TensorFlow Frozen GraphDef (single saved_model.pb) 进行推理和迁移学习

带你了解TensorFlow pb模型常用处理方法

Tensorflow Lite tflite模型的生成与导入

tensorflow和theano的python3 keras导入错误

基于腾讯手机QQ规范移动web的UI框架Frozen UI

IO is frozen on database xxx, No user action is required