YOLO算法
引言
YOLO 算法是目前广泛应用的目标识别算法, 也是学习计算机视觉必须弄懂得算法, 但是阅读完 YOLO 算法论文之后, 也不一定说能头脑清晰的实现一个自己的版本, 因为其中有许多细节导致这个算法似乎变成有点困难。 但是实际上算法是简单, 只是要在理解论文的基础上, 研究作者公布源码便可以尝试自己实现。 这里研究的是 YAD2K Tensorflow 和 Keras 的实现版本( python3.6)。 将 YAD2K 克隆到本地然后进行改写, 运行。
git clone https://github.com/allanzelener/YAD2K.git
则会在当前目录下生成 yad2k , 然后再进行下面的工作, 一些信息在 github 上有, 例如预训练模型的获取以及 yolo.cfg , 需要自行查看。
关于 YOLO
https://pjreddie.com/publications/ 这是 YOLO 算法作者的个人网站, 在其中可以找到 YOLO v1~v3 的论文。 此文章探究的是YOLOv2, 所以有必要阅读 YOLOv1 及 YOLOv2 。 这里会以我的理解简单的对 YOLO 进行解说再进行后面的工作, 但是无论如何都必须先阅读 YOLO 论文, 理解 YOLO 的思想是研究源码的前提, 阅读时特别注意算法思想以及目标函数。 所以是可以阅读完 YOLO 论文后然后选择一个 YOLO 算法的实现进行研究便可, 只是我在这里让它更像一个教程。
YOLO 算法首先使用卷积神经网络训练一个分类器(YOLOv2 为 9000),所以在训练分类器时的输出层为 FC 层 (其它都为卷积层), YOLO 使用 darknet (简单理解成为一种网络结构)来进行训练。 将在预训练完成后的 darknet 由分类任务转变成目标识别任务 (即为迁移学习, 预先实现分类任务使得目标识别任务的训练效果更佳) 。
理解“目标识别任务”及“Anchor Boxes”
目标识别任务
目标识别任务比分类任务更加复杂, 要完成的任务是识别图片中的对象并确定对象所处的位置。 所以预先在 darknet 上训练一个分类器再转移到目标识别任务时会有更好的效果。
Anchor Boxes
根据 YOLO 算法的思想会将图片分成 13 * 13 的网格, 每个网格负责中心(x, y)落在自己的区域内的对象识别, 但是由于可能存在多个对象的 (x, y)可能落在同一个网格中,所以引入了 Anchor Boxes 。 预先定义5个长宽不同的 Anchor Boxes , 通过计算对象和 Anchor Boxes 的 IOU 确定哪个 Anchor Box 来负责这个对象。 因此如果有 5 个 Anchor Boxes 那么一个网格最多可以同时识别出5个对象, 那么一张图片最多可以识别 13 * 13 * 5 = 845 个对象。
明确数据格式
阅读论文便可以知道 inputs 即 X 的 shape 应为 (None, 416, 416, 3) , 但是 labels 即 Y 的格式可能还是有点模糊, 不过我们却可以明确 YOLO 的输出的 shape 为 (None, 13, 13, anchor_box_num * (5 + 9000))。 其中 anchor_box_num 为 anchor box 的个数, 5 + 9000 代表了 (p, x, y, w, h, c1, c2, …, c9000) (注: P 为有对象的概率, 论文中为 confidence)。 所以一种可能的实现就是将 labels 的 shape 也控制成这样, 这样就可以写出 YOLO_LOSS ,但是这样使用了另外一种方法, 后面注意便可。
探索数据格式
下载数据
这里的数据格式是指未经过我们处理的 images 以及 labels。 从网上下载不同的数据集之间的 labels 的格式可能不一样。 例如可以在 pascal VOC2007 的数据集, 但是这里尽量将问题简单化, 理解之后可以自行将 VOC 2007 的数据格式转成目标格式。 这里使用 YAD2K 中使用到的数据集 underwater 。 简单的:
git clone https://github.com/alecGraves/DATA.git
cd data
python package_dataset.py
会生成 my_dataset.npz 的数据文件, 改名为 underwater_data.npz 。 其中也有用到的 underwater_classes.txt , 类别的个数。然后将 underwater_data.npz 和 underwater_classes.txt 放到 data 文件夹并剪切到 yad2k 中, 结果文件目录结构如下:
data 中有 underwater_classes.txt 和 underwater_data.npz 文件。
探索数据
发现图片都是 480 * 640 * 3 的,表明我们需要将图片转换成 416 * 416 *3 , 而 labels 则是(1114, )明显代表的是样本的个数。 再次探索如下: