马春杰杰博客
致力于深度学习经验分享!

使用Python or C++调用tensorflow教程

文章目录
[隐藏]

使用Python/C++调用tensorflow教程

1 准备工作

全文参考此链接:

在C ++ Tensorflow中运行Keras模型

目前测试成功的系统配置为:

1.1 获取数据集

您已经在Keras中构建了一个非常棒的机器学习模型,现在您希望通过Tensorflow本机运行它。本教程将向您展示如何。可以从https://github.com/bitbionic/keras-to-tensorflow.git克隆/下载本教程中的所有代码   。您可能希望克隆它以跟随它。

Keras是用于构建机器学习模型的精彩高级框架。它可以利用Tensorflow  或Theano等多个后端来实现这一目标。当通过.save方法保存Keras模型时,规范保存方法序列化为HDF5格式。Tensorflow与协议缓冲区配合使用,因此可以加载和保存.pb文件。本教程演示如何:

  • 在Keras中构建SIMPLE卷积神经网络用于图像分类
  • 将Keras模型保存为HDF5模型
  • 验证Keras模型
  • 将HDF5模型转换为协议缓冲区
  • 构建Tensorflow C ++共享库
  • 在纯Tensorflow应用程序中使用.pb
  • 我们将使用Tensorflow自己的示例代码

它大约是218 MB,您可以从http://download.tensorflow.org/example_images/flower_photos.tgz下载它。 提取数据后,您应该看到与此处显示的图像类似的文件夹结构。有5个类别,数据预先分类到测试和训练中。

1.2 训练你的模型

在这个例子中,我将使用非常简单的CNN,但移植模型的技术同样适用于内置的Keras模型,如Inception和ResNet。我并不幻想这个模型会赢得任何奖项,但它将符合我们的目的。

下面列出的代码有几点需要注意:

  • 标记输入和输出层 – 这将使模型转换时更容易调试。
  • 我依靠模型检查点来保存我的.h5文件 – 你也可以在训练结束后调用classifier.save。
  • 记下您使用的形状参数,我们将在以后运行模型时需要它。

下面是使用的命令过程:

1.3 测试你的模型

所以现在让我们对我们的模型进行快速检查 – 这是一个加载模型,图像,形状和索引的小脚本(特别是如果你没有使用花集),以下是我的例子:

1.4 从HDF5转换为.pb

归因:此脚本改编自https://github.com/amir-abdi/keras_to_tensorflow

我将上面链接中的笔记本改为我们可以从命令行运行的脚本。除了参数解析之外,代码几乎相同。此代码执行以下操作:

  • 加载.h5文件
  • 用命名的Identity Tensor替换你的输出张量 – 如果你使用的是你没有构建的模型并且不知道所有的输出名称(当然你可以去挖掘,这可能会有用) )。
  • 保存图形定义的ASCII表示。我使用它来验证Tensorflow的输入和输出名称。这在调试中很有用。
  • 将图中的所有变量替换为常量。
  • 将结果图形写入您在脚本中指定的输出名称。

下面是命令过程:

如您所见,写出了两个文件。ASCII和.pb文件。让我们看看图形结构,注意输入节点名称“firstConv2D_input”和输出名称“k2tfout_0”,我们将在下一节中使用它们:

2 使用Tensorflow的label_image示例

2.1 使用python

本教程的其余部分将大量利用Tensorflow的图像识别示例。具体而言该文件为Python和此文件中的C ++

我将这两个文件复制到本教程的git repo中。现在让我们测试一下。

使用Python运行Tensorflow模型

运行Python脚本非常简单。请记住,我们需要提供以下参数:

  • 我们上面生成的output_graph.pb
  • 标签文件 – 这是随数据集提供的,但您可以从我们在Keras模型培训中生成的indices.txt文件生成类似的labels.txt
  • 输入宽度和高度。记得我训练过80×80,所以我必须在这里进行调整
  • 输入层名称 – 我在上面转换的生成的ASCII文件中找到了这个。在这种情况下,它是“firstConv2D_input” – 记住我们的k2tf_trainer.py命名为第一层“firstConv2D”。
  • 输出层名称 – 我们用前缀创建了它,可以在我们的ASCII文件中验证它。我们使用脚本默认值“k2tfout_0”
  • 最后,我们想要处理的图像。

我们来试试吧:

所以现在Tensorflow在Python中运行我们的模型 – 但是我们如何使用C ++?

2.2 使用C ++运行Tensorflow模型

如果您还在阅读,那么我假设您需要弄清楚如何在C ++的生产环境中运行Tensorflow。

2.2.1 编译tensorflow

对于我的项目,我想要一个可以链接和部署的Tensorflow共享库。这就是我们将在此项目中构建的内容,并使用它构建label_image示例。对于tensorflow c++接口来说,只能通过源码进行编译安装,不能通过pip安装。

要在C ++中运行我们的模型,我们首先需要获取Tensorflow源代码树。该指令在这里,但我们将在下面走通他们。

查看tensorflow的要求,我们选择bazel0.15.0,要求如下:


bazel的安装说明如下:
【mcj】bazel安装指定版本

验证以下bazel的版本信息:
bazel help

现在我们已经安装了所有东西,我们可以配置和构建。确保您位于顶级tensorflow目录中。我使用了所有默认配置选项。执行此操作时,配置工具将下载一堆依赖项 – 这需要一两分钟。

接下来进行build,如下:
bazel build --jobs=6 --verbose_failures -c opt --copt=-mavx --copt=-mfpmath=both --copt=-msse4.2 //tensorflow:libtensorflow_cc.so

上面是ubuntu下进行编译tensorflow,对于centos来说,类似,只不过bazel安装更加简单。

2.2.2 编译程序

在教程git repo中,我包含了一个qmake .pro文件,该文件链接.so和所有必需的标头位置。我将它包括在内作为参考 – 你不需要qmake来构建它。实际上,我要包含要构建的g ++命令。您可能需要根据您的环境进行调整。假设您正在从repo的根目录构建main.cpp,并且我们刚刚创建的tensorflow构建被克隆并构建在同一目录中,所有路径都应该是相对的并且开箱即用。

下面是编译命令:

执行第一条命令的时候总是出现错误:

然后进行debug,发现是absl这个文件的问题,找到absl这个文件,然后放到tensorflow目录下,重新执行,这时,只剩下这三条错误:

按照@李丰存 的帮助,那就不用TensorFlow 的StringPiece了,直接修改代码使用C++的string 。把用到StringPiece 的地方函数用相应的string 的函数实现。
这是修改后的main.cpp文件:

https://www.jianguoyun.com/p/DfisZ-0QwYPTBhjf6ZwB

接着执行第二条命令,结果报错:

找了好多方法,最后在github上找到的,将:
g++  -o Tutorial main.o   -L./tensorflow/bazel-bin/tensorflow -ltensorflow_cc替换为:
g++ -std=c++11 -o Tutorial main.bak.o -L./tensorflow/bazel-bin/tensorflow -ltensorflow_cc -I./tensorflow -I./tensorflow/bazel-tensorflow/external/eigen_archive -I./tensorflow/bazel-tensorflow/external/protobuf/src -I./tensorflow/bazel-genfiles -I/usr/include/eigen3 -ltensorflow_cc -ltensorflow_framework

中间安装了eigen3、G++-4.8不知道跟这个有没有关系。

好了,到这一步就得到Tutorial 这个文件了,使用./Tutorial -h应该能得到使用帮助,可是我在这一步的时候又报错,说找不到libtensorflow_cc.so文件:
./Tutorial: error while loading shared libraries: libtensorflow_cc.so: cannot open shared object file: No such file or directory

于是将这个文件所在的路径包含在/etc/ld.so.conf这个文件里,然后ldconfig一下,再重新执行./Tutorial -h就行了。

执行一个命令试试:

./Tutorial --graph=./output_graph.pb --labels=./data/flowers/raw-data/labels.txt --input_width=80 --input_height=80 --input_layer=firstConv2D_input --output_layer=k2tfout_0 --image=./data/flowers/raw-data/validation/dandelion/13920113_f03e867ea7_m.jpg

完成。

接下来的工作就是修改main.cpp,然后使其可以读取我们自己训练的faster rcnn模型了。

3 使用c++调用对方给的faster模型

3.1 ubuntu

@李丰存 给了一个main1.cpp的文件,里面是经过了修改的可以调用给定模型。经过前面的环境搭建之后,同样,先对cpp文件进行build

这一步没有问题,只是有一些警告,没有错误。

然后进行下一步:

在这一步的时候出现了错误:

应该是没有添加合适的依赖造成的,于是增加:

这时错误少了一些:

在这里:https://bbs.csdn.net/topics/390206286,找到了一个解决方法,于是添加
-I /usr/local/include/opencv -L /usr/local/lib -lopencv_core -lopencv_highgui -lopencv_imgproc -lopencv_gpu -lopencv_ts -lopencv_video -lopencv_objdetect -lopencv_ml -lpthread
,即:

这时错误又少了几个,看出来是有效的。

精简了一下,变成下面:

针对最后两个错误,imread和imwrite,导致错误的原因是由于忘记添加opencv_imgcodecs。自opencv3.0之后,图像读取相关代码在imgcodes中。因此,加上这个依赖就行了。最终命令如下:

3.2 centos

上面是ubuntu下的编译过程,下面是centos中遇到的问题:

遇到的主要问题是bazel版本问题和protobuf的版本问题,tensorflowr1.12版本所需bazel版本为0.15.0。还有,r1.12需要的protobuf版本为3.6.0以上,我装了3.6.1之后,仍然报错:

查找多个地方之后,决定忽略这个错误,找到相对应的错误文件,将对应错误输出代码删掉,问题解决
对于上述致命错误,需要下载absl,然后将其放到tensorflow目录,在命令后加入-I./tensorflow/abseil-cpp/即可。
除了tensorflow,opencv的依赖添加也有问题。最终在centos下进行编译的完整命令为:

编译完成后,在执行的时候,会遇到错误:
./Tutorialfaster: error while loading shared libraries: libtensorflow_cc.so: cannot open shared object file: No such file or directory
解决方法为:
使用sudo cp -frap ./tensorflow/bazel-bin/tensorflow/libtensorflow* .将TensorFlow的so文件都复制到当前目录,不过其实应该选一个固定的目录代替当前目录,如/etc/lib。然后sudo ldconfig使其生效即可。

如果你对这篇文章有什么疑问或建议,欢迎下面留言提出,我看到会立刻回复!

打赏
未经允许不得转载:马春杰杰 » 使用Python or C++调用tensorflow教程

留个评论吧~ 抢沙发 评论前登陆可免验证码!

私密评论
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址(选填,便于回访^_^)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏

登录

忘记密码 ?

切换登录

注册