Keras-yolov3训练

本教程为keras-yolov3版本的训练及测试全过程实现,为保证对新手的友好性,不会过多解释原理,主要是让新手能对全过程有个比较清楚的概念和认识,方便训练自己的数据。
本教程一共有三个部分:一.数据集准备及生成 二.训练所需知识 三.测试及相关性能测试可视化

一.数据集准备及生成:
1.先来熟悉文件结构

font文件夹下是保存keras-yolov3可能会调用到的字体及颜色,在测试部分有用,方便在图片上显示相应文字标签

logs文件夹是保存模型权重的,在训练时也会保存tensorflow下的tensorboard可视化图,可供查看训练曲线

model_data文件夹下保存有coco_classes.txt,tiny_yolo_anchors.txt,voc_classes.txt,yolo.h5,yolo_anchors.txt,yolo-tiny.h5这6个文件,其中必须需要的是后5个。因为在本次训练中,全程按照VOC2007数据集格式来,所以coco_classes.txt文件中保存的coco数据集类别数据可以删除不要,而后5个分别是yolo和tiny-yolo的anchors(锚点)大小和其在原版darknet下载训练并转换成keras模型的预训练权重,这些在训练过程中都要用到。

results文件夹是保存测试部分中对测试集图片进行测试的结果,在测试分析中需要用到

VOCdevkit文件夹是所有数据存放的文件夹,其下文件夹目录为


进入VOC2007文件夹可看到


这里Annotations文件夹保存的是所有图片的标注框xml格式的数据。ImageSets文件夹下还有

在这里插入图片描述三个子文件夹,其中只有Main文件夹有用,里面存放着训练需要调用的图片名称,

在这里插入图片描述

这里放着的是训练集和测试集的图片名称,方便训练时的调用。

JPEGImages文件夹下放着所有的图片文件,可以是JPG或者PNG格式的图片。
SegmentationClass和SegmentationObject是作为语义分割中用的,这里keras-yolov3是目标检测,所以可以删去不要。

训练验证测试集生成.py 文件是根据已有的xml(图片)数据生成Main文件夹下的test.txt和train.txt文件的脚本。
新建文本文档.py 文件是修改保存Annotations文件夹下的xml文件路径的脚本,如果路径都是对了,可以不用管这个脚本,如果不对,可以根据自己的文件所在目录进行更改。

回到最开始的目录,yolo3文件夹下保存的是keras-yolov3的模型源码。

2007_train.txt和2007_test.txt是在标注完数据后调用voc_annotation.py文件生成的训练数据和测试数据文件的集合,里面存放着图片路径和目标框信息及类别信息。

剩下的.py文件中最重要的是convert.py,kmeans.py,train.py,voc_annotation.py,yolo.py,yolo_detect.py,yolov3.cfg,yolov3-tiny.cfg这几个文件,其作用分别是:
convert.py 将darknet下训练的权重转化为keras权重使用
kmeans.py 可以根据你自己的xml数据生成新的anchors(锚点),如果自己的数据集数据太特殊,目标太大或者太小导致使用原版效果不好,可以使用这个文件修改anchors,以达到检测更好的效果
train.py 是训练模型并保存权重的文件
voc_annotation.py 是根据已有数据集生成2007_train.txt和2007_test.txt这两个训练时真正调用的文件
yolo.py 定义了yolo模型类,并提供了一些方法,可以方便调用yolo功能进行测试
yolo_detect.py 可以测试图片、视频及实时摄像头,直接生成结果
yolov3.cfg和yolov3-tiny.cfg是模型的config文件,里面定义了模型的结构,一般不用改变,在训练时会有一点地方需要改动

2.文件夹结构及作用讲完后,可以开始准备数据了。先限定是自己的数据集,那么只有源视频数据或者图片,没有任何标注,那么要做的第一件事是将视频转化为图片后存入VOCdevkit/VOC2007/JPEGImages文件目录下,然后使用已经安装好的labelImg对该目录下图片进行标注,并将生成的xml文件存入VOCdevkit/VOC2007/Annotations文件目录下。这两步做完后,运行 python 训练验证测试集生成.py 命令会在同目录下的ImageSets/Main文件下生成train.txt和test.txt,其train和test之间的比例可以通过改变训练验证测试集生成.py脚本中的test_percent = 0.1和train_percent = 0.9这两个数字进行改变。
之后返回根目录,运行 python voc_annotation.py 命令生成训练模型真正需要的2007_train.txt和2007_test.txt文件。至此,数据集的准备已经全部完成。

二.训练所需知识 :
准备好数据集后当然就是开始训练,在训练前有两个文件中的内容需要修改
–model_data/voc_classes.txt文件和yolov3.cfg文件,在voc_classes.txt中你只需要将根据你数据集的种类和标注时的标签对上,写下英文名字即可

在这里插入图片描述

这里只有房子这一类,那么房子在标注时label设为0,在这里放第一个,如果有多类,只需要按照标注时的label数字从小到大写好就可以了;
yolov3.cfg中需要改的地方一共有三处:先进入文件,搜索 yolo 变会有三处地方显示出来,这三处都需要根据自己数据进行修改。如下图:

在这里插入图片描述

这是其中一处,这里我标注了三个地方需要改变,带有###change的就是了,filters根据公式3*(5+数据集类别数目)可以修改,这里只有一类那么修改为filters=18就可以(3*(5+1)=18);classes=2修改classes=1,因为只有一类;random=0代表了多尺度训练不开启,不开启对显存的要求会更低,这样显存不够的显卡也可以训练,如果random=1那么多尺度训练开启,在训练中图片会随机增强放大等等,对显存要求更高,这里设为0即可。
剩下两处也跟这里一样进行修改即可。

修改完这两个文件后,就可以进行train.py文件准备开始训练了,下面讲解一下train.py文件中的一些参数,方便自己训练修改:

在这里插入图片描述上图中的annotation_path,log_dir,classes_path,anchors_path分别代表了训练图片数据的路径,模型存放路径,数据集种类路径,模型anchors数据路径,这些自己都是可以修改的,这里我们因为前面的数据生成一直按照VOC2007格式来,所以这里可以不用变。

上图代表训练图片输入的宽高大小,其数值必须是32的倍数,一般设置为(320

,320),(416,416),(608,608)这个根据你显存的大小和数据目标框大小进行改变,一般情况下(416,416)即可,这代表训练时会把图片都变成这个大小再送入网络中。

在这里插入图片描述

这里选择是使用yolov3的模型还是tiny-yolov3模型,tiny相对小速度快,不过精度降低。

这里进行数据的训练集和验证集划分,比例9:1,可以自行更改。

在这里插入图片描述

这里加载预训练模型进行预热,其作用在于使用预训练模型权重,只改变后两层的权重,前面特征提取的权重都没变,为后面不冻结模型-全部层训练打下了基础,方便其loss的降低,这里batch_size和epochs都可以更改,不过一般修改batch_size就够了,显存大的可以改大,预热训练完成后模型权重会保存到’logs/000/trained_weights_stage_1.h5’这里。

在这里插入图片描述

这里开启了所有层,都进行训练,轮数更多,以便训练到比较好的效果,让loss收敛。
注意:在keras-yolov3中因为模型构建时使用了l2正则化的措施,所以最终模型的loss都不会降到特别低,一般keras-yolov3loss降到10左右效果便可以了。
训练到结束即可,训练过程就此结束。

三.测试及相关性能测试可视化:
对单张图片,视频及摄像头测试可以使用 yolo_detect.py , 只要输入相应的参数即可,比如输入 python yolo_detect.py --image 后就可以对单张图片进行测试等等。这里要注意其调用的都是 yolo.py 中的Yolo类

在这里插入图片描述

这些都是可以根据你自己实际需求改的,比如model_path就是你想测试的模型权重路径,anchors_path和classes_path也是同理,score代表一个阈值,只有置信度高于此值的目标才会被框出来,iou也是同理,model_image_size需要跟你训练时的input_shape一致,gpu_num代表你是否加载多GPU进行测试。
VOC测试集信息生成.py 文件使用了yolo.py 中的Yolo类进行测试集图片的测试,并将生成的结果保存下来,可以作为 pr曲线绘制和map计算的依据。
VOC测试集PR和MAP结果.py 文件调用了 voc_eval_py3.py 文件中的方法计算pr曲线和MAP,并将结果保存下来。

四. 结语:
这篇教程详细阐述了keras-yolov3下的训练和测试全过程,对关键地方进行了解释和说明,读者可以自行更改。关于yolov3 的原理可以自行去查阅资料,这里不作过多解释。

心得:

在keras-yolov3下,.cfg文件可以不用,在darknet下才有用,只是作为学习其结构的参考,所以我改了backbone后,将darknet_body改为mobilenet_body,一样可以正常训练和运行,只要保持结构一致即可。
在keras-yolov3下,主要修改的参数还是yolo_anchors.txt和train.py里create_model的ignoresh参数,还有input_shape,这个是决定你显存的,所以,由此也可以看出,keras-yolov3的效果比darknet原版差一些也是自然的,因为很多设置都是没法调的,能改的地方不多。
仿照原版的结构来理解即可,参读了一下源码,还是基本一致的,所以效果也还是可以的。进一步改进除了我改了的backbon外,估计就是改进结构了,那这个模型就得重新写了。大概就是这样
————————————————

1. 下载YOLOv3工程项目
git clone https://github.com/pjreddie/darknet  
cd darknet  
1
2
2. 修改Makefile配置,使用GPU训练,修改如下:
GPU=1 #如果使用GPU设置为1,CPU设置为0
CUDNN=1  #如果使用CUDNN设置为1,否则为0
OPENCV=0 #如果调用摄像头,还需要设置OPENCV为1,否则为0
OPENMP=0  #如果使用OPENMP设置为1,否则为0
DEBUG=0  #如果使用DEBUG设置为1,否则为0

CC=gcc
NVCC=/home/user/cuda-9.0/bin/nvcc   #NVCC=nvcc 修改为自己的路径
AR=ar
ARFLAGS=rcs
OPTS=-Ofast
LDFLAGS= -lm -pthread 
COMMON= -Iinclude/ -Isrc/
CFLAGS=-Wall -Wno-unused-result -Wno-unknown-pragmas -Wfatal-errors -fPIC
...
ifeq ($(GPU), 1) 
COMMON+= -DGPU -I/home/hebao/cuda-9.0/include/  #修改为自己的路径
CFLAGS+= -DGPU
LDFLAGS+= -L/home/hebao/cuda-9.0/lib64 -lcuda -lcudart -lcublas -lcurand  #修改为自己的路径
endif

保存完成后,在此路径下执行make,如果出现如下错误:

Loadingweights from yolo.weights...Done!
CUDA Error:invalid device function
darknet: ./src/cuda.c:21: check_error: Assertion `0' failed.
Aborted (core dumped)

这是因为配置文件Makefile中配置的GPU架构和本机GPU型号不一致导致的。更改前默认配置如下(不同版本可能有变):

ARCH= -gencode arch=compute_30,code=sm_30 \
      -gencode arch=compute_35,code=sm_35 \
      -gencode arch=compute_50,code=[sm_50,compute_50] \
      -gencode arch=compute_52,code=[sm_52,compute_52]
#      -gencode arch=compute_20,code=[sm_20,sm_21] \ This one is deprecated?
# This is what I use, uncomment if you know your arch and want to specify
# ARCH= -gencode arch=compute_52,code=compute_52

CUDA官方说明文档:http://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#virtual-architecture-feature-list

然后重新编译即可:


3. 准备训练数据集
按下列文件夹结构,将训练数据集放到各个文件夹下面,生成4个训练、测试和验证txt文件列表
VOCdevkit
—VOC2007
——Annotations
——ImageSets
———Layout
———Main
———Segmentation
——JPEGImages
Annotations中是所有的xml文件
JPEGImages中是所有的训练图片
Main中是4个txt文件,其中test.txt是测试集,train.txt是训练集,val.txt是验证集,trainval.txt是训练和验证集。

3. 生成2007_train.txt和2007_val.txt文件
下载voc_label.py文件,将文件下载到VOCdevkit同级的路径下,生成训练和验证的文件列表
wget https://pjreddie.com/media/files/voc_label.py

修改sets为训练样本集的名称
sets=[('2007', 'train')]
修改classes为训练样本集的类标签
classes=[str(i) for i in range(10)]
1
2
3
4
运行python voc_label.py,生成2007_train.txt训练文件列表。

4.下载Imagenet上预先训练的权重
wget https://pjreddie.com/media/files/darknet53.conv.74 
1
5. 修改cfg/voc.data
classes= 10  #classes为训练样本集的类别总数
train  = /home/user/darknet/2007_train.txt  #train的路径为训练样本集所在的路径
valid  = /home/user/darknet/2007_val.txt  #valid的路径为验证样本集所在的路径
names = data/voc.names  #names的路径为data/voc.names文件所在的路径
backup = backup

6. 在darknet文件夹下面新建文件夹backup
7. 修改data/voc.name为样本集的标签名

8. 修改cfg/yolov3-voc.cfg
关于cfg修改,以10类目标检测为例,主要有以下几处调整(蓝色标出):

[net]
# Testing            ### 测试模式                                          
# batch=1
# subdivisions=1
# Training           ### 训练模式,每次前向的图片数目 = batch/subdivisions 
batch=64
subdivisions=16
width=416            ### 网络的输入宽、高、通道数
height=416
channels=3
momentum=0.9         ### 动量 
decay=0.0005         ### 权重衰减
angle=0
saturation = 1.5     ### 饱和度
exposure = 1.5       ### 曝光度 
hue=.1               ### 色调
learning_rate=0.001  ### 学习率 
burn_in=1000         ### 学习率控制的参数
max_batches = 50200  ### 迭代次数                                          
policy=steps         ### 学习率策略 
steps=40000,45000    ### 学习率变动步长 
scales=.1,.1         ### 学习率变动因子  

[convolutional]
batch_normalize=1    ### BN
filters=32           ### 卷积核数目
size=3               ### 卷积核尺寸
stride=1             ### 卷积核步长
pad=1                ### pad
activation=leaky     ### 激活函数

......

[convolutional]
size=1
stride=1
pad=1
filters=45  #3*(10+4+1)
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=10  #类别
num=9
jitter=.3
ignore_thresh = .5
truth_thresh = 1
random=0  #1,如果显存很小,将random设置为0,关闭多尺度训练;
......

[convolutional]
size=1
stride=1
pad=1
filters=45  #3*(10+4+1)
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=10  #类别
num=9
jitter=.3
ignore_thresh = .5
truth_thresh = 1
random=0  #1,如果显存很小,将random设置为0,关闭多尺度训练;
......

[convolutional]
size=1
stride=1
pad=1
filters=45  #3*(10+4+1)
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=10  #类别
num=9
jitter=.3  # 数据扩充的抖动操作
ignore_thresh = .5  #文章中的阈值1
truth_thresh = 1  #文章中的阈值2
random=0  #1,如果显存很小,将random设置为0,关闭多尺度训练;

9. 开始训练
./darknet detector train cfg/voc.data cfg/yolov3-voc.cfg darknet53.conv.74 -gpus 0,1
1
10. 识别
将训练得到的weights文件拷贝到darknet/weights文件夹下面

./darknet detect cfg/yolov3-voc.cfg weights/yolov3.weights data/dog.jpg
————————————————
版权声明:本文为CSDN博主「john_bh」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/john_bh/article/details/80625220

发布了88 篇原创文章 · 获赞 9 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/jwy2014/article/details/103828330