(tiny) YOLOv4 详细训练指南(附下载链接)

    技术2022-07-10  99

    目录

    相关资料官方链接权重文件 训练步骤(1)编译(2)数据准备(3)修改配置(a) cfg/yoloV4-custom(tiny).cfg(b) data/voc.names(c) cfg/voc.data (4)训练(a) 多GPU训练:(b) 指定GPU训练:(c) 重定向生成log,方便分析(V4已有可视化):(d) 停止后继续训练:(e) mAP可视化 停止训练选取最优权重测试

    相关资料

    官方链接

    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/1pIGTyXrp1Py10DwSLtsPnw (提取码:g9b2) (2)yoloV4预训练权重:yolov4.conv.137 https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v3_optimal/yolov4.conv.137 https://pan.baidu.com/s/1PIDlAtOEKYGN1YQ4lFBFlg (提取码:cs4k) (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/1rS3DIlARFCiqId0TmN1XYg (提取码:16ln)

    (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/16b7GpOU50B2YkjriVQl1UQ (提取码:xbqc)

    训练步骤

    (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示例 不过都是输入路径,如果想读取图片输入接口,后续加。

    Processed: 0.021, SQL: 9