目标检测模型有单阶和二阶的区分,二阶中以Faster Rcnn为代表,对于单阶模型,除了SSD之外,我们还有YoLo这一个主流模型。
简介
Yolo将目标检测问题转为边界框和类概率的回归问题,它通过一个卷积网络来同时处理多个边界框的预测以及这些框的类概率,所以这个模型的运行速度十分的快,但在精度方面的话会有点损失,毕竟没了像Faster RCnn那样的候选框生成过程。其次,Yolo模型有着更低的背景误识率和很好的泛化特性,作者甚至在抽象画作里进行了目标检测,效果海星:)
设计
首先模型先将输入图片划分为\(S \times S\)个网格,如果有目标对象的中心落在某个网格内,则该网格负责预测该对象(具体则是再训练阶段选取与真实框有最大IOU的边界框来负责对应真实例的检测。这样每个检测器都会各司其职,只检测一类对象)。每一个网格都会预测\(B\)个边界框以及这些框的置信度。这里置信度是指该框里是否有对象和做出这个判断的把握:\(Pr(Object)*IOU^{truth}_{pred}\)。如果没有对象在框内则\(Pr(Object)\)为0,否则使用预测框和真实框之间的\(IOU\)作为其置信度数值。
每个边界框都包含有5个变量:\(x,y,w,h,conf\)。前四个是坐标变量,其中\(x,y\)为框的中心,\(w,h\)则表示宽和长。这里要注意中心坐标是相对网格大小的,而长宽是相对整张图像的。
每个网格会预测\(C\)个类条件概率(\(C\)为待预测类别数)。这些概率是在有对象的条件下计算的:\(Pr(Class_i\vert Object)\)。在训练阶段,将该概率跟框的置信度相乘从而得到每个框对于每一类的预测概率:
\[ Pr(Class_i\vert Object) * Pr(Object) * IOU^{truth}_{pred} = Pr(Class_i) * IOU^{truth}_{pred} \]
综上可以得到模型最终输出的张量大小为\(S\times S\times (B*5+C)\)。作者选择的参数为\(S=7\),\(B=2\),训练所用的数据集为\(PASCAL \ VOC\),所以标签数为\(C=20\)。这里附上论文里的一张经典图:

结构
整体的模型结构是卷积网络来提取特征和全连接网络层来输出预测概率以及坐标值。对于特征提取部分,作者构建的网络一共有24层卷积层(对于yolo tiny,使用9层卷积同时减少卷积核数),同时使用了\(1\times 1\)降采样层加\(3\times 3\)的卷积层来替代GoogLeNet的inception部分。同样附上论文结构图:

训练
作者使用Darknet框架来完成模型的训练和推断。预训练阶段,作者选用了模型的前20层卷积网络,后接一个全局平均池化层和全连接层组成一个分类网络在\(ImageNet\)数据集上进行训练。由于将卷积层和连接层都添加到预训练模型中能提高性能,所以作者添加了随机进行初始化的四个卷积层(所以最后模型为24层卷积网络层)和两个全连接层。因为目标检测要求有更大的分辨率,所以将输入图片由预训练的\(224\times 224\)提高到\(448\times 448\)。最后一层同时预测出类概率和框坐标,这里将框坐标进行归一化,具体操作上面已经有提及(中心坐标是相对网格大小的,而长宽是相对整张图像的)。网络层使用激活函数为\(Leak\ ReLU\):
\[ \phi(x) = \begin{cases} x, \ &\text{if x > 0} \\ 0.1x, \ &\text{otherwise} \end{cases} \]
模型的损失函数选用的是平方和误差损失函数,因为优化简单(嗯,有时就是你想多了),当然作者对该函数进行了一些调整以适应本模型。这里列举了几点不足之处:
- 一些并不够理想的框的定位权重跟预测得较好的框的定位权重是一样的;
- 在划分出来的网格中,有时候有许多网格内并没有目标对象存在,而这些网格的置信度为0,这样它的梯度通常会超过包含目标对象的那些框的梯度,从而造成模型的不稳定。
为了弥补这些问题,作者通过参数\(\lambda_{coord}\)增加了边界框的坐标损失同时通过\(\lambda_{noobj}\)减少了不包含对象的框的置信度损失,论文里设置了\(\lambda_{coord}=5\)和\(\lambda_{noobj}=0.5\)。
同时,平方和误差对大框和小框的误差是一样的,这并不符合我们大框的小偏差要比小框中的小偏差小的要求。作者采取了一个取巧的做法:对框的宽高求平方根再作平方误差。
最终的损失函数如下:
\[ \begin{aligned} Loss =\ & \lambda_{coord}\sum_{i=0}^{S^2}\sum_{j=0}^B\mathbb{I}_{ij}^{obj}[(x_i-\hat{x}_i)^2+(y_i-\hat{y}_i)^2] \\ &+\lambda_{coord}\sum_{i=0}^{S^2}\sum_{j=0}^B\mathbb{I}_{ij}^{obj}\left[\left(\sqrt{w_i}-\sqrt{\hat{w}_i}\right)^2-\left(\sqrt{h_i}-\sqrt{\hat{h}_i}\right)^2\right] \\ &+\sum_{i=0}^{S^2}\sum_{j=0}^B\mathbb{I}_{ij}^{obj}(C_i-\hat{C}_i)^2 \\ &+\lambda_{noobj}\sum_{i=0}^{S^2}\sum_{j=0}^B\mathbb{I}_{ij}^{obj}(C_i-\hat{C}_i)^2 \\ &+\sum_{i=0}^{S^2}\mathbb{I}_i^{obj}\sum_{c \in classes}(p_i(c)-\hat{p}_i(c))^2 \end{aligned} \]
上式注意:
\(\mathbb{I}_i^{obj}\)为指示函数,用来指示目标对象是否在相应的单元格\(i\)内;
\(\mathbb{I}_{ij}^{obj}\)也为指示函数,用来指示第\(i\)单元格的第\(j\)个边界框是否负责预测某一对象。
该函数的前两项为模型的坐标预测损失,第三项为含有目标对象的边界框的置信度预测损失,第四项为不含目标对象的边界框的置信度预测损失。最后一项为模型的类别损失(这里注意该函数只惩罚了那些网格内有目标对象的分类损失)。
关于训练的具体参数设置可以参考原论文。作者为了避免模型过拟合,还使用了Dropout层和常见的数据扩充技术。
局限
- 每个单元格只预测2个边界框,然后每个单元格最后只取与真实标记框的IOU值最高的那个作为最后的检测框,即每个单元格最多只预测一个目标,对小目标的检测并不好;
- 虽然损失函数中采用平方根来缓解相同位置误差对大、小框产生的影响相同的情况,但其作用较小,没有从根本上解决问题;
- 模型学会了根据数据预测边界框,因此很难推广到具有新的或不同的长宽比配置的对象中,而且模型还是使用比较粗略的特征来生成边界框。
致谢
本文主要参考自一下论文: