YOLOv3训练自己的数据详细步骤

目录

  • 前言
  • 编译安装
    • 1. 环境要求
    • 2. 下载及编译
  • 训练
    • 1. 准备数据
      • 1.1 使用yolo_mark对图片进行标注
      • 1.2 将图片保存到data目录
    • 2. 修改配置文件
      • 2.1 train文件
      • 2.2 valid文件
      • 2.3 names文件
      • 2.4 data文件
      • 2.5 cfg文件
      • 2.6 权重文件
    • 3. 训练过程及输出
      • 3.1 命令行参数
      • 3.2 训练输出参数及输出文件
  • 测试
    • 1. 验证模型效果
    • 2. 使用模型进行预测
      • 2.1 检测图片
      • 2.2 检测视频

前言

本篇文章记录了在centos7(Linux)上使用YOLOv3训练自己数据的操作步骤,YOLOv3使用AlexeyAB大神改进的darknet(Github地址),内容也主要参考自其中,使用其它系统或框架的同学可以酌情参考或直接阅读Github。

题外话:第一次写博客,可能存在诸多问题和遗漏,欢迎大家指出更正。

编译安装

1. 环境要求

由于环境的准备工作不是本篇文章的重点,这里只做简单叙述。
根据Github上的要求:

  • CMake >= 3.8
  • CUDA 10.0
  • cuDNN >= 7.0 for CUDA 10.0 (注意要和CUDA版本对应)
  • OpenCV >= 2.4
  • GPU with CC >= 3.0
  • GCC

2. 下载及编译

darknet源码下载地址:https://github.com/AlexeyAB/darknet

下载解压后进入darknet根目录,根据机器情况修改Makefile文件:

GPU=1			# 是否使用GPU
CUDNN=1			# 是否使用CUDNN
CUDNN_HALF=1	# 是否为Tensor核心加速,
				  Titan V / Tesla V100 / DGX-2及更高版本显卡可以使用
OPENCV=1		# 是否使用OPENCV
OPENMP=0		# 是否使用OPENMP 

修改后进行编译,在darknet根目录执行:

make

训练

1. 准备数据

1.1 使用yolo_mark对图片进行标注

yolo_mark下载地址:https://github.com/AlexeyAB/Yolo_mark

对于每个图片,yolo_mark输出一个txt文件,每一行代表一个bounding box,格式如下:

<类别>        

设该bounding box中心的绝对坐标为(,)
该bounding box在绝对坐标下宽高为(,)
图片的宽高为(,)
则每个参数的含义如下:

参数 含义
<类别> 该bounding box内物体的类别,为[0, class-1]之间整数
/ ,为[0,1]之间浮点数
/ ,为[0, 1]之间浮点数
/ ,为[0, 1]之间浮点数
/ ,为[0, 1]之间浮点数

例:1 0.609766 0.660417 0.388281 0.215278

1.2 将图片保存到data目录

图片的存放位置可以自行决定,但建议存放在darknet根目录下的data目录下,方便管理。
进入data目录,创建用于存放数据的文件夹,命名为obj (目录名可以根据自己需求更改):

cd data
mkdir obj

将图片文件和对应的txt标注文件一起存放进data/obj/目录下。
注意:图片文件和对应的txt标注文件的文件名要保持一致。

2. 修改配置文件

2.1 train文件

作用:训练数据集路径。

在data目录下创建train文件train.txt (文件名可以自行更改,但要保持前后一致),文件内容为用作训练数据的图片路径。如:
我要使用data/obj/目录下的如下文件进行训练:

obj_0.jpg    obj_130.jpg  obj_152.jpg
obj_0.txt    obj_130.txt  obj_152.txt

则对应的train.txt文件内容为:

data/obj/obj_0.jpg
data/obj/obj_130.jpg
data/obj/obj_152.jpg

2.2 valid文件

作用:验证数据集路径。使用map指令验证模型效果时,程序会调用该路径。

在data目录下创建valid文件test.txt (文件名可以自行更改,但要保持前后一致),文件内容为作为验证数据的文件路径,格式与train文件相同。

2.3 names文件

作用:指明类别名称。

在data目录下创建names文件obj.names (文件名可以自行更改,但要保持前后一致),文件内容为每一类检测物体的名称,具体如下:
如果我要检测两类物体,类别0代表apple,类别1代表orange,则obj.names内容为:

apple
orange

需要注意顺序,第一行对应类别0,第二行对应类别1,依此类推。

2.4 data文件

作用:指明上述各个文件的位置。

在data目录下创建data文件obj.data (文件名可以自行更改,执行指令时保持输入参数一致即可),文件内容如下:

classes = 2				# 检测物体类别数,如:检测apple和orange两类物体,则类别数为2。
train = data/train.txt	# train文件位置,需保持路径及文件名前后一致。
valid = data/test.txt	# valid文件位置,需保持路径及文件名前后一致。
names = data/obj.names	# names文件位置,需保持路径及文件名前后一致。
backup = backup/		# 训练过程产生的模型参数文件会保存在该文件夹下,
						# 这里设置为darknet根目录下的backup文件夹。

2.5 cfg文件

作用:神经网络的详细构建参数。

在darknet根目录的cfg文件夹下,复制yolov3.cfg命名为yolo-obj.cfg (文件名可以自行更改,执行指令时保持输入参数一致即可)。
修改文件内容:

batch=64			# 每个迭代训练的图片数,一个迭代更新一次参数
subdivisions=8		# 将一个迭代的图片分成subdivisions次进行训练,内存不足时可以适当调大
					# 这里batch=64,subdivisions=8,则每个subdivision训练的图片数量为64/8=8
...
max_batches=4000	# 最大迭代次数,建议设置为(classes*2000), 比如识别两类物体,则设置为4000
					# 如果训练效果不理想,也可以调大,通过测试集的mAP判断模型是否可用或是否过拟合
					
steps=3200,3600		# 迭代到steps对应的次数时,学习率衰减,衰减系数通过scales设定,
					# 建议将steps设置为max_batches的80%和90%

另外,在三个[yolo]层中,将classes修改为识别类别数,如classes=2
在三个位于[yolo]层之前的[convolutional]层中,将filters修改为(classes + 5) × 3,如filters=21
注意,要将filters设置为整数,不能直接写表达式。

cfg文件中的部分参数含义如下1,2,3,4

[net]
# Testing			# 测试时,将batch和subdivisions设为1
# batch=1
# subdivisions=1
# Training
batch=64			# 每个迭代训练的图片数
subdivisions=8		# 将每个迭代分成subdivisions次训练,内存不足时可以适当调大

width=416			# 输入图像宽度
height=416			# 输入图像高度
channels=3			# 输入图像通道数
					# darknet有resize步骤,不需要预先将图片转换成设定的宽高
					# width和height影响图片在网络中的分辨率,可以自行调整为32的倍数

momentum=0.9		# 梯度下降中的动量参数
decay=0.0005		# 权重衰减正则项,防止过拟合
					# 每次学习参数后,将参数按照decay的比例进行降低,防止过拟合

angle=0				# 通过旋转增加数据
saturation = 1.5	# 通过更改饱和度增加数据
exposure = 1.5		# 通过更改曝光度增加数据
hue=.1				# 通过更改色调增加数据

learning_rate=0.001	# 学习率
burn_in=1000		# 小于burn_in使用默认学习率策略,大于burn_in使用设定的学习策略,详见参考2 
max_batches=4000	# 最大迭代次数,即停止条件
policy=steps		# 学习率调整策略,详见参考3
steps=3200,3600		# 迭代次数达到steps时,使学习率衰减
scales=.1,.1		# 学习率衰减系数

...

[yolo]
mask = 0,1,2		# YOLOv3中共提前预设了9种尺寸的anchor,每个yolo层负责其中3种尺寸的预测
					# 如:这个yolo层负责第0,1,2个anchor的预测
anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326
					# 预设anchor的width和height,可以预先自行对ground truth做k-means聚类得到
classes=2			# 预测物体的种类数
num=9				# YOLO划分的每个网格内预测的bounding box数量
jitter=.3			# [存疑]数据扩充的抖动操作

ignore_thresh = .7	# 当bounding box与ground truth的IOU不是最大,但大于ignore_thresh时,
					# 网络会忽略其confidence的更改,既不奖励也不惩罚。这种做法借鉴自Faster RCNN
					# 注:IOU最大的bounding box的confidence会被奖励,IOU过小的会被惩罚
truth_thresh = 1
random=1			# 关闭则图片大小与输入大小一致,打开则每迭代几次后,网络会随机更改输入尺寸
					# 想提升训练速度时可以关闭,即random=0

2.6 权重文件

下载预训练好的权重文件darknet53.conv.74到darknet根目录下。
地址:https://pjreddie.com/media/files/darknet53.conv.74

3. 训练过程及输出

3.1 命令行参数

使用配置好的data文件,cfg文件,以及下载的预训练权重文件,开始训练自己的数据。
在darknet根目录下(包含可执行文件darknet的目录)执行如下命令:

./darknet detector train data/obj.data cfg/yolo-obj.cfg darknet53.conv.74

使用指定GPU训练,如使用0号和1号GPU训练,则加上参数-gpus 0,1,执行:

./darknet detector train data/obj.data cfg/yolo-obj.cfg darknet53.conv.74 -gpus 0,1

训练过程不显示损失变化图,则加上参数-dont_show,执行:

./darknet detector train data/obj.data cfg/yolo-obj.cfg darknet53.conv.74 -dont_show

在上一次训练好的模型的基础上继续训练,将权重文件更改即可。
比如上一次训练好的权重文件为backup/目录下的yolo-obj_final.weights文件,则执行:

./darknet detector train data/obj.data cfg/yolo-obj.cfg backup/yolo-obj_final.weights

更多详细参数,参考项目的Github说明。

3.2 训练输出参数及输出文件

输出参数格式如下:

...
Region 82 Avg IOU: 0.830165, Class: 0.999033, Obj: 0.936065, No Obj: 0.002346, .5R: 1.000000, .75R: 1.000000,  count: 2
Region 94 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.000005, .5R: -nan, .75R: -nan,  count: 0
Region 106 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.000001, .5R: -nan, .75R: -nan,  count: 0
Region 82 Avg IOU: 0.831569, Class: 0.990958, Obj: 0.845798, No Obj: 0.002309, .5R: 1.000000, .75R: 1.000000,  count: 2
Region 94 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.000002, .5R: -nan, .75R: -nan,  count: 0
Region 106 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.000001, .5R: -nan, .75R: -nan,  count: 0
Region 82 Avg IOU: 0.814712, Class: 0.991421, Obj: 0.605646, No Obj: 0.001831, .5R: 1.000000, .75R: 1.000000,  count: 2
Region 94 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.000002, .5R: -nan, .75R: -nan,  count: 0
Region 106 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.000001, .5R: -nan, .75R: -nan,  count: 0

 1481: 0.094071, 0.133265 avg loss, 0.000100 rate, 3.951930 seconds, 94784 images
...

可以看到有两种输出参数,下面分别进行说明1

  • 种类1
Region 82 Avg IOU: 0.814712, Class: 0.991421, Obj: 0.605646, No Obj: 0.001831, .5R: 1.000000, .75R: 1.000000,  count: 2
Region 94 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.000002, .5R: -nan, .75R: -nan,  count: 0
Region 106 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.000001, .5R: -nan, .75R: -nan,  count: 0

这三行代表一个subdivision内的参数,分别代表了三种尺寸anchor的结果,具体含义如下:

参数 含义
Avg IOU 该subdivision内,bounding box与ground truth的平均IOU
Class 物体分类的正确率,期望其趋于1
Obj 期望其趋于1
No Obj 期望其趋于0
.5R IOU=0.5时的recall
.75R IOU=0.75时的recall
count 该subdivision内,正样本(即检测到正确物体)的个数

注意,一个subdivision训练的图片数量,等于batch / subdivisions

  • 种类2
 1481: 0.094071, 0.133265 avg loss, 0.000100 rate, 3.951930 seconds, 94784 images

这一行表示一次迭代(batch个图片)的训练输出参数,具体含义如下:

参数 含义
1481 当前迭代次数
0.094071 总体Loss[存疑]
0.133265 avg loss 平均Loss,判断模型效果的重要指标
0.000100 rate 当前学习率
3.951930 seconds 本次迭代到目前所用的时长
94784 images 所有迭代中,训练过的图片总量

输出的权重文件保存在backup/目录下。
每1000次迭代自动保存一次,每100次迭代自动更新backup/yolo-obj_last.weights文件。

测试

1. 验证模型效果

使用验证集查看模型mAP,precision,recall,F1,命令如下:
假设训练好的模型权重文件为backup/目录下的yolo-obj_final.weights,则执行:

./darknet detector map data/obj.data cfg/yolo-obj.cfg backup/yolo-obj_final.weights

输出格式如下:

 detections_count = 744, unique_truth_count = 712  
class_id = 0, name = apple, 	 ap = 100.00 % 
class_id = 1, name = orange, 	 ap = 99.97 % 
 for thresh = 0.25, precision = 1.00, recall = 1.00, F1-score = 1.00 
 for thresh = 0.25, TP = 712, FP = 1, FN = 0, average IoU = 91.33 % 

 IoU threshold = 50 % 
 mean average precision ([email protected]) = 0.999841, or 99.98 % 

2. 使用模型进行预测

2.1 检测图片

假设图片路径为data/p1.jpg,则执行:

./darknet detector test data/obj.data cfg/yolo-obj.cfg backup/yolo-obj_final.weights data/p1.jpg

检测结果为darknet根目录下的predictions.jpg

2.2 检测视频

假设视频路径为data/video.avi,则执行:

./darknet detector demo data/obj.data cfg/yolo-obj.cfg backup/yolo-obj_final.weights data/video.avi

  1. cfg文件参数及训练输出参数参考自:Yolov3参数理解 ↩︎ ↩︎

  2. burn_in参数参考自:darknet-配置参数burn-in ↩︎

  3. policy参数参考自:学习率改变策略 ↩︎

  4. ignore_thresh参数参考自:论文 - YOLO v3
    这篇对YOLOv3的讲解很详细,建议想深入了解的同学阅读一下。 ↩︎

你可能感兴趣的:(yolo,目标检测,训练自己的数据,教程)