在 C/C++ 中使用 TensorFlow 预训练好的模型—— 直接调用 C++ 接口实现
现在的深度学习框架一般都是基于 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++ 接口实现的更多相关文章
- 在 C/C++ 中使用 TensorFlow 预训练好的模型—— 间接调用 Python 实现
现在的深度学习框架一般都是基于 Python 来实现,构建.训练.保存和调用模型都可以很容易地在 Python 下完成.但有时候,我们在实际应用这些模型的时候可能需要在其他编程语言下进行,本文将通过 ...
- TensorFlow 调用预训练好的模型—— Python 实现
1. 准备预训练好的模型 TensorFlow 预训练好的模型被保存为以下四个文件 data 文件是训练好的参数值,meta 文件是定义的神经网络图,checkpoint 文件是所有模型的保存路径,如 ...
- TensorFlow 同时调用多个预训练好的模型
在某些任务中,我们需要针对不同的情况训练多个不同的神经网络模型,这时候,在测试阶段,我们就需要调用多个预训练好的模型分别来进行预测. 调用单个预训练好的模型请点击此处 弄明白了如何调用单个模型,其实调 ...
- 【猫狗数据集】使用预训练的resnet18模型
数据集下载地址: 链接:https://pan.baidu.com/s/1l1AnBgkAAEhh0vI5_loWKw提取码:2xq4 创建数据集:https://www.cnblogs.com/xi ...
- pytorch中如何使用预训练词向量
不涉及具体代码,只是记录一下自己的疑惑. 我们知道对于在pytorch中,我们通过构建一个词向量矩阵对象.这个时候对象矩阵是随机初始化的,然后我们的输入是单词的数值表达,也就是一些索引.那么我们会根据 ...
- 转载:tensorflow保存训练后的模型
训练完一个模型后,为了以后重复使用,通常我们需要对模型的结果进行保存.如果用Tensorflow去实现神经网络,所要保存的就是神经网络中的各项权重值.建议可以使用Saver类保存和加载模型的结果. 1 ...
- tensorflow 使用预训练好的模型的一部分参数
vars = tf.global_variables() net_var = [var for var in vars if 'bi-lstm_secondLayer' not in var.name ...
- Tensorflow 用训练好的模型预测
本节涉及点: 从命令行参数读取需要预测的数据 从文件中读取数据进行预测 从任意字符串中读取数据进行预测 一.从命令行参数读取需要预测的数据 训练神经网络是让神经网络具备可用性,真正使用神经网络时,需要 ...
- Tensorflow使用训练好的模型进行测试,发现计算速度越来越慢
实验时要对多个NN模型进行对比,依次加载直到第8个模型时,发现运行速度明显变慢而且电脑开始卡顿,查看内存占用90+%. 原因:使用过的NN模型还会保存在内存,继续加载一方面使新模型加载特别特别慢,另一 ...
随机推荐
- 【题解】洛谷P2607【ZJOI2008】骑士
洛谷P2607:https://www.luogu.org/problemnew/show/P2607 一道毒瘤的环基树问题 第一次做环基树的题目 刚看题目的时候觉得不就是跟没有上司的舞会一样嘛 然后 ...
- select选中的值改变另一个input的值
HTML: <select id="hhh" onchange="aa()"><option value="11"> ...
- [Linux/Unix]用户和用户组管理
Linux系统是一个多用户多任务的分时操作系统,任何一个要使用系统的用户,都必须拥有自己的账号. 实现用户的管理,主要做: 用户账号的添加.删除.修改: 用户口令的管理: 用户组的管理. (一)用户的 ...
- 【oracle使用笔记2】使用Oracle数据库遇到的若干问题总结
一. 关于Oracle 11g数据库在查询表中数据显示中文乱码问题 [描述]本人一开始使用的Oracle是11g版本的,用PLSQL一次查询表中的数据时出现了中文显示乱码,为此搜了许多解决办法,最终通 ...
- hdu_2067_小兔的棋盘
小兔的叔叔从外面旅游回来给她带来了一个礼物,小兔高兴地跑回自己的房间,拆开一看是一个棋盘,小兔有所失望.不过没过几天发现了棋盘的好玩之处.从起点(0,0)走到终点(n,n)的最短路径数是C(2n,n) ...
- MySQL——用户与密码
mysql安装完成之后,在/var/log/mysqld.log文件中给root生成了一个默认密码.通过下面的方式找到root默认密码,然后登录mysql进行修改: grep 'temporary p ...
- ASP.NET Web用户控件
用户控件可用来实现页面中可重用的代码,是可以一次编写就多处方便使用的功能块.它们是 ASP.NET控件封装最简单的形式.由于它们最简单,因此创建和使用它们也是最简单的.用户控件实际上是把已有的服务器控 ...
- PHP中对字符串的一些操作
php中判断字符串在另一个字符串中是否存在(strpos): if(strpos('www.baidu.com', 'www') !== false){ // 存在 }else{ // 不存在 } p ...
- JAVA Web 项目中用到的技术
JSPServletTomcatMySQL MavenSpringMVCHibernatejQueryBootstrapAngularJSBootStrap Table 下边两个是移动APP开发要用到 ...
- JavaSE库存管理系统项目实战
需求分析 企业库房用于存放成品.半成品.原材料.工具等物资,一般情况下,这些物资统称为物料.库存管理常见业务包括物资的入库.出库.盘点.退货.报废以及财务核算等,业务逻辑比较复杂,库房信息系统项目开发 ...