用c++API加载python训练好的tensorflow模型

原创 2018年04月16日 16:35:30
由于在生产环境,很多情况下没有python的环境,只能用c/c++的环境,而且很多情况下是用python训练好模型后,用c++加载模型运行即可,那么如何才能用c++加载模型并运行呢?这里做一些说明。




主要参考两个网址,tensorflow的c++ API官网(https://www.tensorflow.org/api_guides/cc/guide)和Loading a TensorFlow graph with the C++ API(https://medium.com/jim-fleming/loading-a-tensorflow-graph-with-the-c-api-4caaff88463f),按道理,应该只需要参考后者,即可,但我在实践的时候,碰到了一些问题。






1、用python创建graph,并保存成pb文件


-Python 代码
01
import tensorflow as tf
02
import numpy as np
03
 
04
with tf.Session() as sess:
05
    a = tf.Variable(5.0, name='a')
06
    b = tf.Variable(6.0, name='b')
07
    c = tf.multiply(a, b, name="c")
08
 
09
    sess.run(tf.global_variables_initializer())
10
 
11
    print a.eval() # 5.0
12
    print b.eval() # 6.0
13
    print c.eval() # 30.0
14
     
15
    tf.train.write_graph(sess.graph_def, 'models/', 'graph.pb', as_text=False)
执行代码后,会得到model文件夹,在model文件夹下有一个graph.pb文件。






2、用c++ 构建session,读取pb文件,执行


在tensorflow的源码目录中,创建文件夹 /tensorflow-master/tensorflow/heke/loader/


在该文件夹下创建loader.cc文件,粘贴如下的代码:






-Cpp 代码
01
#include "tensorflow/core/public/session.h"
02
#include "tensorflow/core/platform/env.h"
03
 
04
using namespace tensorflow;
05
 
06
int main(int argc, char* argv[]) {
07
  // Initialize a tensorflow session
08
  Session* session;
09
  Status status = NewSession(SessionOptions(), &session);
10
  if (!status.ok()) {
11
    std::cout << status.ToString() << "\n";
12
    return 1;
13
  }
14
 
15
  // Read in the protobuf graph we exported
16
  // (The path seems to be relative to the cwd. Keep this in mind
17
  // when using `bazel run` since the cwd isn't where you call
18
  // `bazel run` but from inside a temp folder.)
19
  GraphDef graph_def;
20
  status = ReadBinaryProto(Env::Default(), "models/graph.pb", &graph_def);
21
  if (!status.ok()) {
22
    std::cout << status.ToString() << "\n";
23
    return 1;
24
  }
25
 
26
  // Add the graph to the session
27
  status = session->Create(graph_def);
28
  if (!status.ok()) {
29
    std::cout << status.ToString() << "\n";
30
    return 1;
31
  }
32
 
33
  // Setup inputs and outputs:
34
 
35
  // Our graph doesn't require any inputs, since it specifies default values,
36
  // but we'll change an input to demonstrate.
37
  Tensor a(DT_FLOAT, TensorShape());
38
  a.scalar<float>()() = 3.0;
39
 
40
  Tensor b(DT_FLOAT, TensorShape());
41
  b.scalar<float>()() = 2.0;
42
 
43
  std::vector<std::pair<string, tensorflow::Tensor>> inputs = {
44
    { "a", a },
45
    { "b", b },
46
  };
47
 
48
  // The session will initialize the outputs
49
  std::vector<tensorflow::Tensor> outputs;
50
 
51
  // Run the session, evaluating our "c" operation from the graph
52
  status = session->Run(inputs, {"c"}, {}, &outputs);
53
  if (!status.ok()) {
54
    std::cout << status.ToString() << "\n";
55
    return 1;
56
  }
57
 
58
  // Grab the first output (we only evaluated one graph node: "c")
59
  // and convert the node to a scalar representation.
60
  auto output_c = outputs[0].scalar<float>();
61
 
62
  // (There are similar methods for vectors and matrices here:
63
  // https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/public/tensor.h)
64
 
65
  // Print the results
66
  std::cout << outputs[0].DebugString() << "\n"; // Tensor<type: float shape: [] values: 30>
67
  std::cout << output_c() << "\n"; // 30
68
 
69
  // Free any resources used by the session
70
  session->Close();
71
  return 0;
72
}


3、创建BUILD文件 (输入命令, touch BUILD)
粘贴如下的代码:


-Bash 代码
01
load("//tensorflow:tensorflow.bzl", "tf_cc_binary")
02
 
03
tf_cc_binary(
04
    name = "loader",
05
    srcs = ["loader.cc"],
06
    deps = [
07
        "//tensorflow/cc:cc_ops",
08
        "//tensorflow/cc:client_session",
09
        "//tensorflow/core:tensorflow",
10
    ],
11
)
这里的代码和那边博客里的代码有区别,按照博客里的代码,会出错,不能编译成功,用这个代码后,编译成功了。这里的代码时从官网C++ API介绍从copy出来的。


这里出现的问题如下,


-Html 代码
01
用bazel build :loader 时
02
 
03
在bazel-bin/tensorflow/loader下不能找到可执行文件./loader
04
 
05
在build时,也是会报错的,提示如下:
06
 
07
collect2: error: ld returned 1 exit status
08
Target //tensorflow/heke/loader:loader failed to build
09
 
10
用bazel run :loader会报错,同上
11
 
12
collect2: error: ld returned 1 exit status
13
Target //tensorflow/heke/loader:loader failed to build






最后,在/heke/loader目录下,有两个文件
BUILD
loader.cc




4、编译运行


a)、配置tensorflow-master中的./configure


b)、在loader目录下,执行 bazel build :loader


c)、进入到tensorflow-master/bazel-bin/tensorflow/heke/loader,并把前面用python生成的model/graph.pb 复制到loader目录下


d)、运行./loader






这里运行的时候,也可以直接用bazel run :loader来运行,结合了编译和运行两个阶段。






注:这里用的c++代码的编译方式和前面的博客用c++API加载python训练好的tensorflow模型 里用的编译不一致,那么相当于提供了两种c++代码的编译方式。都可以尝试。这里也试过用libtensorflow.so库的方式来编译,但有一些bug,看下能否解决吧。




用 gcc gcc -I /usr/local/include/tf -L /usr/local/lib train.cc -ltensorflow 报需要用-std=c++11,


以及/usr/local/include/tf/third_party/eigen3/unsupported/Eigen/CXX11/Tensor:1:42: fatal error: unsupported/Eigen/CXX11/Tensor: No such file or directory 的错误




用gcc -std=c++11 -I /usr/local/include/tf -L /usr/local/lib train.cc -ltensorflow 就不会报-std=c++11的错误,但是下面的错误继续会报。


这个错误,目前先解决不了,后续再看吧




其实上面的问题,不是关键,这个应该可以通过安装eigen,并在编译时,指定eigen的目录可以解决。




更重要的错误在于,用gcc编译时,目前只有tensorflow/c/c_api.h支持的最好,其它的都需要导入各种各样的头文件。会提醒缺少各种各样的头文件。这个问题目前好像还比较难解决,可以参见https://github.com/tensorflow/tensorflow/issues/2412 中asimshankar的回复。
版权声明: https://blog.csdn.net/b876144622/article/details/79962556

tensorflow如何使用训练好的模型做测试

方法1 保存 1、定义变量 2、使用saver.save()方法保存 import tensorflow as tf import numpy as np W = tf.Va...
  • Touch_Dream
  • Touch_Dream
  • 2018-01-27 11:18:58
  • 1636

TensorFlow使用C++加载使用训练好的模型,.cc文件代码实现的相关类及方法总结

在官网API和Tensorflow源码头文件中查看获取。 同时参考 https://medium.com/jim-fleming/loading-a-tensorflow-graph-with-the...
  • BadMushroom
  • BadMushroom
  • 2017-12-05 15:14:21
  • 267

Tensorflow之用自己的训练好的cpkt模型,进行测试识别

上街讲了如何使用tensorflow生成自己的图片训练模型cpkt。这节讲述如何讲如何使用训练好的cpkt模型进行测试识别。    直接线上代码:     ######################...
  • csuzhaoqinghui
  • csuzhaoqinghui
  • 2016-07-06 15:36:12
  • 4189

Tensorflow训练好的模型,怎么调用 下载地址

  • 2017年03月03日 12:58
  • 17KB
  • 下载

Tensorflow使用训练好的模型

        深度学习大部分时间花费在利用海量的数据训练出一个精确的模型,并且对训练主机的性能有较高的要求。那么能不能直接使用别人训练好的模型,免去繁琐的训练过程以及超高配置的机器要求?答案是肯定的...
  • improve_perfect
  • improve_perfect
  • 2018-03-18 20:15:59
  • 111

用tensorflow在mnist数据集下训练、测试模型

  • 2018年03月01日 22:41
  • 25.2MB
  • 下载

Tensorflow学习(7)用别人训练好的模型进行图像分类

谷歌在大型图像数据库ImageNet上训练好了一个Inception-v3模型,这个模型我们可以直接用来进来图像分类。 下载地址:https://storage.googleapis.com/dow...
  • u011600477
  • u011600477
  • 2017-11-22 20:23:02
  • 1029

TensorFlow保存和加载训练模型

对于机器学习,尤其是深度学习DL的算法,模型训练可能很耗时,几个小时或者几天,所以如果是测试模块出了问题,每次都要重新运行就显得很浪费时间,所以如果训练部分没有问题,那么可以直接将训练的模型保存起来,...
  • JasonZhangOO
  • JasonZhangOO
  • 2017-03-07 11:13:33
  • 9994

opencv调用tf训练好的模型

        tensorflow训练好的模型,如何使用?在tensorflow上使用,当然很好实现啊。但是在实际生产部署时,主机要求不安装tf,也没有显卡,何解?本博文对此做一个记录。一、open...
  • hust_bochu_xuchao
  • hust_bochu_xuchao
  • 2018-03-03 11:03:29
  • 608

tensorflow将训练好的模型

tensorflow将训练好的模型freeze,即将权重固化到图里面,并使用该模型进行预测 http://blog.csdn.NET/lujiandong1/article/details...
  • BBZZ2
  • BBZZ2
  • 2017-09-08 09:32:29
  • 837
收藏助手
不良信息举报
您举报文章:用c++API加载python训练好的tensorflow模型
举报原因:
原因补充:

(最多只允许输入30个字)