目录
相关资料
官方链接
yoloV4论文:《YOLOv4: Optimal Speed and Accuracy of Object Detection》
yoloV4 Github代码:https://github.com/AlexeyAB/darknet
yoloV1~V3 Github代码:https://github.com/pjreddie/darknet
darknet官网:https://pjreddie.com/darknet/
权重文件
可以从指定链接或百度网盘下载:
(1)yoloV4.weights(245MB):
https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v3_optimal/yolov4.weights
https://pan.baidu.com/s/1KBCYYZdJ1XshFUqSWy8EcA
(提取码:htlf)
(2)yoloV4预训练权重:yolov4.conv.137
https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v3_optimal/yolov4.conv.137
https://pan.baidu.com/s/1pEmlzaevA6SHBjQImqRUnw
(提取码:ujy5)
(3)yolov4-tiny.weights(23.1MB):
https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v4_pre/yolov4-tiny.weights
https://pan.baidu.com/s/1Ea9w4LoOXuwgIqFGhfG_dQ
(提取码:da8k)
(4)tiny yoloV4预训练权重:yolov4-tiny.conv.29:
https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v4_pre/yolov4-tiny.conv.29
https://pan.baidu.com/s/1xkSUkvTwLe4PmH_v3vM3aQ
(提取码:7m7o)
训练步骤
(1)编译
下载darknet:
git clone https://github.com/AlexeyAB/darknet.git
编译有两种方式Makefile和Cmake(推荐make),Makefile配置项及解释如下:
其中,GPU和CUDNN是GPU加速,CUDNN_HALF是特定硬件加速,OPENCV是否使用OpenCV,AVX和OPENMP是CPU加速
cd darknet
make 或者 make -j8(加速编译)
(2)数据准备
数据按照VOC或者COCO数据集的格式准备,以VOC格式示例(也可以自定义格式,直接生成label,后续加):
----VOCdevkit\
|----VOC2020\ # 目录
| |----Annotations\
| | |----00000001.xml # 图片标注信息
| |----ImageSets\
| | |----Main\ # 训练:验证:测试=1:1:2
| | | |----test.txt # 测试集
| | | |----train.txt # 训练集
| | | |----val.txt # 验证集
| |----JPEGImages\
| | |----00000001.jpg # 对应图片
复制/darknet/scripts/VOC_label.py与VOCdevkit文件夹并列,修改VOC_label.py并运行
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
sets=[('2020', 'train'), ('2020', 'val'), ('2020', 'test')] # **对应VOC2020和Main下面的数据集**
classes = ["car", "bus", "motor"] # **训练类别信息**
def convert(size, box):
dw = 1./(size[0])
dh = 1./(size[1])
x = (box[0] + box[1])/2.0 - 1
y = (box[2] + box[3])/2.0 - 1
w = box[1] - box[0]
h = box[3] - box[2]
x = x*dw
w = w*dw
y = y*dh
h = h*dh
return (x,y,w,h)
def convert_annotation(year, image_id):
in_file = open('VOCdevkit/VOC%s/Annotations/%s.xml'%(year, image_id))
out_file = open('VOCdevkit/VOC%s/labels/%s.txt'%(year, image_id), 'w')
tree=ET.parse(in_file)
root = tree.getroot()
size = root.find('size')
w = int(size.find('width').text)
h = int(size.find('height').text)
for obj in root.iter('object'):
difficult = obj.find('difficult').text
cls = obj.find('name').text
if cls not in classes or int(difficult)==1:
continue
cls_id = classes.index(cls)
xmlbox = obj.find('bndbox')
b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text))
bb = convert((w,h), b)
out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
wd = getcwd()
for year, image_set in sets:
if not os.path.exists('VOCdevkit/VOC%s/labels/'%(year)):
os.makedirs('VOCdevkit/VOC%s/labels/'%(year))
image_ids = open('VOCdevkit/VOC%s/ImageSets/Main/%s.txt'%(year, image_set)).read().strip().split()
list_file = open('%s_%s.txt'%(year, image_set), 'w')
for image_id in image_ids:
list_file.write('%s/VOCdevkit/VOC%s/JPEGImages/%s.jpg\n'%(wd, year, image_id))
convert_annotation(year, image_id)
list_file.close()
os.system("cat 2020_train.txt 2020_val.txt > train.txt")
生成yolo训练数据格式如下:
----train_data\
|----2020_test.txt
|----2020_train.txt
|----2020_val.txt
|----train.txt
|----VOCdevkit\
| |----VOC2020\
| | |----Annotations\
| | | |----00000001.xml
| | |----ImageSets\
| | | |----Main\
| | | | |----test.txt
| | | | |----train.txt
| | | | |----val.txt
| | |----JPEGImages\
| | | |----00000001.jpg
| | |----labels\
| | | |----00000001.txt
|----voc_label.py
(3)修改配置
(a) cfg/yoloV4-custom(tiny).cfg
[net]层要改batch,[yolo]层要改classes,[convolutional]要改filters
(t配置文件搜yolo,tiny改两处,V4改三处)
[net]
# Testing #测试模式,测试时开启
#batch=1 #
#subdivisions=1 #
# Training #训练模式,训练时开启,测试时注释
**batch=256** # 每批数量,根据配置设置,如果内存小,改小batch和subdivisions, batch和subdivisions越大,效果越好
**subdivisions=16** #
width=416
height=416
channels=3 # 输入图像width height channels 长宽设置为32的倍数,因为下采样参数是32,最小320*320 最大608*608
momentum=0.9 # 动量参数,影响梯度下降速度
decay=0.0005 # 权重衰减正则项,防止过拟合
angle=0 # 旋转
saturation = 1.5 # 饱和度扩增
exposure = 1.5 # 曝光度
hue=.1 # 色调
learning_rate=0.00261 # 学习率,权值更新速度
burn_in=1000 # 迭代次数小于burn_in,学习率更新;大于burn_in,采用policy更新
max_batches = 500200 # 训练达到max_batches停止
policy=steps # 学习率调整策略policy:constant, steps, exp, poly, step, sig, RANDOM
steps=400000,450000 # 步长
scales=.1,.1 # 学习率变化比例
[convolutional]
batch_normalize=1
filters=32
size=3
stride=2
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=64
size=3
stride=2
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=64
size=3
stride=1
pad=1
activation=leaky
[route]
layers=-1
groups=2
group_id=1
[convolutional]
batch_normalize=1
filters=32
size=3
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=32
size=3
stride=1
pad=1
activation=leaky
[route]
layers = -1,-2
[convolutional]
batch_normalize=1
filters=64
size=1
stride=1
pad=1
activation=leaky
[route]
layers = -6,-1
[maxpool]
size=2
stride=2
[convolutional]
batch_normalize=1
filters=128
size=3
stride=1
pad=1
activation=leaky
[route]
layers=-1
groups=2
group_id=1
[convolutional]
batch_normalize=1
filters=64
size=3
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=64
size=3
stride=1
pad=1
activation=leaky
[route]
layers = -1,-2
[convolutional]
batch_normalize=1
filters=128
size=1
stride=1
pad=1
activation=leaky
[route]
layers = -6,-1
[maxpool]
size=2
stride=2
[convolutional]
batch_normalize=1
filters=256
size=3
stride=1
pad=1
activation=leaky
[route]
layers=-1
groups=2
group_id=1
[convolutional]
batch_normalize=1
filters=128
size=3
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=128
size=3
stride=1
pad=1
activation=leaky
[route]
layers = -1,-2
[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky
[route]
layers = -6,-1
[maxpool]
size=2
stride=2
[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky
##################################
[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky
[convolutional]
size=1
stride=1
pad=1
**filters=24** # 3*(classes+5)
activation=linear
[yolo]
mask = 3,4,5
anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319
**classes=3** # 类别数,修改为实际需要数量
num=6
jitter=.3
scale_x_y = 1.05
cls_normalizer=1.0
iou_normalizer=0.07
iou_loss=ciou
ignore_thresh = .7
truth_thresh = 1
random=0
resize=1.5
nms_kind=greedynms
beta_nms=0.6
[route]
layers = -4
[convolutional]
batch_normalize=1
filters=128
size=1
stride=1
pad=1
activation=leaky
[upsample]
stride=2
[route]
layers = -1, 23
[convolutional]
batch_normalize=1
filters=256
size=3
stride=1
pad=1
activation=leaky
[convolutional]
size=1
stride=1
pad=1
**filters=24** # 3*(5+classes)
activation=linear
[yolo]
mask = 1,2,3
anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319 #预测框的初始宽高,第一个是w,第二个是h,总数量是num*2
**classes=3** # 类别数,修改为实际需要数量
num=6 # 每个grid预测的BoundingBox个数
jitter=.3 # # 利用数据抖动产生更多数据抑制过拟合.YOLOv2中使用的是crop,filp,以及net层的angle,flip是随机的,crop就是jitter的参数,tiny-yolo-voc.cfg中jitter=.2,就是在0~0.2中进行crop
scale_x_y = 1.05
cls_normalizer=1.0
iou_normalizer=0.07
iou_loss=ciou
ignore_thresh = .7 # # 决定是否需要计算IOU误差的参数,大于thresh,IOU误差不会夹在cost function中
truth_thresh = 1
random=0 # 如果为1每次迭代图片大小随机从320到608,步长为32,如果为0,每次训练大小与输入大小一致
resize=1.5
nms_kind=greedynms
beta_nms=0.6
(b) data/voc.names
car
bus
motor
© cfg/voc.data
classes= 3 # 类别数
train = /home/keygo/darknet-master/traindata/train.txt # 训练集路径
valid = /home/keygo/darknet-master/traindata/2020_test.txt # 测试集路径
names = data/voc.names # 类别详细
backup = /home/keygo/darknet-master/backup # 模型生成路径,没有需新建
(4)训练
可以根据需求设置不同的flag
(a) 多GPU训练:
(0,1, 指GPU索引,可以nvidia-smi查看)
./darknet detector train data\voc.data cfg\yolov4.cfg yolov4.conv.137 -gpus 0,1
(b) 指定GPU训练:
(GPU 0)
./darknet detector train data\voc.data cfg\yolov4.cfg yolov4.conv.137 -gpus 0
./darknet detector train data\voc.data cfg\yolov4.cfg yolov4.conv.137 -gpus 0
© 重定向生成log,方便分析(V4已有可视化):
./darknet detector train cfg/voc.data cfg/yolov3-tiny.cfg yolov3-tiny.conv.15 -gpus 0,1 2>&1 > tiny.log
(d) 停止后继续训练:
./darknet detector train cfg/voc.data cfg/yolov4-tiny.cfg backup/yolov4-tiny_99000.weights -gpus 0,1
(e) mAP可视化
类别平均精度,每4个epoch会算一次(Epoch = images_in_train_txt / batch)
./darknet detector train cfg/voc.data cfg/yolov4-tiny.cfg backup/yolov4-tiny_99000.weights -gpus 0,1 -map
停止训练
一般最好训练(类别数2000)迭代次数,停止标志:
(1)当看到平均loss0.XXXXXXX avg**不下降时,平均loss小于 0.05
(小模型简单数据集) to 3.0
(大模型复杂数据集).
(2)如果训练时加上 -map
控制台上mAp提示比loss下降更好,当精度不再上升时停止
选取最优权重
训练结束后,/darknet/backup文件夹下有很多权重文件,如何知道哪个模型是最优模型
./data/VOC.data有验证集路径,分别测试不同权重在验证集上测试效果
./darknet detector map data/VOC.data yolo-obj.cfg backup\yolo-obj_6000.weights
比较最后一行,选mAP (mean average precision) 最大的 ,或者IoU(intersect over union)最好的
测试
./darknet detect cfg/yolov3.cfg yolov3.weights data/dog.jpg
darknet文件夹也有darknet.py和darknet_video.py示例
不过都是输入路径,如果想读取图片输入接口,后续加。