使用 Tensorflow 进行物品预测

这套流程主要是为了记录我在学习以及模型训练的过程,以及其中遇见的相关问题

环境

  • CPU: Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GHz
  • MEM: 384GB 2400 DDR4
  • GPU: Matrox Electronics Systems Ltd. G200eR2
  • DISK: 1.1 TB
  • System: Ubuntu 18.04 LTS
  • Python: 3.6.7
  • TensorFlow: 1.12.0

因为 GPU 并不是 NVIDIA,所以不支持 CUDA 加速,目前只能使用 CPU 进行 Tensorflow 学习,在 10 月 20 日,Python 版本升级到了 3.7,然而到现在 (11 月 28 日),Tensorflow 还只支持 3.6,故 Python 版本我们选择了 3.6.7,也就是 Python 3.6 的最后一个版本

流程

1. 安装 Python
2. 编译并安装 Tensorflow 以及相关依赖
3. 安装 Tensorflow Model
4. 使用 labelImg 进行图片标注
5. 修改 Model 代码,生成 trainval.txt,将图片及标注文件转换成 TFRecord
6. 下载一套 COCO 数据集,并更改 pipeline.config
7. 进行 40000 次的模型训练,生成 ckpt 文件
8. 将 ckpt 转换成 GRAPH 的 pb 冻结图
9. 使用 pb 冻结图进行物品图片预测

Miniconda

conda 和 virtualenv 一样,可用于 Python 项目做多版本环境创建与切换的,也就是在同一个环境中,可以存在几个不同 python 版本或者不同 requirement 的虚拟环境,在安装依赖更新包都十分方便,anaconda 太大了,我也不需要那么多的包,所以我这里使用的是 Miniconda

下载

首先我们需要下载 Miniconda,可以点击这里,进入 Miniconda 的官网

Miniconda的官网

右键复制他的下载地址,通过 wget 进行下载

1
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh

等待进度条走完后完成下载

Miniconda下载

安装

现在完毕后我们使用 bash 命令运行这个 sh 文件

1
bash Miniconda3-latest-Linux-x86_64.sh

按下回车,查看 Licenses,并输入 yes 进行下一步安装

Miniconda安装

下一步输入安装路径,我这里是安装到了 /opt/miniconda3 这个目录下

Miniconda环境变量

经过解包后,会提示你是否添加环境变量,这里我们选择 yes,进行添加环境变量

最后完成环境 Miniconda 的安装

Miniconda环境变量查看

我们可以通过下面的命令查看环境变量是否添加

1
tail .bashrc

添加完环境变量后,我们需要用 source 更新一下,才能使环境变量生效

1
source .bashrc

使用

降级

因为 Tensorflow 现在只支持 3.6 版本的 Python,然而我们下载的是最新版本的 Miniconda,里面预装的是 3.7 最新版本的,所有我们需要进行降级,将 python 切换到 3.6.7

1
conda install python=3.6.7

Python降级确认

经过解析环境后 Solving environment 后,我们选择 yes,进行降级操作

Python降级

经过一段时间的等待,我们就成功的将 Python 版本降到了 3.6.7

之后运行下面的命令 安装必要的包

1
conda install numpy keras-preprocessing 

更新

可以使用下面的命令进行 conda 升级

1
conda update conda

可以使用下面的命令进行当前所有包进行升级

1
conda update --all

清理

conda 长时间使用后,体积会很大,可以使用下面命令将已经下载包进行清理

1
conda clean -a -y

卸载

如果需要需要卸载 conda,可以用下面的命令将相应位置的 Miniconda 目录直接删除

1
rm -rf /opt/miniconda3/

然后使用下面的命令,编辑环境变量

1
vi ~/.bashrc

Miniconda环境变量

将环境变量中的关于 conda 的内容直接删除即可

Tensorflow

Tensorflow 目前分 2 个安装方法

  • CPU 版
  • GPU 版

除了通常的算术和逻辑,现代 CPU 提供了许多低级指令,称为扩展,例如, SSE2,SSE4,AVX 等来自维基百科:

高级矢量扩展(AVX)是英特尔在 2008 年 3 月提出的英特尔和 AMD 微处理器的 x86 指令集体系结构的扩展,英特尔首先通过 Sandy Bridge 处理器在 2011 年第一季度推出,随后由 AMD 推出 Bulldozer 处理器在 2011 年第三季度.AVX 提供了新功能,新指令和新编码方案。
特别是,AVX 引入了融合乘法累加(FMA)操作,加速了线性代数计算,即点积,矩阵乘法,卷积等。几乎所有机器学习训练都涉及大量这些操作,因此将会支持 AVX 和 FMA 的 CPU(最高达 300%)更快。该警告指出您的 CPU 确实支持 AVX(hooray!)。

在此强调一下:

这只限于 CPU。如果你有一个 GPU,你不应该关心 AVX 的支持,因为大多数昂贵的操作将被分派到一个 GPU 设备上(除非明确地设置)。在这种情况下,您可以简单地忽略此警告。

那为什么会出现这种警告呢?

由于 tensorflow 默认分布是在没有 CPU 扩展的情况下构建的,例如 SSE4.1,SSE4.2,AVX,AVX2,FMA 等。默认版本(来自 pip install tensorflow 的版本)旨在与尽可能多的 CPU 兼容。另一个观点是,即使使用这些扩展名,CPU 的速度也要比 GPU 慢很多,并且期望在 GPU 上执行中型和大型机器学习培训。

我们机器没有 GPU 能够使用,为了尽可能多地利用 CPU,且我们的 CPU 支持 AVX,AVX2,为了更好效率,我们使用 Bazel 重新构建 Tensorflow,不仅在以后的使用中,消除 AVX 等警报,还可以改善 Tensorflow 的性能

可以根据个人需求选择是否编译,也可以直接安装发行版本的 Tensorflow

JDK

安装 Bazel,需要 Java JDK1.8 或更高版本的支持,所以我们的第一项工作就是安装 JDK

关于 JDK 的安装教程,可以点击这里查看。

Bazel

依赖

首先运行下面的代码,安装 Bazel 相关依赖,因为我们已经安装过 python 就不需要安装了

1
apt-get install pkg-config zip g++ zlib1g-dev unzip

安装

Bazel Releases下载

点击这里打开 Bazel Releases 下载页面,选择相应版本进行下载

然后运行下面的命令,给 sh 文件加权限并运行

1
2
chmod +x bazel-0.19.2-installer-linux-x86_64.sh
./bazel-0.19.2-installer-linux-x86_64.sh

Bazel安装成功

加载完毕后,看到 Bazel is now installed! 标明 Bazel 已安装成功

编译 Tensorflow

首先我们先用 git 把 Tensorflow 的源码下载下来

1
git clone https://github.com/tensorflow/tensorflow.git

现在完毕后,我们需要运行 configure, 做一些必要的配置

1
2
cd tensorflow
./configure

Tensorflow configure

接下来,配置系统会给出各种询问,以确认编译时的配置参数,请根据个人情况配置参数,我这里全部选择的 n,其他的为默认选项

在配置完 Bazel 的编译选项之后,接下来就可以使用如下指令编译 TensorFlow 的源代码

1
bazel build --config=opt //tensorflow/tools/pip_package:build_pip_package

Tensorflow编译

这个时候,我们就可以去喝喝水,休息一会,等待编译完毕即可

Tensorflow编译成功

半个小时后,当我们看到这个提示,就标明 tensorflow 已经编译成功,在临时文件夹中生成了一堆 binary,当前目录下也有软连接,可以直接运行下面的命令,生成 whl 文件,

1
bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg

生成whl

成功生成 whl 文件

安装 Tensorflow

接下来运行下面的命令,直接安装生成的 whl

1
pip install /tmp/tensorflow_pkg/tensorflow-1.12.0rc0-cp36-cp36m-linux_x86_64.whl

生成whl

在经过相关依赖安装之后,提示安装成功

接下来我们可以跑一个例子

1
2
3
4
5
6
7
cd ~
python
import tensorflow as tf
a = tf.constant(2)
b = tf.constant(3)
with tf.Session() as sess:
print("Addition with constants: %i" % sess.run(a+b))

Tensorflow例子

如图所示,可以得到结果,则说明 Tensorflow 已成功安装了

Tensorflow Object Detection API

Tensorflow Object Detection API 可实现基于给定模型检测图像中的特定目标,是典型的深度学习在计算机视觉中的应用

包含在 Tensorflow Model 中

Tensorflow 旧版本自带 model,然而新版本已经没有了,就需要我们自己单独下载

下载

首先运行下面的命令,安装 Tensorflow Object Detection API 的依赖

1
conda install Cython contextlib2 pillow lxml jupyter matplotlib

虽然都在本次教程中,都不会全用上,但是以后总会用找到了

使用下面的命令,从 Tensorflow models 下载最新的文件

1
git clone https://github.com/tensorflow/models.git

如果网络不太好,就多 clone 几次,总会成功的

COCO API installation

我们需要使用 COCO 预处理数据集,需要下载 cocoapi,使用下面命令完成 COCO API 的安装

1
2
3
4
git clone https://github.com/cocodataset/cocoapi.git
cd cocoapi/PythonAPI
make
cp -r pycocotools <path_to_tensorflow>/models/research/

Protobuf 编译器安装和使用

Tensorflow 对象检测 API 使用 Protobufs 配置模型和训练参数。

在使用框架之前,必须编译 Protobuf 库。

Protobuf Releases下载

首先点击这里 Protobuf Releases 下载页面,选择相应版本进行下载

然后使用下面的命令解压 zip 的包到存储的目录下

1
unzip -d /opt/protoc protoc-3.6.1-linux-x86_64.zip

并将下面的信息添加至环境变量到.bashrc

1
export PATH="/opt/protoc/bin:$PATH"

添加完毕并 source 更新环境变量后,运行以下命令来编译 Protobuf 库

1
2
cd /opt/models/research/
protoc object_detection/protos/*.proto --python_out=.

将库添加到 PYTHONPATH

在本地运行时,models/research/ 和 slim 目录应该附加到 PYTHONPATH。这可以通过从 tensorflow/models/research/ 运行以下命令来完成:

1
export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim

此命令需要从您启动的每个新终端运行。如果您希望避免手动运行,可以将其作为新行添加到~/.bashrc 文件的末尾,将 pwd 替换为系统上 tensorflow/models/research 的绝对路径。

如果你要添加环境变量,可以将下面的内容添加至环境变量并用 source 更新

1
export PATH="/opt/models/research:/opt/models/research/slim:$PATH"

测试安装

您可以测试是否已正确安装 Tensorflow 对象检测

通过运行以下命令 API:

1
python object_detection/builders/model_builder_test.py

model_builder_test

运行结果如图所示,表明 Tensorflow Object Detection API 已配置完毕

LabelImg

首先需要先要标注图像相应标签,这里可以使用 labelImg 工具。

下载

LabelImg Download list

点击这里打开 LabelImg Download list 页面,下载合适版本的图片

使用

labelImg.exe

解压后,直接双击 labelImg.exe 文件运行

标注

对对象物体画框,并记录相应对象的名称,save 完成保存 xml 文件完成标注

每标注一张样本,即生成一个 xml 的标注文件

单类别图片标注预览图

并分类别保存,记得保持图片名称及 XML 标注文件名称一致,最后同一类别文件夹效果如图所示

多类别图片标注预览图

一次完成,每个类别保证有 200 张左右的样本,多个类别下的图片再统一放到一个目录下,效果如图所示

填写 pbtxt 文件

pbtxt文件

在图片预测的时候,并不会直接把对象名字反馈回来,所以我们需要一个映射文件 pbtxt,进行标签名和数字的转换,格式如图所示

将自己标记的图片中对象及自己编号按照格式放到一个 pbtxt 文本中,之后会用得到

trainval.txt 文件生成

接下来就要进行 TFRecord 格式文件转换了,使用官方版的 Api 就可以生成 trainval.txt,但是为了方便多个类别的使用,我对代码进行了一些更改,对类别下的样本进行随机,并按 4:1 的比率生成 train.txt 和 val.txt,以保证总体样本上的随机,以提高数据的准确性

trainval生成代码

关键代码如图所示

trainval

最后会生成 2 个文件内容如图所示

TFRecord 文件生成

在生成 TFRecord 的时候,会根据 train.txt 和 val.txt 的内容,逐条生成产生 train.record 和 val.record

我是用的是 object_detection/dataset_tools/create_pet_tf_record.py,并进行了一定的更改,对 tainval 分别处理,进行图片格式转换,都转换成 JPEG 格式,对 mask 去除,并将输出 record 保存为一个

图片格式转换

图片格式转换代码如图所示

record

最后生成 2 个文件,以便进行下一步训练

预训练模型下载

detection_model_zoo

Tensorflow Object Detection API 提供了很多模型进行下载,可以点击这里打开 Tensorflow detection model zoo 页面,选择想要的模型进行下载

我选择的是 ssd_inception_v2_coco 模型下载,下载后将 object_detection/samples/configs/ssd_inception_v2_coco.config 这里的文件放到解压后的模型下,并修改参数

pipeline.config

主要是 5 个地址进行修改,更换成刚刚生成好的 tfreord 文件地址,和模型下的 ckpt 地址

num_examples 是 val.txt 中测试样本的数目

num_steps 是训练步数

train 训练

目录结构

首先说明我的目录结构如图所示,我直接将 object_detectionslim 到工程文件夹下了,使用起来更方便

修改完毕后,我们就可以进行样本训练了

在早期的版本 Tensorflow 中,使用 train.py 进行训练,在 object_detection 目录下,现在已经搬到 object_detection\legacy 目录下了,现在还可以使用,使用命令如下

1
2
3
4
object_detection\legacy\train.py \
--logtostderr \
--pipeline_config_path=/root/<name_to_project>/ssd_inception_v2/pipeline.config \
--train_dir=/root/<name_to_project>/data/model

在新版本的 Tensorflow 中,都是使用 model_main.py 进行训练,在 object_detection 目录下,使用命令如下

1
2
3
4
object_detection\model_main.py \
--model_dir=/root/<name_to_project>/data/model \
--pipeline_config_path=/root/<name_to_project>/ssd_inception_v2/pipeline.config \
--num_train_steps=40000

<name_to_project> 是我的项目名称

log

在经过漫长的等待 (2 天) 后,日志终于结束打印

model

我们也可以在输出文件夹 data/model 中看到相应步数的检查点

导出推理图

要在代码中使用模型,需要将检查点文件(model.ckpt-STEP_NUMBER.*)转换为推理图。

你可以运行下面的代码,将检查点的 ckpt 文件转换成推理图

1
2
3
4
5
python object_detection\export_inference_graph.py \
--input_type image_tensor \
--pipeline_config_path /root/<name_to_project>/ssd_inception_v2/pipeline.config \
--trained_checkpoint_prefix /root/<name_to_project>/data/model-bak/model.ckpt-20000 \
--output_directory /root/<name_to_project>/data/graph

graph

导出后的文件如图所示,我们使用的就是 frozen_inference_graph.pb 文件

测试模型

如何使用模型呢,我们可以点击这里,这是 Jupyter 的运行文件,我们可以将运行代码拷贝到新建的一个 python 文件中,或者查找相应的转换工具使用

PATH_TO_TEST_IMAGES_DIR 参数改为自己要测试的图片
PATH_TO_FROZEN_GRAPH 参数改为 frozen_inference_graph.pb 的路径
PATH_TO_LABELS 参数改为 xxx.pbtxt 的路径

test

然后运行这个 python,稍等片刻,我们就看到的预测结果

附件

相关链接: