目标检测 One Stage Detection (Yolo系列上)
- 在CNN出现之后,人工智能的研究被推向了高潮,其中图片分类和目标检测也飞速发展。在目标检测领域,首先兴起的是以RCNN系列为代表的两阶段检测(Two Stage Detection)方法。最初的RCNN其实是传统计算机视觉算法和深度学习的结合。它首先用传统的select search算法提取2000个左右的特征图像块(region proposel),之后用CNN提取到图像特征,最后用包含(支持向量机)SVM分类器和目标选框回归(bbox regression)的功能头进行分类和回归操作。然而它在检测的时候速度太慢,很难用在实时的目标检测和比较低端的硬件上。虽然之后Fast-RCNN和Faster-RCNN对模型推理速度和精度进行了优化,但是推理速度依然有很大提升空间。
- 天下武功为快不破,横空出世yolo网络以它惊人的检测速度成为了目标检测领域的一颗明珠,也开启了一阶段目标检测(One Stage Detection)的时代。快速的目标检测能够使得检测系统在安防,无人驾驶,公共场所秩序的管理维护等方面落地成为可能。
YoloV1:
- YoloV1为今后的Yolo模型定下了基础,之后的模型都是在YoloV1总思想的指导下进行调整的。
总流程:
- 首先将448 * 448的图片输入到darknet的backbone中,得到size是7*7的特征图。这个特征图和原图的映射关系和RCNN系列是一样的。在预测的时候,一旦一个物体的中心点落到了某个格子之中,那么这个格子就负责这个物体的检测。
- 当物体中心在网格上呢?就直接左开右闭处理。如果有两个物体中心都落在一个格子里面呢?就把置信度高的BBox挑选出来,总之只能预测一个物体。
- 网络预测的参数有 :
BBox:x,y,w,h(center)还有置信度:Confidence: object IoU
得到的output维度是 对于论文也就是
B指代有2个bbox,20指代一共有20中类别。
损失函数:
- 要进行检测选框回归就必然要有损失函数,yolov1的损失函数比较复杂。但是可以大致分成三个部分,总之可以分成三部分bbox回归/置信度回归/分类的回归。通过这个复杂的损失函数,网络就可以通过梯度下降法更新参数进而学习。
- YoloV1 的损失函数:
- 2.1部分是BBox回归的Loss函数,其中我们可以看到,作者在w和h的损失函数上加了根号,这是为了使得大物体的loss不要太大,否则小物体的特征无法被训练。加了
- 公式2.2部分是置信度的损失函数,其中 表示是物体的蒙版, 表示不是物体的蒙版,他们在各个数值上是完全相反的。 平衡不均匀正负样本的参数。 是预测的BBox和标签的IOU 乘以真实的物体的模板。
- 2.3是对正样本分类置信度损失的计算。每一个小格子只能预测一个物体,预测出的物体由有大的IOU的bbox决定。最终要进行NMS把没有用的选框给清除了
YoloV2:
- YoloV1最大的优点就是快,但是太快就没有什么感觉,会忽视一些东西。比如说:
- YoloV1对密集物体的检测效果不好,因为一张图片到顶就预测49个物体。
- 对小物体不友好这是肯定的。毕竟损失函数这么复杂有这么粗糙。
- 对不同长宽比的物体预测不太好,毕竟这是无意识的anchor free网络吧
- 没有BN层,原来的作者真的厉害,怎么训练的网络都不知道
- YoloV2努力实现又快又好又有感觉:首先的改进就是加了BN层,使得网络更好训练,表现得更好
- 然后再Backbone训练的时候也用了一些trick,比如说,先再224X224的Image网络上训练,然后继续在448X448的ImageNet上finetune,这样在输入大图片的时候检测的效果会好很多
- 最后在在真实的目标检测dataset上进行微调,最后得到13x13的feature map。
Reorg网络层:
- 在介绍这个层之前,我们要知道层数比较低的卷积核得到的是空间,颜色,纹理,边缘等信息,层数比较深的卷积核得到的是抽象的语义信息。
- 如何把两种信息结合起来,使得深层网络在进行目标检测的时候不会丢失位置信息呢?作者想到了把浅层feature map和深层feature map拼接起来的方法。然而深层feature map的size毕竟还是比较小的,如何contact呢?作者就把浅层的feature map进行一定的拆分:
- 拆分的过程如上图所示,经过这样的拆分就可以成功的和深层的feature map拼接起来了。
多尺度训练:
- 为了使得网络能够输入不同大小的图片,作者把FC层给取出了,这样就可以接受各种size的图片,然后使得模型更有鲁棒性。
Anchor:
- Yolo和Faster RCNN也是你抄我我抄你,不抄白不抄。Yolo的Anchor是用label进行Kmeans计算出来的,一共有五个。中心点数值有10个。不过anchor也还是有一些缺点,就是要根据不同数据集设计不同anchor,计算比较复杂。
- 比如Anchors: 0.57273, 0.677385, …, 9.77052, 9.16828 [10 numbers]
- 分别代表是
- anchors
- anchor改变了,那么真实的BBox也要跟着改变,也要相对于图像的长宽进行归一化,然后乘以13.使得真实的BBox范围也在0-13之间,方便网络进行训练。
- final box:
- anchors [0])
anchors [1]
# 伪代码:
box_xy =sigmoid (feats..., 2)
box_wh=k.exp(feats[...2: 4])
box_confidence =K.simoid(feats[..., 4: 5])
box_class_probs =K.softmax(feats[..., 5:])
#Adjust preditions to each spatial grid point and anchor size.
#Note: YOLO iterates over height index before width index.
box_xy =(box_xy + conv_index) / conv_dims
box_wh = box_wh * anchors_tensor / conv_dims
- 一共输出25个feature,其中有x,y,w,h+置信度,一共五个anchor。
- 当然YoloV2还是有一些问题,就是它对于小物体检测还是不太行,虽然精确率高了些。
损失函数:
- 为什么要
- 这个其实也是一种残差拟合的方法,加上SmoothL1应该就可以进行反向传播了。论文并没有写损失函数是什么的感觉。
- KaTeX parse error: Undefined control sequence: \C at position 75: … &\left(C_{x}, \̲C̲_{y}\right) \le…
- 这个公式算是对上面的公式的一个解释吧
YoloV3:
- YoloV2在残差网络出来了之后还可以进行进一步的改进。YoloV3其实并不是一片论文,而是一个报告。
模块改进:
- 这是一个不彻底的残差结构,我偏偏就用一半的结构你能给我怎么地
多尺度输出:
- 三层的resolution不同(就是有13x13,26x26,52x52(小图像)每一层有3个anchor,用了kmeans做了9个anchor,用小中大进行分类,每一组有三个anchor,主要是针对大小不同的物体进行分类)增大featuremap的resolution,对小物体更加友好。通过不同的scale设计不同的feature map同时进行训练。
- 其实就是把格子打得更加密集一些,预测小物体的时候比较好搞定。
- 在分类的时候因为有很多类别,作者把softmax改成了logistics regression
- 网络在输出的时候,输出的尺度如下图所示:
- 80 表示COCO数据集一共有80个类别,3表示每一个size一共有三种anchor,对应的输出也有三种。4+1就是熟悉的xywh+置信度c
FPN Net:
- 这个网络其实是一个比较万金油的网络,放在One Stage和Two Stage里面都可以,也叫做特征金字塔网络。它是由以下网络逐渐发展而来的。这个网络也是YoloV3设计的一个思路来源。
(a): 图像金字塔:featurized image pyramid。靠高斯核去模拟(原始的手算算法,高斯核唯一能够模拟人眼。。),要有尺度不变形!这个是没有cnn的时候这样做的。但是显然各个特征图之间没有交互,高层容易丢失一些信息。
(b):sigle feature map ,一个尺度输出一个预测,这就是传统CNN在做的事情。
(c):pyramidal feature hierarchy,通过降采样进行预测,不同的特征图之间有连接。只不过高层的位置信息会缺一些,底层的语义信息会缺失一些。
(d):FPN,其实和U-Net异曲同工,FPN把高层的语义信息和底层的位置纹理等信息结合了起来。如何进行互联呢:通过1x1修改channel,然后要进行upsampling之后再相加,最后对每一个尺度进行预测。当然FPN是一个比较吃资源的网络,对于速度型网络慎用。
- 关于损失函数的变化其实应该不大。具体还是得从代码中看。
休息一下,换一个网络之RetinaNet:
- 以Yolo为代表的One Stage检测精度一直都比Two Stage差,这是为什么呢?原来的人们一直以为这是因为Two Stage有Region Proposal,可以进行微调,而One stage并没有这个东西,所以效果会差一些。然而这个答案只是经验的结果,何大神再次出场提出了自己的见解:
- 效果有差别最重要的是:正负样本不均衡问题。以YoloV1为例,看看那个正负样本物体模板,一张图样本的正例寥寥无几,更不用说YoloV3了,52 * 52的格子,正负样本比例真的跟寺庙(某某工科大学)男女比差不多了。而看看RCNN系列,一直都是batchsize是128,正负样本比1:3牢牢保持着。正负样本差别马上就体现出来了。
- 正负样本失衡会使得整个样本的梯度和损失函数被简单样本占据,这样,网络就会学习一堆的简单信息,一堆负样本的没有用的信息,不知不觉,网络学坏了。
- 网络结构如下:
- 为了解决正负样本不均衡的问题,何大神提出了Focal Loss的方法:
- focal loss是在交叉熵的基础上进行改进得到的,总体思想是提高正样本的权重,降低容易分类的样本和负样本的权重。最终出现了以下公式:α是用来解决正负样本的问题,γ用来解决样本难易的问题(focusing paramters)
- 交叉熵是:,之后化一下就变成了下面的交叉熵
- 为什么要加上这个调制系数呢?目的是通过减少易分类样本的权重,从而使得模型在训练时更专注于难分类的样本。
- 当pt=0时就分错了,正常学习,当pt是1就分对了,就不用学习了。