做者:ll_sunsmile
来源:CSDN
原文:https://blog.csdn.net/ll_master/article/details/81392013
版权声明:本文为博主原创文章,转载请附上博文连接!python
(一、二、3在test中出现,4在train中出现)git
改darknet下makefile文件参数,修改不成功。
解决:服务器配置有问题。检查cuda,cudnn,opencv这些版本是否兼容吧。。要是一直修改不成功,就去删darknet,从新作一遍。要出来结果,确定要付出代价的么。一遍不成功就再来一遍。反正我改了修也作了三遍。github
backup生成的权重文件不会用。傻里巴叽还用以前自带版本的权重,结果哭唧唧,生成一大堆车、马、人,根本不是本身须要的类别标签。
解决:固然使用本身生成的权重文件啦,backup下每次都有会新的迭代权重。bash
好不容易解决了前面两个,终于熬到检测这一步,奇怪的发现仍是什么都没有。
解决:检测语句有问题,细心的我特别去看了官网的检测语句。有两条等同的检测语句,咱们选择那条指明分类的语句。由于分类结果出不来,确定是没有找到分类文件呀。咱们给他指明,就清楚咯。
选择这种:服务器
./darknet detector test cfg/voc.data cfg/yolov3-voc.cfg backup/yolov3-voc_10000.weights data/1.jpg
不选择这种:dom
./darknet detect cfg/yolov3-voc.cfg backup/yolov3-voc_600.weights data/1.jpg
还有就是开始train的时候cuda out of memory等问题。
例如 :ide
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,强制执行
标注本身的数据集。根据本身划分的类别用labelimg进行标注,保存后会生成与所标注图片文件名相同的xml文件。测试
下载官网yolov3工程.net
git clone https://github.com/pjreddie/darknet cd darknet cd darknet
修改配置文件
打开Makefile,修改编译选择。
make #保存,记住必定要make才能生效
修改完成后,在darknet目录下进行编译。
若是服务器配置没有问题,那么会成功,若是不成功的话就检查一下cuda,cudnn,opencv这些版本是否兼容的问题。
准备数据集,创建层级结构存储目录便于数据的管理。文件名称的命名也是为了之后方便修改配置文件。
Annotations中放全部的xml文件;JPEGImages中放全部的图片;Main中放train.txt和test.txt。
然而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+'\n') #用于训练前149个的图片路径保存在train.txt里面,结尾加回车换行 else : val_file.write(file_name+'\n') #其他的文件保存在val.txt里面 train_file.close()#关闭文件 val_file.close()
下载和修改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]) + '\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()
执行voc_label.py:
python voc_label.py
在voc下生成了2018_train.txt 和 2018_test.txt,分别存放了训练集和测试集图片的路径。
ps:这里用到了以前main下的train和test文本文件,使得xml和jpg文件一一对应,而且生成最后的图片路径。
以后训练时候就能够根据图片路径和一些配置文件信息进行训练咯。
下载预训练模型
wget https://pjreddie.com/media/files/darknet53.conv.74
修改 cfg/voc.data
修改data/voc.names
修改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即关闭多尺度训练
具体每一个参数的意思,我会继续更新总结的。怎么调整参数,使得效果最佳,还要依靠人为经验。
开始训练:
./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张图片,跟设定的batch和subdivision的值一致。
• 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 版权声明:本文为博主原创文章,转载请附上博文连接!