天天看点

【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

文章目录

  • 0. 前期准备(因人而异)
  • 1. 试验官方模型
    • 1.1 下载工程文件
    • 1.2 转换权重文件
    • 1.3 图片识别
  • 2. 制作VOC数据集
    • 2.1 格式介绍
    • 2.2 准备样本及XML标记
    • 2.3 生成索引
  • 3. YOLO模型训练
    • 3.1 生成训练索引
    • 3.2 修改配置文件
    • 3.3 执行训练
  • 4. 模型验证
  • 5. 常见问题
    • 5.1 如何提高检测效果
    • 5.2 Found 0 boxes for img
    • 5.3 loss值异常
    • 5.4 ResourceExhaustedError: OOM
    • 5.5 检测时打开程序报错:Dimension 0 in both shapes must be equal, but are 1 and 24.
    • 5.6 训练模型如何在OpenCV中使用?

参考:

https://blog.csdn.net/patrick_Lxc/article/details/80615433

https://blog.csdn.net/m0_37857151/article/details/81330699

0. 前期准备(因人而异)

记录一下前期的一些配置:

首先要安装好python,博主这里用的是Python 3.6 64-bit。

path环境变量中加入python36和python36/Scripts的路径。

使用管理员权限进入cmd命令提示符,运行一下代码:

pip install --upgrade pip #更新pip
pip install tensorflow #安装 tensorflow
pip install --upgrade numpy #numpy是一个基础的数组计算包,有时候版本较老会报错 
pip install keras #yolo train.py文件里面要用到keras这个高层神经网络API
pip install pillow #安装 图片处理模块PIL(pillow)
pip install matplotlib #安装 2D绘图库matplotlib
pip install opencv-python #安装 opencv视觉库
           

中间记得测试一下tensorflow安装有没有问题:

import os
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
import tensorflow as tf
hello = tf.constant('Hello,TensorFlow!')
sess = tf.Session()
print(sess.run(hello))
           

如果打算用 GPU版本 训练的话,可以参考我另外一篇文章:https://blog.csdn.net/qinchang1/article/details/90693983

给个版本建议:

Tensorflow-gpu 1.4.0 + Keras 2.2.4(我用的版本)

Tensorflow-cpu 1.13.1 + Keras2.2.4(网友提供成功的版本)

1. 试验官方模型

1.1 下载工程文件

YOLOv3下载:

1)yolov3.weights权重文件:https://pjreddie.com/media/files/yolov3.weights

2)keras-yolo3代码: https://github.com/qqwweee/keras-yolo3 (工程文件如下,记得把 .weights权重文件也放进去)

推荐:百度网盘打包下载(* ̄︶ ̄):链接:https://pan.baidu.com/s/1OIQGthndfLSfMC1ZlZH6lA 提取码:rlkd

(建议用我的网盘资源下载,因为github上面的工程文件可能会有更改,导致后续的操作出现不同或问题)

【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

1.2 转换权重文件

这里首先要需要将 DarkNet 的

.weights

文件转换成 Keras 的

.h5

文件,在cmd中打开工程文件的路径,运行

convert.py

并告知 “.weights的输入路径 ” 和 “.h5的输出路径” ,代码如下:

python convert.py yolov3.cfg yolov3.weights model_data/yolo.h5
           
【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

会在model_data文件夹中生成一个yolo.h5文件。

+注意:这个权重文件要留着,后面可能会用上。

【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

1.3 图片识别

在工程文件中打开yolo_video.py,其用法如下:

usage: yolo_video.py [-h] [–model MODEL] [–anchors ANCHORS]

[–classes CLASSES] [–gpu_num GPU_NUM] [–image]

[–input] [–output]

positional arguments:

–input Video input path

–output Video output path

optional arguments:

-h, --help show this help message and exit

–model MODEL path to model weight file, default model_data/yolo.h5

–anchors ANCHORS path to anchor definitions, default

model_data/yolo_anchors.txt

–classes CLASSES path to class definitions, default

model_data/coco_classes.txt

–gpu_num GPU_NUM Number of GPU to use, default 1

–image Image detection mode, will ignore all positional arguments

例如:识别一张图片,则在cmd中的工程文件路径下输入:

python yolo_video.py --image
           
【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

会提示你输入图片路径(这里我的图片是直接放在工程文件里面的,所以直接输入文件名):

【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

效果如下:

【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

2. 制作VOC数据集

VOC全称Visual Object Classes,出自The PASCAL Visual Object Classes(VOC)Challenge,这个挑战赛从2005年开始到2012年,每年主办方都会提供一些图片样本供挑战者识别分类。

PASCAL VOC官网:http://host.robots.ox.ac.uk/pascal/VOC/

2.1 格式介绍

可以在官网中下载每一年的数据集,也可以自己仿照VOC的格式制作。

其文件格式如下图:

【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

下面是本人对每个文件功能的总结和理解:

【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

我们可以把官方下载的VOC数据集里面的内容删除,只保留各个文件夹;或者按照这个格式建立一个文件夹集。

这个文件夹我们直接放到前面的工程文件keras-yolo3-master中(以便之后的训练不用更改路径)。

【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

2.2 准备样本及XML标记

在JPEGImage文件夹中放入准备好的样本图片:

【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

需要制作每张图片对应的同名xml文件,这里我们以下面这张图片为例,右边的代码是其对应的xml文件内容:

【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

如果你有精力的话,当然可以自己一个个去写:)

不过这里我们用一个labelImg的软件进行标记,

labelImg下载链接:https://pan.baidu.com/s/1Ibenx26FaJUI_t-J3EhSLw 提取码:2gba

解压之后就两个文件,labelImg.exe运行文件,data文件夹里面有个predefined_classes.txt文件。

【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

在predefined_classes.txt文件里面添加需要标记的类的名称。

打开软件,其实操作很简单,就是手动去标注物体,并给其选择对应的类名称:

【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

之后保存xml文件,注意路径。

把所有xml文件都放置到VOC数据集里面的Annotations文件夹中。

【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

打了3种标签,如下所示。

【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

2.3 生成索引

在VOC2007文件夹中新建一个**.py文件**(名字随意)

【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

在py文件中输入以下代码并运行,用以生成索引

import os
import random
 
trainval_percent = 0.1
train_percent = 0.9
xmlfilepath = 'Annotations'
txtsavepath = 'ImageSets\Main'
total_xml = os.listdir(xmlfilepath)
 
num = len(total_xml)
list = range(num)
tv = int(num * trainval_percent)
tr = int(tv * train_percent)
trainval = random.sample(list, tv)
train = random.sample(trainval, tr)
 
ftrainval = open('ImageSets/Main/trainval.txt', 'w')
ftest = open('ImageSets/Main/test.txt', 'w')
ftrain = open('ImageSets/Main/train.txt', 'w')
fval = open('ImageSets/Main/val.txt', 'w')
 
for i in list:
    name = total_xml[i][:-4] + '\n'
    if i in trainval:
        ftrainval.write(name)
        if i in train:
            ftest.write(name)
        else:
            fval.write(name)
    else:
        ftrain.write(name)
 
ftrainval.close()
ftrain.close()
fval.close()
ftest.close()
           

之后就会在ImageSets\Main文件夹中生成几个索引文件

【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

{class}_train.txt 保存类别为 class 的训练集的所有索引

{class}_val.txt 保存类别为 class 的验证集的所有索引

{class}_trainval.txt 保存类别为 class 的训练验证集的所有索引

3. YOLO模型训练

3.1 生成训练索引

在工程文件keras-yolo3-master中,修改voc_annotation.py文件

【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

主要是把里面classes的内容改成要训练的对象(要和前面标记的一致,这里我只有三个对象"twistlock",后两个没加上,图片是老的了)

【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

运行这个py程序,生成三个文件"2007_test.txt", “2007_train.txt”, “2007_val.txt”,把前缀"2007_"去掉,得到 “test.txt”, “train.txt”, “val.txt”。

【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

PS:其实这一步有个问题,仔细看过train.py代码的人估计会发现实际训练只加载了train.txt文件,然后将train.txt文件里面的索引再分成了训练集和样本集。

3.2 修改配置文件

首先要修改一下 model_data 文件夹中的coco_classes.txt和voc_classes.txt,将里面的对象改成自己要训练的对象名称

【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

3.3 执行训练

直接将model_data文件夹中原版的yolo.h5复制,改名为yolo_weights.h5,将其作为预训练权重。

PS: 对于这个预训练权重,其实是迁移学习的方法,有些博文其实是让修改yolo3.cfg文件,然后重新生成权重文件,但是我发现这样的做法最后训练时会出现val_loss:nan的情况,所以我建议直接用原来官方的权重文件yolo.h5。还有一些博文修改了原来train.py的训练代码,不预加载训练权重,重头开始训练,但是我发现由于样本量少,这样训练出来的结果很不稳定,所以我也不推荐。

【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

完成yolo_weights.h5文件之后,在keras-yolo3-master工程文件夹中找到train. py,根据需要,可以更改里面的迭代次数epochs 等参数。如果显存小的话,可以改小batch_size。

【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

之后运行这个python程序,下面是我的运行效果

【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

训练过程:

【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

训练结束后,会生成很多过程的h5文件,最后只需要保留trained_weights_final.h5就行。

训练样本约400多张,最后两种loss都降到15左右。

4. 模型验证

参照前面1.3节内容,可以在yolo. py 中把权重文件的名字改成 trained_weights_final.h5 ,也可以直接把 trained_weights_final.h5名字改成 yolo. h5,总之就是之后要加载新的权重文件。

同样地,则在cmd中的工程文件路径下输入:

python yolo_video.py --image
           

输入图片路径(这里是将图片直接放在工程文件里,所以直接输入名字就行)

【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题
【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题
【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

B站上放了一个最新的训练效果:

https://www.bilibili.com/video/av78397208

5. 常见问题

5.1 如何提高检测效果

参考:https://github.com/AlexeyAB/darknet#how-to-train-to-detect-your-custom-objects

1. 训练前

(1)在.cfg文件中设置flag

random=1

,它将通过不同分辨率来训练yolo以提高精度。

(2)提高.cfg文件中网络的分辨率,(例如

height = 608

width = 608

或者任意32的倍数),这样可以提高精度。

(3)确保数据集中每个类都带有标签,并且保证标签正确。(原文里面提供一个脚本工具)

(4)对于要检测的每个对象,训练数据集中必须至少有一个类似的对象,其形状、对象侧面、相对大小、旋转角度、倾斜、照明等条件大致相同。

(5)数据集中应包括对象的不同缩放、旋转、照明、不同的面、不同背景的图像,最好为每个类提供2000个不同的图像,并且训练(

2000* 类的数量

)的迭代次数或更多。

(6)确保训练的数据集中包含不想被检测的不带标签的对象,即负样本,负样本的数量最好和正样本的数量相同。

(7)对于目标物体较多的图像,在.cfg文件中最后一个[yolo]层加入

max=200

参数或者更高的值。(yolov3可以检测到的对象的全局最大数目是

0.0615234375 *(width*height)

,其中width和height是.cfg文件中[net]部分的参数)

(8)训练小物体时(图像调整到416x416后物体小于16x16),将[route]参数替换为

layers = -1, 11

,将[upsample]参数改为

stride =4

(9)对于都包含小对象和大对象可以使用以下的修改模型:

Full-model: 5 yolo layers: https://raw.githubusercontent.com/AlexeyAB/darknet/master/cfg/yolov3_5l.cfg

Tiny-model: 3 yolo layers: https://raw.githubusercontent.com/AlexeyAB/darknet/master/cfg/yolov3-tiny_3l.cfg

Spatial-full-model: 3 yolo layers: https://raw.githubusercontent.com/AlexeyAB/darknet/master/cfg/yolov3-spp.cfg

(10)如果要训练区分左右的对象(例如左手右手,道路上左转右转标志等),需要禁用数据翻转增强,在.cfg文件中17行左右的位置加入

flip=0

(11)一般规律——训练数据集应该包含一组您想要检测的对象的相对大小。简单来说,就是需要检测的对象在图像中的百分比是多少,那么训练的图像中也应该包含这个百分比的对象。例如:如果训练的时候目标在图像中都占80-90%,那检测的时候很可能就检测不出目标占0-10%情况。

(12)同一个对象在不同的光照条件、侧面、尺寸、倾斜或旋转30度的情况下,对于神经网络的内部来说,都是不同的对象。因此,如果想检测更多的不同对象,就应该选择更复杂的神经网络。

(13)在.cfg中重新计算锚(anchors)的width和height:在.cfg文件中的3个[yolo]层中的每个层中设置相同的9个锚,但是应该为每个[yolo]层更改锚点

masks=

的索引,以便[yolo]第一层的锚点大于60x60,第二层大于30x30,第三层剩余。此外,还应在每个[yolo]层之前更改过滤器

filters=(classes + 5) * <number of mask>

。如果许多计算出的锚找不到适当的层,那么只需尝试使用所有的默认锚。

2.训练后(对于检测):

通过在.cfg文件中设置(

height=608

width=608

)或(

height=832

width=832

)或(32的任意值倍数)来提高网络的分辨率,这将提高精度并使检测小对象成为可能。

这里提高了网络的分辨率,但是可以不需要重新训练(即使之前使用416*416分辨率训练的)。但是为了提高精度,还是建议使用更高的分辨率来重新训练。

注意:如果出现了

Out of memory

的错误,建议提高.cfg文件中的

subdivisions=16

参数,改成32或者64等。

5.2 Found 0 boxes for img

在检测时,减小 yolo. py 文件参数中的 score 和 iou,如下图:

(这样可以使得置信度小和交并比小的框也能显示出来)

【YOLO】使用VOC数据集训练自己的YOLOv3模型(Keras/TensorFlow)0. 前期准备(因人而异)1. 试验官方模型2. 制作VOC数据集3. YOLO模型训练4. 模型验证5. 常见问题

如果这时候能出现框了,但是会发现效果不是很好,或者说置信度特别低,说明检测是成功的,但是训练做得比较差;

如果还是不能出现框,考虑有可能检测方法错了(路径设置等),或者是训练过程错误(类名称和索引没配置好等)。

不管什么情况都可以试试5.1节中提到的方法。

5.3 loss值异常

模型训练时,有两个loss值:

1)Train loss(对应本次训练中的

loss

):使用训练集的样本来计算的损失;

2)Test loss(对应本次训练中的

val_loss

):使用验证集的样本来计算的损失。

一般来说,损失函数越小,模型就越好。但要考虑过拟合情况:

过拟合:为了得到一致假设而使假设变得过度严格。

例如:训练出来的模型对训练样本检测的效果很好,但是对于验证集(也就是没有进行训练的样本)的检测效果却很差。

结果分析:( ↓ 表示 不断下降,↑ 表示 不断增加,→ 表示 趋于不变)

train loss test loss 说明
网络正在不断学习收敛
网络过拟合
数据集有问题
此次条件下学习达到瓶颈
网络结构或设计参数有问题,无法收敛

5.4 ResourceExhaustedError: OOM

开始训练后有时候会报错,例如:

ResourceExhaustedError (see above for traceback): OOM when allocating tensor with shape[10,256,52,52]

这种情况通常是GPU显存被占满了,你要么清理一下,要么把程序中的

batch_size

改小

5.5 检测时打开程序报错:Dimension 0 in both shapes must be equal, but are 1 and 24.

这个是由于标明的类数量和训练的类数量对应不上,检查一下voc_classes.txt和coco_classes.txt

5.6 训练模型如何在OpenCV中使用?

参考我另一篇文章:

https://blog.csdn.net/qinchang1/article/details/105776132

如有错误,欢迎指正!

继续阅读