YOLO自诞生以来,每个版本都会引起学术界和工业界的极大关注。在工业界,即使精度稍差,YOLO往往也会比一些Two-Stage的目标检测器更受青睐,因为它是真的很快,完全能满足实时性的应用要求。YOLO最新的版本是YOLOv3,主要改进是提升了小目标检测的效果。YOLOv3官方的权重是在COCO数据集上训练的,总共有80类目标,但是在实际应用中,我们往往需要检测特定的目标。比如在自动驾驶应用中,我们需要检测的目标有汽车 、 行人 、 自行车 、 交通灯 、 交通标志等。为了检测这些目标,我们就需要用自己的数据集来训练目标检测器。本文将介绍如何用一个猫狗数据集训练YOLOv3来检测图片中的猫和狗。
本文使用的猫狗数据集来源于数据集Open Images Dataset V4,该数据集总共包含600类目标,我们从中其中的Cat和Dog类中分别取出
4 000张图像用来训练YOLOv3。
Darknet需要的标注信息格式为
<object-class -id
其含义 如下 :
object-class -id : 类别序号。
x: 目标中心点的横坐标,相对于图像的宽度做归一化处理。
y: 目标中心点的纵坐标,相对于图像的高度做归一化处理。
width: 目标的宽度,相对于图像的宽度做归一化处理。
height: 目标的高度,相对于图像的高度做归一化处理。
如果数据集的标注信息不是这种格式,可以写一个python脚本来做转换,这个比较简单,可以参考scripts/目录下的voc\_label.py脚本来实现。转换后的标注文件为txt格式,与图像放在同一目录下,每张图像对应一个标注文件。
准备好图像和标注文件后,我们还要生成训练集和验证集的文件列表。训练集和验证集按9:1的比例划分,生成的文件列表文件分别为train.list和val.list。
文件列表中的每一行都对应一张图片的路径(最好用绝对路径),训练的时候程序会根据这个路径去读取图片。 文件列表中的格式类似于:
/home/anyu/datasets/cat_dog/dog/144fda747fc5bda8.jpg
/home/anyu/datasets/cat_dog/cat/03c22fcbc7ce0312.jpg
YOLOv3的作者自己用C语言写了一个深度学习框架Darknet,所以我们要训练YOLOv3的话需要先从github上下载Darknet:
git clone https://github.com/pjreddie/darknet
下载完成后,先修改Makefile文件。如果我们的机器有英伟达显卡,并安装了CUDA,cuDNN和OpenCV,可以按下面的修改:
GPU=1
CUDNN=1
OPENCV=1
这样就能用GPU进行加速。如果还需要CPU优化,可以设置OPENMP=1。
修改完成后,执行make命令进行编译,如果没有错误的话,会在当前目录下生产可执行文件“darknet”。
在进行训练之前,我们还需要准备几个文件
(下面这些 文件放在哪个目录 都可以 ,只要对应上就好了 ) 。
- YOLOv3模型配置文件
首先把cfg/目录下的yolov3.cfg文件复制一份,重命名为cat_and_dog_yolov3.cfg,然后设置里面的内容。
[net]
#设置batchsize
batch=64
subdivisions=16
#输入图像的分辨率
width=608
height=608
channels=3
#momentum参数
momentum=0.9
decay=0.0005
#数据增强参数
angle=0
saturation = 1.5
exposure = 1.5
hue=.1
#最大训练次数
max_batches =20000
#学习率及调整策略
learning_rate=0.001
burn_in=1000
policy=steps
steps=15000
scales=.1
然后修改yolo层的参数,把类别数量classes改为2。另外还要把yolo层上面convolutional层中filters的参数改为21,该参数的计算方法为(classes+5)*3,在本文中是(2+5)*3=21。如果是用COCO数据集训练,该参数就是(80+5)*3=255,在实际应用中注意根据实际情况进行修改。
[convolutional]
size=1
stride=1
pad=1
filters=21
activation=linear
[yolo]
mask = 6,7,8
anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
classes=2
num=9
jitter=.3
ignore_thresh = .7
truth_thresh = 1
random=1
注意 :YOLOv3有3个yolo层,都需要进行上述修改。
- 类别名称文件
在data/目录下新建一个文件cat_and_dog.names用来保存类别的名称,文件内容为:
cat
dog
- 配置文件
在cfg/目录下新建一个文件cat_and_dog.data,内容如下:
#类别数量
classes= 2
#训练集文件列表的路径
train = /path/to/train.list
#验证集文件列表的路径
valid = /path/to/val.list
#类别名称文件
names = data/cat_and_dog.names
#训练过程中权重文件的保存目录
backup =backup/
-
预训练权重文件
用下面的命令下载预训练的权重文件:
wget https://pjreddie.com/media/files/darknet53.conv.74
此文件是YOLOv3的骨干网络darknet53在ImageNet上训练得到的权重文件,可以加速训练过程,因为ImageNet里是有猫和狗的。当然,这个文件不是必须的,不用也是可以的。
准备好这些文件后,我们就可以执行以下命令开始训练了:
./darknet detector train cfg/cat\_and\_dog.data cfg/cat\_and\_dog\_yolov3.cfg darknet53.conv.74
训练完成后,在backup/目录下会得到权重文件 cat_and_dog_yolov3 _final.weights。首先把 cat_and_dog_yolov3.cfg 文件中 batch 和 subdivisions 都设置为1,然后运行下面的命令就可以进行测试了:
./darknet detector train cfg/cat\_and\_dog.data cfg/cat\_and\_dog\_yolov3.cfg backup/cat\_and\_dog\_yolov3\_final.weights data/dog.jpg
其中data/dog.jpg是要检测的图片。以下是我的一些检测结果:
来看几张难度高一点的:
本文以猫狗数据集为例,详细介绍了如何在Darknet框架下用自己的数据集训练YOLOv3的过程,希望本文能对不熟悉Darknet和YOLOv3的朋友有所帮助。