anchor设置 yolo_目标检测——YOLO-v2!

本文介绍了YOLOv2的目标检测技术,包括如何将anchor box引入检测器,以及一系列提高性能的技巧。通过BN、hi-res classifier、convolutional、new network、passthrough和multi-scale training等trick,YOLOv2在VOC 2007 test上取得了显著的提升。同时,文章探讨了anchor box的设置方法,如手工设计、kmeans聚类和网络自动学习,并讨论了确定anchor box数目和大小的问题。最后,作者分享了自己复现YOLOv2的实践经验与测试结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 目标检测——从简单的开始!进击的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上的测试结果:

d8b11082791ee35086448bee5a23eeb2.png

测试时,conf thresh设置为0.001,nms thresh设置为0.5,mAP如上图。

COCO的结果也出来了!

fa4ecf9c3327442adf450862976eb792.png

我的训练参数是:

  • 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);刷榜的话,调低点,总会有好处的,嘿嘿嘿~

推理速度上(输入图像大小是

的,conf thresh是0.001,换成0.01会更快),在我的
1660ti上,能达到 65+FPS(0.014ms);TITAN Xp上,能达到 140+(0.007ms)

老实说,从最开始写yolov2的代码,到得到了上面的结果,这中间也是花了快一年了,踩了太多的坑,真的是一步一步爬过来的,满满的辛酸泪。


在yolo-v1中,我们都是直接去预测框的参数,没有任何先验信息。

06d69e87b1f2aead43e5e91fb98fe891.png
anchor free

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

个anchor box,也称之为“先验框”,同时这种先眼眶也可以解决“语义歧义”的问题,即一个网格中落入多个物体该检测谁的问题。

c92a93d9497ba4ddc1b3246bed10b3fd.png
anchor box——先验框

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

d4c24444a7dd5d631b38ab650b6289d4.png

因此,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:

3daf509d46801dfd7522ba312bd36444.png

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

去掉最后的全连接层和最后的一个池化层,使得网络的

,然后加上anchor box(anchor box的设置和Faster RCNN一样),mAP-0.3=69.2,但召回率recall增加了7%;

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

接着,作者又从

层的卷积输出的feature map
passthrough了一下,和
feature map合并一下,再做预测。作者认为这么做可以获得更高细粒度的信息。但是,我不这么认为,因此即使是从
层获得的fmap,但为了和最后的
层的fmap合并,它必须降采样,具体操作是在
这两个维度上二等分,得到四个小块,每个小块都是

7422346f7f5e09ca6b1bdf2b95141d58.png
此图有误!!!

PS: 抱歉!!!!上面这个示意图不对,应该类似于yolov5的focal模块,还请大家原谅,有时间我会立马修改的!!!

由于经过passthrough后,通道会变成4倍,所以,要先将

层的卷积输出的feature map的512通道压缩到64通道,再去做着操作,得到256通道的,然后和
feature map在通道上用cat操作来进行拼接,得到1024+256=1280通道的feature map。

从上图显然能看出这种做法只能保住各自小块内的细粒度,但处在分割线上的物体信息就完蛋了,本身的完整性和邻域信息都被破坏,对于feature map上的一个位置

,它的通道包含了来字四个块的信息,有的信息本来不应该在这的,只是被拼接了过来,很诡异有木有。尽管文中说有了1%的mAP涨点,但真的是因为这个trick本身带来的吗?有没有可能是因为参数变多了,或者随机初始化的原因呢?我暂时存疑~至此,yolo-v2就出来了,mAP=75.4%;

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。我觉得原因就是这个“随机选择新的图像尺寸”,其中的随机性可能会带来些影响。

以上的测试结果,都是使用

的图像来得到的。而用更大的
的图像做测试,mAP则达到了78.6,打败同年ECCV的SSD工作。

到此,yolo-v2的工作就功德圆满了,一篇CVPR顶会工作就出来了。怎么样?是不是满满的trick骚操作呢?不服不行~也是从v2开始,yolo系类的风格就定下来了:trick盛宴。这么一算,我估计yolo-v5要等很久了,这期间还得积累一波好用的trick才行——v4,v5都出来了,虽然v4和v5的称号合不合适大家都众说纷纭,但就其性能来讲,很是厉害,为目标检测社区带来了很多的好用trick,总体来说都是一次很出色的增量式的改进,没有改变one-stage 的检测范式。

说完了yolo-v2的各种trick,我们再补充一下文中的location perdiction,这里我们放出来yolo-v2原文中的图像:

1f7e1c2efeebf5ff996e82aa95e1ba09.png

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

954838370392c325436c11459aad41ad.png

上面这个图,就是Faster RCNN中用到的计算bounding box 的loss。为什么会用到log函数呢?我的理解是,对于同一个anchor box

,网络输出的小的
算出的
和大的
算出的
显然差的很多,一旦网络“抽风”,输出个很大的
,那loss也会很大,很容易导致NAN,于是,通过加一个log对数函数,就可以防止这种事情,减小大小框之间的loss差距,也更好地抑制过大loss出现。

但是,

yolo-v2中虽然提到了这个,但并没有将其加入到loss地计算中。而是用log来计算label。具体来说,给定一个真实框

,和一个anchor box
,计算
:

就是我们网络要输出的量,而不是直接输出
。这么做的目的我认为还是为了缩短大小框之间的差距。相关的loss也是用MSE来做的。

在inference的时候,网络输出

,然后用指数函数就能映射回bbox的宽和高:

<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值