继前两篇简单的YOLO博文
上面两篇博文主要在理论上记录了YOLO版本迭代后的区别,并没有去实验源码解读,YOLO-V3-SPP主要在YOLO-V2的基础上加了很多 t r i c k trick trick,其中涉及了很多论文,这些 t r i c k trick trick非常重要,图像分类网络到目标检测网络的研究中,各种 t r i c k trick trick一直在更新迭代,不断优化使模型能够更好训练,获得更好的结果。
这次主要从以下几个方面来解读YOLO-V3-SPP
(如果无法下载以上论文,可以将以上论文链接复制到迅雷下载)
图(a)使用图像金字塔构建特征金字塔。独立地在每个图像中计算特征,这样的预测效率是非常慢的。
图(b)最近的检测系统选择仅使用单尺度特征,以便更快地检测。
图(c)重用由卷积神经网络计算的金字塔特征层次结构,就像它是具有功能化图像金字塔一样
图(d)提出了特征金字塔FPN网络结构,预测效率像图(b)和图(c)一样快速,但更准确。在这个图中,feature maps用蓝色轮廓指出,并且更宽的轮廓表示了语义上更强大的特征
作者对RPN,Fast R-CNN,Faster R-CNN网络加入了FPN结构和加入其他结构进行了对比实验
从以上表格可以看出FPN结构的特征提取能力非常强大。
这里我们主要关注FPN结构带来的指标增益,其他结构有兴趣翻看原文。
YOLO-V3-SPP会将该结构应用起来,具体看下图(该图后面会作详细解释,此图引用自B站UP霹雳啪啦Wz)
上图红色打勾处应用到了FPN网络结构,将主干网络backbone的后三个残差块输出Concatenate到三个预测器中。(三个预测器的作用后面会作解释)
IoU、GIoU、DIoU、CIoU损失函数的那点事儿
一文搞懂极大似然估计
交叉熵损失函数的理解
Focus Loss解决one-stage目标检测中正负样本不均衡的问题
常见的非极大值抑制方法:(Hard) NMS、Soft NMS、DIoU NMS
上图解释:
当我们输入feature maps进入SPP网络时,我们利用三种size将每个feature map进行划分。
(width,high为feature map的大小)
第一种size为4X4的划分,将feature map分成16个块,每块大小为(width/4, high/4)
第二种size为2X2的划分,将feature map分成4个块,每块大小为(width/2, high/2)
第三种size为1X1的划分,将整个feature map作为一块,块大小为(width, high)
三种size划分了feature map为21块,对这21块进行max pooling操作的化得到21维特征,上图从左至右表示金字塔底层堆叠到顶层的过程。这样的操作,对于输入进来的任何大小的feature maps都能得到固定大小的特征。
在实际应用时,原论文采用sliding window pooling的方式去实现,下图展示了3层SPP结构,并且给出了每层pooling的一个参数
这里的块的大小计算可参照我之前写的卷积神经网络输出的计算公式推导证明
其中注意到,第一层和第二层的滑动区域是有重叠的(重叠区域为滑动窗口的一列),而在上上副图的解释中没有提现这点,不要简单地以为就是对feature maps进行划分块的操作,实际应用是采用sliding window pooling。块与块之间是否重叠要以实际设计的pooling为准。
作者将SPP应用于4种网络结构中进行对比实验,其中金字塔结构统一为{6x6,3x3,2x2,1x1}总共50个块。
从中可以知道无论是单尺度还是多尺度的SPP结构,相对于no-SPP结构得到了非常大的提升。
更多的实验部分请看作者原论文。
在YOLO-V3-SPP中,网络结构中应用了该SPP结构:
这里SPP结构并没有像SPP论文用的步距stride,这里stride为1,padding为 f i l t e r s i z e − 1 2 \frac{filtersize-1}{2} 2filtersize−1,意味着金字塔每层的块都是相同数量的,而且这里SPP后续的层是卷积层,处理方式和SPP论文不太相同(SPP论文中,SPP结构后续跟着的层是全连接层),尽管和SPP有点结构上的差别,但主要采用了多尺度的特征融合,可以得出金字塔结构为{16X16,16X16,16X16,16X16}这里因为输入是16X16X512,Concatenate之后得到16X16X2048.
mosaic数据增强
源码解读的部分大部分都是我对每一个函数,文件进行详解,有些比较难的部分花了相当多的时间去debug分析,而且有些问题在我能力范围之外,交流的圈子比较小,没有特别全面系统,只是一个大致的解读。
就在2021-8-5的晚上,我找到了一个关于yolov3的源码解释的pdf文件,该资源来源于GiantPandaCV公众号,由于GiantPandaCV禁止任何形式的转载,传播、商用,这里分享他们的公众号:
在里面回复yolov3即可获得源码详解,我大概看了下里面的文件内容,有一个点讲得比较好,是关于yolov3中forcalloss正负样本不均匀采用偏置的处理,大概在forcalloss第3.3节,这是我一直搞不明白的一个点,看了这个文件终于明白,分享出来让大家少点掉坑
其他模块的讲解待更新
WiderPerson数据集
数据集标签格式:
第一行是对象个数
从第二行开始,第一列是类别(逻辑序号),其次为GroundTruth的坐标,xmin,ymin,xmax,ymax
归一化数据集标签后:
由于YOLOV3-SPP需要的标签数据为类别(物理序号),xcenter,ycenter,w,h(相对于原图像归一化后的值)
经过我自己编写的脚本WiderPerson_dataset.py(见附录)生成:
训练集采用7999张图片,验证集采用1000张图片。
采用预训练权重yolov3-spp-ultralytics-508
(链接: https://pan.baidu.com/s/1k5yeTZZNv8Xqf0uBXnUK-g 密码: e3k1)
训练方式:
MAP迭代趋势
可见map一直饱和在一个点,上不去。
一开始我怀疑是anchorbox原本是基于coco64生成的,于是我将coco64的anchorbox更换为WiderPerson的anchorbox(通过聚类及遗传算法生成),发现更换后效果一样,根本解决不了问题。
后来对数据集进行分析,发现严重的问题,分析如下:
我对原数据集的标签在原图上画出,发现如下问题:
原数据集包含了5个类别
而3,5这三个类别的框会和1,2,3类别的框严重重叠,导致模型的map并不理想。
下次更新会更换数据集进行训练,对于WiderPerson这种数据集yolo确实不太合适。
鉴于上述结果,我对WiderPerson数据集进行了数据清洗,只保留了前两种类别:
对原数据集的的partially-visible persons,ignore regions,crowd类标签进行清除。
相比于未经过数据清洗的WiderPerson数据集效果好了非常多,[email protected]在第133个epoch达到峰值34.23,提高了15.93,大约87%的增益,可见数据集的选择非常重要。但是随着epoch迭代次数增加,map的提升并不会有太大提高,可能跟数据集的关系有很大关系,WiderPerson的数据集中的行人密集成都过高,Yolov3-SPP并不擅长处理密集目标的检测。
霹雳吧啦Wz UP的贡献,该博主涉及图像分类到目标检测领域有颇深的研究,无私地发布学习经验,手把手教你搭建网络,啃源码。感谢大佬的奉献!