YOLO v2(Darknet)训练自定义数据集使用记录

1、环境准备

Darknet官网:https://pjreddie.com/darknet/yolo/

GitHub地址:https://github.com/pjreddie/darknet

Windows版本可参考:https://github.com/AlexeyAB/darknet

参照官网流程:下载源码,编译,下载基于voc或者coco数据集已训练好的权重文件,进行目标检测测试。

一切顺利的话,则可以准备自己的数据集进行训练了。

2、准备数据

准备好训练图片(以武器图片识别为例),参考VOC Data数据集格式,样本统一采用jpg格式的图像,名字上也使用像VOC一样类似000001.jpg、000002.jpg的格式命名。

按VOC数据集的结构放置图像文件。VOC的结构如下:

--VOC
    --Annotations
    --ImageSets
      --Main
      --Layout
      --Segmentation
    --JPEGImages
    --SegmentationClass
    --SegmentationObject

     这里面用到的文件夹是Annotations、ImageSets和JPEGImages。其中文件夹Annotations中主要存放xml文件,每一个xml对应一张图像,并且每个xml中存放的是标记的各个目标的位置和类别信息,命名通常与对应的原始图像一样;而ImageSets我们只需要用到Main文件夹,这里面存放的是一些文本文件,通常为train.txt、test.txt等,该文本文件里面的内容是需要用来训练或测试的图像的名字(无后缀无路径);JPEGImages文件夹中放我们已按统一规则命名好的原始图像。

      1.新建文件夹WeaponData

      2.在WeaponData文件夹下新建三个文件夹Annotations、ImageSets和JPEGImages,并把准备好的自己的原始图像放在JPEGImages文件夹下

      3.在ImageSets文件夹中,新建三个空文件夹Layout、Main、Segmentation,然后把写了训练或测试的图像的名字的文本拷到Main文件夹下,按训练(train)、验证(val)、测试(test)的目的命名(见后文)。

3、标注数据集

在获取到大量数据之后,为了实现目标检测,还需要对图片进行物体类别和位置的标注。Darknet使用xml文件格式来存储标注的物体坐标位置,训练自己的数据可以参考Pascal VOC Data数据集的文件夹以及文件组成结构创建相应的label文件。标注图片相关工具有很多,这里以labelImg为例,操作如下图:

标注完成后,在Annotation文件夹下便会生成所有图片的物体标注信息,每张图片对应一个xml文件。最后生成的文件如下:

其中每个xml文件中包含了图片的大小,所标注物体的类别及坐标位置。

4、准备训练

1、将所有样本按一定比例分为训练集、测试集、验证集三部分,比如按训练集、测试集、验证集的比例3:1:1分布,分别生成三个文件train.txt、val.txt、test.txt:

可以使用自己熟悉的语言写生成生成,文件中每一行就是一个文件名,不含扩展名,如下图所示:

2、将WeaponData文件夹、Darknet源码上传到服务器上(如果一开始就在服务器上做则省略),比如放到 /opt/dev/yolo 文件夹下,其中 /opt/dev/yolo/darknet为源码。

3、 在/opt/dev/yolo文件夹中新建文件夹VOCdevkit,再将前面准备好的整个WeaponData文件夹都拷到VOCdevkit文件夹下,并重命名为VOC2018(如果不重命名的话就需要修改voc_label.py脚本中相应位置来匹配文件夹名称)。

mkdir VOCdevkit
mv WeaponData VOCdevkit/VOC2018

4、 下载voc_label.py文件到/opt/dev/yolo下:

cd /opt/dev/yolo
wget https://pjreddie.com/media/files/voc_label.py

并修改voc_label.py中的sets和classes部分:

最后运行该脚本:

python voc_label.py

完成便会在文件夹/opt/dev/yolo/VOCdevkit/WeaponData下生成了文件夹lables, 文件夹里面包含了类别和对应归一化后的位置,同时在/opt/dev/yolo/下应该也生成了2018_train.txt、2018_test.txt、2018_val.txt三个文件,里面包含了所有样本的绝对路径。

再执行如下命令,将2018_train.txt和2018_val.txt的内容都用于训练:

cat 2018_train.txt 2018_val.txt > train.txt

5、配置文件修改

1、修改/opt/dev/yolo/darknet/data/voc.names,改为需要识别的目标类别:

aeroplane
person
building
ship
vehicle

2、 修改cfg/voc.data

classes= 5
train  = /opt/dev/yolo/train.txt
valid  = /opt/dev/yolo/2018_test.txt
names = /opt/dev/yolo/darknet/data/voc.names
backup = /opt/dev/yolo/results

其中classes为样本类别数, train 为训练样本的文件路径,valid为验证样本文件路径,names为类别文件,backup为权重文件备份目录(先创建好)。

3、 修改cfg/yolo-voc.2.0.cfg (也可以用 cfg/yolo-voc.cfg

修改最后一个卷基层的filters和最后一个region的classes。
其中,filters=num×(classes + coords + 1)=5*(5+4+1)=50,这里只有5个类别。

[convolutional]
size=1
stride=1
pad=1
filters=50
activation=linear

[region]
anchors = 1.08,1.19,  3.42,4.41,  6.63,11.38,  9.42,5.11,  16.62,10.52
bias_match=1
classes=5
coords=4
num=5
softmax=1
jitter=.2
rescore=1

……

6、修改 Makefile 文件

训练最好使用GPU,否则CPU非常慢,源码默认没有开启,一开始没有注意被坑了很久。

安装 cuda+cudnn 参考:https://www.cnblogs.com/573177885qq/p/6632576.html

然后修改Makefile文件:

cd /opt/dev/yolo/darknet
vim Makefile

修改顶部的三行开启GPU和CUDNN:

GPU=1
CUDNN=1
OPENCV=1
以及后面的NVCC为自己的路径:

NVCC=/usr/local/cuda-8.0/bin/nvcc

重新编译

make clean
make

7、开始训练

可以下载 ImageNet 的前23层预训练权重文件加快训练:

cd /opt/dev/yolo/darknet
wget https://pjreddie.com/media/files/darknet19_448.conv.23

然后执行如下命令开始训练:

./darknet detector train cfg/voc.data cfg/yolo-voc.2.0.cfg ./darknet19_448.conv.23 

如果需要分析输出日志的话,可以在命令后面使用tee将日志输出到文件。

训练时间比较长,可以观察loss,如果稳定到一定程度,则可以停止训练。

下面是训练过程的每一轮迭代输出例子:

Loaded: 0.000031 seconds
Region Avg IOU: 0.805040, Class: 0.929115, Obj: 0.777778, No Obj: 0.004146, Avg Recall: 0.875000,  count: 8
Region Avg IOU: 0.826887, Class: 0.999643, Obj: 0.778379, No Obj: 0.006632, Avg Recall: 0.916667,  count: 12
Region Avg IOU: 0.760517, Class: 0.999070, Obj: 0.698473, No Obj: 0.004795, Avg Recall: 0.846154,  count: 13
Region Avg IOU: 0.840628, Class: 0.999687, Obj: 0.805357, No Obj: 0.005085, Avg Recall: 0.900000,  count: 10
Region Avg IOU: 0.670166, Class: 0.944164, Obj: 0.620956, No Obj: 0.004349, Avg Recall: 0.777778,  count: 18
Region Avg IOU: 0.849498, Class: 0.999253, Obj: 0.743897, No Obj: 0.006114, Avg Recall: 0.933333,  count: 15
Region Avg IOU: 0.625192, Class: 0.957918, Obj: 0.562712, No Obj: 0.005363, Avg Recall: 0.550000,  count: 20
Region Avg IOU: 0.711634, Class: 0.999687, Obj: 0.687795, No Obj: 0.006114, Avg Recall: 0.941176,  count: 17
29391: 1.344486, 1.478107 avg, 0.000100 rate, 4.674087 seconds, 1881024 images

以上截图显示了所有训练图片的一个批次(batch),批次大小的划分根据我们在 .cfg 文件中设置的subdivisions参数。在我使用的 .cfg 文件中 batch = 64 ,subdivision = 8,所以在训练输出中,训练迭代包含了8组,每组又包含了8张图片,跟设定的batch和subdivision的值一致。

(注: 也就是说每轮迭代会从所有训练集里随机抽取 batch = 64 个样本参与训练,所有这些 batch 个样本又被均分为 subdivision = 8 次送入网络参与训练,以减轻内存占用的压力)

针对上图中最后一行中的信息 ,含义如下:

  •     29391: 指示当前训练的迭代次数
  •     1.344486: 是总体的Loss(损失)
  •     1.478107 avg: 是平均Loss,这个数值应该越低越好,一般来说,一旦这个数值低于0.060730 avg就可以终止训练了(由于我的样本质量不太好,这里值一直降不下去)。
  •     0.000100 rate: 代表当前的学习率,是在.cfg文件中定义的。
  •     4.674087 seconds: 表示当前批次训练花费的总时间。
  •     1881024 images: 表示到目前为止,参与训练的图片的总量。

8、测试

训练到一定阶段,中间输出权重可以拿来做识别测试,比如将10000次迭代的文件用于测试:

./darknet detector test cfg/voc.data cfg/yolo-voc.2.0.cfg yolo-voc_10000.weights data/person.jpg

这里需要注意的是,一定要使用./darknet detector test命令,指定自己的 voc.data和cfg文件。

检测结果会输出到predictions.png(或者predictions.jpg)中,可打开查看是否检测正确。

猜你喜欢

转载自my.oschina.net/nivalsoul/blog/1620768
今日推荐