• yolov3训练


    作者:ll_sunsmile
    来源:CSDN
    原文:https://blog.csdn.net/ll_master/article/details/81392013
    版权声明:本文为博主原创文章,转载请附上博文链接!

    列举问题:

    (1、2、3在test中出现,4在train中出现)

    1.

    改darknet下makefile文件参数,修改不成功。
    解决:服务器配置有问题。检查cuda,cudnn,opencv这些版本是否兼容吧。。要是一直修改不成功,就去删darknet,重新做一遍。要出来结果,肯定要付出代价的么。一遍不成功就再来一遍。反正我改了修也做了三遍。

    2.

    backup生成的权重文件不会用。傻里巴叽还用之前自带版本的权重,结果哭唧唧,生成一大堆车、马、人,根本不是自己需要的类别标签。
    解决:当然使用自己生成的权重文件啦,backup下每次都有会新的迭代权重。

    3

    好不容易解决了前面两个,终于熬到检测这一步,奇怪的发现还是什么都没有。
    解决:检测语句有问题,细心的我特别去看了官网的检测语句。有两条等同的检测语句,我们选择那条指明分类的语句。因为分类结果出不来,肯定是没有找到分类文件呀。我们给他指明,就清楚咯。
    选择这种:

    ./darknet detector test cfg/voc.data cfg/yolov3-voc.cfg backup/yolov3-voc_10000.weights data/1.jpg
    

    不选择这种:

    ./darknet detect cfg/yolov3-voc.cfg backup/yolov3-voc_600.weights data/1.jpg
    

    4.

    还有就是开始train的时候cuda out of memory等问题。
    例如 :

    0 CUDA Error: out of memory 
    darknet: ./src/cuda.c:36: check_error: Assertion `0’ failed.
    

    原因:gpu占用有问题,gpu全部占用,或内存不足时会出现此问题。
    解决方案1:修改batch=1与subdivision=1,减少每次的输入量。
    解决方案2:查看GPU占用,

    nvidia-smi	#查看GPU占用情况,
    kill -9 <pid>	#-9,强制执行
    

    训练正式开始

    1.

    标注自己的数据集。根据自己划分的类别用labelimg进行标注,保存后会生成与所标注图片文件名相同的xml文件。

    2.

    下载官网yolov3工程

    git clone https://github.com/pjreddie/darknet cd darknet
    cd darknet
    

    3.

    修改配置文件
    打开Makefile,修改编译选择。

    1. GPU=1 #使用GPU训练,其他参数可根据需要调整
    2. CUDNN=0 #可选
    3. OPENCV=1 #需安装opencv
    4. OPENMP=0
    5. DEBUG=0
    make #保存,记住一定要make才能生效 
    

    修改完成后,在darknet目录下进行编译。
    如果服务器配置没有问题,那么会成功,如果不成功的话就检查一下cuda,cudnn,opencv这些版本是否兼容的问题。

    4.

    准备数据集,建立层级结构存储目录便于数据的管理。文件名称的命名也是为了以后方便修改配置文件。

    1. darknet
    2. --voc
    3. ​ --VOCdevkit
    4. ​ --VOC2018 #voc%s 这个%s最好是按照自己的数据集名称命名,为了以后区分自己数据集。
    5. ​ --Annotations
    6. ​ --ImageSets
    7. ​ --Main
    8. ​ --JPEGImages

    Annotations中放所有的xml文件;JPEGImages中放所有的图片;Main中放train.txt和test.txt。

    5.

    然而train.txt和test.txt是如何生成的呢?
    生成python文件取出训练集和测试集的图片名称没有后缀名。

    import os
    from os import listdir, getcwd
    from os.path import join
    if __name__ == '__main__':
        source_folder='/home/lll/darknet/voc/VOCdevkit/VOC2018/JPEGImages/'#地址是所有图片的保存地点
        dest='/home/lll/darknet/voc/VOCdevkit/VOCClock/ImageSets/Main/train.txt'  #保存train.txt的地址
       dest2='/home/lll/darknet/voc/VOCdevkit/VOCClock/ImageSets/Main/test.txt'  #保存val.txt的地址
        file_list=os.listdir(source_folder)       #赋值图片所在文件夹的文件列表
        train_file=open(dest,'a')                 #打开文件
        val_file=open(dest2,'a')                  #打开文件
        for file_obj in file_list:                #访问文件列表中的每一个文件
            file_path=os.path.join(source_folder,file_obj) 
            #file_path保存每一个文件的完整路径
            file_name,file_extend=os.path.splitext(file_obj)
            #file_name 保存文件的名字,file_extend保存文件扩展名
            file_num=int(file_name) 
            #把每一个文件命str转换为 数字 int型 每一文件名字都是由四位数字组成的  如 0201 代表 201     高位补零  
            if(file_num<150):                     #保留149个文件用于训练
                #print file_num
                train_file.write(file_name+'
    ')  #用于训练前149个的图片路径保存在train.txt里面,结尾加回车换行
            else :
                val_file.write(file_name+'
    ')    #其余的文件保存在val.txt里面
        train_file.close()#关闭文件
    val_file.close()
    

    6.

    下载和修改voc_label.py(这个文件就说明了为什么一开始建立层级目录,因为可以避免很多路径的修改呀)
    下载:
    wget https://pjreddie.com/media/files/voc_label.py
    修改:

    import xml.etree.ElementTree as ET
    import pickle
    import os
    from os import listdir, getcwd
    from os.path import join
     #根据自己的需要修改,只要前后路径对应就行。
    sets=[('2018', 'train'), ('2018', 'test')]
     #我的类是5个(^U^)ノ~YO
    classes = ["m", "s","l","xl","xxl"]
    def convert(size, box):
        dw = 1./size[0]
        dh = 1./size[1]
        x = (box[0] + box[1])/2.0
        y = (box[2] + box[3])/2.0
        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]) + '
    ')
    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
    '%(wd, year, image_id))
            convert_annotation(year, image_id)
        list_file.close()
    

    7.

    执行voc_label.py:

    python voc_label.py
    

    在voc下生成了2018_train.txt 和 2018_test.txt,分别存放了训练集和测试集图片的路径。
    ps:这里用到了之前main下的train和test文本文件,使得xml和jpg文件一一对应,并且生成最后的图片路径。
    之后训练时候就可以根据图片路径和一些配置文件信息进行训练咯。

    8.

    下载预训练模型

    wget https://pjreddie.com/media/files/darknet53.conv.74
    

    9.

    修改 cfg/voc.data

    1. classes= 5 #classes为训练样本集的类别总数
    2. train = /home/lll/darknet/voc/2018_train.txt #train的路径为训练样本集所在的路径
    3. valid = /home/lll/darknet/voc/2018_test.txt #test的路径为验证样本集所在的路径
    4. names = data/voc.names #names的路径为data/voc.names文件所在的路径
    5. backup = backup

    10.

    修改data/voc.names

    • s
    • m
    • l
    • xl
    • xxl
    • 上面python文件中也要与之对应哈

    11.

    修改cfg/yolov3-voc.cfg

    [net]
    #Testing
    #batch=1
    #subdivisions=1
    #Training
     batch=64            
     subdivisions=8    #---------------修改
    ......
    [convolutional]
    size=1
    stride=1
    pad=1
    filters=30        #---------------修改
    activation=linear
    [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=5        #---------------修改
    num=9
    jitter=.3
    ignore_thresh = .5
    truth_thresh = 1
    random=0            #---------------修改
    ......
    [convolutional]
    size=1
    stride=1
    pad=1
    filters=30        #---------------修改
    activation=linear
    [yolo]
    mask = 3,4,5
    anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326
    classes=5        #---------------修改
    num=9
    jitter=.3
    ignore_thresh = .5
    truth_thresh = 1
    random=0        #---------------修改
    ......
    [convolutional]
    size=1
    stride=1
    pad=1
    filters=30        #---------------修改
    activation=linear
    [yolo]
    mask = 0,1,2
    anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326
    classes=5        #---------------修改
    num=9
    jitter=.3
    ignore_thresh = .5
    truth_thresh = 1
    random=0        #---------------修改
    标记的地方需要修改,classes是你的分类数,filters=3*(classes+5),random=0即关闭多尺度训练
    

    具体每个参数的意思,我会继续更新总结的。怎么调整参数,使得效果最佳,还要依靠人为经验。

    12.

    开始训练:

    ./darknet detector train cfg/voc.data cfg/yolov3-voc.cfg darknet53.conv.74 -gpus 0,1,2,3
    

    开始测试

    ./darknet detector test  cfg/voc.data cfg/yolov3-voc.cfg backup/yolov3-voc_900.weights  voc/VOCdevkit/VOC2018/test/169.jpg
    

    测试权重用自己生成的backup下的,测试照片用自己测试集的。
    希望可爱的你也会出现自己想要的结果哦!!

    参数解释

    还想解释一下训练过程中出现的种种参数,那都是是个啥?来来来,看一看。
    参考一下
    原英文地址: https://timebutt.github.io/static/understanding-yolov2-training-output/
    原中文翻译地址:https://blog.csdn.net/dcrmg/article/details/78565440
    8个分组,因此有八个subdivision,每个subdivision有八个照片
    以上截图显示了所有训练图片的一个批次(batch),批次大小的划分根据我们在 .配置cfg 文件中设置的subdivisions参数。修改的cfg 文件中 batch = 64 ,subdivision = 8,所以在训练输出中,训练迭代包含了8组,每组又包含了8张图片,跟设定的batchsubdivision的值一致。
    Region Avg IOU: 0.326577: 表示在当前subdivision内的图片的平均IOU,代表预测的矩形框和真实目标的交集与并集之比,这里是32.66%,这个模型需要进一步的训练。
    Class: 0.742537: 标注物体分类的正确率,期望该值趋近于1。
    Obj: 0.033966: 越接近1越好。
    No Obj: 0.000793: 期望该值越来越小,但不为零。
    Avg Recall: 0.12500: 是在recall/count中定义的,是当前模型在所有subdivision图片中检测出的正样本与实际的正样本的比值。在本例中,只有八分之一的正样本被正确的检测到。(和最开始初定的阈值有关系)
    count: 8:count后的值是所有的当前subdivision图片(本例中一共8张)中包含正样本的图片的数量。在输出log中的其他行中,可以看到其他subdivision也有的只含有6或7个正样本,说明在subdivision中含有不含检测对象的图片。
    9798: 指示当前训练的迭代次数
    0.370096: 是总体的Loss(损失)
    0.451929 avg: 是平均Loss,这个数值应该越低越好,一般来说,一旦这个数值低于0.060730 avg就可以终止训练了。
    0.001000 rate: 代表当前的学习率,是在.cfg文件中定义的。
    3.300000 seconds: 表示当前批次训练花费的总时间。
    627072 images: 这一行最后的这个数值是9798*64的大小,表示到目前为止,参与训练的图片的总量。

    作者:ll_sunsmile
    来源:CSDN
    原文:https://blog.csdn.net/ll_master/article/details/81392013
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    Leetcode单链表反转
    算法--二叉搜索树的python实现
    云服务器(阿里和腾讯)搭建网络云盘Nextcloud
    VGG16和集成模型(LeNet,CNN,Net均匀池化)比较
    git与github
    pyspider-崔庆才猫途鹰
    给 Python 添加进度条 | 给小白的 tqdm 精炼实例!
    @wraps 修饰器:让你的 Python 代码更加简短可爱 | 从简单实例来认识它
    并发和并行 | Python中实现多线程 threading 和多进程 multiprocessing
    Python格式化字符串字面值 | 被官方文档称之为『漂亮』的输出格式
  • 原文地址:https://www.cnblogs.com/ruiyang-/p/10222177.html
Copyright © 2020-2023  润新知