该文件表示的是你的检测网络的结构,类似caffe的prototxt文件。
YOLOv3的cfg文件
上篇介绍YOLOv3网络中提到的去掉上采样操作的YOLOv3cfg文件
如下文件中规定了当前目标检测网络中的类别数量为4。训练数据的路径train.txt的位置,hs.names的路径的位置,以及最终训练得到的网络模型保存的位置。
classes = 4
train = /home/yuanlei/darknet_yolov3/backup/yolov3_initial/4_cls/train.txt
names = /home/yuanlei/darknet_yolov3/backup/yolov3_initial/4_cls/hs.names
backup = /home/yuanlei/darknet_yolov3/backup/yolov3_initial/4_cls
/home/yuanlei/traindata_4cls/0.jpg
/home/yuanlei/traindata_4cls/1.jpg
/home/yuanlei/traindata_4cls/2.jpg
/home/yuanlei/traindata_4cls/3.jpg
...
...
/home/yuanlei/traindata_4cls/1000.jpg
/home/yuanlei/traindata_4cls/1001.jpg
...
people
car
bicycle
truck
训练数据的保存位置要和步骤2中的train.txt文件中的路径对应起来,当然除了train.txt中的图片数据,我们还需要准备基于对应图片的目标位置和类别数据,也就是图片对应的标签文件,具体存放方式如下。
而上图中的txt
文件中的格式如下:
每一行代表了当前图片中的一个目标,每一行数据由5个字段组成,第一个字段表示了当前目标的类别,0:people, 1:car, 2:bicycly, 3.truck
和上述的hs.names文件相对应。而第二,三字段表示了在全图中当前目标的中心点位置,第四,五字段表示了在全图中当前目标的宽,高。我们可以看到这四个字段都是小于1的,因为都是以全图的宽高的百分比来表示的(回归网络训练时会更加容易收敛)。
如下所示的代码可以用来解析jpg,txt
文件,从大图中根据标签数据把小图抠出来,这段代码对YOLOv3网络的训练没有用处,把这段代码放在这里就是让大家对txt
文件中的字段有更清晰的理解。
from PIL import Image
img = Image.open("0.jpg")
width = img.size[0]
height = img.size[1]
with open("0.txt") as f:
lines = f.readlines()
for line in lines:
center_width = int(width * float(line.split(" ")[1]))
center_height = int(height * float(line.split(" ")[2]))
patch_width = int(width * float(line.split(" ")[3]))
patch_height = int(height * float(line.split(" ")[4]))
left_top_width = center_width - patch_width/2
left_top_height = center_height - patch_width/2
right_down_width = center_width + patch_width/2
right_down_height = center_height + patch_width/2
pic = img.crop(box=(left_top_width,left_top_height,right_down_width,right_down_height))
pic.show()
如果需要预训练权重,就重网上下载和cfg文件相对应的权重文件,并保存到/home/yuanlei/darknet_yolov3/backup/yolov3_initial/pretrain/yolov3.weights
路径下边即可。
批处理脚本如下所示,要训练检测网络,主要使用的两个字段为detetor,train
,以及一些必须的路径,如cfg,weights等路径。darknet中的主函数会解析给定的字段,进行训练,本文不展开讲,后续会专门这对这个过程写一篇文章。
cfg_dir = /home/yuanlei/darknet_yolov3 \
root_dir = /home/yuanlei/darknet_yolov3 \
$root_dir/darknet \
detector \
train \
$cfg_dir/backup/yolov3_initial/4_cls/hs.data \
$cfg_dir/backup/yolov3_initial/4_cls/yolov3_initial.cfg \
$cfg_dir/backup/yolov3_initial/pretrain/yolov3.weights
在命令行输入sh train.sh
,就可以开始训练了,至此利用YOLOv3训练自己的数据集全部完成~
如下的代码所示,网络训练过程中,每一个batch都会打印如下所示的信息。需要注意的是原始的基于darknet框架的YOLOv3网络并不会打印出l.batch 16, l.h 11, l.w 20, l.n 3
此类信息,这是我为了便于理解,在源码中添加后让其打印出来的。
Loaded: 0.000045 seconds
l.batch 16, l.h 11, l.w 20, l.n 3
Region 71 Avg IOU: 0.1578377, Class:0.329731, Obj: 0.614276, No Obj: 0.497656, .5R: 0.090909, .75R: 0.000000, count: 11
l.batch 16, l.h 22, l.w 40, l.n 3
Region 79 Avg IOU: 0.172776, Class:0.443888, Obj: 0.514122, No Obj: 0.489635, .5R: 0.052632, .75R: 0.000000, count: 19
l.batch 16, l.h 44, l.w 80, l.n 3
Region 87 Avg IOU: 0.169250, Class:0.485123, Obj: 0.664770, No Obj: 0.4577785, .5R: 0.102564, .75R: 0.000000, count: 39
l.batch 16, l.h 11, l.w 20, l.n 3
Region 71 Avg IOU: 0.159549, Class:0.464980, Obj: 0.487730, No Obj: 0.496075, .5R: 0.000000, .75R: 0.000000, count: 10
l.batch 16, l.h 22, l.w 40, l.n 3
Region 79 Avg IOU: 0.210336, Class:0.425438, Obj: 0.47328, No Obj: 0.489249, .5R: 0.095238, .75R: 0.000000, count: 21
l.batch 16, l.h 44, l.w 80, l.n 3
Region 87 Avg IOU: 0.144593, Class:0.413408, Obj: 0.617854, No Obj: 0.4457386, .5R: 0.000000, .75R: 0.000000, count: 53
8666434: 1440.400757, 1468.966187 avg, 0.000050 rate, 3.923887 seconds, 27725888 images
输出log中,分为两部分,这主要基于cfg文件中的batch=32,subdivisions=2
,所以第一部分用到了16张图,第二部分用到了另外16张图。而任意部分中输出了三块,其中每一块代表了一种特征图上的detection结果,利用我打印出来的l.batch 16, l.h 11, l.w 20, l.n 3
语句能更好的区分每一小块代表的是哪种尺度的detection。
简单介绍下cfg文件中的一些参数:
batch=32
subdivisions=2
angle=0
saturation = 1.5
exposure = 1.5
hue=.1
policy=steps
steps=866633,876633,896633
scales=10,.5,.2
lr = base_lr * power(batch_num/burn_in,pwr)
更新。其背后的假设是:全局最优点就在网络初始位置附近,所以训练开始后的burn_in次更新,学习速率从小到大变化。update次数超过burn_in后,采用配置的学习速率更新策略从大到小变化,显然在finetune时可以尝试使用该参数。burn_in=200
[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=4
num=9
jitter=.3
ignore_thresh = .5
truth_thresh = 1
random=0
anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
mask = 6,7,8
mask = 4,5,6
mask = 1,2,3
random为1时会启用Multi-Scale Training,随机使用不同尺寸的图片进行训练,如果为0,每次训练大小与输入大小一致;