zoukankan      html  css  js  c++  java
  • TensorFlow C++接口编译和使用

    部分内容from: Tensorflow C++ 从训练到部署(1):环境搭建

    在之前的编译中,已经编译好了tensorflow_pkg相关的wheel。现在有一个需求,需要按照C++的代码进行模型加载和训练。查询资料后发现,需要重新编译一套TensorFlow支持的C++接口,主要是编译出来libtensorflow_cc.so和libtensorflow_framework.so这两个文件。

    bazel build -c opt --copt=-mavx --copt=-msse4.2 --config=monolithic //tensorflow:libtensorflow_cc.so
    bazel build -c opt --copt=-mavx  --copt=-msse4.2 --config=monolithic //tensorflow:libtensorflow_framework.so

    像这种严格与机器相关的选项,虽然可以加快执行速度,但是在使用之前一定要查明自己的目标机器是否适合。

    中间可能会遇到之前的一些问题,功查找https://www.cnblogs.com/jourluohua/p/9180709.html

    编译完成后,安装第三方库

    source tensorflow/contrib/makefile/build_all_linux.sh
    若出现 /autogen.sh: 4: autoreconf: not found 错误,安装 sudo apt-get install autoconf automake libtool
    安装头文件和lib文件(不安装也可以,主要是要在CMakeLists文件中配置好就可以)
    sudo cp -r bazel-genfiles/ /usr/local/include/tf
    sudo cp -r tensorflow/cc /usr/local/include/tf/tensorflow
    sudo cp -r tensorflow/core /usr/local/include/tf/tensorflow
    sudo cp -r third_party /usr/local/include/tf
    sudo cp bazel-bin/tensorflow/libtensorflow_cc.so /usr/local/lib
    sudo cp bazel-bin/tensorflow/libtensorflow_framework.so /usr/local/lib

    如果你使用的是C的接口,用的是libtensorflow.so库的话,需要拷贝tensorflow/c/相关的文件

    之后是新建一个Python文件,去生成相关的pb文件(代码来源于他人代码,有修改)

    #!/usr/bin/env python
     
    import tensorflow.compat.v1 as tf
    import numpy as np
     
    with tf.Session() as sess:
     
        a=tf.placeholder(tf.float32,shape=None, name='a')
        b=tf.placeholder(tf.float32,shape=None, name='b')
        c = tf.multiply(a, b, name='c')
     
        sess.run(tf.global_variables_initializer())
     
        tf.train.write_graph(sess.graph_def, 'model/', 'simple.pb', as_text=False)
     
        res = sess.run(c, feed_dict={'a:0': 2.0, 'b:0': 3.0})
        print("res = ", res)

    生成了model/simple.pb文件

    写load_simple_net.cpp文件(代码来源于他人代码,有修改https://gitee.com/liuzc/tensorflow_cpp.git)

    #include "tensorflow/core/public/session.h"
    #include "tensorflow/core/platform/env.h"
    
    using namespace tensorflow;
    int main(int argc, char* argv[]) {
        // Initialize a tensorflow session
        Session* session;
        Status status = NewSession(SessionOptions(), &session);
        if (!status.ok()) {
            std::cerr << status.ToString() << std::endl;
            return 1;
        } else {
            std::cout << "Session created successfully" << std::endl;
        }
    
        if (argc != 2)
        {
            std::cerr << std::endl << "Usage: ./project path_to_graph.pb" << std::endl;
            return 1;
        }
    
        // Load the protobuf graph
        GraphDef graph_def;
        std::string graph_path = argv[1];
        status = ReadBinaryProto(Env::Default(), graph_path, &graph_def);
        if (!status.ok()) {
            std::cerr << status.ToString() << std::endl;
            return 1;
        } else {
            std::cout << "Load graph protobuf successfully" << std::endl;
        }
    
        // Add the graph to the session
        status = session->Create(graph_def);
        if (!status.ok()) {
            std::cerr << status.ToString() << std::endl;
            return 1;
        } else {
            std::cout << "Add graph to session successfully" << std::endl;
        }
    
        // Setup inputs and outputs:
    
        // Our graph doesn't require any inputs, since it specifies default values,
        // but we'll change an input to demonstrate.
        Tensor a(DT_FLOAT, TensorShape());
        a.scalar<float>()() = 2.0;
    
        Tensor b(DT_FLOAT, TensorShape());
        b.scalar<float>()() = 3.0;
    
        std::vector<std::pair<string, tensorflow::Tensor>> inputs = {
                { "a:0", a },
                { "b:0", b },
        };
    
        // The session will initialize the outputs
        std::vector<tensorflow::Tensor> outputs;
    
        // Run the session, evaluating our "c" operation from the graph
        status = session->Run(inputs, {"c:0"}, {}, &outputs);
        if (!status.ok()) {
            std::cerr << status.ToString() << std::endl;
            return 1;
        } else {
            std::cout << "Run session successfully" << std::endl;
        }
    
        // Grab the first output (we only evaluated one graph node: "c")
        // and convert the node to a scalar representation.
        auto output_c = outputs[0].scalar<float>();
    
        // (There are similar methods for vectors and matrices here:
        // https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/public/tensor.h)
    
        // Print the results
        std::cout << outputs[0].DebugString() << std::endl; // Tensor<type: float shape: [] values: 30>
        std::cout << "Output value: " << output_c() << std::endl; // 30
    
        // Free any resources used by the session
        session->Close();
    
        return 0;
    }

    添加CMakeLists文件,目录结构变为

     添加eigen库,这里的原因是TensorFlow默认的eigen库,里边实际上是不支持C++接口的,不信的人可以试下,里边的unsupported/CXX/Tensor里边自己include了自己,会导致递归死循环包含错误,因此需要自己添加eigen库,拷贝到当前目录eigen3文件夹下

    修改CMakeLists文件,内容为

    cmake_minimum_required(VERSION 3.5)
    project(tensorflow_cpp)
    
    set(CMAKE_CXX_STANDARD 11)
    
    find_package(OpenCV 3.0 QUIET)
    if(NOT OpenCV_FOUND)
        find_package(OpenCV 2.4.3 QUIET)
        if(NOT OpenCV_FOUND)
            message(FATAL_ERROR "OpenCV > 2.4.3 not found.")
        endif()
    endif()
    
    set(TENSORFLOW_INCLUDES
            /usr/local/include/tf/
            /usr/local/include/tf/bazel-genfiles
            /usr/local/include/tf/tensorflow/
            /usr/local/include/tf/tensorflow/third-party
            )
    
    set(TENSORFLOW_LIBS
            /usr/local/lib/libtensorflow_cc.so
            /usr/local/lib/libtensorflow_framework.so
            )
    
    
    include_directories(
            ${TENSORFLOW_INCLUDES}
            ${PROJECT_SOURCE_DIR}/eigen3
    )
    
    
    add_executable(load_simple_net load_simple_net.cpp)
    target_link_libraries(load_simple_net
            ${TENSORFLOW_LIBS}
            ${OpenCV_LIBS}
            )

    新建build文件,进入该build文件中

    cd ./build
    cmake ..
    make

    这里有一个非常重要的点,/usr/local/lib/libtensorflow_cc.so /usr/local/lib/libtensorflow_framework.so的顺序关系,如果顺序不对,会一直报

    E tensorflow/core/common_runtime/session.cc:89] Not found: No session factory registered for the given session options: {target: "" config: } Registered factories are {}.

    使用./load_simple_net  ../model/simple.pb,按道理可以得到正确的值

    Session created successfully
    Load graph protobuf successfully
    Add graph to session successfully
    Run session successfully
    Tensor<type: float shape: [] values: 6>
    Output value: 6

    参考资料:

    https://medium.com/jim-fleming/loading-tensorflow-graphs-via-host-languages-be10fd81876f

    https://medium.com/jim-fleming/loading-a-tensorflow-graph-with-the-c-api-4caaff88463f#.z4qeoyfb0

    https://www.tensorflow.org/install/install_c

    http://www.liuxiao.org/2018/08/ubuntu-tensorflow-c-%e4%bb%8e%e8%ae%ad%e7%bb%83%e5%88%b0%e9%a2%84%e6%b5%8b1%ef%bc%9a%e7%8e%af%e5%a2%83%e6%90%ad%e5%bb%ba/

    https://blog.csdn.net/melissa_cjt/article/details/85983659

    https://www.cnblogs.com/shouhuxianjian/p/9416934.html

  • 相关阅读:
    (转)python request用法
    QLabel 文本内容自动换行显示
    事件的传递 键盘事件作为例子
    qt中添加Q_OBJECT报错的问题
    Q_OBJECT宏的作用
    C++中的RAII介绍 资源管理
    C++ explicit关键字详解
    信号和槽 带不带参数
    enum 枚举类型默认值
    创建工具条ToolBar
  • 原文地址:https://www.cnblogs.com/jourluohua/p/11947176.html
Copyright © 2011-2022 走看看