![](https://img.haomeiwen.com/i12824314/3abff1cae5824ea6.png)
关于YOLOv3的介绍我们就不过多的介绍了,我们前面的文章从目标检测算的介绍、数据集的制作,如何使用K-Means算法寻找数据集的锚框如何训练数据,以及如何做数据测试?如果想了解的话,可以看看我们前面的文章。
- 使用K-means算法寻找yolo的锚框 - 简书 (jianshu.com)
-
如何将图片和锚框一起resize——python代码实现 - 简书 (jianshu.com)
3.YOLO学习笔记——目标检测算法的简介(RCNN, SSD, YOLO) - 简书 (jianshu.com)
4.YOLOv3网络结构和基础知识学习笔记 - 简书 (jianshu.com) - 如何制作YOLOv3模型训练数据集? - 简书 (jianshu.com)
- 如何训练YOLOv3模型?pytorch代码实现 - 简书 (jianshu.com)
- YOLOv3、YOLOv4、YOLOv5之间的区别 - 简书 (jianshu.com)
一、YOLO v4做出了那些改进
首先,我们讨论一下如何提高模型的精度,可能是调整学习率可能是调整网络结构,可能是增加优化策略。但其实最重要的是对数据进行增强,适当的进行数据增可以让模型更好的提取数据特征。当数据的多样性和数量上去之后,我们在使用模型训练,自然精度就提高了。
![](https://img.haomeiwen.com/i12824314/4342263bed9ce70f.png)
(1)数据和模型方面的改变
所以YOLO v4首先在数据上做了改进,对数据进行以下操作:
- 几何变换:平移、缩放、放射变换
- 遮挡:对图片进行遮挡,技术包括:random erase、cutout、hide-and-seek、grid mask、正则化等
- 多张图像的拼接:Mixup、CutMix
- GAN:使用生成式对抗网络生成样本,样式迁移
- Fcal Loss:解决数据分布不均衡的问题,也就是正负样本数量不一致的问题
- Label Smoothing:替换掉one-hot
- BBox回归:使用不同的IOU算法替换损失函数(IOU Loss、DIOU Loss、GIOU Loss、CIOU Loss)
关于模型方面:
- 使用增加模型感受野的块:SPP、RFB、ASPP
- 加入注意力机制:SE、SAM、modified SAM等
- 增加特征融合模块:skip connection、hyper column、FPN等
- 使用不同的激活函数:LReLU、Swish、Mish等
- 关于候选框的筛选采用了不同的NMS算法:greedy NMS、soft nms、DIOU nms等
yolo v4的创新点主要是:
- 使用了mosaic数据增强技术
- 使用自对抗的训练方法
- 改进了CBN,提出CmBN
- 改进了SAM,提出modified SAM
- 提出PANet,将short cut方法改为concate
(2)YOLO v4的最终改进方案
![](https://img.haomeiwen.com/i12824314/658dc7915ecd8ddb.png)
侦测头的改变:
上图就是YOLO v4的最终版本。其在主干网络上的部分模块进行了改进,使得网络更加复杂。并且三个侦测头的顺序与YOLO v3截然相反。网络浅层输出的是小目标,最后输出大目标。因为当我们输出的目标框越大,就需要偏移量更准确,从而要求模型的能力更高。
SPP模块增加感受野
YOLOV4中增加了SPP模块,其作用是增加感受野,融合不同尺度上的特征。SPP通常是放在神经网络的最后一层,SPP是一个空间金字塔池化,使得任意大小的特征图都能够转换成固定大小的特征向量。
![](https://img.haomeiwen.com/i12824314/544eb2912739910b.png)
(非官方源码)
class SPP(nn.Module):
def __init__(self):
super().__init__()
self.maxpool1 = nn.MaxPool2d(kernel_size = 5, stride = 1, padding=2)
self.maxpool2 = nn.MaxPool2d(9, 1, padding=4)
self.maxpool3 = nn.MaxPool2d(13, 1, padding=6)
def forward(self, x):
o1 = self.maxpool1(x)
o2 = self.maxpool2(x)
o3 = self.maxpool3(x)
return torch.cat([x, o1, o2, o3], dim=1)
使用Mish激活函数:
使用Mish激活函数替代Leaky Relu激活函数。使用CBM代替原来的CBL模块。在每一个参茶中加入concat
![](https://img.haomeiwen.com/i12824314/59e2c3624b5978a4.png)
sigmoid和tanh都是饱和函数,不管数据在多少维的空间,他们的非线性都存在。然而Relu的一阶导是1,但是二阶导是0,也就是说,模型越深,relu的非线性性越差。然而sigmoid或者tanh的n阶导数都存在,所以我们将两个激活函数的特点结合起来。
(非官方源码)
def mish(x):
return x * torch.tanh(F.softplus(x))
# used as class:
class Mish(nn.Module):
def __init__(self):
super().__init__()
def forward(self, x):
return x * (torch.tanh(F.softplus(x)))
使用Smooth L1损失函数:
![](https://img.haomeiwen.com/i12824314/2b9dd0a53b61c2e3.png)
- L1损失函数(即:MAE损失函数)在x=0处的变化过于剧烈。
- L2损失函数(即:MSE损失函数)虽然在x=0处变化较缓,但是在x变大或者变小的时候梯度剧烈变化。容易出现梯度爆炸
- 于是将两个损失函数相结合。就是YOLO使用的Smooth L1损失函数,不会在拐角处过于剧烈,也不会产生梯度爆炸。
IOU的改进:
![](https://img.haomeiwen.com/i12824314/96a5fd89a6560326.png)
![](https://img.haomeiwen.com/i12824314/0728647542f6c44b.png)
- DIOU = IOU - 两个中心点的距离除以最小外接矩形的距离
![](https://img.haomeiwen.com/i12824314/d5bae6e976ab41ea.png)
- CIOU : 使用宽高比衡量两个矩形是否相似。可以比较锚框和预测框两个对角线的夹角。两个对角线夹角越小越相似。
NMS可以结合GIOU Loss和DIOU Loss使用,但不会结合CIOU Loss,因为CIOU Loss是需要正确的锚框,而NMS算法中不涉及到锚框。
数据增强的方法:
- cutout:随机生成一个正方形,将图片中的一部分给遮住,遮罩区域像素值全置为0.
![](https://img.haomeiwen.com/i12824314/ecd0e99d56413601.png)
- dropblock:弥补了drop out会使得特征较为离散的缺点。它随机抑制一块数据。
![](https://img.haomeiwen.com/i12824314/937dcd2f30886c18.png)
- Mixup:将随机的两个样本随机混合,分类的标签按比例分配。
![](https://img.haomeiwen.com/i12824314/afdf6a5312502c4a.png)
- CutMix:首先随机选取两个样本,将其中一张图片随机切除一块区域,然后该部分区域填充另一张图片。分类标签按比例分配。
![](https://img.haomeiwen.com/i12824314/4876986335325ac5.png)
- Mosaic:这个方法是cutmix方法的一个改进版本。其实用四张图片,对四张图片进行拼接,拼接成一张新的图片。这样能够丰富物体检测的背景。
第一步:随机取样四张图片。
第二步:分别对四张图片进行翻转、缩放、裁剪和仿射变换。分别放到四个角的位置。
第三步:固定截取区域,然后将四张图片拼接成一张图片。
第四步:对框进行调整,超出截取区域的要进行边缘处理。
二、YOLO v5做出了那些改进
![](https://img.haomeiwen.com/i12824314/8a3bb5726584ac6e.png)
(1)网络模型
YOLO v5在网络结构上没有过多的改进,继续沿用了YOLOv4的网络架构。但是在YOLO v4的基础上又进行了改进,但是其在技术上的改进并不大,其主要改进是让其框架更加方便使用者的使用,让框架更加完善。
例如在激活函数上将Mish函数换成了Leaky ReLu函数。CBM结构换成了CBL结构。
(2)focus模块增加感受野
![](https://img.haomeiwen.com/i12824314/83e1cbd06aa99235.png)
YOLO v5中最明显的是,加入了focus模块,用于增加感受野,类似于空洞卷积。她能够将输入图片进行宽高减半,通道数量*2.并且没有信息的丢失,进行像素融合。其多用于神经网络最前面。
class Focus(nn.Module):
"""Focus width and height information into channel space."""
def __init__(self, in_channels, out_channels, ksize=1, stride=1, act="silu"):
super().__init__()
self.conv = BaseConv(in_channels * 4, out_channels, ksize, stride, act=act)
def forward(self, x):
# shape of x (b,c,w,h) -> y(b,4c,w/2,h/2)
patch_top_left = x[..., ::2, ::2]
patch_top_right = x[..., ::2, 1::2]
patch_bot_left = x[..., 1::2, ::2]
patch_bot_right = x[..., 1::2, 1::2]
x = torch.cat(
(
patch_top_left,
patch_bot_left,
patch_top_right,
patch_bot_right,
),
dim=1,
)
return self.conv(x)
网友评论