目标检测四
YOLO v1
参考:https://zhuanlan.zhihu.com/p/32525231
参考:https://zhuanlan.zhihu.com/p/31427164
yolo (you only look once)。 Yolo算法采用一个单独的CNN模型实现end-to-end的目标检测 ,整个系统如下图所示:首先将输入图片resize到448x448,然后送入CNN网络,最后处理网络预测结果得到检测的目标。相比R-CNN算法,其是一个统一的框架,其速度更快,而且Yolo的训练过程也是end-to-end的。
原理
YOLO将输入图像分成SxS个格子,每个格子负责检测‘落入’该格子的物体。 每个格子输出B个bounding box(包含物体的矩形区域)信息,以及C个物体属于某种类别的概率信息。
- YOLO的bounding box并不是Faster RCNN的Anchor 。Faster RCNN等一些算法采用每个grid中手工设置n个Anchor(先验框,预先设置好位置的bounding box)的设计,每个Anchor有不同的大小和宽高比。YOLO的bounding box看起来很像一个grid中2个Anchor,但它们不是。YOLO并没有预先设置2个bounding box的大小和形状,也没有对每个bounding box分别输出一个对象的预测。它的意思仅仅是对一个对象预测出2个bounding box,选择预测得相对比较准的那个。
Bounding box信息包含5个数据值,分别是x,y,w,h,和confidence。其中x,y是指当前格子预测得到的物体的bounding box的中心位置的坐标。w,h是bounding box的宽度和高度。 x,y 是相对于每个单元格左上角坐标点的偏移值,并且单位是相对于单元格大小的,被归一化到[0,1]。注意:实际训练过程中,w和h的值使用图像的宽度和高度进行归一化到[0,1]区间内。
confidence反映当前bounding box是否包含物体以及物体位置的准确性。前者记为$Pr(object)$ ,当该边界框是背景时(即不包含目标),此时$Pr(object)=0$。而当该边界框包含目标时 $Pr(object=1)$。边界框的准确度可以用预测框与实际框(ground truth)的IOU(intersection over union,交并比)来表征,记为 $IOU^{truth} _{pred}$ 。因此置信度可以定义为 $Pr(object)=0$。
每个单元格需要预测$B*5+C$ 个值。如果将输入图片划分为$S*S$ 网格,那么最终预测值为$S×S×(B*5+C)$大小的张量。整个模型的预测值结构如下图所示。对于PASCAL VOC数据,其共有20个类别,如果使用$S=7,B=2$ ,那么最终的预测结果就是$7×7×30$大小的张量。
网络结构
Yolo采用卷积网络来提取特征,然后使用全连接层来得到预测值。网络结构参考GooLeNet模型,包含24个卷积层和2个全连接层,如图8所示。对于卷积层,主要使用1x1卷积来做channle reduction,然后紧跟3x3卷积。对于卷积层和全连接层,采用Leaky ReLU激活函数:$max(x,0.1x)$。但是最后一层采用线性激活函数。
网络训练
在训练之前,先在ImageNet上进行了预训练,其预训练的分类模型采用上图前20个卷积层,然后添加一个average-pool层和全连接层。预训练之后,在预训练得到的20层卷积层之上加上随机初始化的4个卷积层和2个全连接层。由于检测任务一般需要更高清的图片,所以将网络的输入从224x224增加到了448x448。整个网络的流程如下图所示:
在test的时候,每个网格预测的class信息和bounding box预测的confidence信息相乘,就得到每个bounding box的class-specific confidence score:
等式左边第一项就是每个网格预测的类别信息,第二三项就是每个bounding box预测的confidence。这个乘积即encode了预测的box属于某一类的概率,也有该box准确度的信息。
得到每个box的class-specific confidence score以后,设置阈值,滤掉得分低的boxes,对保留的boxes进行NMS处理,就得到最终的检测结果。
损失函数
下面是训练损失函数的分析,Yolo算法将目标检测看成回归问题,所以采用的是均方差损失函数。
其中,coordError、iouError和classError分别代表预测数据与标定数据之间的坐标误差、IOU误差和分类误差。
- 首先区分定位误差和分类误差,位置相关误差(坐标、IOU)与分类误差对网络loss的贡献值是不同的:对于定位误差,即边界框坐标预测误差,采用较大的权重$\lambda_{coord}=5$。
- 然后其区分不包含目标的边界框与含有目标的边界框的置信度,对于前者,采用较小的权重值$\lambda_{noobj}=0.5$。其它权重值均设为1。这是因为在计算IOU误差时,包含物体的格子与不包含物体的格子,二者的IOU误差对网络loss的贡献值是不同的。若采用相同的权值,那么不包含物体的格子的confidence值近似为0,变相放大了包含物体的格子的confidence误差在计算网络参数梯度时的影响。为解决这个问题,YOLO 使用 $\lambda_{noobj} = 0.5$修正iouError。(注此处的‘包含’是指存在一个物体,它的中心坐标落入到格子内)。
- 然后采用均方误差,其同等对待大小不同的边界框,但是实际上较小的边界框的坐标误差应该要比较大的边界框要更敏感。为了保证这一点,将网络的边界框的宽与高预测改为对其平方根的预测,即预测值变为$(x,y,\sqrt{w},\sqrt{h})$。
另外一点是,由于每个单元格预测多个边界框。但是其对应类别只有一个。那么在训练时,如果该单元格内确实存在目标,那么只选择与ground truth的IOU最大的那个边界框来负责预测该目标,而其它边界框认为不存在目标。这样设置的一个结果将会使一个单元格对应的边界框更加专业化,其可以分别适用不同大小,不同高宽比的目标,从而提升模型性能。大家可能会想如果一个单元格内存在多个目标怎么办,其实这时候Yolo算法就只能选择其中一个来训练,这也是Yolo算法的缺点之一。要注意的一点时,对于不存在对应目标的边界框,其误差项就是只有置信度,坐标项误差是没法计算的。而只有当一个单元格内确实存在目标时,才计算分类误差项,否则该项也是无法计算的。
其中第一项是边界框中心坐标的误差项,$1^{obj}_{ij}$ 指的是第$i$个单元格存在目标,且该单元格中的第$j$个边界框负责预测该目标。第二项是边界框的高与宽的误差项。第三项是包含目标的边界框的置信度误差项。第四项是不包含目标的边界框的置信度误差项。而最后一项是包含目标的单元格的分类误差项, $1^{obj}_{i}$ 指的是第 $i$个单元格存在目标。这里特别说一下置信度的target值$C_i$ ,如果是不存在目标,此时由于$Pr_{object}=0$,那么 $C_i=0$。如果存在目标$Pr_{object}=1$, 此时需要确定 $IOU^{truth}_{pred}$,当然你希望最好的话,可以将IOU取1,这样$C_i= 1$,但是在YOLO实现中,使用了一个控制参数rescore(默认为1),当其为1时,IOU不是设置为1,而就是计算truth和pred之间的真实IOU。不过很多复现YOLO的项目还是取 $C_i=1$,这个差异应该不会太影响结果吧。
性能
Yolo的Correct的是低于Fast R-CNN。另外Yolo的Localization误差偏高,即定位不是很准确。但是Yolo的Background误差很低,说明其对背景的误判率较低。
- 优点:Yolo采用一个CNN网络来实现检测,是单管道策略,其训练与预测都是end-to-end,所以Yolo算法比较简洁且速度快。第二点由于Yolo是对整张图片做卷积,所以其在检测目标有更大的视野,它不容易对背景误判。其实我觉得全连接层也是对这个有贡献的,因为全连接起到了attention的作用。另外,Yolo的泛化能力强,在做迁移时,模型鲁棒性高。
- 缺点:最后不得不谈一下Yolo的缺点,首先Yolo各个单元格仅仅预测两个边界框,而且属于一个类别。对于小物体,Yolo的表现会不如人意。这方面的改进可以看SSD,其采用多尺度单元格。也可以看Faster R-CNN,其采用了anchor boxes。Yolo对于在物体的宽高比方面泛化率低,就是无法定位不寻常比例的物体。当然Yolo的定位不准确也是很大的问题。