文章目录[隐藏]
目标检测Part2(R-FCN,Yolo)
总结一下Part1的四种模型:
(1)R-CNN VS SPP-Net:
(2)SPP-Net vs Fast R-CNN
(3)Fast R-CNN vs Faster R-CNN
1.R-FCN
为了适应全卷积化的过程,在Resnet的预训练上进行迁移学习的一个模型,目的还是为了减少全连接层。和Faster R-CNN相比,R-FCN具有更深的共享卷积网络层,这样可以获得更加抽象的特征;同时,它没有RoI-wise subnetwork,不像Faster R-CNN的feature map左右都有对应的网络层,它是真正的全卷积网络架构
1.1 检测网络的变换敏感性 和 分类网络的变换不变性
检测网络的变换敏感性(位置敏感性):简单来讲,对于检测任务而言,我希望我的网络有一个好的检测性能,可以准确的输出目标所在的位置值。随着某个目标的移动,我的网络希望能够和它一起移动,仍然能够准确的检测到它,即我对目标位置的移动很敏感。我需要计算对应的偏差值,我需要计算我的预测和GT的重合率等。但是,深的全卷积网路不具备这样的一个特征。
分类网络的变换不变性(位置不敏感性):简单来讲,对于分类任务而言,我希望我的网络有一个很好地分类性能,随着某个目标在图片中不断的移动,我的网络仍然可以准确的将你区分为对应的类别。如上图左边所示,不管你这只鸟在图片中如何移动,我的分类网络都想要准确的将你分类为鸟。即我的网络有很好地区分能力。实验表明,深的全卷积网络能够具备这个特性,如ResNet-101等。
即卷积层越深,不变性越强,对变换越不敏感
所以这就存在检测网络的变换敏感性 和 分类网络的变换不变性的一个矛盾问题,而我们的目标检测中不仅要分类也要定位,那么如何解决这个问题呢?
R-FCN提出了Position-sensitive score maps来解决这个问题
1.2 设计动机(模型优势)
Faster R-CNN是首个利用CNN来完成proposals预测的,从此之后很多的目标检测网络都开始使用Faster R-CNN的思想。而Faster R-CNN系列的网络都可以分成2个部分:ROI Pooling之前的共享全卷积网络和ROI Pooling之后的ROI-wise子网络(用来对每个ROI进行特征提出,并进行回归和分类)。第1部分就是直接用普通分类网络的卷积层,用来提取共享特征,然后利用ROI Pooling在最后一层网络形成的feature map上面提取针对各个RoIs的特征向量,然后将所有RoIs的特征向量都交给第2部分来处理(即所谓的分类和回归),而第二部分一般都是一些全连接层,在最后有2个并行的loss函数:softmax和smooth-L1,分别用来对每一个RoI进行分类和回归,这样就可以得到每个RoI的真实类别和较为精确的坐标信息啦(x, y, w, h)。
需要注意的是第1部分通常使用的都是像VGG、GoogleNet、ResNet之类的基础分类网络,这些网络的计算都是所有RoIs共享的,在一张图片上面进行测试的时候只需要进行一次前向计算即可。而对于第2部分的RoI-wise subnetwork,它却不是所有RoIs共享的,主要的原因是因为这一部分的作用是“对每个RoI进行分类和回归”,所以不能进行共享计算。那么问题就处在这里,首先第1部分的网络具有“位置不敏感性”,而如果我们将一个分类网络比如ResNet的所有卷积层都放置在第1部分用来提取特征,而第2部分则只剩下全连接层,这样的目标检测网络是位置不敏感的translation-invariance,所以其检测精度会较低,而且这样做也会浪费掉分类网络强大的分类能力。
而ResNet论文中为了解决这个问题,做出了一点让步,即将RoI Pooling层不再放置在ResNet-101网络的最后一层卷积层之后而是放置在了“卷积层之间”,这样RoI Pooling Layer之前和之后都有卷积层,并且RoI Pooling Layer之后的卷积层不是共享计算的,它们是针对每个RoI进行特征提取的,所以这种网络设计,其RoI Pooling层之后就具有了位置敏感性translation-variance,但是这样做会牺牲测试速度,因为所有的RoIs都需要经过若干层卷积计算,这样会导致测试速度很慢。R-FCN就是针对这个问题提出了自己的解决方案,在速度和精度之间进行折中。
1.3 R-FCN架构分析-算法步骤
如图所示,先来宏观分析一下R-FCN算法的整个运行步骤
Step1:选择一张输入处理的图片,并对这张图片进行相应的预处理操作
Step2:将预处理后的图片送入一个预训练好的分类网络中(这里使用了ResNet-101网络的Conv4之前的网络),固定其对应的网络参数
Step3:在预训练网络的最后一个卷积层获得的feature map上存在3个分支
分支1:在该feature map上面进行RPN操作,获得相应的ROI
分支2:在该feature map上获得一个KK(C+1)维的位置敏感得分映射(position-sensitive score map),用来进行分类
分支3:在该feature map上获得一个4KK维的位置敏感得分映射,用来进行回归
Step4:在KK(C+1)维的位置敏感得分映射和4KK维的位置敏感得分映射上面分别执行位置敏感的ROI池化操作(Position-Sensitive Rol Pooling,这里使用的是平均池化操作),获得对应的类别和位置信息。
1.4 位置敏感分值图(Position-sensitive score maps)
Score map的设计思路:
如果一个ROI中含有一个类别为C1的物体,我们将该RoI划分为KxK 个区域,其分别表示该物体的各个部位.
比如假设该RoI中含有的目标类别C1是人,K=3,那么就将“人”划分成了9个子区域,如下图所示:
其中top-center区域毫无疑问应该是人的头部,而bottom-center应该是人的脚部,我们将RoI划分为KxK个子区域是希望这个RoI在其中的每一个子区域都应该含有该类别C1的物体的各个部位,即如果是人,那么RoI的top-center区域就应该含有人的头部。
当所有的子区域都含有各自对应的该物体的相应部位后,那么分类器才会将该RoI判断为该类别。也就是说物体的各个部位和RoI的这些子区域是“一一映射”的对应关系。
OK,现在我们知道了一个RoI必须是KxK个子区域都含有该物体的相应部位,我们才能判断该RoI属于该物体,如果该物体的很多部位都没有出现在相应的子区域中,那么就该RoI判断为背景类别。
##那么现在的问题就是网络如何判断一个RoI的 KxK个子区域都含有相应部位呢?
前面我们是假设知道每个子区域是否含有物体的相应部位,那么我们就能判断该RoI是否属于该物体还是属于背景。那么现在我们的任务就是判断RoI子区域是否含有物体的相应部位。这其实就是position-sensitive score map设计的核心思想了。
R-FCN会在共享卷积层的最后一层网络上接上一个卷积层,而该卷积层就是位置敏感得分图-position-sensitive score map,该score map的含义如下所述:
首先它就是一层卷积层,它的height和width和共享卷积层的一样(即具有同样的感受野),但是它的通道个数为KxKx(C+1) 。其中C表示物体类别种数,再加上1个背景类别,所以共有(C+1)类,而每个类别都有 KxK个score maps。
现在我们只针对其中的一个类别如C1来进行说明,假设我们的目标属于C1这个类别,那么其有 KxK 个score maps,每一个score map表示原始图像中的哪些位置含有C1的某个部位,该score map会在含有对应的C1的某个部位的位置有高的响应值,也就是说每一个score map都是用来描述类别C1的其中一个部位出现在该score map的何处,而在出现的地方就有高响应值”。既然是这样,那么我们只要将RoI的各个子区域对应到属于类别C1的每一个score map上然后获取它的响应值就好了。但是要注意的是,由于一个score map都是只属于一个类别的一个部位的,所以RoI的第 i个子区域一定要到第i张score map上去寻找对应区域的响应值,因为RoI的第i个子区域需要的部位和第i张score map关注的部位是对应的。如上图我们需要找头部这个区域就需要去第二个score map的相应位置去找响应值。
如果该RoI的KxK个子区域都已经分别在属于C1的KxK个score maps上找到其响应值了,那么如果这些响应值都很高,那么就证明该RoI是人吗?
当然这有点不严谨,因为我们只是在属于人的 KxK个score maps上找响应值,我们还没有到属于其它类别的score maps上找响应值呢,万一该RoI的各个子区域在属于其它类别的上的score maps的响应值也很高,那么该RoI就也有可能属于其它类别呢?是吧,如果2个类别的物体本身就长的很像呢?这就会涉及到一个比较的问题,那个类别的响应值高,我就将它判断为哪一类目标。
1.5 位置敏感RoI池化(Position-Sensitive Rol Pooling)
在解释位置敏感分值图的时候,提到了ROl的K*K个子区域在各个类别的score maps上找到其每个子区域的响应值,但是这个找到的过程是如何实现的呢?
这就需要位置敏感Rol池化操作(Position-sensitive RoI pooling),其字面意思是池化操作是位置敏感的
通过RPN提取出来的RoI区域,其是包含了x,y,w,h的4个值,也就是说不同的RoI区域能够对应到score map的不同位置上,而一个RoI会被划分成KxK个bins(也就是子区域。每个子区域bin的长宽分别是 h/k 和 w/k ),每个bin都对应到score map上的某一个区域。既然该RoI的每个bin都对应到score map上的某一个子区域,那么池化操作就是在该bin对应的score map上的子区域执行,且执行的是平均池化。我们在前面已经讲了,第i个bin应该在第i个score map上寻找响应值,那么也就是在第i个score map上的第i个bin对应的位置上进行平均池化操作。由于我们有(C+1)个类别,所以每个类别都要进行相同方式的池化操作。
其实就是在每个score map上面进行一个均值池化,池化后的值填入到输出的ROI的对应的bin区域,如上图对应圈中黄色区域的值就是黄色的score map里面均值池化得到的。
对于每个类别,它都有KxK个score maps,那么按照上述的池化方式,ROI可以从一个score map得到一个值,针对一个类别可以获得KxK个值,那么一共有(C+1)个类别,那么一个RoI就可以得到KxKx(C+1)个值,就是上图的特征图。那么对于每个类别,该类别的KxK个值都表示该RoI属于该类别的响应值,那么将这KxK个数相加就得到该类别的score,那么一共有(C+1)个scores,那么在这(C+1)个数上面使用简单的softmax函数就可以得到各个类别的概率了
(注意,这里不需要使softmax分类器了,只需要使用简单的softmax函数,因为这里就是通过简单的比大小来判断最终的类别的)。
1.6 R-FCN的多任务损失函数
总损失函数:
这个Loss就是两阶段目标检测框架常用的形式。包括一个分类Loss和一个回归Loss。lamdy用来平衡两者的重要性。
(part1)分类损失函数:
(part2)回归损失函数:
对于任意一个RoI,我们需要计算它的softmax损失,和当其不属于背景时的回归损失。这很简单,因为每个RoI都被指定属于某一个GT box或者属于背景,即先选择和GT box具有最大重叠率(IOU)的Rol,然后在剩余的Rol中选择与GT box的重叠率值大于0.5Rol进行匹配操作,最后将剩余的Rol都归为背景类。即每个Rol都有了对应的标签,我们就可以根据监督学习常用的方法来训练它啦。
1.7 OHEM(Online Hard Example Mining)
这个方法是目标检测框架中经常会用到的一个tricks,其主要的思路如下所示:
• 首先对RPN获得的候选ROI(正负样本分别进行排序)进行排序操作;
• 然后在含有正样本(目标)的ROI中选择前N个ROI,将正负样本的比例维持在1:3的范围内,基本上保证每次抽取的样本中都会含有一定的正样本
• 这样训练可以提高网络的分类能力,如果不进行此操作的话,很可能会出现抽取的所有样本都是负样本(背景)的情况,这样让网络学习这些负样本,会影响网络的性能。
2 Yolo-V1
YOLO全称You Only Look Once: Unified, Real-Time Object Detection,是在CVPR2016提出的一种目标检测算法,核心思想是将目标检测转化为回归问题求解,并基于一个单独的end-to-end网络,完成从原始图像的输入到物体位置和类别的输出。
2.1 difference between Faster R-CNN
Faster RCNN将目标检测分解为分类为题和回归问题分别求解:首先采用独立的RPN网络专门求取region proposal,即计算下图中的P(objetness);然后对利用bounding box regression对提取的region proposal进行位置修正,即计算下图中的Box offsets(回归问题);最后采用softmax进行分类(分类问题)。
而YOLO将物体检测作为一个回归问题进行求解:输入图像经过一次网络,便能得到图像中所有物体的位置和其所属类别及相应的置信概率。同时这也是双阶段和单阶段的本质区别。可以看出,YOLO将整个检测问题整合为一个回归问题,使得网络结构简单,检测速度大大加快;由于网络没有分支,所以训练也只需要一次即可完成。这种“把检测转化为回归问题”的思路非常有效,之后的很多检测算法(包括SSD)都借鉴了此思路。
2.2 网络结构
下图中展示了YOLO的网络结构。相比Faster RCNN,YOLO结构简单而,网络中只包含conv,relu,pooling和全连接层,以及最后用来综合信息的detect层。其中使用了1x1卷积用于多通道信息融合
YOLO是一种传统的one-stage的卷积神经网络:
(1)网络输入:448×448×3的彩色图片。
(2)中间层:由若干卷积层和最大池化层组成,用于提取图片的抽象特征。
(3)全连接层:由两个全连接层组成,用来预测目标的位置和类别概率值。
(4)网络输出:7×7×30的预测结果。
2.3设计思路-步骤
YOLO的工作过程分为以下几个过程:
(Step1)
YOLOv1采用的是“分而治之”的策略。将原图划分为SxS(常见为7x7)的网格。如果一个目标的中心落入某个网格,这个网格就负责预测该目标。
(在Faster R-CNN中,是通过一个RPN来获得目标的感兴趣区域,这种方法精度高,但是需要额外再训练一个RPN网络,这无疑增加了训练的负担。在YOLOv1中,通过划分得到了7×7个网格,这49个网格就相当于是目标的感兴趣区域。通过这种方式,我们就不需要再额外设计一个RPN网络,这正是YOLOv1作为单阶段网络的简单快捷之处!)
如下图图中物体“狗”的中心点(红色原点)落入第5行、第2列的格子内,所以这个格子负责预测图像中的狗
(Step2)
每个网格要预测B(B=2)个bounding boxes,以及C个类别概率Pr(classi|object)。
什么是类别概率?
即在一个网格包含一个Object的前提下,它属于某个类的概率
这里解释一下,C是网络分类总数,由训练时决定。在作者给出的demo中C=20,包含以下类别:
人person、鸟bird、猫cat、牛cow、狗dog、马horse、羊sheep、飞机aeroplane、自行车bicycle、船boat、巴士bus、汽车car、摩托车motorbike、火车train、瓶子bottle、椅子chair、餐桌dining table、盆景potted plant、沙发sofa、显示器tv/monitor
在YOLO中,每个格子只有一个C类别,即相当于忽略了B个bounding boxes,每个格子只判断一次类别,这样做非常简单粗暴。
(Step3)
其中网格中的B个bounding boxes,每个bounding box除了要回归自身的位置 (x, y, w, h) 之外,还要附带预测一个confidence值。这个confidence代表了所预测的box中含有目标的置信度和这个bounding box预测的有多准两重信息:
如果这个栅格中不存在object,则confidence score应该为0;否则的话,confidence score则为 predicted bounding box与 ground truth box之间的 IOU(intersection over union)。
即有目标落中心在格子里,那么Pr(Object)=1;否则Pr(Object)=0。 第二项是预测的bounding box和实际的ground truth之间的IOU。
所以,每个bounding box都包含了5个预测量:(x, y, w, h, confidence),其中(x, y)代表预测box相对于格子的中心,(w, h)为预测box相对于图片的width和height比例,confidence就是上述置信度。需要说明,这里的x, y, w和h都是经过归一化的,之后有解释。
(Step4)
总的来说,S×S 个网格,每个网格要预测 B个bounding box ,还要预测 C 个类。网络输出就是一个 S × S × (5×B+C) 的张量。每一个网格的输出内容如下所示(B=2,C=20)
(Step5)
在检测目标的时候,每个网格预测的类别条件概率和bounding box预测的confidence信息相乘,就得到每个bounding box的class-specific confidence score:
每一项信息如图所示:
显然这个class-specific confidence score既包含了bounding box最终属于哪个类别的概率,又包含了bounding box位置的准确度。最后设置一个阈值与class-specific confidence score对比,过滤掉score低于阈值的boxes,然后对score高于阈值的boxes进行非极大值抑制(NMS, non-maximum suppression)后得到最终的检测框体。
非极大值抑制(NMS):
首先从所有的检测框中找到置信度最大的那个框,然后挨个计算其与剩余框的IOU,如果其值大于一定阈值(重合度过高),那么就将该框剔除;之后对剩余的检测框重复上述过程,直到处理完所有的检测框
2.4 目标损失函数
损失由三部分组成,分别是:坐标预测损失、置信度预测损失、类别预测损失。
(Part1:坐标预测损失)
在检测算法的实际使用中,一般都有这种经验:对不同大小的bounding box预测中,相比于大box大小预测偏一点,小box大小测偏一点肯定更不能被忍受。所以在Loss中同等对待大小不同的box是不合理的。为了解决这个问题,作者用了一个比较取巧的办法,即对w和h求平方根进行回归。从后续效果来看,这样做很有效,但是也没有完全解决问题。
(Part2:置信度confidence预测损失)
由于绝大部分网格中不包含目标,导致绝大部分box的confidence=0,所以在设计confidence误差时同等对待包含目标和不包含目标的box也是不合理的,否则会导致模型不稳定。作者在不含object的box的confidence预测误差中乘以惩罚权重λnoobj=0.5。
除此之外,同等对待4个值(x, y, w, h)的坐标预测误差与1个值的conference预测误差也不合理,所以作者在坐标预测误差误差之前乘以权重λcoord=5(至于为什么是5而不是4,搞不太清楚)。
(Part3:类别预测损失)
即每个box属于什么类别,需要注意一个网格只预测一次类别,即默认每个网格中的所有B个bounding box都是同一类。
所以,YOLO的最终误差为下:
Loss = λcoord * 坐标预测误差 + (含object的box confidence预测误差 + λnoobj * 不含object的box confidence预测误差) + 类别预测误差
=
2.5 Yolo 特点
综上所述,YOLO有如下特点:
优点:
1.快。YOLO将物体检测作为回归问题进行求解,整个检测网络pipeline简单,且训练只需一次完成。
2.假阳性率低,背景误检率低。YOLO在训练和推理过程中能“看到”整张图像的整体信息,而基于region proposal的物体检测方法(如Fast RCNN)在检测过程中,只“看到”候选框内的局部图像信息。因此,若当图像背景(非物体)中的部分数据被包含在候选框中送入检测网络进行检测时,容易被误检测成物体[1]。
不足:
1.物体检测精度低于其他state-of-the-art的
物体检测系统。
2.识别物体位置精准性差,容易产生物体的定位错误,对w和h求平方根的策略并没有完全解决location准确度问题。
3.召回率低,尤其是对小目标。对小物体的检测效果不好(尤其是密集的
小物体,因为一个栅格只能预测2个物体)。
3. Yolo v2/9000 and Yolo V3
3.1 Yolo v2改进介绍
YOLO与Fast R-CNN相比有较大的定位误差,与基于region proposal的方法相比具有较低的召回率。因此YOLO v2主要改进是提高召回率和定位能力
改进之处:
(1:Batch Normalization)
实际上在v1中也大量用了Batch Normalization,同时在定位层后边用dropout,但是在v2中主要是取消了dropout,在卷积层全部使用Batch Normalization。YOLOv2 对每一个卷积层输入的数据都进行Batch Normalization,这样网络就不需要每层都去学数据的分布,收敛会变得更快,使结果提升了2%。
什么是Batch Normalization?–之前有介绍过,这里简单介绍一下:
Batch Normalization 简称 BN ,意思是批量标准化。2015年由 Google 研究员在论文《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》中提出。
BN 对数据进行预处理(统一格式、均衡化、去噪等)能够大大提高训练速度,提升训练效果,而且可以提高模型收敛速度,减少过拟合。
BN算法实现:
在卷积或池化之后,激活函数之前,对每个数据输出进行标准化,实现方式如下图所示:
如上图所示,前三行是对Batch进行数据归一化(如果一个Batch中有训练集每个数据,那么同一Batch内数据近似代表了整体训练数据),第四行引入了附加参数 γ 和 β,这两个参数的具体取值可以参考上面提到的 Batch Normalization 这篇论文。
想更深入了解 Batch Normalization 的原理和应用,可以参见:深度学习理论专栏—Batch Normalization
(2:High Resolution Classifier)
v1中使用224 × 224训练分类器网络,扩大到448用于检测网络。但是v2直接将ImageNet以448×448 的分辨率微调最初的分类网络,迭代10 epochs。首先采用448×448分辨率的ImageNet数据fine tune使网络适应高分辨率输入;
然后将该网络用于目标检测任务finetune。高分辨率输入会使结果提升4%mAP。
(3:Convolutional With Anchor Boxes)
YOLOv1 有一个致命的缺陷就是:一张图片被分成7×7的网格,一个网格只能预测一个类,当一个网格中同时出现多个类时,就无法检测出所有类。针对这个问题,YOLOv2做出了相应的改进:
(1)首先将YOLOv1网络的FC层和最后一个Pooling层去掉,使得最后的卷积层的输出可以有更高的分辨率特征。
(2)然后缩减网络,用416×416大小的输入代替原来的448×448,使得网络输出的特征图有奇数大小的宽和高,进而使得每个特征图在划分单元格的时候只有一个中心单元格(Center Cell)。YOLOv2通过5个Pooling层进行下采样,得到的输出是13×13的像素特征。
(3)借鉴Faster R-CNN,YOLOv2通过引入Anchor Boxes,预测Anchor Box的偏移值与置信度,而不是直接预测坐标值。
(4)YOLOv2确定Anchor Boxes的方法是维度聚类,每个Cell选择5个Anchor Box,共13×13×5=845个。比YOLOv1预测的98个bounding box 要多很多,因此在定位精度方面有较好的改善。
(4:Direct location prediction–改进Anchors机制)
第3点改进中提到引入Anchors box 机制,但是如何引入呢?
在YOLOv1中,作者设计了端对端的网路,直接对边界框的位置(x, y, w, h)进行预测。这样做虽然简单,但是由于没有类似R-CNN系列的推荐区域,所以网络在前期训练时非常困难,很难收敛。
于是,自YOLOv2开始,引入了 Anchors box 机制,希望通过提前筛选得到的具有代表性先验框Anchors,使得网络在训练时更容易收敛。同时对于Anchors Box机制做出了如下改变:
在 Faster R-CNN 算法中,是通过预测 bounding box 与 ground truth 的位置偏移值tx,ty ,间接得到bounding box的位置。其公式如下:
这个公式是无约束的,无约束的概念是最优化无约束条件,不容易收敛,预测的边界框很容易向任何方向偏移。因此,每个位置预测的边界框可以落在图片任何位置,这会导致模型的不稳定性。
因此 YOLOv2 在此方法上进行了一点改变:预测边界框中心点相对于该网格左上角坐标 (Cx,Cy)的相对偏移量,同时为了将bounding box的中心点约束在当前网格中,使用 sigmoid 函数将 tx,ty 归一化处理,将值约束在0-1,这使得模型训练更稳定。
下图为 Anchor box 与 bounding box 转换示意图,其中蓝色的是要预测的bounding box,黑色虚线框是Anchor box。
YOLOv2 在最后一个卷积层输出 13×13 的 feature map,意味着一张图片被分成了13×13个网格。每个网格有5个anchor box来预测5个bounding box,每个bounding box预测得到5个值:tx、ty、tw、th 和 to(类似YOLOv1的confidence)。引入Anchor Box 机制后,通过间接预测得到的 bounding box 的位置的计算公式为:
置信度to的计算公式为:
总结:
在YOLO模型上采用anchor boxes的是模型不稳定性,大部分不稳定因素来源于预测boxes位置(x,y)。所以通过上述方法将预测偏移量改变为YOLO的预测grid cell的位置匹配性(location coordinate),将预测值限定在0-1范围内,增强稳定性。
(5:Dimension Clusters)
YOLOv2 使用 K-means 聚类方法得到 Anchor Box 的大小,选择具有代表性的尺寸的Anchor Box进行一开始的初始化。聚类的目的是使 Anchor boxes 和临近的 ground truth boxes有更大的IOU值。使用了K-means聚类方法类训练bounding boxes,可以自动找到更好的boxes宽高维度。
(6:Fine-Grained Features-细粒度特征)
细粒度特征,可理解为不同层之间的特征融合。
首先我们经过前面的改进会发现,改进后的YOLO对13×13的feature map进行目标检测。所以需要更精确的特征(finer grained features)从而提高对于小目标的检测
YOLO-v2通过添加一个Passthrough Layer,将高分辨率特征和低分辨率特征结合,把高分辨率的浅层特征连接到低分辨率的深层特征(把特征堆积在不同Channel中)而后进行融合和检测。具体操作是:先获取前层的26×26的特征图,将其同最后输出的13×13的特征图进行连接,而后输入检测器进行检测(而在YOLOv1中网络的FC层起到了全局特征融合的作用),以此来提高对小目标的检测能力。
Passthrough层与ResNet网络的shortcut类似,以前面更高分辨率的特征图为输入,然后将其连接到后面的低分辨率特征图上。前面的特征图维度是后面的特征图的2倍,passthrough层抽取前面层的每个2×2的局部区域,然后将其转化为channel维度,对于26×26×512的特征图,经Passthrough层处理之后就变成了13×13×2048的新特征图(特征图大小降低4倍,而channles增加4倍),这样就可以与后面的13×13×1024特征图连接在一起形成13×13×3072的特征图,然后在此特征图基础上卷积做预测。示意图如下:
(7:Multi-Scale Training)
和YOLOv1训练时网络输入的图像尺寸固定不变不同,YOLOv2(在cfg文件中random=1时)每隔几次迭代后就会微调网络的输入尺寸。训练时每迭代10次,就会随机选择新的输入图像尺寸。因为YOLOv2的网络使用的downsamples倍率为32,所以使用32的倍数调整输入图像尺寸{320,352,…,608}。训练使用的最小的图像尺寸为320 x 320,最大的图像尺寸为608 x 608。 这使得网络可以适应多种不同尺度的输入.
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
3.1 Yolo v2网络结构
YOLOv2提出了一种新的分类模型Darknet-19.借鉴了很多其它网络的设计概念.
(1)主要使用3x3卷积并在每一次池化之后把通道数加倍(VGG)
(2)全局平均池化(global average pooling)替代全连接做预测分类,并在3x3卷积之间使用1x1卷积压缩特征表示(Network in Network)
(3)使用 batch normalization 来提高稳定性,加速收敛,对模型正则化.结构如下:
3.2 Yolo 9000
YOLO9000是在YOLOv2的基础上得到的,相比于YOLO v2,YOLO9000
具有更强大(Stronger)的检测功能,可以检测出更多的类别。作者提出了一种在分类数据集和检测数据集上联合训练的机制。使用检测数据集的图片去学习检测相关的信息,例如bounding box 坐标预测,是否包含物体以及属于各个物体的概率。使用仅有类别标签的分类数据集图片去扩展可以检测的种类。
训练过程中把监测数据和分类数据混合在一起。当网络遇到一张属于检测数据集的图片就基于YOLOv2的全部损失函数(包含分类部分和检测部分)做反向传播。当网络遇到一张属于分类数据集的图片就仅基于分类部分的损失函数做反向传播。 作者最后采用一种不要求互不包含的多标签模型(multi-label model)来整合数据集。这种方法忽略了数据集的结构(例如 COCO数据集的所有类别之间是互不包含的)。
作者也分析了YOLO9000在ImageNet上的性能,发现可以学习新的动物表现很好,但是学习衣服和设备这类物体则不行。因为从COCO数据集上动物类别那里学习到的物体预测泛化性很好。但是COCO数据集并没有任何衣服类别的标签数据(只有”人”类别),所以YOLO9000很难对“太阳镜”,“游泳裤”这些类别建模。
最重要的一点是:使用WordTree把多个数据集整合在一起。
WordNet是一个有向图结构(而非树结构),因为语言是复杂的(例如“dog”既是“canine”又是“domestic animal”),为了简化问题,作者从ImageNet的概念中构建了一个层次树结构(hierarchical tree)来代替图结构方案。最终结果是一颗 WordTree (视觉名词组成的层次结构模型)
3.3 Yolo v3改进介绍
主要改进是以下几点
(1)特征提取部分采用darknet-53网络结构代替原来的darknet-19
(2)利用特征金字塔网络结构实现了多尺度检测
(3)分类方法使用逻辑回归代替了softmax,在兼顾实时性的同时保证了目标检测的准确性。
(1:多尺度预测)
每种尺度预测3个box, anchor的设计方式仍然使用聚类,得到9个聚类中心,将其按照大小均分给3中尺度.
尺度1: 在Darknet-53得到的特征图的基础上,经过7个卷积得到第一个特征图谱,在这个特征图谱上做第一次预测,输出box信息.
尺度2:从尺度1中的从后向前获得倒数第3个卷积层的输出,进行一次卷积一次x2上采样,将上采样特征与第43个卷积特征(最后一个16x16大小的特征图)连接,经过7个卷积得到第二个特征图谱,在这个特征图谱上做第一次预测,输出box信息。相比尺度1变大两倍.
尺度3:与尺度2类似,从尺度1中的从后向前获得倒数第3个卷积层的输出,进行一次卷积一次x2上采样,将上采样特征与第26个卷积特征(最后一个32x32大小的特征图)连接,经过7个卷积得到第三个特征图谱,在这个特征图谱上做第一次预测,输出box信息。
(2:分类器-类别预测)
YOLOv3不使用Softmax对每个框进行分类,主要考虑因素有两个:
(1)
YOLOv3在类别预测方面将YOLOv2的单标签分类改进为多标签分类
而Softmax使得每个框分配一个类别(score最大的一个),而对于Open Images这种数据集,目标可能有重叠的类别标签,因此Softmax不适用于多标签分类。
在网络结构中将YOLOv2中用于分类的softmax层修改为逻辑分类器。在YOLOv2中,算法认定一个目标只从属于一个类别,根据网络输出类别的得分最大值,将其归为某一类。然而在一些复杂的场景中,单一目标可能从属于多个类别。
比如在一个交通场景中,某目标的种类既属于汽车也属于卡车,如果用softmax进行分类,softmax会假设这个目标只属于一个类别,这个目标只会被认定为汽车或卡车,这种分类方法就称为单标签分类。如果网络输出认定这个目标既是汽车也是卡车,这就被称为多标签分类。
(2)
Softmax可被独立的多个logistic分类器替代,且准确率不会下降。
分类损失采用binary cross-entropy loss.
Yolo V3网络结构
相比于 YOLOv2 的 骨干网络,YOLOv3 进行了较大的改进。借助残差网络的思想,YOLOv3 将原来的 darknet-19 改进为darknet-53。论文中给出的整体结构如下:
Darknet-53主要由1×1和3×3的卷积层组成,每个卷积层之后包含一个批量归一化层和一个Leaky ReLU,加入这两个部分的目的是为了防止过拟合。卷积层、批量归一化层以及Leaky ReLU共同组成Darknet-53中的基本卷积单元DBL。因为在Darknet-53中共包含53个这样的DBL,所以称其为Darknet-53。
为了更加清晰地了解darknet-53的网络结构,可以看下面这张图:
为了更好的理解此图,下面我将主要单元进行说明:
DBL: 一个卷积层、一个批量归一化层和一个Leaky ReLU组成的基本卷积单元。
res unit: 输入通过两个DBL后,再与原输入进行add;这是一种常规的残差单元。残差单元的目的是为了让网络可以提取到更深层的特征,同时避免出现梯度消失或爆炸。
resn: 其中的n表示n个res unit;所以 resn = Zero Padding + DBL + n × res unit 。
concat: 将darknet-53的中间层和后面的某一层的上采样进行张量拼接,达到多尺度特征融合的目的。这与残差层的add操作是不一样的,拼接会扩充张量的维度,而add直接相加不会导致张量维度的改变。
Y1、Y2、Y3: 分别表示YOLOv3三种尺度的输出。
与darknet-19对比可知,darknet-53主要做了如下改进:
(1)没有采用最大池化层,转而采用步长为2的卷积层进行下采样。
(2)为了防止过拟合,在每个卷积层之后加入了一个BN层和一个Leaky ReLU。
(3)引入了残差网络的思想,目的是为了让网络可以提取到更深层的特征,同时避免出现梯度消失或爆炸。
(4)将网络的中间层和后面某一层的上采样进行张量拼接,达到多尺度特征融合的目的。
4.一些数据集
(1)FDDB - Face Detection Data set and Benchmark-人脸检测
(2)IJB-A - IARPA Janus Benchmark A-无约束的人脸数据集
(3)Caltech-车载摄像头行人数据集
Leetcode 733 图像渲染
主要是用广度搜索的方式去执行(即队列),向四周散开一层层去查找,也可以用深度搜索,往一个方向不断走,找不到为止(递归,栈)
(1)广度搜索实现
class Solution:
def floodFill(self, image: List[List[int]], sr: int, sc: int, newColor: int) -> List[List[int]]:
#同色直接出
if image[sr][sc]==newColor:
return image
#首先建立队列,并输入起点位置
queue=[]
queue.append((sr,sc))
oricolor=image[sr][sc]
while len(queue)>0:
# print(queue)
# print(image)
#首先取出队尾内容,并赋色
point=queue.pop()
image[point[0]][point[1]]=newColor
#然后遍历四周,相同颜色入队
for i in range(4):
newx=point[0]
newy=point[1]
if i==0:#上边
newx-=1
elif i==1:#下边
newx+=1
elif i==2:#左边
newy-=1
elif i==3:#右边
newy+=1
# 判断是否入队
if 0 <= newx < len(image) and 0 <= newy < len(image[0]) and image[newx][newy] == oricolor:
queue.append((newx,newy))
return image
版权声明:本文为CSDN博主「HammerHe」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_41036272/article/details/122802310
暂无评论