目标检测系列:
目标检测(object detection)系列(一) R-CNN:CNN目标检测的开山之作
目标检测(object detection)系列(二) SPP-Net:让卷积计算可以共享
目标检测(object detection)系列(三) Fast R-CNN:end-to-end的愉快训练
目标检测(object detection)系列(四) Faster R-CNN:有RPN的Fast R-CNN
目标检测(object detection)系列(五) YOLO:目标检测的另一种打开方式
目标检测(object detection)系列(六) SSD:兼顾效率和准确性
目标检测(object detection)系列(七) R-FCN:位置敏感的Faster R-CNN
目标检测(object detection)系列(八) YOLOv2:更好,更快,更强
目标检测(object detection)系列(九) YOLOv3:取百家所长成一家之言
目标检测(object detection)系列(十) FPN:用特征金字塔引入多尺度
目标检测(object detection)系列(十一) RetinaNet:one-stage检测器巅峰之作
目标检测(object detection)系列(十二) CornerNet:anchor free的开端
目标检测(object detection)系列(十三) CenterNet:no Anchor,no NMS
目标检测(object detection)系列(十四)FCOS:用图像分割处理目标检测
目标检测扩展系列:
目标检测(object detection)扩展系列(一) Selective Search:选择性搜索算法
目标检测(object detection)扩展系列(二) OHEM:在线难例挖掘
目标检测(object detection)扩展系列(三) Faster R-CNN,YOLO,SSD,YOLOv2,YOLOv3在损失函数上的区别
前言:取百家所长成一家之言
取百家所长成一家之言是一句书面意思上绝对褒义的话,形容一个论文却有些许的尴尬,但是YOLOv3确实是这样,没什么大的改动和创新点,而是融合借鉴了很多在其他的方案,最后效果还是很好的,文章中自己也提到了:“We made a bunch of little design changes to make it better”,YOLOv3的论文是《YOLOv3: An Incremental Improvement》,真的是个很低调的题目,没有Better, Faster和Stronger。╮( ̄▽  ̄)╭而且论文的篇幅比较短,一共只有6页。
YOLOv3原理
设计理念
相比于YOLOv2,YOLOv3主要有下面几个改动:
- YOLOv3的主干网络又变了,设计了基础网络结构Darknet-53;
- YOLOv3终于加入多层分支了,一共拉取了三层;
- YOLOv3选择了更多的archor box先验;
- YOLOv3类别损失换了,由SoftMax换成了Logistic。
更多细节的东西我们下面说明。
网络结构
首先,YOLOv3重新设计了主干网络,Darknet-53,就是下面这个结构:
这是一个引入了残差直连的主干网络,最左侧的一列数字是残差单元的个数,最右侧的output是特征图的尺寸,这个结构和ResNet50很像,但是它没有用瓶颈层设计,也不是朴素的残差单元设计,而是每个残差单元里有2个卷积,不是三个,第一个卷积层是一个1times1 的卷积,第二个是3times3 的卷积,每进一次残差单元,第一个卷积总是会把通道先降下来,然后第二个再负责升上去,以降低网络的计算量。此外,这个网络除了最后的全局平均池化外,再没有别的池化层,下采样都靠stride=2的卷积来完成。
上面这个图是YOLOv2采用的Darknet-19,可以看出来,它其实是加了1times1 卷积的VGG结构。这是两版YOLO的backbone的区别。
上图是各个主干网络在准确率和效率方面的对比,首先准确率没啥说的就是Top-1和Top-5,这两个指标上Darknet-53都是优于ResNet-101的,并非常接近于ResNet-152,奇怪的是在后面,YOLOv3用了三个指标说明Darknet-53好,分别是Bn Ops,BFLOP/s和FPS,一般情况下分类网络都只用一个指标说明网络的计算量那就是FLOPs或MFLOPs,但是YOLOv3用了三个。
下面分别说明一下,在论文中Bn Ops和BFLOP/s的解释分别是“billions of operations”和“billion floating point operations per second”,分别代表着网络一个需要多少个10亿次的计算以及这个结构在同一平台下每秒可以跑多少次10亿次计算,这两个值就决定了FPS,这个硬件平台是Titan x。
而且,这里的Bn Ops的计算方式和常规操作不一样,一般情况下网络去统计FLOPs是不算加操作的,所以在ResNet的原始论文中,ResNet-101和ResNet-152的算力分别是7.6times10^9 FLOPs和11.3times10^9 FLOPs,折算到Bn Ops应该分别是7.6Bn Ops和11.3Bn Ops,但是上表中给出的是19.7Bn Ops和29.4Bn Ops,这是因为计算的时候包含了加操作,而Darknet-53是18.7Bn Ops。
这还不算完,YOLOv3还统计了BFLOP/s,就是这结构实际跑在平台上效率如何,因为ResNet-101和ResNet-152的层很多,数据在层之间需要传输,所以实际跑出来ResNet-101和ResNet-152的BFLOP/s要低Darknet-53很多。
最后,FPS实际体现了这个结构的速度,Darknet-53与ResNet-101的计算量是相似的,但是由于BFLOP/s更高,所以Darknet-53比ResNet-101快1.5倍,Darknet-53计算量本来就比ResNet-152低,BFLOP/s还要更高,所以快了2倍。
论文最后提到,“ResNets have just way too many layers and aren’t very efficient”,YOLOv3吸取了ResNet的长处,最后还不忘黑它一下。╮( ̄▽  ̄)╭
多层分支
多层拉取分支的策略终于在YOLOv3中用到了,也可以说这其实是一种FPN结果,在YOLOv2中,多层特征就已经被使用了,但是使用的方式并不直接,它是一种不同层的特征图拼接,让最后一层具有不同的特征,具体可以参考之前的文章。可以理解为它是一种特征的融合,而不是多层分支。
那么这种多层特征融合的方式和多层拉取分支的方式冲突吗?显然是不冲突的,它们可以并存,于是YOLOv3就这样做了,可以说YOLOv3在这方面结合了YOLOv2和SSD。
上面这张图就是YOLOv3的结构图,其中ResX代表着残差组内单元的个数是X,ConvBA是卷积 BN 激活,BN在YOLOv2的时候就有了。YOLOv3的分支有三个,分别是第三个残差组后面的卷积输出,第四个残差组后面的卷积输出和最后的卷积输出,当输入时416时,它们的特征图尺寸分别是52times52times256 ,26times26times512 和13times13times1204 。
这样一来,分支有了,那么怎么做融合,YOLOv2采用的奇怪的reshape方式,就是维度不匹配就硬凑,这会造成特征图的空间信息被破坏掉了,所以YOLOv3使用的是Upsamlpe,不在用reshape,后面的分支输出特征图,会上采样2倍,刚好可以匹配前一层的维度,然后同样是做拼接操作。
在这以后,几层卷积进一步提取特征,然后控制通道数到255,三层分支都是255。255这个数又和之前不同了,YOLO是90,YOLOv2是125。
首先的区别是数据集换了,现在的目标检测任务主流数据集不再是VOC,而是COCO,COCO有80个类别,其次由于YOLOv3有三层,所以每一层的参考框变少了,从5个变成了3个,根据之前的计算方式:255=3times(80 4 1)
YOLOv3的anchor box
anchor box有两部分内容,分别是:
- 先验框怎么编码ground truth
- 先验框怎么选取
编码的方式,YOLOv3和YOLOv2是一致的,这里不再重复了,剩下的先验框的选取,YOLOv3采用了和SSD一致的策略,不同的分支有不同的尺度,随着网络的加深,特征图逐渐变小,负责预测的先验框尺度逐渐变大,因为小目标在大的特征图上更容易体现,同时先验框的选择还是使用的k-means
最终,通过三个分支和每个分支上三个archor box,YOLOv3一共可以产生的预测个数为:
而YOLO最终总共只有49个类别结果和98个预测框,YOLOv2有845个,SDD有8732个,YOLOv3比它们都要多。
YOLOv3的损失函数
YOLOv3的另一个关键的改动是在损失函数,类别损失由Softmax换成了Logistic,这个改变其实个人感觉很牵强,论文给出的两点解释:
- 对于一个好的结果,softmax不是必须的,用logistic也行;
- 很多其他的任务和数据集,存在多标签的情况,比如Open Image,类别的标注有层次结构,比如“Person”和“Wonmen”是一个多标签。 怎么说呢,首先COCO列表标注没有多标签,softmax和logistic的在COCO上的消融实验论文没给,怎么说它们结果相当呢?其次,YOLOv3在Open Image的实验并没有做,这样一来,上面两个理由站不住脚啊。 但是,既然用都用了,就顺便解释下多标签的分类问题,多标签顾名思义就是一张图有多种属性,比如人脸属性问题,有性别,年龄,种族,眼镜,口罩等,每个属性是独立的,也就是一张脸这五个属性都要预测。 处理这个问题的时候,一个最简单粗暴的方法就是,有几个标签就拉几个分支,分支独立计算损失,最后把损失加起来并乘上权重一起训练。 但是多标签分类还有特殊的情况,我们先把年龄和种族移出去,剩下的性别只预测男女,眼镜只预测戴不戴,口罩也只预测戴不戴,那这个三个任务就都变成了2分类,所有的标签都是二分类标签,是多标签分类中的一个特例。这个情况有一个最经典的数据集是CelebA。由于都是2分类问题,Logistic回归就能排上用场了,因为可以用一个维度的输出是否大于0.5,决定类别应该属于哪一类。 此外,输出层的每一个维度都应该经过sigmoid函数做压缩,把输出控制在(0,1)之间,然后就可以用二值交叉熵做loss了,这个loss应该是所以的标签类别都做一次,然后加起来。所以,对于COCO的话,YOLOv3是把80类的单标签分类问题硬生生的转化成了80个二分类标签。 剩下的东西就和YOLOv2一样了。
YOLOv3性能评价
定量实验
YOLOv3给了两套评价标准下的结果,一个是按照IOU=0.5算出来的mAP-50,一个事按照COCO标准算出来的mAP,COCO要计算IOU从0.5到0.95之间间隔为0.05的10个平均值。在第一个标准上,YOLOv3表现很惊艳,只用1/4的耗时,就取得了RetinaNet-101-800的效果,但是按照第二个标准,YOLOv3就要差一些。最后YOLOv3论文吐槽说“ humans have a hard time distinguishing an IOU of .3 from .5!”
定性分析
YOLOv3为什么对小目标检测效果有提升?
- YOLOv3换了性能更强的主干网络;
- YOLOv3拉取了多层分支,而且最大的特征图达到了52times52 ,这让小目标更容易被检测到;
- YOLOv3的多层分支存在上一层的特征融合,用upsample替换了reshape,让特征在channel上没有形变;
- YOLOv3的多层分支后还有多层卷积,缓解了特征图尺寸足够,但是语义信息不足的情况;
- YOLOv3的archor输出达到了106747个。