现在的深度学习框架一般都是基于 Python 来实现,构建、训练、保存和调用模型都可以很容易地在 Python 下完成。但有时候,我们在实际应用这些模型的时候可能需要在其他编程语言下进行,本文将通过直接调用 TensorFlow 的 C/C++ 接口来导入 TensorFlow 预训练好的模型。

1.环境配置 点此查看 C/C++ 接口的编译

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++ 接口实现的更多相关文章

  1. 在 C/C++ 中使用 TensorFlow 预训练好的模型—— 间接调用 Python 实现

    现在的深度学习框架一般都是基于 Python 来实现,构建.训练.保存和调用模型都可以很容易地在 Python 下完成.但有时候,我们在实际应用这些模型的时候可能需要在其他编程语言下进行,本文将通过 ...

  2. TensorFlow 调用预训练好的模型—— Python 实现

    1. 准备预训练好的模型 TensorFlow 预训练好的模型被保存为以下四个文件 data 文件是训练好的参数值,meta 文件是定义的神经网络图,checkpoint 文件是所有模型的保存路径,如 ...

  3. TensorFlow 同时调用多个预训练好的模型

    在某些任务中,我们需要针对不同的情况训练多个不同的神经网络模型,这时候,在测试阶段,我们就需要调用多个预训练好的模型分别来进行预测. 调用单个预训练好的模型请点击此处 弄明白了如何调用单个模型,其实调 ...

  4. 【猫狗数据集】使用预训练的resnet18模型

    数据集下载地址: 链接:https://pan.baidu.com/s/1l1AnBgkAAEhh0vI5_loWKw提取码:2xq4 创建数据集:https://www.cnblogs.com/xi ...

  5. pytorch中如何使用预训练词向量

    不涉及具体代码,只是记录一下自己的疑惑. 我们知道对于在pytorch中,我们通过构建一个词向量矩阵对象.这个时候对象矩阵是随机初始化的,然后我们的输入是单词的数值表达,也就是一些索引.那么我们会根据 ...

  6. 转载:tensorflow保存训练后的模型

    训练完一个模型后,为了以后重复使用,通常我们需要对模型的结果进行保存.如果用Tensorflow去实现神经网络,所要保存的就是神经网络中的各项权重值.建议可以使用Saver类保存和加载模型的结果. 1 ...

  7. tensorflow 使用预训练好的模型的一部分参数

    vars = tf.global_variables() net_var = [var for var in vars if 'bi-lstm_secondLayer' not in var.name ...

  8. Tensorflow 用训练好的模型预测

    本节涉及点: 从命令行参数读取需要预测的数据 从文件中读取数据进行预测 从任意字符串中读取数据进行预测 一.从命令行参数读取需要预测的数据 训练神经网络是让神经网络具备可用性,真正使用神经网络时,需要 ...

  9. Tensorflow使用训练好的模型进行测试,发现计算速度越来越慢

    实验时要对多个NN模型进行对比,依次加载直到第8个模型时,发现运行速度明显变慢而且电脑开始卡顿,查看内存占用90+%. 原因:使用过的NN模型还会保存在内存,继续加载一方面使新模型加载特别特别慢,另一 ...

随机推荐

  1. (转)HTML5之渐变

    <!DOCTYPE> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta h ...

  2. mysql获取汉字首字母函数

    DELIMITER ;;CREATE FUNCTION `GET_FIRST_PINYIN_CHAR`(PARAM VARCHAR(255)) RETURNS VARCHAR(2) CHARSET u ...

  3. djano-模板层基础知识

    ########模板层######## 模板层其实就是templates文件夹里的html文件 其实这里的每个html不是真正意义的上html代码,只有经过模板渲染过后才算的上真正的html页面. 一 ...

  4. 【TOJ 3005】Triangle(判断点是否在三角形内+卡精度)

    描述 Given the coordinates of the vertices of a triangle,And a point. You just need to judge whether t ...

  5. Angular : 绑定, 参数传递, 路由

    如何把jquery导入angular npm install jquery --savenpm install @type/jquery --save-dev "node_modules/z ...

  6. tarnado源码解析系列一

    目录 tarnado tarnado源码安装 tarnado测试程序 application类的解析 一. tarnado简介 最近在学习Python,无意间接触到的tarnado,感觉tarnado ...

  7. Leecode刷题之旅-C语言/python-35.搜索插入位置

    /* * @lc app=leetcode.cn id=35 lang=c * * [35] 搜索插入位置 * * https://leetcode-cn.com/problems/search-in ...

  8. Kubernetes-深入分析集群安全机制

    Kubernetes过一系列机制来实现集群的安全机制,包括API Server的认证授权.准入控制机制及保护敏感信息的Secret机制等.集群的安全性必须考虑以下的几个目标: 保证容器与其所在宿主机的 ...

  9. 【Java】关于Spring框架的总结 (二)

    上文提到了 Spring 的 IoC 特性和 AOP 特性,只提到个别的实现方法.本文将对 IoC 和 AOP 其他方法进行讲解. 多种方式实现依赖注入 1.设值注入 上文中使用的注入方法:通过 se ...

  10. Vue 去脚手架插件,自动加载vue文件

    接上回 一些本质 本质上,去脚手架也好,读取vue文件也好,无非是维护options,每个Vue对象的初始化配置对象不触及Vue内部而言,在外部想怎么改都是可以的,只要保证options的正确,一切都 ...