内容简介:现在的深度学习框架一般都是基于 Python 来实现,构建、训练、保存和调用模型都可以很容易地在 Python 下完成。但有时候,我们在实际应用这些模型的时候可能需要在其他编程语言下进行,本文将通过直接调用 TensorFlow 的 C/C++ 接口来导入 TensorFlow 预训练好的模型。获取更多精彩,请关注「seniusen」!
现在的深度学习框架一般都是基于 Python 来实现,构建、训练、保存和调用模型都可以很容易地在 Python 下完成。但有时候,我们在实际应用这些模型的时候可能需要在其他编程语言下进行,本文将通过直接调用 TensorFlow 的 C/C++ 接口来导入 TensorFlow 预训练好的模型。
2. 导入预定义的图和训练好的参数值
// set up your input paths const string pathToGraph = "/home/senius/python/c_python/test/model-10.meta"; const string checkpointPath = "/home/senius/python/c_python/test/model-10"; auto session = NewSession(SessionOptions()); // 创建会话 if (session == nullptr) { throw runtime_error("Could not create Tensorflow session."); } Status status; // Read in the protobuf graph we exported MetaGraphDef graph_def; status = ReadBinaryProto(Env::Default(), pathToGraph, &graph_def); // 导入图模型 if (!status.ok()) { throw runtime_error("Error reading graph definition from " + pathToGraph + ": " + status.ToString()); } // Add the graph to the session status = session->Create(graph_def.graph_def()); // 将图模型加入到会话中 if (!status.ok()) { throw runtime_error("Error creating graph: " + status.ToString()); } // Read weights from the saved checkpoint Tensor checkpointPathTensor(DT_STRING, TensorShape()); checkpointPathTensor.scalar<std::string>()() = checkpointPath; // 读取预训练好的权重 status = session->Run({{graph_def.saver_def().filename_tensor_name(), checkpointPathTensor},}, {}, {graph_def.saver_def().restore_op_name()}, nullptr); if (!status.ok()) { throw runtime_error("Error loading checkpoint from " + checkpointPath + ": " + status.ToString()); } 复制代码
3. 准备测试数据
const string filename = "/home/senius/python/c_python/test/04t30t00.npy"; //Read TXT data to array float Array[1681*41]; ifstream is(filename); for (int i = 0; i < 1681*41; i++){ is >> Array[i]; } is.close(); tensorflow::Tensor input_tensor(tensorflow::DT_FLOAT, tensorflow::TensorShape({1, 41, 41, 41, 1})); auto input_tensor_mapped = input_tensor.tensor<float, 5>(); float *pdata = Array; // copying the data into the corresponding tensor for (int x = 0; x < 41; ++x)//depth { for (int y = 0; y < 41; ++y) { for (int z = 0; z < 41; ++z) { const float *source_value = pdata + x * 1681 + y * 41 + z; input_tensor_mapped(0, x, y, z, 0) = *source_value; } } } 复制代码
- 本例中输入数据是一个 [None, 41, 41, 41, 1] 的张量,我们需要先从 TXT 文件中读出测试数据,然后正确地填充到张量中去。
4. 前向传播得到预测值
std::vector<tensorflow::Tensor> finalOutput; std::string InputName = "X"; // Your input placeholder's name std::string OutputName = "sigmoid"; // Your output tensor's name vector<std::pair<string, Tensor> > inputs; inputs.push_back(std::make_pair(InputName, input_tensor)); // Fill input tensor with your input data session->Run(inputs, {OutputName}, {}, &finalOutput); auto output_y = finalOutput[0].scalar<float>(); std::cout << output_y() << "\n"; 复制代码
- 通过给定输入和输出张量的名字,我们可以将测试数据传入到模型中,然后进行前向传播得到预测值。
5. 一些问题
- 本模型是在 TensorFlow 1.4 下训练的,然后编译 TensorFlow 1.4 的 C++ 接口可以正常调用模型,但若是想调用更高版本训练好的模型,则会报错,据出错信息猜测可能是高版本的 TensorFlow 中添加了一些低版本没有的函数,所以不能正常运行。
- 若是编译高版本的 TensorFlow ,比如最新的 TensorFlow 1.11 的 C++ 接口,则无论是调用旧版本训练的模型还是新版本训练的模型都不能正常运行。出错信息如下:Error loading checkpoint from /media/lab/data/yongsen/Tensorflow_test/test/model-40: Invalid argument: Session was not created with a graph before Run()!,网上暂时也查不到解决办法,姑且先放在这里。
6. 完整代码
#include </home/senius/tensorflow-r1.4/bazel-genfiles/tensorflow/cc/ops/io_ops.h> #include </home/senius/tensorflow-r1.4/bazel-genfiles/tensorflow/cc/ops/parsing_ops.h> #include </home/senius/tensorflow-r1.4/bazel-genfiles/tensorflow/cc/ops/array_ops.h> #include </home/senius/tensorflow-r1.4/bazel-genfiles/tensorflow/cc/ops/math_ops.h> #include </home/senius/tensorflow-r1.4/bazel-genfiles/tensorflow/cc/ops/data_flow_ops.h> #include <tensorflow/core/public/session.h> #include <tensorflow/core/protobuf/meta_graph.pb.h> #include <fstream> using namespace std; using namespace tensorflow; using namespace tensorflow::ops; int main() { // set up your input paths const string pathToGraph = "/home/senius/python/c_python/test/model-10.meta"; const string checkpointPath = "/home/senius/python/c_python/test/model-10"; auto session = NewSession(SessionOptions()); if (session == nullptr) { throw runtime_error("Could not create Tensorflow session."); } Status status; // Read in the protobuf graph we exported MetaGraphDef graph_def; status = ReadBinaryProto(Env::Default(), pathToGraph, &graph_def); if (!status.ok()) { throw runtime_error("Error reading graph definition from " + pathToGraph + ": " + status.ToString()); } // Add the graph to the session status = session->Create(graph_def.graph_def()); if (!status.ok()) { throw runtime_error("Error creating graph: " + status.ToString()); } // Read weights from the saved checkpoint Tensor checkpointPathTensor(DT_STRING, TensorShape()); checkpointPathTensor.scalar<std::string>()() = checkpointPath; status = session->Run({{graph_def.saver_def().filename_tensor_name(), checkpointPathTensor},}, {}, {graph_def.saver_def().restore_op_name()}, nullptr); if (!status.ok()) { throw runtime_error("Error loading checkpoint from " + checkpointPath + ": " + status.ToString()); } cout << 1 << endl; const string filename = "/home/senius/python/c_python/test/04t30t00.npy"; //Read TXT data to array float Array[1681*41]; ifstream is(filename); for (int i = 0; i < 1681*41; i++){ is >> Array[i]; } is.close(); tensorflow::Tensor input_tensor(tensorflow::DT_FLOAT, tensorflow::TensorShape({1, 41, 41, 41, 1})); auto input_tensor_mapped = input_tensor.tensor<float, 5>(); float *pdata = Array; // copying the data into the corresponding tensor for (int x = 0; x < 41; ++x)//depth { for (int y = 0; y < 41; ++y) { for (int z = 0; z < 41; ++z) { const float *source_value = pdata + x * 1681 + y * 41 + z; // input_tensor_mapped(0, x, y, z, 0) = *source_value; input_tensor_mapped(0, x, y, z, 0) = 1; } } } std::vector<tensorflow::Tensor> finalOutput; std::string InputName = "X"; // Your input placeholder's name std::string OutputName = "sigmoid"; // Your output placeholder's name vector<std::pair<string, Tensor> > inputs; inputs.push_back(std::make_pair(InputName, input_tensor)); // Fill input tensor with your input data session->Run(inputs, {OutputName}, {}, &finalOutput); auto output_y = finalOutput[0].scalar<float>(); std::cout << output_y() << "\n"; return 0; } 复制代码
- Cmakelist 文件如下
cmake_minimum_required(VERSION 3.8) project(Tensorflow_test) set(CMAKE_CXX_STANDARD 11) set(SOURCE_FILES main.cpp) include_directories( /home/senius/tensorflow-r1.4 /home/senius/tensorflow-r1.4/tensorflow/bazel-genfiles /home/senius/tensorflow-r1.4/tensorflow/contrib/makefile/gen/protobuf/include /home/senius/tensorflow-r1.4/tensorflow/contrib/makefile/gen/host_obj /home/senius/tensorflow-r1.4/tensorflow/contrib/makefile/gen/proto /home/senius/tensorflow-r1.4/tensorflow/contrib/makefile/downloads/nsync/public /home/senius/tensorflow-r1.4/tensorflow/contrib/makefile/downloads/eigen /home/senius/tensorflow-r1.4/bazel-out/local_linux-py3-opt/genfiles ) add_executable(Tensorflow_test ${SOURCE_FILES}) target_link_libraries(Tensorflow_test /home/senius/tensorflow-r1.4/bazel-bin/tensorflow/libtensorflow_cc.so /home/senius/tensorflow-r1.4/bazel-bin/tensorflow/libtensorflow_framework.so ) 复制代码
获取更多精彩,请关注「seniusen」!
以上所述就是小编给大家介绍的《在 C/C++ 中使用 TensorFlow 预训练好的模型—— 直接调用 C++ 接口实现》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 调用 TensorFlow 已训练好的模型做图像识别
- TensorFlow 调用预训练好的模型—— Python 实现
- 机器学习weka,java api调用随机森林及保存模型
- 加入Transformer-XL,这个PyTorch包能调用各种NLP预训练模型
- 在 C/C++ 中使用 TensorFlow 预训练好的模型—— 间接调用 Python 实现
- 直观讲解-RPC调用和HTTP调用的区别
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。