标签 目标识别 下的文章

摘要

​ Faster RCNN在Fast RCNN的基础上增加了RPN网络来代替比较耗时的Selective SearchRPN网络和检测网络共享同一张卷积特征图,他同时预测每个位置的前景(背景)概率和每一类相对于锚框的偏移,得到的预测框将送入Fast RCNN的检测头进行进一步的分类和BBOX回归。

​ 对于非常深的VGG-16模型,Faster RCNN在GPU上的帧速率为5fps(包括所有步骤),同时在PASCAL VOC 2007、2012和MS COCO数据集上实现了最先进的对象检测精度,每张图像只有300个建议框。在ILSVRC和COCO 2015竞赛中,Faster R-CNN和RPN是多个赛道第一名获奖作品的基础。

算法流程

image-20230308091659327

image-20230308091742426

RPN网络结构

正向传播

image-20230308091838188

对于特征图上的每个3x3的滑动窗口(实际实现就是用conv3x3 p1 s1),首先计算窗口中心点在原图上的位置,并计算出k个anchor box

​ 对于anchor的选择,共有三种比例,三种尺度,即每个位置都有9个anchor

image-20230308092338534

感受野

​ 对于特征图上的感受野,骨干网络为ZFNet时,感受野为171;骨干网络为VGG16时,感受野为228(具体计算如下)

image-20230308092633528

有个问题是,无论是VGG/ZF骨干网络,一个位置的感受野最多也就是228x228,那为什么anchor box的尺寸可以设置到256x256甚至512x512? 在论文中解释是说,通过物体的局部来预测物体是有可能的,实际上这么设置表现也确实有所提升

image-20230308092958530

anchor->proposal

image-20230308093042856

正负样本选择

​ 训练时,每个mini-batch,即每张图片随机选择256个anchor,这些anchor中正负样本比例大约是1:1。如果正样本数目不足128,那就用负样本补足到256.

image-20230308093402534

​ 正负样本定义如下:

正样本:①和某个GT Box的IoU大于0.7

​ ②是和某个GT Box的IoU最大的anchor(就是对第一条规则的补充,避免出现某个GT Box没有分配anchor)

负样本:和所有的GT Box的IoU都小于0.3

RPN 损失

​ RPN网络的损失分为两部分,分类损失和边界框损失。分类主要是衡量预测框中是否含有物体(类似于YOLO系列中的objectness),边界框损失就是简单的回归损失。

image-20230308093901988

image-20230308093935964

​ 分类损失有两种实现:

​ 如果每个anchor只有一个预测值,那么就使用BCE二元交叉熵损失

image-20230308094354826

​ 如果每个anchor有两个预测值,那么就使用Softmax Cross Entropy

image-20230308094431386

​ 边界框回归损失和Fast RCNN一样,都是用SmoothL1 Loss.标注值t*的计算参考RCNN中的实现。

image-20230308094537614

Detect Loss

​ 检测网络的损失和Faster-RCNN网络的损失一摸一样。这里不再赘述。

image-20230307213352907

网络训练

image-20230308094828414

现在可以直接采用RPN loss+Fast R-CNN Loss联合训练网络

image-20230308095010636

自己的一点理解

​ 从损失函数来看,Faster R-CNN和YOLO挺像的(应该是YOLO借鉴的ROI思想)。

​ 在YOLO系列中,对于每个grid cell会预测k个anchor(since v2),对于每个anchor会预测一个置信度(objectness),边界框偏移和类别预测。这里的类别预测同v1一样,是条件概率,即在置信度基础上的概率。

​ 而在Faster R-CNN中,置信度和类别预测被拆开成了两个网络,RPN网络负责预测置信度和边界框偏移;Fast R-CNN网络负责预测类别和边界框偏移

​ RPN网络提供Proposal,其实就是在置信度的基础上筛选出一些质量高的锚框(当然还需要根据边界偏移调整获得最后的region proposal)。

​ Fast R-CNN接到Proposal后,根据它在特征图上的映射获得特征矩阵,再通过RoI pooling层获得获得固定大小的矩阵,送入全连接层预测类别和bbox回归。那么这里的类别同样可以理解成条件概率,因为得到的候选框是经过RPN网络筛选过的,即在置信度满足一定条件时预测出的概率。

​ 所以YOLO系列其实就是将RPN网络和Fast R-CNN网络进行了合并。至于锚框生成,区别于RPN网络在特征图上通过滑动窗口生成,YOLO更加简单粗暴,直接将原图分割并在每个单元上生成锚框

相较于RCNN的改进

  • Fast RCNN仍然使用selective search选取2000个建议框,但是这里不是将这么多建议框都输入卷积网络中,而是将原始图片输入卷积网络中得到特征图,再使用建议框对特征图提取特征框。这样做的好处是,原来建议框重合部分非常多,卷积重复计算严重,而这里每个位置都只计算了一次卷积,大大减少了计算量
  • 由于建议框大小不一,得到的特征框需要转化为相同大小,这一步是通过ROI池化层(region of interest)来实现的
  • Fast RCNN里没有SVM分类器和回归器了,分类和预测框的位置大小都是通过卷积神经网络输出
  • 为了提高计算速度,网络最后使用SVD代替全连接层

算法流程

  • 输入一张图片,使用Selective Search获取建议框(region proposal)
  • 将原始图片输入卷积神经网络之中,获取特征图
  • 对每个建议框,从特征图中找到对应位置(按照比例映射),截取出特征框(深度保持不变)
  • 将每个特征框划分为 HxW个网格(论文中是 7×7 ),在每个网格内进行最大池化(即每个网格内取最大值),这就是ROI池化。这样每个特征框就被转化为了 7×7×C 的矩阵
  • 每个矩阵展平为一个向量,分别作为之后的全连接层的输入
  • 全连接层的输出有两个,计算class得分bounding box回归。前者是sotfmax的21类分类器(假设有20个类别+背景类),输出属于每一类的概率(所有建议框的输出构成得分矩阵);后者是输出一个 20×4 的矩阵,4表示(x, y, w, h),20表示20个类,这里是对20个类分别计算了框的位置和大小
  • 对输出的得分矩阵使用非极大抑制方法选出少数框,对每一个框选择概率最大的类作为标注的类,根据网络结构的第二个输出,选择对应类下的位置和大小对图像进行标注

image-20230307213534355

网络结构

​ 网络backbone采用VGG-16,不用resnet是因为那个时候还没有resnet

​ 最开始仍然是在ImageNet数据集上训练一个1000类的分类网络,随后将模型进行以下改动

  • 最后一个最大池化层换成ROI池化层
  • 将最后一个全连接层和后面的softmax1000分类器换成两个并行层,一个是全连接层1+21分类器,另一个是全连接层2+表示每个类预测框位置的输出

​ 使用变动后的模型,在标注过的图像数据上fine-tuning,训练时要输入图像、标注(这里将人为标注的框称为ground truth)和建议框信息。这里为了提高训练速度,采取了小批量梯度下降的方式,每次使用2张图片的128张建议框(每张图片取64个建议框)更新参数

训练网络

每次更新参数的训练步骤如下

  • 2张图像直接经过前面的卷积层获得特征图
  • 根据ground truth标注所有建议框的类别。具体步骤为,对每一个类别的ground truth,与它的iou大于0.5的建议框标记为groud truth的类别(正样本),对于与ground truth的iou介于0.1到0.5之间的建议框,标注为背景类别(负样本)
  • 每张图片随机选取64个建议框(要控制背景类的建议框占75%),提取出特征框
  • 特征框继续向下计算,进入两个并行层计算损失函数
  • 反向传播更新参数(关于ROI池化的反向传播细节可以参考这篇博客

image-20230307213611296

损失函数

​ 跟YOLO系列类似(其实应该是YOLO与rcnn类似),损失函数分成两部分——分类损失和回归损失。

  • 对类别输出按照softmax正常计算损失(交叉熵损失)
  • 对框的位置的损失方面,标注为背景类的建议框(负样本)不增加损失(体现在下面公式中的 [u>1] 艾弗森括号)。对于标注为物体类别的建议框(正样本)来说,先计算ground truth的四个标注参数,再和网络的预测值来计算loss(采用smoothL1 loss)

image-20230307213352907

论文中的其他

  • 全连接层使用SVD分解来减少计算时间
  • 模型在各种数据集上的测试效果及对比
  • 在fine-tuning基础上更新哪些层的参数实验
  • SVM V.S. softmax,输入多种规格的图片,更多训练数据等等

image-20230307213740234

摘要

YOLOv4使用了一些新特性:

WRC/CSP/CmBN/SAT/Mish && activation/Mosaic && data augmentation/DropBlock && regularization/CIou loss

Introduction

​ 当前(2020)最精确的现代神经网络无法实时进行目标检测,并且需要多块GPU进行训练(对显存有较高要求)。

​ 而YOLOv4可以在一个传统GPU上进行训练/推断,降低了使用门槛。具体来说,GPU可以是1080 Ti/2080 Ti

​ 除此之外,在YOLOv4上对比了“Bag-of-freebies”“Bag-of-Specials”这两类方法对模型的影响。

​ 最后,通过改进CBN/PAN/SAM,使YOLOv4更适合单GPU训练

Related work

Ordinary object detector

​ 一般来说,一个现代detector应该由两部分组成——一个在ImageNet预训练过的backbone、一个检测头用于类别和BBox的预测

骨干网络

  • GPU平台有VGG/ResNet/ResNeXt/DenseNet
  • CPU平台有SqueezeNet/MobileNet/ShuffleNet

检测头

  • two-stage:R-CNN/faster R-CNN/R-FCN/Libra R-CNN anchor-free:RepPoints
  • one-stage:YOLO/SSD/RetinaNet anchor-free:CenterNet/CornerNet/FCOS

Neck:

Neck介于backbone和head之间,主要功能是融合不同阶段的特征图,混合浅层细粒度特征和深层的语义特征

  • 主要代表有:FPN/PAN/BiFPN/NAS-FPN

以下是通用检测器的结构图

image-20230226172814228

Bag of freebies

Definitions:We call these methods that only
change the training strategy or only increase the training
cost as “bag of freebies.“

​ Bag of freebies指只改变训练策略或只增加训练开销的方法。其中一个典型代表是data augmentation(数据增强)。

data augmentation

常见的数据增强有:

  • 调整图像的亮度、对比度、色调、饱和度,添加噪点
  • 随机缩放、裁剪、翻转、旋转
以上方法都是逐像素调整,保留了原始像素信息。

除此之外,还有数据遮挡方面的增强:

  • CutOut:随机选择图像中的矩形区域,填充随机值/0
  • hide-and-seek/grid mask:随机或均匀地选择图像中的多个矩形区域并替换为零
  • 特征映射中也有和hide-and-seek类似的方法,DropOut/DropConnect/DropBlock
  • MixUp:将两个图像以不同系数叠加,并按照系数调整标签
  • CutMix:将裁剪后的图像覆盖到其他图像的矩形区域,并根据混合区域的大小调整标签
  • GAN:风格转移也可以做数据增强,并且这种使用可以减少CNN学习的纹理偏差

image-20230226201332445

Imbalance between different classes

​ 在数据集中可能会存在语义分布偏差问题,也就是不同类之间存在较大的数据量差异。这个问题可以通过难例挖掘解决。不过难例挖掘不适用于单阶段检测器,因为单阶段检测器属于密集预测架构。

​ 因此focal loss被提出(这个方法在YOLOv3论文中有被提到。不过不怎么work),focal loss用于解决正负类样本数量不均衡的问题,对于YOLOv3而言,由于IOU阈值设得比较高(好像是0.5),一些预测的比较好的框被判为负类,从而使负类里混了正样本。focal loss又会强调这些负类的loss,导致网络无法学到较好的效果。

BBox regression

​ 之前BBox的损失计算,是直接对四个参数(可能是左上角右下角坐标,也可能是中心点宽高,再或者中线点以及相对于锚框大小的偏移)直接计算MSE,这有个问题就是没有考虑到对象本身的完整性,四个参数都是视作独立变量处理

​ 新改进就是引入IoU损失,因为IoU计算本身会用到BBox四个坐标点,反向传播的时候可以都更新到,并且这个时候这四个点是作为一个整体考虑的。其次IoU损失是一种尺度不变的表示,可以解决传统方法的问题。即无论是L1 loss还是L2 loss,尺度增加loss都会不可避免的增大。

​ 近年来,推出了GIoU损失,它不仅考虑了覆盖区域,还考虑了物体的形状和方向,具体来说就是找到同时覆盖预测框和真实框的最小的BBox作为新的分母,代替原来的分母计算IoU.

DIoU损失则额外考虑了物体中心点的距离CIoU则同时考虑了覆盖面积、中心点之间的距离和宽高比,具有更好的收敛速度和精度。

Bag of specials

Definitions: For those plugin modules and post-processing methods that only increase the inference cost by a small amount but can significantly improve the accuracy of object detection, we call them “bag of specials”.

​ Bag of specials 指那些增加少量推理开销却能显著提高目标检测准确率的模块和后处理方法。

​ 一般来说,这些模块增强了模型中的某些属性,比如扩大感受野、引入注意力机制、增强特征整合等。

​ 后处理则是对模型的预测结果进行筛选。

enhance receptive field

​ 增强感受野的模块有SPP/ASPP/RFB。

​ SPP起源于SPM,SPM是分割特征图并提取词袋特征。SPP则是将SPM集成到CNN中,使用Maxpool代替词袋操作。改进后的SPP是具有核大小k × k的maxpool输出的级联,其中k = {1,5,9,13},并且stride等于1。

​ ASPP和RFB是对SPP的进一步改进。

the attention module

​ 物体检测中常用的注意力模型主要分为通道注意力和点注意力,这两种注意力模型的代表分别是挤压和激励(SE)和空间注意力模型(SAM)。

​ 虽然SE模块可以在ImageNet图像分类任务中以仅增加2%的计算量为代价提高ResNet50 1%的top-1准确率,但在GPU上通常会增加约10%的推理时间,因此更适合在移动设备上使用

​ 而对于SAM,它只需要付出0.1%的额外计算,就可以将ResNet50-SE在ImageNet图像分类任务中的top-1准确率提高0.5%。最棒的是,它完全不影响GPU上的推理速度

feature integrations

​ 特征集成方面,早期的实践是使用跳跃连接(skip connection)或超列(hyper-column)将低级物理特征集成到高级语义特征。随着FPN等多尺度预测方法的流行,许多集成不同特征金字塔的轻量级模型被提出。这类模块包括SFAM、ASFF和BiFPN。SFAM的主要思想是利用SE模块对多尺度级联特征图进行通道级重加权。对于ASFF,它使用softmax进行逐点水平重加权,然后添加不同尺度的特征图。在BiFPN中,提出了多输入加权残差连接进行尺度级重加权,然后添加不同尺度的特征图。

good activation function

​ 一个好的激活函数可以使梯度更有效地传播,同时不会引起太多额外的计算代价。2010年,Nair和Hinton提出ReLU,实质上解决了tanh和sigmoid中经常遇到的梯度消失问题.(但是relu也可能会导致梯度爆炸吧?)随后,LReLU、PReLU 、ReLU6 、缩放指数线性单元(SELU)、Swish 、硬Swish和Mish等,其也被用于解决梯度消失问题。LReLU和PReLU的主要目的是解决当输出小于零时ReLU的梯度为零的问题。(leaky relu也可以吧)至于ReLU6和硬Swish,它们是专门为量化网络设计的。为了实现神经网络的自归一化,提出了SELU激活函数来满足这一目标。值得注意的是Swish和Mish都是连续可微的激活函数。

post-process

​ 基于深度学习的目标检测中常用的后处理方法是NMS,它可以过滤掉对同一目标预测不好的BBox,只保留响应较高的候选BBox。NMS试图改进的方法与优化目标函数的方法是一致的。NMS提出的原始方法没有考虑上下文信息,Girshick等在R-CNN中加入了分类置信度作为参考,并根据置信度的大小,按照得分从高到低的顺序进行贪婪NMS。对于soft NMS,考虑了对象遮挡可能导致具有IoU值的贪婪NMS的置信度下降的问题。DIoU NMS 开发者的思路是在soft NMS的基础上,在BBox筛选过程中加入中心点距离的信息。值得一提的是,由于上述后处理方法均未直接参考捕获的图像特征,因此在后续开发无锚方法时不再需要进行后处理

Methodology

架构选择

  • 骨干网络选择CSPDarknet53,有29个3 × 3的卷积层,725 × 725的感受野和27.6M的参数。
  • 在CSPDarknet53上添加SPP块,因为它显著增加了感受野,分离出最显著的上下文特征,并且几乎不引起网络运行速度的降低
  • 使用PANet作为针对不同检测器水平的不同骨干水平的参数聚合方法,而不是YOLOv3中使用的FPN
  • 选择CSPDarknet53 backbone、SPP附加模块、PANet Neck和YOLOv3 head作为YOLOv4的体系结构。

用到的BoF/BoS

​ 对于Bag of freebiesBag of specials见这里。

​ YOLOv4里用到了以下这些技术。

image-20230226194356292

对于训练激活函数,由于PReLU和SELU较难训练,而ReLU6是专门为量化网络设计的,因此将上述激活函数从候选列表中移除。在正则化的方法上,发表DropBlock的人详细地将他们的方法与其他方法进行了比较,他们的正则化方法大获全胜。因此作者选择DropBlock作为正则化方法。对于归一化方法的选择,由于关注仅使用一个GPU的训练策略,因此不考虑syncBN。

针对单GPU训练的进一步改进

  • 介绍了一种新的数据增强马赛克自对抗训练(SAT)方法
  • 在应用遗传算法时选择最佳超参数
  • 修改了一些现有方法使其更适合于高效训练和检测:修改SAM、修改PAN和交叉小批量归一(CmBN)

mosaic augmentation

​ Mosaic是一种新的数据增广方法,它混合了4个训练图像,而CutMix仅混合2个输入图像。这允许检测其正常上下文之外的对象。(检测比较突兀的物体)此外,BN在每层上计算4个不同图像的activation statistics(这里不是很懂)。这显著降低了对大的小批量的需求。也就是一张图相当于四个图(batch size有x4的效果)。

image-20230226195129562

SAT

​ 自我对抗训练(SAT)也代表了一种新的数据增广技术,其在2个阶段中操作。在第一阶段,神经网络改变原始图像而不是网络权重。通过这种方式,神经网络对自身执行对抗性攻击,改变原始图像以创建图像上没有期望对象的欺骗。在第二阶段,训练神经网络以正常方式检测该修改图像上的对象

这里论文也没细说如何修改原始图像的....说的比较笼统

CmBN

​ CmBN表示CBN的修改版本,如图4所示,定义为交叉小批量归一化(CmBN)。这只在单个batch内的mini-batch之间收集统计信息。(大概就是把batch norm再细化了一下,从更小的单位做归一化吧)

image-20230226195612298

modify SAM/PAN

​ modify SAM这玩意作者在最后代码里没用,估计是效果不好。

image-20230226200012675

最终网络一览

image-20230226200122835

一些值得注意的改进点

1.之前为了让预测的坐标中心点落在当前grid cell里面,采用sigmoid函数对txty进行约束,这导致了只有在tx/ty特别大的时候,这一项才会是1,即预测很难到达网格边缘,为了解决这个问题,在sigmiod前乘了一个大于1的因子,来稍微补偿一下这个问题。

image-20230226201553852

2.实验对比表示,CSPResNeXt50+PAN+SPP+SAM效果最好

image-20230226201841301

3.PAN结构如下,就是在FPN的基础上多了一个下采样操作。通过第二次下采样,期望将浅层的定位信息也传递到深层的特征图中。

具体步骤

  • 先复制特征金字塔中最底下的那层(①),变成新特征金字塔的最底层。
  • 将新特征金字塔的最底层来一个下采样操作,然后原特征金字塔的倒数第二层进行一个3 3卷积,步幅为2;然后与下采样后的最底层进行一个横向连接,两者相加。最后再来一个33卷积来融合他们的特征。
  • 新特征金字塔其他层的操作与(2)一致

原文链接:https://blog.csdn.net/weixin_55073640/article/details/122637249

image-20230302171919060

Conclusions

​ 本篇文章算是对之前YOLOv3的延续,网络本身没有什么大的改动(无非换了一个backbone/把FPN换成SAM/加了SPP,算法核心没变),而是使用了很多trick来提高性能(BOF/BOS),并且对单GPU训练提供更好的支持。

image-20230226202243879

复现

​ 感觉是在复现各种trick...暂时先咕了

网络

​ 网络整体框图如下。

  • 输入为416*416*3的图像,经过若干卷积三件套ResN残差结构抽取图像特征。并通过控制卷积stride实现下采样,最终将图片下采样32倍
  • 在下采样8倍/16倍/32倍产生的特征图上进行多尺度的预测,特征图大小分别为52x52、26x26、13x13。最终通道数都是255 = (3*(80+5))
  • SSD类似采用多级检测方法。在三个尺度上进行预测,尺寸越大的特征图负责检测小物体,尺寸越小的特征图负责检测大物体(related to 感受野)
  • 负责预测的浅层特征图还使用了深层特征图的特征(也就是所谓的特征金字塔FPN),通过上采样和通道融合实现。这个好处是让浅层特征图预测小(或者说复杂)物体时更容易(因为深层特征图提取的大多是语义特征,容易区分复杂目标)

3.1 YOLO入门教程:YOLOv3(1)-解读YOLOv3

具体解读

主干网络backbone:DarkNet-53

image-20230226093758481

相较于YOLOv2中所使用的DarkNet19,新的网络使用了更多的卷积——52层卷积(外加一个全连接层),同时,添加了残差网络中的残差连结结构,以提升网络的性能。DarkNet53网络中的降采样操作没有使用Maxpooling层,而是由stride=2的卷积来实现。卷积层仍旧是线性卷积、BN层以及LeakyReLU激活函数的串联组合。

FPN与多级检测

​ FPN的最早是在2017年的CVPR会议上提出的,其创新点在于提出了一种自底向上(bottom-up)的结构融合多个不同尺度的特征图去进行目标预测。FPN工作认为网络浅层的特征图包含更多的细节信息,但语义信息较少,而深层的特征图则恰恰相反。原因之一便是卷积神经网络的降采样操作,降采样对小目标的损害显著大于大目标,直观的理解便是小目标的像素少于大目标,也就越难以经得住降采样操作的取舍,而大目标具有更多的像素,也就更容易引起网络的“关注”,在YOLOv1+和YOLOv2+的工作中我们也发现了,相较于小目标,大目标的检测结果要好很多。

img

从网格的角度来看,越浅层的网格,划分出的网格也越精细,以416的输入尺寸为例,经过8倍降采样得到的特征图C3相当于是一个52x52的网格,这要比经过32倍降采样得到的特征图C5所划分13x13的网格精细得多,也就更容易去检测小物体。同时,更加精细的网格,也就更能避免先前所提到的“语义歧义”的问题。

多级检测方法最早可以追溯到SSD网络,SSD正是使用不同大小的特征图来检测不同尺度的目标,不过当时并没有结合FPN网络来做,这一方法的思想内核便是用不同尺度的物体由不同尺度的特征图去做检测,而不是像YOLOv2那样,都堆在最后的C5特征图上去做检测。而FPN正是在这个基础上,让不同尺度的特征图先融合一遍,再去做检测。

单级检测(single-level detection),比如早期的YOLOv1和YOLOv2,便是最为经典的单级检测工作。只不过,主流普遍认为这种只在C5特征图上去单级检测的检测器,小目标检测效果是不行的,尽管这一点被ECCV2020的DeTRCVPR2021的YOLOF工作否决了,却依旧难以扭转这一根深蒂固的观念,前者似乎只被关注了Transformer这一点上,而后者似乎被认为是“开历史倒车”。

还有一类单级检测工作则另辟蹊径,借鉴人体关键点检测工作的思想,使用高分辨率的特征图如只经过4倍降采样得到的特征图C2来检测物体,典型的工作包括CornerNet和脍炙人口的CenterNet。以512的输入尺寸为例,只经过4倍降采样得到的特征图C2相当于是一个128×128的网格,要比C5的16×16精细的多,然后再将所有尺度的信息都融合到这一张特征图来,使得这样一张具有精细的网格的特征图既具备足够的细节信息,又具备足够的语义信息。不难想象,这样的网络只需要一张特征图便可以去检测所有的物体。这一类工作具有典型的encoder和decoder的结构,通常encoder由常用的ResNet组成,decoder由简单的FPN结构或者反卷积(叫成转置卷积层比较好)组成,当然,也可以使用Hourglass网络。这一类的单级检测很轻松的得到了研究学者们的认可,毕竟,相较于在粗糙的C5上做检测,直观上便很认同分辨率高得多的C2特征图检测方式。只不过,C2特征图的尺寸太大,会带来很大的计算量,但是,这类工作不需要诸如800×1333的输入尺寸,仅仅512×512的尺寸便可以达到与之相当的性能。

​ YOLOv3训练/检测时,在每个网格处放置3个先验框。由于YOLOv3一共使用3个尺度,因此,YOLOv3一共设定了9个先验框,这9个先验框仍旧是使用kmeans聚类的方法获得的。在COCO上,这9个先验框的宽高分别是(10, 13)、(16, 30)、(33, 23)、(30, 61)、(62, 45)、(59, 119)、(116, 90)、(156, 198)、(373, 326)。注意,YOLOv3的先验框尺寸不同于YOLOv2,后者是除以了32,而前者是在原图尺寸上获得的,没有除以32。

损失函数

​ 损失函数较之前没有大的改动,比较重要的一点是类别预测不再使用softmax进行预测,因为softmax处理后各类别概率是互斥的。而实际上有些标签是可以共存的(比如"max"和"woman"),所以作者抛弃了softmax,改用sigmod对每个类别进行单独预测。损失也使用BCE对各个类别单独计算。

​ 置信度objectness也使用交叉熵函数(之前当成回归问题处理)

image-20230226130951523

当然,作者也只是说softmax不会表现更好,所以代码里还是用的softmax加MSE

image-20230226131032015

Q&A

​ 这一栏是问题与知乎大佬的回复

  • Q1

    • Q:多尺度训练中的先验框设置这方面一直不是很懂,无论除不除32(下采样倍数)都是相较于数据集中固定大小的图片的尺度。那采用多尺度训练的时候,先验框大小是否需要进行对应的缩放呢? 比如先验框都是基于416x416的图片聚类得到的,多尺度训练时输入换成了608x608,先验框的尺度应该扩大到608/416倍吧
    • A:不需要随之改变的。多尺度训练的一个作用就是在训练过程中,让一些原本较大的物体变小,让一些原本较小的物体变大,这个目的就是为了增加数据集里不同大小的物体的数量,相当于人,对数据集做了一次扩展,如果anchor box 也跟着变,那就和多尺度训练的目的背道而驰了。但多尺度训练是一个比较强的训练技巧,不是那种一加上就好使的。你可以使用我的强化版yolo v1项目,里面也实现了一整套的yolo ,训练更稳定一些

复现

​ 代码与先前YOLOv1、YOLOv2差异不大,主要添加了残差结构、多级预测、FPN特征金字塔、backbone改进等一些trick;训练、测试以及评估(mAP)代码基本没有修改.

​ 详见JJJYmmm‘s YOLOv3

预测效果

​ 在小物体和密集物体预测上有所改进。主要原因如下:

  • 多级预测使网络在浅层特征图上也进行预测,浅层特征图首先尺寸较大,每个grid cell都预测B个box(v3中B=3),box的数量相比于前代(v1里是98个box,v2里是845个box)有了数量级的提升(num = (52x52+26x26+13x13)*3 = 10647)。自然更容易捕捉到小物体,提升整体的召回率(recall)
  • 在浅层特征图进行预测时,还使用了FPN特征金字塔,融合了深层特征图的语义信息
  • backbone使用了残差连接,起到了和FPN差不多效果(应该
  • 损失函数里有惩罚小框项,在之前的YOLOv2中有提到

image-20230226125825584

image-20230226131452305

评估

​ 在输入图片大小为416x416情况下,AP50达到0.58,mAP@0.5:0.95达到0.36。与论文里的效果相差不大。

损失函数里的类别损失代码里使用的是SOFTMAX+MSE,并不是论文里提到的BCE。事实上,使用BCE,从mAP衡量的话其实效果是变差了的。当然,对于作者来说,mAP并不是好的评价指标,详情见yolov3论文最后一部分Rebuttal

image-20230226133208749

image-20230226132535303

附录

YOLO系列与RetinaNet的对比

​ 目前来看,目标检测领域的baseline几乎已经被RetinaNet工作统治了,很多增量式的改进也都是在RetinaNet的基础上做的,往往Mask R-CNN和Faster R-CNN也会用上,毕竟是双阶段检测器的经典之作。之所以会采用RetinaNet作为baseline,一个原因是RetinaNet的网络十分简洁,训练起来也没有太tricky的东西。也许有人会说,YOLO也很简洁呀,确实,YOLO正因为其网络十分简洁,因而有着较好的泛化性,没有设计过多的trick来在COCO上刷性能(有可能过拟合)。但另一个很重要的原因便是RetinaNet的训练时间很短,通常只需要在COCO上训练12个epoch,数据增强也只需要使用随机水平翻转即可。相反,YOLOv3往往需要在COCO上训练超过200个epoch,并且使用包括随机水平翻转、颜色扰动、随机剪裁和多尺度训练在内等大量的数据增强手段。因此,就训练时间而言,YOLOv3往往会需要多得多的时间,这对于没有太多显卡的研究员来说并不友好。尤其是当今又是一个“拼手速”的时代,我们往往急于求成,快点拿到涨点的结果然后写到实验里,发出论文来,因此,训练耗时更少的RetinaNet显然是个更好的选择。不过,在解决实际问题时,YOLO系列更加受欢迎,毕竟在实际任务里,“实时性”是个很重要的指标,这一点恰恰是RetinaNet的劣势。YOLO性能强、速度快、计算量也要远小于RetinaNet,因此更适合用在实际部署中,无非是训练成本大了些。所以孰优孰劣,不能一概而论。

链接:https://zhuanlan.zhihu.com/p/440402807

序言

​ 在2016年的CVPR会议上,继YOLOv1工作后,原作者再次推出YOLOv2(YOLO9000)。相较于上一代的YOLOv1,YOLOv2在其基础之上做了大量的改进和优化,不仅仅是对模型本身做了优化,同时还引入了由Faster R-CNN工作提出的anchor box机制,并且使用了kmeans聚类方法来获得更好的anchor box,边界框的回归方法也因此做了调整。在VOC2007数据集上,YOLOv2超越了同年发表在ECCV会议上的SSD工作,是那个年代当之无愧的最强目标检测器之一。那么,接下来就让我们去看看YOLOv2究竟做了哪些改进吧。

较之先前工作的改进

添加Batch Normalization

​ 在YOLOv1中,每一层卷积的结构都是线性卷积和激活函数,并没有使用诸如批归一化(batch normalization,简称BN)、层归一化(layer,normalization,简称LN)、实例归一化(instance normalization,简称IN)等任何归一化层。

这一点是受限于那个年代的相关技术的发展,而以现在的眼光来看,这些归一化层几乎是搭建网络的标配,尤其是在计算机视觉领域中,BN层几乎随处可见。

img

这项改进使YOLO在VOC2007测试集上的mAP从63.4%提升到了65.8%

高分辨率的主干网络

​ 在YOLOv1中,其backbone先在ImageNet上进行预训练,预训练时所输入的图像尺寸是224×224,而做检测任务时,YOLOv1所接收的输入图像尺寸是448×448。因此在训练过程中,网络必须要先克服由分辨率尺寸的剧变所带来的问题。直觉上来说,backbone网络在ImageNet上看得都是224×224的低分辨率图像,突然看到448×448的高分辨率图像,难免会“眼晕”。

​ 为了缓解这一问题,作者将已经在224×224的低分辨率图像上训练好的分类网络又在448×448的高分辨率图像上进行微调(fine tuning),共微调10个轮次。微调完毕后,再去掉最后的全局平均池化层和softmax层,作为最终的backbone网络。

​ YOLOv1网络获得了第二次性能提升:从65.8% mAP提升到69.5% mAP。

这一技巧并未成为主流训练技巧,可能这个问题并不算严重,稍微延长训练时间便可以了。

锚框(anchor box)机制

​ anchor box,字面翻译为“锚框”。锚框的意思是将一堆边界框放置在特征图网格的每一处位置(每个像素),通常每个位置都放置相同数量的相同尺寸的锚框,如下图。

img

该图并不完整 每两个pixel才绘制一次锚框

​ 这一机制最早是在Faster R-CNN工作中提出的,用在RPN网络中,RPN网络在这些预先放置好的锚框上去为后续的预测提供感兴趣区域(Region of Interest,RoI)。每个网格处设定了k个不同尺寸、不同宽高比的anchor box,RPN网络会为每一个anchor box学习若干偏移量:中心点的偏移量宽高的偏移量。用这些偏移量去调整每一个anchor box,得到最终的边界框。由此可见,anchor box的本质是提供边界框的尺寸先验,网络使用偏移量在这些先验值上进行调整,从而得到最终的尺寸,对于边界框的学习,不再是之前的“无中生有”了。因此,anchor box与其直接翻译成“锚框”,不如翻译成“先验框”更加贴切。加入先验框的目标检测网络,后来都被称为“Anchor-based”模型。

​ 设计先验框的一个难点在于设计多少个先验框,且每个先验框的尺寸(宽高比和面积)又是多少。对于宽高比,研究者们通常采取的配置是1 : 1、1 : 3以及3 : 1;对于面积,常用的配置是32、64、128、256以及512。

​ 以上述两个配置为例,每一个面积都使用3个长宽比,因此,不难算出共有15个先验框,即k=15。对于一个13×13的网格,每一处的网格都要放置15个先验框,因此,这张网格上共有13×13×15=2535个先验框。如果我们用更多的网格,这个数量会更多。先验框越多,所需的参数量就越大,自然就会带来更多的计算量上的压力。

论文里权衡了Average IOU后选择了k=5 兼顾了运算效率

​ 总之,先验框的作用就是提供边界框的尺寸先验信息,让网络只需学习偏移量来调整先验框去获得最终的边界框,相较于YOLOv1的直接回归边界框的宽高,基于先验框的方法表现得往往更好。

全卷积网络结构

​ 在YOLOv1中,有一个很显著的问题就是网络在最后阶段使用了全连接层,这不仅破坏了先前的特征图所包含的空间信息结构,同时也导致参数量爆炸。为了解决这一问题,作者便将其改成了全卷积结构,并且添加了Faster R-CNN工作所提出的anchor box机制。具体来说,首先,网络的输入图像尺寸从448改为416,去掉了YOLOv1网络中的最后一个池化层和所有的全连接层,修改后的网络的最大降采样倍数为32,最终得到的也就是13×13的网格,不再是7×7。每个网格处都预设了k个的anchor box。网络只需要学习将先验框映射到真实框的尺寸的偏移量即可,无需再学习整个真实框的尺寸信息,这使得训练变得更加容易。

​ 其实,在之前的YOLOv1中,我们已经知道每个网格处会有1个边界框输出,而现在变成了预测k个先验框的偏移量。原先的YOLOv1中,每个网格处的B个边界框都有一个置信度,但是类别是共享的,因此每个网格处最终只会有一个输出,而不是B个输出(置信度最高的那一个),倘若一个网格包含了两个以上的物体,那必然会出现漏检问题。加入先验框后,YOLOv2改为每一个先验框都预测一个类别和置信度,即每个网格处会有多个边界框的预测输出。因此,现在的YOLOv1的输出张量大小是S×S×k×(1+4+C),每个边界框的预测都包含1个置信度、4个边界框的位置参数和C个类别预测。

img

​ 尽管网络结构变成了全卷积网络,并使用了anchor box机制,但网络的精度并没有提升,反倒是略有所下降,69.5% mAP降为69.2% mAP,但召回率却从81%提升到88%召回率的提升意味着YOLO可以找出更多的目标了,尽管精度下降了一点点。由此可见,每个网格输出多个检测结果确实有助于网络检测更多的物体。因此,作者并没有因为这微小的精度损失而放弃掉这一改进。

backbone

​ 主干网络从类GoogLenet换成了Darknet19,Darknet19网络结构如下图。

img

​ 这里的卷积层由之前提到的三部分组成——线性卷积、BN、LeakyRelu。

The 19 of Darknet19 means the network has 19 conv layers.

​ 作者首先将DarkNet19在ImageNet上进行预训练,获得了72.9%的top1准确率和91.2%的top5准确率。在精度上,DarkNet19网络达到了VGG网络的水平,但前者模型更小。

​ 预训练完毕后,去掉表最后第24层的卷积层、第25层的平池化层以及第26层的softmax层,然后换掉原先的backbone网络。于是,YOLOv1网络从上一次的69.2% mAP提升到69.6% mAP。

kmeans聚类先验框

​ 在之前说到的anchor box机制中,这些先验框(即anchor box)的一些参数需要人工设计,包括先验框的数量和大小。在Faster R-CNN中,这些参数都是由人工设定的,然而YOLO作者认为人工设定的不一定好。为了去人工化,作者采用kmeans方法在VOC数据集上进行聚类,一共聚类出k个先验框,通过实验,作者最终设定 。聚类的目标是数据集中所有检测框的宽和高,与类别无关。为了能够实现这样的聚类,作者使用IoU作为聚类的衡量指标,$d(box,centroid)=1-IoU(box,centroid)$

​ 通过kmeans聚类的方法所获得的先验框显然会更适合于所使用的数据集,但这也会带来一个问题:从A数据集聚类出的先验框显然难以适应新的B数据集。尤其A和B两个数据集中所包含的数据相差甚远时,这一问题会更加的严重。因此,当我们换一个数据集,如COCO数据集,则需要重新进行一次聚类,如果样本不够充分,这种聚类出来的先验框也就不够好,这也是YOLOv2以及后续的YOLO版本的潜在问题之一。另外,由聚类所获得的先验框严重依赖于数据集本身,倘若数据集规模过小、样本不够丰富,那么由聚类得到的先验框也未必会提供足够好的尺寸先验信息。当然,即便是人工设计的先验框也有着类似的问题,甚至整个anchor-based模型都有这一类问题,所以才有了后来的anchor free工作,

​ 在YOLOv2工作中,换上新的先验框后,对边界框的预测也发生了变化。

​ 首先,对每一个边界框,YOLO仍旧去学习中心点偏移量tx和ty 。我们知道,这个中心点偏移量是介于01范围之间的数,在YOLOv1时,作者没有在意这一点,直接使用线性函数输出,这显然是有问题的,在训练初期,模型很有可能会输出数值极大的中心点偏移量,导致训练不稳定甚至发散。于是,作者使用sigmoid函数使得网络对偏移量的预测是处在01范围中。我们的YOLOv1+正是借鉴了这一点。

其次,对每一个边界框,由于有了边界框的尺寸先验信息,故网络不必再去学习整个边界框的宽高了。假设某个先验框的宽和高分别为pw和pℎ,网络输出宽高的偏移量为tw和tℎ,则使用以下公式即可解算出边界框的宽和高。

$$ w = p_w e^{t_w} \quad h = p_h e^{t_h} $$

img

这种边界框预测方法,在论文中被命名为“location prediction”。

​ 使用kmeans聚类方法获得先验框,再配合“location prediction”的边界框预测方法,YOLOv1的性能得到了显著的提升:从69.6% mAP提升到74.4% mAP。不难想到,性能提升的主要来源在于kmeans聚类,更好的先验信息自然会有效提升网络的检测性能。只不过,这种先验信息是依赖于数据集的。

聚类具体代码实现见K-means 计算 anchor boxes_hrsstudy的博客-CSDN博客_kmeans-anchor-boxes

Passthrough

​ 随后,YOLO作者又借鉴了同年的SSD工作:使用更高分辨的特征。在SSD工作中,检测是在多张特征图上进行的,不同的特征图的分辨率也不同。可以理解为,特征图的分辨率越高,所划分的网格也就越精细,能够更好地捕捉目标的细节信息。相较于YOLOv1只在一张7×7的过于粗糙的网格上做检测,使用多种不同分辨率的特征图自然会更好。

​ 于是,YOLO作者借鉴了这一思想。具体来说,之前的改进中,YOLOv1都是在最后一张大小为13×13×1024的特征图上进行检测,为了引入更多的细节信息,作者将backbone的第17层卷积输出的26×26×512特征图拿出来,做一次特殊的降采样操作,得到一个13×13×2048特征图,然后将二者在通道的维度上进行拼接,最后在这张融合了更多信息的特征图上去做检测。

img

​ 这里的特殊降采样操作并不是常用的步长为2的池化层或步长为2的卷积操作,而是一种类似于在图像分割任务中常用到的pixelshuffle操作的逆操作,如图7所示。依据YOLO官方配置文件中的命名方式,我们暂且称之为reorg操作。

img

​ 特征图在经过reorg操作的处理后,特征图的宽高会减半,而通道则扩充至4倍,因此,从backbone拿出来的26×26×512特征图就变成了13×13×2048特征图。这种特殊降采样操作的好处就在于降低分辨率的同时,没丢掉任何细节信息,信息总量保持不变。

这一改进在论文中被命名为“passthrough”。加上该操作后,在VOC 2007测试集上的mAP从74.4%再次涨到了75.4%。由此可见,引入更多的细节信息,确实有助于提升模型的检测性能

多尺度训练

​ cv中有一个十分常见的图像处理操作是图像金字塔,即将一张图像缩放到不同的尺寸,同一目的,在不同分辨率的图像中,所包含的信息量也不一样,直观的体现便是分辨率越高,构成目标所需要的像素量就越多,目标本身的大小(或像素面积)也就越大。通过使用图像金字塔的操作,网络能够在不同尺寸下去感知同一目标,从而增强了其本身对目标尺寸变化的鲁棒性,如下图所示。YOLO作者便将这一思想用到了模型训练中,以提升YOLO对物体的尺度变化的适应能力

img

该方法在myYOLOv1也使用到 具体YOLOv1.md

最终网络结构

img

​ DarkNet网络结构如下,使用全卷积代替了全连接层

image-20230220103240207

Anchor box匹配

​ 该部分和损失函数并没有在论文中提及,参考(60条消息) 论文笔记1 --(YOLOv2)YOLO9000:Better,Faster,Stronger_零尾的博客-CSDN博客_yolov2论文和源码可以得到以下信息。

​ 和YOLOv1一样,对于训练图片中的ground truth,若其中心点落在某个cell内,那么该cell内的5个先验框所对应的边界框负责预测它,具体是哪个边界框预测它,需要在训练中确定,即由那个与ground truth的IOU最大的边界框预测它,而剩余的4个边界框不与该ground truth匹配。YOLOv2同样需要假定每个cell至多含有一个grounth truth,而在实际上基本不会出现多于1个的情况。与ground truth匹配的先验框计算坐标误差、置信度误差(此时target为1)以及分类误差,而其它的边界框只计算置信度误差(此时target为0)。

​ 对于某个ground truth,首先要确定其中心点要落在哪个cell上,然后计算这个cell的5个先验框与ground truth的IOU值(YOLOv2中bias_match=1),计算IOU值时不考虑坐标,只考虑形状,所以先将先验框与ground truth的中心点都偏移到同一位置(原点),然后计算出对应的IOU值,IOU值最大的那个先验框与ground truth匹配,对应的预测框用来预测这个ground truth。

损失函数

​ 损失函数与yolov1相差不大,主要修改了引入锚框的几项,如下图所示。

在这里插入图片描述

在这里插入图片描述

  • (1)W,H分别指的是特征图(13*13)的宽与高
  • (2)A指的是先验框数目(这里是5)
  • (3)各个λ值是各个loss的权重系数,参考YOLOv1的loss
  • (4)第一项loss是计算background的置信度误差,但是哪些预测框来预测背景呢,需要先计算各个预测框和所有ground truth的IOU值,并且取最大值Max_IOU,如果该值小于一定的阈值(YOLOv2使用的是0.6),那么这个预测框就标记为background,需要计算noobj的置信度误差
  • (5)第二项是计算先验框与预测宽的坐标误差,但是只在前12800个iterations间计算,我觉得这项应该是在训练前期使预测框快速学习到先验框的形状
  • (6)第三大项计算与某个ground truth匹配的预测框各部分loss值,包括坐标误差、置信度误差以及分类误差。
在计算obj置信度时,在YOLOv1中target=1,而YOLOv2增加了一个控制参数rescore,当其为1时,target取预测框与ground truth的真实IOU值。对于那些没有与ground truth匹配的先验框(与预测框对应),除去那些Max_IOU低于阈值的,其它的就全部忽略,不计算任何误差。这点在YOLOv3论文中也有相关说明:YOLO中一个ground truth只会与一个先验框匹配(IOU值最好的),对于那些IOU值超过一定阈值的先验框,其预测结果就忽略了。这和SSD与RPN网络的处理方式有很大不同,因为它们可以将一个ground truth分配给多个先验框。
尽管YOLOv2和YOLOv1计算loss处理上有不同,但都是采用均方差来计算loss
另外需要注意的一点是,在计算boxes的和误差时,YOLOv1中采用的是平方根以降低boxes的大小对误差的影响,而YOLOv2是直接计算,但是根据ground truth的大小对权重系数进行修正:l.coord_scale (2 - truth.wtruth.h),这样对于尺度较小的boxes其权重系数会更大一些,起到和YOLOv1计算平方根相似的效果。

"语义歧义"问题

​ 理想情况下,每个真实样本都会匹配到一个先验框,作为正样本,其余的先验框要么成为负样本,要么被忽略。但是,稍加思考,不难发现这其中有个问题,那就是倘若有两个目标的中心点都落在同一个网格,有没有可能原本分配给目标A的先验框后来又分配给了目标B,导致目标A就没有匹配上的先验框,从而丢失了正样本,这种问题有时被称为“语义歧义(semantic ambiguity)”。

复现

​ 代码主要框架与myYOLOv1一致。主要修改了模型文件yolov2.py/骨干网络backbone/正样本制作方法matcher.py/损失函数loss.py

image-20230220141637708

测试

​ 测试效果如下。

image-20230220192326558

image-20230220192501048

python eval.py --cuda -d voc --weight ./weights/yolov2_voc.pth --save

评估

​ yolov2+在voc2007测试集上的mAP达到了0.785

image-20230220191113884

python eval.py --cuda -d voc --weight ./weights/yolov2_voc.pth -size 608

代码

详见JJJYmmm/MyYOLOv2 (github.com)