前言:
Fatser RCNN算法利用两阶结构,先实现感兴趣区域(RoI)的生成,在进行精细的分类和回归,虽然能很好的对物体进行检测,但是其缺点是速度仍然不够快,在更多追求实时的应用场景下,仍不能满足需求。在此背景下,YOLO v1来了,其主要利用了回归的思想,使用一阶网络直接完成了分类和位置定位两个任务,且速度极快。后面的v2和v3,在检测精度和速度上均有提升,最近v4也出来了。
YOLO v1:无锚框预测
(1) 网络结构:
和其他算法一样,YOLO v1使用了卷积神经网络进行特征提取,如上图所示。输入的图像尺寸是448*448,经过24个卷积层与两个全连接层后,输出特征图大小7*7*30.
(2) 对特征图的操作
YOLO v1的网络结构并没有太多的新颖之处,其精髓是对最后的7*7*30大小的特征图进行操作。如下图所示,YOLO v1将输入的图像(原图)划分为7*7(可设置)的区域,每一个区域对应于最后特征图的一个点,该点的通道数为30,代表了预测的30个特征,代表预测的30个特征。
YOLO v1在每个区域内预测两个边框,如上图,预测框A和预测框B,则整个图的预测框的个数为7*7*2=98个,这些边框的大小和位置都不一样,其可以覆盖整个图上可能出现的物体。如果一个物体的中心点落在了某个区域内, 则该区域就负责检测该物体。上图中真实物体框的中心点在当前区域内, 该区域就负责检测该物体, 具体是将该区域的两个框与真实物体框进行匹配, IoU更大的框负责回归该真实物体框, 在此A框更接近真实物体。
最终的预测特征由类别概率、 边框的置信度及边框的位置组成 :
- 类别概率: 由于PASCAL VOC数据集一共有20个物体类别, 因此这里预测的是边框属于哪一个类别。
- 置信度: 表示该区域内是否包含物体的概率, 类似于Faster RCNN中是前景还是背景。 由于有两个边框, 因此会存在两个置信度预测值。
- 边框位置: 对每一个边框需要预测其中心坐标及宽、 高这4个量,两个边框共计8个预测值。
(3)损失函数
YOLO v1的损失一共由5部分组成, 均使用了均方差损失, 如式
公式中
- i代表第几个区域, 一共有S^2个区域, 在此为49;
- j代表某个区域的第几个预测边框, 一共有B个预测框, 在此为2;
- obj代表该框对应了真实物体;
- noobj代表该框没有对应真实物体。
- 这5项损失的意义如下:·第一项为正样本中心点坐标的损失。 λcoord的目的是为了调节位置损失的权重, YOLO v1设置λcoord为5, 调高了位置损失的权重。·第二项为正样本宽高的损失。 由于宽高差值受物体尺度的影响,因此这里先对宽高进行了平方根处理, 在一定程度上降低对尺度的敏感, 强化了小物体的损失权重。·第三、 四项分别为正样本与负样本的置信度损失, 正样本置信度真值为1, 负样本置信度为0。 λnoobj默认为0.5, 目的是调低负样本置信度损失的权重。·最后一项为正样本的类别损失。
(4)总结
- 优点:利用了回归的思想, 使用轻量化的一阶网络同时完成了物体的定位与分类, 处理速度极快, 可以达到45 FPS, 当使用更轻量的网络时甚至可以达到155 FPS。
- 缺点:(a)每一个区域默认只有两个边框做预测, 并且只有一个类别,因此YOLO v1有着天然的检测限制。 这种限制会导致模型对于小物体,以及靠得特别近的物体检测效果不好; (b)由于没有类似于Anchor的先验框, 模型对于新的或者不常见宽高比例的物体检测效果不好。 另外,由于下采样率较大, 边框的检测精度不高 ;(c)在损失函数中, 大物体的位置损失权重与小物体的位置损失权重是一样的, 这会导致同等比例的位置误差, 大物体的损失会比小物体大, 小物体的损失在总损失中占比较小, 会带来物体定位的不准确。
YOLO v2
针对v1的不足,YOLO v2通过对网络结构的改善、先验框的设计以及训练技巧三个方面进行改进,使得YOLO v2预测更加准确、速度更快、识别的物体类别更多,其在VOC 2007数据集上可以得到mAP 10%以上的提升效果。
(1)网络结构的改善
如上图所示,提出一种全新的网络结构,DarkNet。原始的DarkNet包含19个卷积层与5个池化层,增加了一个Passthrough层后一共拥有22个卷积层, 精度与VGGNet相当, 但浮点运算量只有VGGNet的1/5左右, 因此速度极快。
def _make_layers(in_channels, net_cfg):
layers = []
# 如果输入是一个list, 继续调用_mask_layers, 拆解到每一个网络基本单元
if len(net_cfg) > 0 and isinstance(net_cfg[0], list):
for sub_cfg in net_cfg:
layer, in_channels = _make_layers(in_channels, sub_cfg)
layers.append(layer)
else:
for item in net_cfg:
# 定义每一个Max Pooling层
if item == 'M':
layers.append(nn.MaxPool2d(kernel_size=2, stride=2))
# 定义每一个卷积层, 这里定义的卷积层已经包含了BN与ReLU层
else:
out_channels, ksize = item
layers.append(net_utils.Conv2d_BatchNorm(in_channels,out_channels,ksize,same_padding=True))
in_channels = out_channels
return nn.Sequential(*layers), in_channels
class Darknet19(nn.Module):
def __init__(self):
super(Darknet19, self).__init__()
# 这里的cfgs与图6.4中的网络结构是一致的
net_cfgs = [
[(32, 3)],
['M', (64, 3)],
['M', (128, 3), (64, 1), (128, 3)],
['M', (256, 3), (128, 1), (256, 3)],
['M', (512, 3), (256, 1), (512, 3), (256, 1), (512, 3)],
['M', (1024, 3), (512, 1), (1024, 3), (512, 1), (1024, 3)],
[(1024, 3), (1024, 3)],
[(1024, 3)]
] #
构建前几个卷积模块
self.conv1s, c1 = _make_layers(3, net_cfgs[0:5])
self.conv2, c2 = _make_layers(c1, net_cfgs[5])
self.conv3, c3 = _make_layers(c2, net_cfgs[6])
# 为了实现Passthrough层, 定义了一个ReorgLayer类
stride = 2
self.reorg = ReorgLayer(stride=2)
# 这里conv4的输入通道数是conv1s的4倍再加conv3的和
self.conv4, c4 = _make_layers((c1*(stride*stride) + c3), net_cfgs[7])
# 最终输出通道数为预选框数量×25, 即5×25=125
out_channels = cfg.num_anchors * (cfg.num_classes + 5)
self.conv5 = net_utils.Conv2d(c4, out_channels, 1, 1, relu=False)
self.global_average_pool = nn.AvgPool2d((1, 1))
(2)先验框的设计
YOLO v2吸收了Faster RCNN的优点, 设置了一定数量的预选框,使得模型不需要直接预测物体尺度与坐标, 只需要预测先验框到真实物体的偏移, 降低了预测难度。
关于先验框, YOLO v2首先使用了聚类的算法来确定先验框的尺度, 并且优化了后续的偏移计算方法, 下面详细介绍这两部分。先验框的设计为YOLO v2带来了7%的召回率提升。
(详细请看原文)
(3)训练技巧
- 多尺度训练
由于移除了全连接层, 因此YOLO v2可以接受任意尺寸的输入图片。 在训练阶段, 为了使模型对于不同尺度的物体鲁棒, YOLO v2采取了多种尺度的图片作为训练的输入。 由于下采样率为32, 为了满足整除的需求, YOLO v2选取的输入尺度集合为{320,352,384,...,608}, 这样训练出的模型可以预测多个尺度的物体。 并且, 输入图片的尺度越大则精度越高, 尺度越低则速度越快,因此YOLO v2多尺度训练出的模型可以适应多种不同的场景要求。
- 多阶段训练
由于物体检测数据标注成本较高, 因此大多数物体检测模型都是先利用分类数据集来训练卷积层, 然后再在物体检测数据集上训练。 例如, YOLO v1先利用ImageNet上224×224大小的图像预训练, 然后在448×448的尺度上进行物体检测的训练。 这种转变使得模型要适应突变的图像尺度, 增加了训练难度。 YOLO v2针对以上问题, 优化了训练过程, 采用如图6.6所示的训
练方式, 具体过程如下: (1) 利用DarkNet网络在ImageNet上预训练分类任务, 图像尺度为224×224。 2) 将ImageNet图片放大到448×448, 继续训练分类任务, 让模型首先适应变化的尺度。 3) 去掉分类卷积层, 在DarkNet上增加Passthrough层及3个卷积层, 利用尺度为448×448的输入图像完成物体检测的训练。
(4)总结
- 优点:YOLO v2相较于之前的版本有了质的飞跃, 主要体现在吸收了其他算法的优点, 使用了先验框、 特征融合等方法, 同时利用了多种训练技巧, 使得模型在保持极快速度的同时大幅度提升了检测的精度。
- 缺点:(1)单层特征图: 虽然采用了Passthrough层来融合浅层的特征, 增强多尺度检测性能, 但仅仅采用一层特征图做预测, 细粒度仍然不够, 对小物体等检测提升有限, 并且没有使用残差这种较为简单、 有效的结构。 (2)受限于其整体结构, 依然没有很好地解决小物体的检测问题。 (3)太工程化: YOLO v2的整体实现有较多工程化调参的过程, 尤其是后续损失计算有些复杂, 不是特别“优雅”, 导致后续改进与扩展空间不足。
YOLO v3
针对YOLO v2的缺陷 ,YOLO v3版本, 将当今一些较好的检测思想融入到了YOLO中, 在保持速度优势的前提下, 进一步提升了检测精度, 尤其是对小物体的检测能力。 YOLO v3主要改进了网络结构、 网络特征及后续计算三个部分 。
(1)新网络结构DarkNet-53
YOLO v3继续吸收了当前优秀的检测框架的思想, 如残差网络和特征融合等, 提出了如上图所示的网络结构, 称之为DarkNet-53。 这里默认采用416×416×3的输入, 图中的各模块意义如下:
- DBL: 代表卷积、 BN及Leaky ReLU三层的结合, 在YOLO v3中,卷积层都是以这样的组件出现的, 构成了DarkNet的基本单元。 DBL后面的数字代表有几个DBL模块。
- Res: 图6.7中的Res代表残差模块, 具体结构请参考第3章。 Res后面的数字代表有几个串联的残差模块。
- 上采样: 上采样使用的方式为上池化, 即元素复制扩充的方法使得特征尺寸扩大, 没有学习参数。
- Concat: 上采样后将深层与浅层的特征图进行Concat操作, 即通道的拼接, 类似于FPN, 但FPN中使用的是逐元素相加。
DarkNet-53结构的一些新特性:
- 残差思想: DarkNet-53借鉴了ResNet的残差思想, 在基础网络中大量使用了残差连接, 因此网络结构可以设计得很深, 并且缓解了训练中梯度消失的问题, 使得模型更容易收敛。
- 多层特征图: 通过上采样与Concat操作, 融合了深、 浅层的特征,最终输出了3种尺寸的特征图, 用于后续预测。 从前面的章节学习中可以知道, 多层特征图对于多尺度物体及小物体检测是有利的。
- 无池化层: 之前的YOLO网络有5个最大池化层, 用来缩小特征图的尺寸, 下采样率为32, 而DarkNet-53并没有采用池化的做法, 而是通过步长为2的卷积核来达到缩小尺寸的效果, 下采样次数同样是5次, 总体下采样率为32。
(2)多尺度预测
从上图中可以看到, YOLO v3输出了3个大小不同的特征图, 从上到下分别对应深层、 中层与浅层的特征。 深层的特征图尺寸小, 感受野大, 有利于检测大尺度物体, 而浅层的特征图则与之相反, 更便于检测小尺度物体, 这一点类似于FPN结构。
YOLO v3依然沿用了预选框Anchor, 由于特征图数量不再是一个,因此匹配方法也要相应地进行改变。 具体方法是, 依然使用聚类的算法得到了9种不同大小宽高的先验框, 然后按照表6.1所示的方法进行先验框的分配, 这样, 每一个特征图上的一个点只需要预测3个先验框, 而不是YOLO v2中的5个 。
(3)Softmax改为Logistic
YOLO v3的另一个改进是使用了Logistic函数代替Softmax函数, 以处理类别的预测得分。 原因在于, Softmax函数输出的多个类别预测之间会相互抑制, 只能预测出一个类别, 而Logistic分类器相互独立, 可以实现多类别的预测。
实验证明, Softmax可以被多个独立的Logistic分类器取代, 并且准确率不会下降, 这样的设计可以实现物体的多标签分类, 例如一个物体如果是Women时, 同时也属于Person这个类别。
(4)总结
- 优点:速度快是YOLO系列最重要的特质, 同时YOLO系列的通用性很强, 由于其正样本生成过程较为严格, 因此背景的误检率也较低。
- 缺点: 位置的准确性较差, 召回率也不高, 尤其是对于遮挡与拥挤这种较难处理的情况, 难以做到高精度。
参考:董洪义. 深度学习之Pytorch物体检测,2020.
本文暂时没有评论,来添加一个吧(●'◡'●)