yolov2训练自己的数据

最近在学习yolo下面是记录自己的训练过程:

准备文件夹:VOC2007下面有:

        Annotations ---- 这个文件夹是放所有xml描述文件的。

        JPEGImages ---- 这个文件夹是放所有jpg图片文件的。

      ImageSets -> Main ---- tain.txt,val.txt文档内容是所有训练集图片的名字,没有后缀名(如果直接生成训练所用到的tain.txt 和       val.txt我认为这个可以没有)

     labels------存放有xml 文件生成的txt文件

1.准备txt文件 先生成Main----tain.txt,val.txt,用到create_list.py文件

# coding:utf-8
import os
from os import listdir, getcwd
from os.path import join
if __name__ == '__main__':
    source_folder='/home/guo/VOC2007/JPEGImages/'#地址是所有图片的保存地点
    dest='/home/guo/VOC2007/ImageSets/Main/train.txt' #保存train.txt的地址
    dest2='/home/guo/VOC2007/ImageSets/Main/val.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<=300):                     #保留900个文件用于训练
            #print file_num
            train_file.write(file_name+'\n')  #用于训练前900个的图片路径保存在train.txt里面,结尾加回车换行
        else :
            val_file.write(file_name+'\n')    #其余的文件保存在val.txt里面
    train_file.close()#关闭文件

    val_file.close()




生成的train.txt如图:

运行voc_label.py(可以修改darknet自带的在通过scripts文件夹下要修改路径)生成labels和infrared_train.txt,infrared_val.txt(带有图片的路径及后缀)

# coding:utf-8
#此脚本修改自voc_label.py。修改的原因是:我的训练集跟voc有些不同。
#由于数据集中包括用于训练的数据和用于验证的数据,所以此脚本可能需要分别对这两种数据各运行一次,对两种数据只需要简单地注释掉相应语句即可
#这个脚本需要train.txt ,这个文件是我用脚本creat_list.py生成的,保存了用于训练的图片的名字id,保存了用于训练的图片的名字
#这个脚本需要val.txt文件,这个文件是我用脚本creat_list.py生成的,保存了用于验证的图片的名字id,保存了用于验证的图片的名字
#这个脚本还需要xml格式的标签文件,我的训练集xml文件的格式与voc2007的类似,xml文件的名称与对应的用于训练的图片的名称相同
#这个脚本会生成 indrared_train.txt文件 ,用于保存每一用于训练的图片的完整的路径,随后会被voc.data yolo.c使用
#这个脚本会生成 indrared_val.txt文件 ,用于保存每一用于验证的图片的完整的路径,随后会被voc.data yolo.c使用
#这个脚本还会生成 txt格式的yolo可识别的标签文件,转换自每一个用于训练或验证的图片对应的xml文件,txt格式的文件名称与对应的xml文件名相同,但是内容不同,扩展名不同
#这个脚本 需要与图片对应的xml文件所在的地址,需要,转换后生成的txt的完整保存路径
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
sets=[ ('2007', 'train')] #按照自己的文件格式改的,不需要判断是那个voc数据包
classes = ["person"]#因为我的数据集只有一个类别
def convert(size, box):#voc_label.py 自带的函数,没有修改
    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(image_id):
    #in_file = open('VOCdevkit/VOC%s/Annotations/%s.xml'%(year, image_id))
    in_file = open('/home/guo/VOC2007/Annotation/%s.xml'%(image_id))#与图片对应的xml文件所在的地址
    out_file = open('/home/guo/VOC2007/labels/%s.txt'%(image_id),'w') #与此xml对应的转换后的txt,这个txt的保存完整路径
    tree=ET.parse(in_file)
    root = tree.getroot()
    size = root.find('size')  #访问size标签的数据
    w = int(size.find('width').text)#读取size标签中宽度的数据
    h = int(size.find('height').text)#读取size标签中高度的数据
 
    for obj in root.iter('object'):
       # difficult = obj.find('difficult').text   #由于自己的文件里面没有diffcult这一个标签,所以就屏蔽之
        cls = obj.find('name').text
        if cls not in classes :#or int(difficult) == 1:
            continue
        cls_id = classes.index(cls)
        xmlbox = obj.find('bndbox')   #访问boundbox标签的数据并进行处理,都按yolo自带的代码来,没有改动
        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')
 
#image_ids = open('VOCdevkit/VOC%s/ImageSets/Main/%s.txt'%(year, image_set)).read().strip().split()  #之前代码是按照sets里面的字符来访问保存有图片名字的train或者val的txt文件
#image_ids = open('/home/guo/VOC2007/ImageSets/Main/train.txt').read().strip().split()  #如果是训练集数据打开这一行,注释下一行
image_ids = open('/home/guo/VOC2007/ImageSets/Main/val.txt').read().strip().split()  #如果是验证数据集数据打开这一行,注释上一行
#list_file = open('%s_%s.txt'%(year, image_set), 'w')
#list_file = open('infrared_train.txt', 'w')     #把结果写入到indrared_train.txt文件中,如果是训练集数据打开这一行,注释下一行
list_file = open('infrared_val.txt', 'w')     #把结果写入到indrared_train.txt文件中,如果是验证数据集数据打开这一行,注释上一行
for image_id in image_ids:
    #list_file.write('%s/VOCdevkit/VOC%s/JPEGImages/%s.jpg\n'%(wd, year, image_id))
    list_file.write('/home/guo/VOC2007/JPEGImages/%s.jpg\n'%(image_id))  #把每一用于训练或验证的图片的完整的路径写入到infrared_train.txt中  这个文件会被voc.data yolo.c调用
    convert_annotation(image_id)   #把图片的名称id传给函数,用于把此图片对应的xml中的数据转换成yolo要求的txt格式
list_file.close() #关闭文件

生成结果图片:labels文件夹下

0.000001.txt内容如下:(分别是类别,x,y,w,h)

2.准备文件person.names,person.data(可修改voc.data),person.cfg(可修改yolo-voc.cfg)(可以根据自己检测的物体改名字)

(1)创建一个person.names文件,内容只有person(你的类别)

(2)创建person.data

classes= 1
train  = /home------/infrared_train.txt(之前第一步生成的infrared_train.txt路径)
valid  = /home/-----/infrared_val.txt(同上)
names  = /home/-------/person.names

backup = /home/-------/weights/(权重文件)

(3)person.cfg

[net]
batch=64(根据需要修改)
subdivisions=8
height=192
width=320
channels=3
momentum=0.9
decay=0.0005
angle=0
saturation = 1.5
exposure = 1.5
hue=.1

learning_rate=0.001(可修改)
max_batches = 80000
policy=steps
steps=20000,20000,20000,10000
scales=.1,.1,.1,.1

[convolutional]
batch_normalize=1
filters=32
size=3
stride=1
pad=1
activation=leaky

[maxpool]
size=2
stride=2

[convolutional]
batch_normalize=1
filters=64
size=3
stride=1
pad=1
activation=leaky

[maxpool]
size=2
stride=2

[convolutional]
batch_normalize=1
filters=128
size=3
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=64
size=1
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=128
size=3
stride=1
pad=1
activation=leaky

[maxpool]
size=2
stride=2

[convolutional]
batch_normalize=1
filters=256
size=3
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=128
size=1
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=256
size=3
stride=1
pad=1
activation=leaky

[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]
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

[maxpool]
size=2
stride=2

[convolutional]
batch_normalize=1
filters=1024
size=3
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=512
size=1
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=1024
size=3
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=512
size=1
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=1024
size=3
stride=1
pad=1
activation=leaky


#######

[convolutional]
batch_normalize=1
size=3
stride=1
pad=1
filters=1024
activation=leaky

[convolutional]
batch_normalize=1
size=3
stride=1
pad=1
filters=1024
activation=leaky

[route]
layers=-9

[reorg]
stride=2

[route]
layers=-1,-3

[convolutional]
batch_normalize=1
size=3
stride=1
pad=1
filters=1024
activation=leaky

[convolutional]
size=1
stride=1
pad=1
filters=30
activation=linear

[region]
anchors = 0.46951302562922004,2.090243673692109,  0.6927112974254737,2.678475609756098, 1.4884746588693953,3.8462908815247996, 0.9816441680839001,3.1391896573444216, 0.2704715330788804,1.307228347940816
(可修改,参考下面的博客第三个 Kmeans 算法)

bias_match=1
classes=1
coords=4
num=5
softmax=1
jitter=.2
rescore=1

object_scale=5
noobject_scale=1
class_scale=1
coord_scale=1

absolute=1
thresh = .6
random=0
batch: 每一次迭代送到网络的图片数量,也叫批数量。增大这个可以让网络在较少的迭代次数内完成一个epoch。在固定最大迭代次数的前提下,增加batch会延长训练时间,但会更好的寻找到梯度下降的方向。如果你显存够大,可以适当增大这个值来提高内存利用率。这个值是需要大家不断尝试选取的,过小的话会让训练不够收敛,过大会陷入局部最优。

      subdivision:这个参数很有意思的,它会让你的每一个batch不是一下子都丢到网络里。而是分成subdivision对应数字的份数,一份一份的跑完后,在一起打包算作完成一次iteration。这样会降低对显存的占用情况。如果设置这个参数为1的话就是一次性把所有batch的图片都丢到网络里,如果为2的话就是一次丢一半。

      angle:图片旋转角度,这个用来增强训练效果的。从本质上来说,就是通过旋转图片来变相的增加训练样本集。

      saturation,exposure,hue:饱和度,曝光度,色调,这些都是为了增强训练效果用的。

      learning_rate:学习率,训练发散的话可以降低学习率。学习遇到瓶颈,loss不变的话也减低学习率。

      max_batches: 最大迭代次数。

      policy:学习策略,一般都是step这种步进式。

      step,scales:这两个是组合一起的,举个例子:learn_rate: 0.001, step:100,25000,35000   scales: 10, .1, .1 这组数据的意思就是在0-100次iteration期间learning rate为原始0.001,在100-25000次iteration期间learning rate为原始的10倍0.01,在25000-35000次iteration期间learning rate为当前值的0.1倍,就是0.001, 在35000到最大iteration期间使用learning rate为当前值的0.1倍,就是0.0001。随着iteration增加,降低学习率可以是模型更有效的学习,也就是更好的降低train loss。

      最后一层卷积层中filters数值是 5×(类别数 + 5)。具体原因就不多说了,知道就好哈。

      region里需要把classes改成你的类别数。

      最后一行的random,是一个开关。如果设置为1的话,就是在训练的时候每一batch图片会随便改成320-640(32整倍数)大小的图片。目的和上面的色度,曝光度等一样。如果设置为0的话,所有图片就只修改成默认的大小 416*416。(2018.04.08更新,评论给里有朋友说这里如果设置为1的话,训练的时候obj和noobj会出现全为0的情况,设置为0后一切正常。)

3.训练

先打开git clone https://github.com/pjreddie/darknet   

下载darknet
之后cd darknet,打开Makefile,GPU=1, CUDNN=1, OPENMP=1,OPENCV=1,(需要配置没有就是=0)
之后make
之后运行./darknet detector train person.data person.cfg darknet19_448.conv.23 2>1 | tee person_train_log.txt,
 

darknet19_448.conv.23在darknet官网下载,2>1 | tee person_train_log.txt为了可视化

训练需要一段时间,有GPU会快,

参考:https://blog.csdn.net/renhanchi/article/details/71077830?locationNum=11&fps=1

http://www.cnblogs.com/kekeoutlook/p/7718211.html

http://blog.csdn.net/hrsstudy/article/details/71173305?utm_source=itdadao&utm_medium=referral


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值