- 目标检测——从简单的开始!进击的YOLO!
- 目标检测——Backbone与Detection head
- 目标检测——搭建更好更快的YOLO!
- 目标检测——制作GroundTruth!开始训练!
- 目标检测——YOLOv2!
- 目标检测——YOLOv3!
- 目标检测——SlimYOLOv2
- 目标检测——TinyYOLOv3
- 目标检测——CenterNet-Lite
- 目标检测——尾声
那么在新的一章,我们就离开anchor free这个流派,让我们一起去体验一下anchor box所带来的优势吧!
之前的几章主要是讲解了如何搭建我们自己的一个yolo检测器,尽管很简单,但性能也因此不是很好。现在,让我们过渡到anchor-based的方法,本章以我复现的yolo-v2来为主,详解一下如何将anchor box加入到我们的检测器中。
放一下我复现的yolov2在voc 2007 test上的测试结果:

测试时,conf thresh设置为0.001,nms thresh设置为0.5,mAP如上图。
COCO的结果也出来了!

我的训练参数是:
- batchsize=20
- epoch=250
AP很强啊!啊哈哈哈哈!
在github上搜了一下用pytorch复现yolov2的,都没有给AP啊,所以也不是很清楚自己这个是处于什么水平。
但我还是想说,我挺强,啊哈哈哈!容我膨胀一下~
我又把conf thresh调低了一个数量级,改为0.01,mAP分别为77.0和78.0,几乎没变化。而且,速度更快,因为调高conf thresh,可以筛掉更多的样本,后续的nms处理就会更快,网络的推理时间也就会更快,在实际应用的时候,可以根据我们自己的需求来调整conf thresh这个值,不需要太低(0.001);刷榜的话,调低点,总会有好处的,嘿嘿嘿~
推理速度上(输入图像大小是
老实说,从最开始写yolov2的代码,到得到了上面的结果,这中间也是花了快一年了,踩了太多的坑,真的是一步一步爬过来的,满满的辛酸泪。
在yolo-v1中,我们都是直接去预测框的参数,没有任何先验信息。

如上图,在grid cell中,直接预测框的参数,有种“无中生有”的感觉。因此,这种方法容易带来不稳定(大家都是这么说的,但是我目前暂时还没有遇到这种所谓的“不稳定”的问题)。因此,为了避免这种“无中生有”的弊端,Faster RCNN 的RPN就介绍了一种提供先验的方法——anchor box。在每个grid cell中,设定一个anchor point(锚点),其实这个锚点没什么实际含义,它就是grid cell这个位置,颇有故弄玄虚的成分。然后在设定

有了这种先验框,我们就可以在先验信息上去做调整。

因此,anchor box会缩小训练的搜索空间,只需要去学习一些更小的增量即可,使得训练更加稳定。这就是anchor box的作用。但这自然就会引来几个问题:
- 如何设置anchor box的大小,即如何设置先验信息?
目前主要有三个做法:手工设计、kmeans聚类以及网络自动学习。
手工设计是最简单最直接的,很多任务中的先验信息事实上都是通过人来提供的,也因此这就很依赖人力了。通常的做法都是设定一系列的长宽比和面积比,然后从中生成anchor box即可。Faster RCNN、SSD、RetinaNet等大部分anchor-box based方法都是这么做的
(这里面我特意强调的是anchor-box based,而不是常用的anchor based写法,因为anchor based和anchor free会让我们误以为区别在于anchor,可实际上二者的区别在于每个anchor处的prior box,anchor就是grid cell,只要是你是在feature map上做预测,那就少不了grid cell,也就不可能把anchor给free了,现在的anchor free更准确地说是anchor-point based,把anchor anchor bo'x给free了,即这个free指的是没用prior box。都是些文字游戏~)。
kmeans聚类是从yolo-v2工作中提出来的,利用已有的数据集,以IoU做为度量便准,使用标准的kmeans或者kmeans++来聚类出若干个anchor box,很明显,这样聚类出来的anchor box肯定会效果要比上面的手工设计要好得多。在yolo-v2原文中,作者使用了这个技术后,在VOC2007test上的有了很大的涨点。不过这种kmeans方法有一个很大的问题:依赖于数据集。也就是说,如果一个数据集中的数量过少,不足以表征数据的原始分布,甚至严重有偏(比如某一类物体在数据集中都是近距离的,没有远距离的数据),那么这样聚类出来的anchor box自然也就存在很大的偏差。同时,在数据集A聚类出来的k个框,它们不一定适用于B,不过,这也不止是kmeans这个方法的弊端,整个anchor-box based方法都有这毛病,所以anchor free又回来了——既然问题不好解决,那就消除问题!因此,想用kmeans聚类得到先验框的这个技术,一定要保证数据集够大,多样性也要很好。
至于最后的网络自动学习anchor box的工作,目前还不是很多,大概从18年开始有的,我看过的一篇是《Region Proposal by Guided Anchoring》,单独接出来一个卷积层,预测几何增量,用这些增量去微调anchor box,这样,不同的输入图像,就会有不同的anchor box,而不像以前那样,anchor box固定不动。不过这也得需要我们提前设置好不错的anchorbox,不然的话,guide anchor学习压力也不小。还有旷世出的一篇MetaAnchor。这一类工作的后续进展我就没有关注了。
插个话,
最近yolov4出了,虽然不是原汁原味,但得到了官方的认可,能有人接过大旗,还是很棒的。有人说“AB大佬就是大佬,行文潇洒,不在乎外界评价行文的评论”,我觉得这没啥吧,人家本来就只是奔着技术报告去做的,然后挂arxiv,压根就没打算投哪个刊或者哪个会,又不是特立独行,不明白为啥总有人要吹这一点,很尬的……这样文笔潇洒的文章,我也能写,然后挂arxiv,顶多没人读而已,哈哈哈哈哈哈哈!抖个机灵了,不要在意~
yolov4总的来说就是继yolov3之后的又一次的trick狂欢,我们可以看到这篇报告里集结了很多优秀的模块,大家若是打比赛之类的,都可以翻开v4的论文瞧一瞧看一看,尽管很多细节在论文里是没说到的,都在代码里,这点是真随v3,难受~但我还是很喜欢这样充满干货、少故弄玄虚的文章,借鉴意义非常大!
言归正传,
总之,目前关于anchor box的设置,大体上就上面的三类。
- 如何确定anchor box 的数目,即
值如何设立?
目前,我暂时尚不太清楚这一块有什么比较好的指导建议。
下面,我们重点关注一下yolo-v2中是如何使用anchor box这一技术的。
yolo-v2可以说是yolo-v1(mAP=63.4)+一大堆tricks:

Trick-1:BN
使用了BN。mAP+2.4=65.8;
Trick-2:hi-res classifier
使用hi-res classifier。将backbone网络在ImageNet上用448的图像fine-tune一下,mAP+3.7=69.5;
Trick-3:convolutional
去掉最后的全连接层和最后的一个池化层,使得网络的
Trick-4:new network
换上了新的backbone——darknet19,mAP=69.6,相较于以前用的GoogLeNet风格的网络,darknet19速度更快,计算量更少。darknet19对标的是VGG,所以大家用VGG的时候,也可以考虑下darknet19,我自己也用pytorch复现了,相关链接在别的文章给出了。
上面4个trick用完后,yolo的mAP是69.6。接着,作者又使用了kmeans的方法来获得anchor box,替代Faster RCNN中anchor box的配置,并且使用了location perdiction方法预测bbox(后面我们会对此做介绍)。于是,一通操作后,mAP=74.4;
Trick-5:passthrough
接着,作者又从

PS: 抱歉!!!!上面这个示意图不对,应该类似于yolov5的focal模块,还请大家原谅,有时间我会立马修改的!!!
由于经过passthrough后,通道会变成4倍,所以,要先将
从上图显然能看出这种做法只能保住各自小块内的细粒度,但处在分割线上的物体信息就完蛋了,本身的完整性和邻域信息都被破坏,对于feature map上的一个位置
Trick-6:multi-scale training
最后,作者使用了multi-scale的技术,即使用320,352,384,416,...,608共10个图像尺寸去训练网络,具体来说,每迭代10次后,就会重新随机选一个尺寸出来,进行下一波训练,训练10此后,再重新随机选择。mAP也从75.4涨到了76.8(SSD开始紧张了~)。
对于这个trick,说实话,不总是work的,涨点也是有点玄学的,我有的时候训练完后,544和608反而会比416更低,但有的时候就正常work。我觉得原因就是这个“随机选择新的图像尺寸”,其中的随机性可能会带来些影响。
以上的测试结果,都是使用
到此,yolo-v2的工作就功德圆满了,一篇CVPR顶会工作就出来了。怎么样?是不是满满的trick骚操作呢?不服不行~也是从v2开始,yolo系类的风格就定下来了:trick盛宴。这么一算,我估计yolo-v5要等很久了,这期间还得积累一波好用的trick才行——v4,v5都出来了,虽然v4和v5的称号合不合适大家都众说纷纭,但就其性能来讲,很是厉害,为目标检测社区带来了很多的好用trick,总体来说都是一次很出色的增量式的改进,没有改变one-stage 的检测范式。
说完了yolo-v2的各种trick,我们再补充一下文中的location perdiction,这里我们放出来yolo-v2原文中的图像:

关于中心点,和yolo-v1没有差别,而不同的是学习bbox 的w和h。让我们先说一下Faster RCNN:

上面这个图,就是Faster RCNN中用到的计算bounding box 的loss。为什么会用到log函数呢?我的理解是,对于同一个anchor box
但是,
yolo-v2中虽然提到了这个,但并没有将其加入到loss地计算中。而是用log来计算label。具体来说,给定一个真实框
在inference的时候,网络输出