基于keras的YOLO V3 和YOLO V4训练自己的模型(一)
本人纯小白,最近在做比赛中需要用到目标检测算法,经过多方对比,我最终选择了yolo系列算法。此文只是记录一下自己的学习过程,也希望可以为后来人提供一些指导。
在学习的过程中,遇到了神仙up主@ Bubbliiiing,本文以下内容很多都来源于他的文章。他有很多关于深度学习的教程,大家可以关注一下。
今天首先先把yolo算法的核心步骤介绍一下。
本项目利用基于YOLO v3的Darknet53、MobileNet v3与基于YOLO v4的CSPDarknet53对模型训练的结果进行比较,找到更精准的目标检测算法。具体介绍如下:
数据集的构建
1.数据集的整理与扩充
1)数据清洗
对错标、漏标的图片、重新标注或者删除;
对于质量低下的图片进行删除;
对图片格式进行转换,使之适应模型,将图片格式改为jpg
2)数据集扩充
为了提高算法在不同条件下的识别率,我们对数据集进行了如下扩充:
重新爬取质量高清的图片,进行标注,扩充数据集。(数据来源:http://image.baidu.com)
利用图像增强技术,将原有图片进行变换,以增强算法鲁棒性。
实际环境是复杂多变的,为了增强算法在各类场景下的检测效率,我们通过改变亮度,图片翻转等方式使得图像变得更加多种多样。将改变后的图片放入神经网络进行训练可以提高网络的鲁棒性,降低各方面额外因素对识别的影响。
2.数据集的构建
将图片文件与标签文件一一对应。
将标签文件放在Annotation文件夹中。
将图片文件放在JPEGImages文件夹中。
随机选择80%的样本进行训练,另外20%作为测试集。
将图片和对应的xml标准转化生成对应的txt格式。
检测网络Darknet53搭建
1.特征提取及检测网络Darknet53搭建
Darknet -53的搭建: 定义Darknet53中基本单元DarknetConv2D_BN_Leaky,由卷积层,归一化层,激活函数层组成。如下图所示:
在每一个卷积层后增加批量归一化操作(Batch Normalization) 和去除Dropout操作,防止出现过拟合现象。
由上图可知,输入N张416x416的图片,在经过多层的运算后,会输出三个shape分别为(N,13,13,255),(N,26,26,255),(N,52,52,255)的数据,对应每个图分为13x13、26x26、52x52的网格上3个先验框的位置,最后的预测结果将在这几个位置产生。
2.学习率的调整
在深度学习中,学习率的调整非常重要。学习率大可以加快学习效率,帮助跳出局部最优值。但是单单使用大学习率容易导致模型不精确,而且可能会导致模型训练不收敛。
学习率小利于帮助模型收敛,有助于模型细化,提高模型精度,但是收敛缓慢,并且可能导致无法跳出局部最优值,
学习率大和学习率小的功能是几乎相反的。因此我们适当的调整学习率,才可以最大程度的提高训练性能。
我们利用Callback类实现学习率指数型下降。指数型下降指的就是学习率会随着指数函数不断下降。
具体公式如下:
其中:learning_rate指的是当前的学习率,learning_rate_base指的是基础学习率,decay_rate指的是衰减系数。
效果如图所示:
我们利用Callback类实现学习率在0.001和0.00001之间进行下降。
检测网络MobileNet v3搭建
1.检测网络MobileNet v3的搭建
上述基于Tensorflow的YOLO v3算法可以通过监控视频的数据流信息,基本可以实现实时检测,但是为了加快YOLO v3算法的检测速度,提高检测效率和准确率,需要对其中的Backbone对算法进行优化,采用性能更优越的CNN网络,我们采用MobileNet v3网络结构,具体介绍如下:
MobileNetV3将Darknet53最后的激活函数Rule换成了h-swish。
Swish具备无上界有下界、平滑、非单调的特性,并且Swish在深层模型上的效果优于ReLU。仅仅使用Swish单元替换ReLU就能把MobileNet在 ImageNet上的top-1分类准确率提高0.9%,Inception-ResNet-v的分类准确率提高0.6%。
h-swish是用一个近似函数来逼近这个Swish,使得模型几乎可以在所有的软件和硬件框架上都可以使用。具体转化如下图:
MobileNet利用分组卷积降低网络的计算量,并且MobileNet将分组卷积应用到极致,即网络的分组数与网络的channel数量相等,使网络的计算量减到最低,提高系统的实时性。同时,MobileNet v3在Bottlenet结构中加入了SE结构,并且放在了Depthwise Filter之后,既提高了精度,同时还没有增加时间消耗。
2.学习率的调整
我们利用Callback类实现学习率在0.001和0.00001之间进行下降。具体介绍参见5.2.2检测网络Darknet53搭建中学习率的调整。
YOLO v4算法构建
1.检测网络CSPDarknet53的搭建
针对不同的硬件条件,我们搭建了如下两种主干特征提取网络:
当电脑显存较小时,可采用输入是416x416的特征结构,具体如下:
当电脑显存较大时,可采用输入是608x608的特征结构,具体如下:
2. 相比于Darknet53,CSPDarknet53做了如下改进:
(1)将DarknetConv2D的激活函数由LeakyReLU修改成了Mish,Mish的表达式为:
(2)将resblock_body的结构修改为CSPnet结构,CSPnet结构并不算复杂,就是将原来的残差块的堆叠进行了一个拆分,拆成左右两部分,主干部分继续进行原来的残差块的堆叠;另一部分则像一个残差边一样,经过少量处理直接连接到最后。
(3)将SPP结构参杂在对CSPDarknet53的最后一个特征层的卷积里,对CSPDarknet53的最后一个特征层进行三次DarknetConv2D_BN_Leaky卷积后,分别利用四个不同尺度(13x13、9x9、5x5、1x1)的最大池化进行处理。能够极大地增加感受野,分离出图像最显著的特征。
(4)原始的PANet的结构如图5-11所示:
PANet一个非常重要的特点就是特征的反复提取,在完成特征金字塔从下到上的特征提取后,还要实现从上到下的特征提取。YOLO v4中主要在在三个有效特征层上使用了PANet结构。更有效的提取目标特征值。
3. Label Smoothing平滑
为了防止训练时过拟合。利用Label Smoothing将标签进行一个平滑,原始的标签是0、1,在平滑后变成0.005(如果是二分类)、0.995,也就是说对分类准确做了一点惩罚,让模型不可以分类的太准确。
4. 学习率余弦退火衰减
Yolo v4采用余弦退火衰减法,学习率会先上升再下降,上升的时候使用线性上升,下降的时候模拟cos函数下降。执行多次。
模型训练
1.利用K-means算法确定先验框的大小
利用K-means算法对训练集中标注的边框进行聚类分析,寻找尽可能匹配样本的边框尺寸,提高安全帽的检测准确率。
2.Google Colab平台的使用
Google Colaboratory是谷歌开放的一款研究工具,提供了免费的GPU Tesla K80使用,支持例如:Keras、Tensorflow、Pytorch等框架。
利用Colab平台,可快速的对模型进行训练。我们对colab环境进行了如下配置
1)修改笔记本环境
新建一个Colab项目,对笔记本环境进行配置,选择Python3(3.6版本)
2)安装必要的包和软件
利用pip搭载需要的Keras版本。
我使用的是tensorflow 1.14,keras 2.15。
3)挂载Google Drive
将代码上传到Google Drive中,在运行前挂载即可。
4)开始训练
设置bathsize为16;
epoch为500;
利用Callback类实现学习率在0.001和0.00001之间进行调整。
3.loss的计算
1)计算loss所需参数
在计算loss的时候,实际上是y_pre和y_true之间的对比:y_pre就是一幅图像经过网络之后的输出,内部含有三个特征层的内容;其需要解码才能够在图上作画;y_true就是一个真实图像中,它的每个真实框对应的(13,13)、(26,26)、(52,52)网格上的偏移位置、长宽与种类。其仍需要编码才能与y_pred的结构一致。
2)loss的计算过程
loss值需要对三个特征层进行处理,这里以最小的特征层为例。利用y_true取出该特征层中真实存在目标的点的位置(m,13,13,3,1)及其对应的种类(m,13,13,3,80)。
将yolo_outputs的预测值输出进行处理,得到reshape后的预测值y_pre,shape分别为(m,13,13,3,85),(m,26,26,3,85),(m,52,52,3,85)。还有解码后的xy,wh。
获取真实框编码后的值,后面用于计算loss,编码后的值其含义与y_pre相同,可用于计算loss。
对于每一幅图,计算其中所有真实框与预测框的IOU,取出每个网络点中IOU最大的先验框,如果这个最大的IOU都小于ignore_thresh,则保留,一般来说ignore_thresh取0.5,该步的目的是为了平衡负样本。
计算xy和wh上的loss,其计算的是实际上存在目标的,利用第三步真实框编码后的的结果和未处理的预测结果进行对比得到loss。
计算置信度的loss,其有两部分构成,第一部分是实际上存在目标的,预测结果中置信度的值与1对比;第二部分是实际上不存在目标的,在第四步中得到其最大IOU的值与0对比。
计算预测种类的loss,其计算的是实际上存在目标的,预测类与真实类的差距。
3)loss计算结果如图所示:
预测流程说明
1.预测结果的解码
输入N张416x416的图片,在经过多层的运算后,会输出三个shape分别为(N,13,13,255),(N,26,26,255),(N,52,52,255)的数据,对应每个图分为13x13、26x26、52x52的网格上3个先验框的位置。
我们获得了三个特征层的预测结果,shape分别为(N,13,13,255),(N,26,26,255),(N,52,52,255)的数据,对应每个图分为13x13、26x26、52x52的网格上3个预测框的位置。但是这个预测结果并不对应着最终的预测框在图片上的位置,还需要解码才可以完成。
YOLO的3个特征层分别将整幅图分为13x13、26x26、52x52的网格,每个网络点负责一个区域的检测。我们知道特征层的预测结果对应着三个预测框的位置,我们先将其reshape一下,其结果为(N,13,13,3,85),(N,26,26,3,85),(N,52,52,3,85)。最后一个维度中的85包含了4+1+80,分别代表x_offset、y_offset、h和w、置信度、分类结果。
YOLO的解码过程就是将每个网格点加上它对应的x_offset和y_offset,加完后的结果就是预测框的中心,然后再利用 先验框和h、w结合 计算出预测框的长和宽。这样就能得到整个预测框的位置。
最终的预测结构后还要进行得分排序与非极大抑制筛选,对于每一个类进行判别:
a)取出每一类得分大于self.obj_threshold的框和得分。
b)利用框的位置和得分进行非极大抑制。
2.在原图上进行绘制
通过上一步,我们可以获得预测框在原图上的位置,而且这些预测框都是经过筛选的。这些筛选后的框可以直接绘制在图片上,就可以获得结果。
评价指标
FPS: Frames Per Second,图像的刷新频率,即每秒多少帧。假设目标检测网络处理1帧要0.02s。此时FPS就是50。
mAP:即Mean Average Precision,均值平均精度,目标检测模型中的性能评估指标。
算法结果对比
由于针对不同的数据集,不同的算法运行结果可能稍有差异,我们采用三种不同的Backbone,对比各算法的结果,YOLO v4确实要比之前的算法优化很多,尤其是提高了对小目标的检测能力。
今天的介绍就到此为止了,后续我会继续把s我做的项目放上来供大家参考。