背景区域为负样本什么意思_⽬标检测正负样本区分策略和平
衡策略总结(⼀)
0 简介
正负样本定义、正负样本采样和平衡loss设本⽂抛弃⽹络具体结构,仅仅从正负样本区分和正负样本平衡策略进⾏分析,⼤体可以分为正负样本定义、正负样本采样和平衡loss设
所有涉及到的代码均以mmdetection为主。本⽂是第计三个⽅⾯,主要是⽹络预测输出和loss核⼼设计即仅仅涉及⽹络的head部分。所有涉及到的代码均以mmdetection为主
计三个⽅⾯
⼀部分,主要包括faster rcnn、libra rcnn、retinanet、ssd和yolo⼀共5篇⽂章。下⼀篇会包括anchor-free的平衡策略,以及最新改进算法。
由于本⼈⽔平有限,如果有分析不对的地⽅,欢迎指正和交流!
1 anchor-ba
1.1 two-stage
1.1.1 faster rcnn
论⽂名称:Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks
(1) head结构
faster rcnn包括两个head:rpn head和rcnn head。其结构如下:
rpn head的输出是包括分类和回归,分类是⼆分类,只区分前景和背景;回归是仅仅对于前景样本(正样本)进⾏基于anchor的变换回归。rpn head的⽬的是提取roi,然后输⼊到rcnn head部分进⾏refine。 rcnn head的输出是包括分类和回归,分类输出是类别数+1(1是考虑背景),回归是仅仅对于前景样本不考虑分类类别进⾏基于roi的变换回归,rcnn head的⽬的是对rpn提取的roi特征进⾏refine,输出精准bbox。
(2) 正负样本定义
rpn和rcnn的正负样本定义都是基于MaxIoUAssigner,只不过定义阈值不⼀样⽽已。 rpn的assigner:
rcnn的assigner:
下⾯对MaxIoUAssigner进⾏详细分析。⾸先分析原理,然后分析细节。 正负样本定义⾮常关键。MaxIoUAssigner的操作包括4个步骤:
1. ⾸先初始化时候假设每个anchor的mask都是-1,表⽰都是忽略anchor
2. 将每个anchor和所有gt的iou的最⼤Iou⼩于neg_iou_thr的anchor的mask设置为0,表⽰是负样本(背景样本)
3. 对于每个anchor,计算其和所有gt的iou,选取最⼤的iou对应的gt位置,如果其最⼤iou⼤于等于pos_iou_thr,则设置该anchor的
mask设置为1,表⽰该anchor负责预测该gt bbox,是⾼质量anchor
4. 3的设置可能会出现某些gt没有分配到对应的anchor(由于iou低于pos_iou_thr),故下⼀步对于每个gt还需要找出和最⼤iou的
anchor位置,如果其iou⼤于min_pos_iou,将该anchor的mask设置为1,表⽰该anchor负责预测对应的gt。通过本步骤,可以最
如果还是⼩于min_pos_iou,那就没办法了,只能当做忽略样本了。从这⼀步可以看⼤程度保证每个gt都有anchor负责预测,如果还是⼩于min_pos_iou,那就没办法了,只能当做忽略样本
出,3和4有部分anchor重复分配了,即当某个gt和anchor的最⼤iou⼤于等于pos_iou_thr,那肯定⼤于min_pos_iou,此时3和4步骤分配的同⼀个anchor。
从上⾯4步分析,可以发现每个gt可能和多个anchor进⾏匹配,每个anchor不可能存在和多个gt匹配的场景。在第4步中,每个gt最多只会和某⼀个anchor匹配,但是实际操作时候为了多增加⼀些正样本,通过参数gt_max_assign_all可以实现某个gt和多个anchor匹配场
景。通常第4步引⼊的都是低质量anchor,⽹络训练有时候还会带来噪声,可能还会起反作⽤。
通常第4步引⼊的都是低质量anchor,⽹络训练有时候还会带来噪声,可能还会起反作⽤。
简单总结来说就是:如果anchor和gt的iou低于neg_iou_thr的,那就是负样本,其应该包括⼤量数⽬;如果某个anchor和其中⼀个gt的最⼤iou⼤于pos_iou_thr,那么该anchor就负责对应的gt;如果某个gt和所有anchor的iou中最⼤的iou会⼩于pos_iou_thr,但是⼤于
min_pos_iou,则依然将该anchor负责对应的gt;其余的anchor全部当做忽略区域,不计算梯度。该最⼤分配策略,可以尽最⼤程度的保证每个gt都有合适的⾼质量anchor进⾏负责预测,
下⾯结合代码进⾏分析:主要就是assign_wrt_overlaps函数,核⼼操作和注释如下:
当设置lf.gt_max_assign_all=True时候是可能出现第4步的某个gt和多个anchor匹配场景,默认参数就是通过代码可以发现,当设置lf.gt_max_assign_all=True时候是可能出现第4步的某个gt和多个anchor匹配场景,默认参数就是True。
由于rcnn head预测值是rpn head的refine,故rcnn head⾯对的anchor(其实就是rpn输出的roi)和gt的iou会⾼于rpn head部
分,anchor质量更⾼,故min_pos_iou阈值设置的⽐较⾼,由于pos_iou_thr和neg_iou_thr设置都是0.5,那么忽略区域那就是没有了,因为rcnn head⾯对的都是⾼质量样本,不应该还存在忽略区域。
(3) 正负样本采样
解决办法可以通过正负样本采样或者loss上⾯⼀定程度解步骤2可以区分正负和忽略样本,但是依然存在⼤量的正负样本不平衡问题,解决办法可以通过正负样本采样或者loss上⾯⼀定程度解决,faster rcnn默认是需要进⾏正负样本采样的。 rpn head和rcnn head的采样器都⽐较简单,就是随机采样,阈值不⼀样⽽已。 rpn head采样器:
rcnn head采样器:
num表⽰采样后样本总数,包括正负和忽略样本,pos_fraction表⽰其中的正样本⽐例。add_gt_as_proposals是为了放在正样本太少⽽加⼊的,可以保证前期收敛更快、更稳定,属于技巧。neg_pos_ub表⽰正负样本⽐例,⽤于确定负样本采样个数上界,例如我打算采样1000个样本,正样本打算采样500个,但是可能实际正样本才200个,那么正样本实际上只能采样200个,如果设置neg_pos_ub=-1,那么就会对负样本采样800个,⽤于凑⾜1000个,但是如果设置为neg_pos_ub⽐例,例如1.5,那么负样本最多采样200x1.5=300个,最终返回的样本实际上不够1000个。默认情况neg_pos_ub=-1。 由于rcnn head的输⼊是rpn head的输出,在⽹络训练前期,rpn ⽆法输出⼤量⾼质量样本,故为了平衡和稳定rcnn训练过程,通常会对rcnn head部分添加gt作为proposal。 其代码⾮常简单:
对正负样本单独进⾏随机采样就⾏,如果不够就全部保留。
由于原始faster rcnn采⽤的loss是ce和SmoothL1Loss,不存在loss层⾯解决正负样本不平衡问题,故不需要分析loss。
由于原始faster rcnn采⽤的loss是ce和SmoothL1Loss,不存在loss层⾯解决正负样本不平衡问题,故不需要分析loss
1.1.2 libra rcnn
论⽂名称:Libra R-CNN: Towards Balanced Learning for Object Detection
libra主要是分析训练过程中的不平衡问题,提出了对应的解决⽅案。由于libra rcnn的head部分和正负样本定义没有修改,故不再分析,仅仅分析正负样本采样和平衡loss设计部分。
(1) 正负样本采样
注意libra rcnn的正负样本采样规则修改仅仅是对于rcnn⽽⾔,对于rpn head没有任何修改,依然是随机采样器。原因是作者的主要⽬的是为了涨点mAP,作者认为rpn涨⼏个点对最终bbox 预测map没有多⼤帮助,因为主要是靠rcnn部分进⾏回归预测才能得到⽐较好的mAP。 其参数如下:
主要看IoUBalancedNegSampler部分即可。仅仅作⽤于负样本(iou=0~0.5之间)。作者认为样本级别的随机采样会带来样本不平衡,由于负样本本⾝iou的不平衡,当采⽤随机采样后,会出现难负(iou 0.5附近)和易负(iou接近0)样本不平衡采样,导致后⾯性能不好。作者发现了如果是随机采样的话,随机采样到的样本超过70%都是在IoU在0到0.05之间的,都是易学习负样本,作者觉得是不科学的,⽽实际统计得到的事实是60%的hard negative都落在IoU⼤于0.05的地⽅,但是随机采样只提供了30%,实在是太少了。最常⽤的解决难易样本不平衡问题的解决办法就是ohem,基于Loss排序来采样难负样本,但是作者分析,(1) 这种⽅法对噪⾳数据会⽐较敏感,因为错误样本loss⾼;
(2) 参数⽐较难调。所以作者提出了IoU-balanced Sampling,如下所⽰:
可以看出,随机采样效果最不好,⽽iou balanced sampling操作会尽量保证各个iou区间内都会采样到。 由于该操作⽐较简单,就不贴论⽂公式了。核⼼操作是对负样本按照iou划分k个区间,每个区间再进⾏随机采样,保证易学习负样本和难负样本⽐例尽量平衡,实验表明对K不敏感,作者设置的是3。
具体做法是对所有负样本计算和gt的iou,并且划分K个区间后,在每个区间内均匀采样就可以了。假设分成三个区间,我想总共取9个,第⼀个区间有20个候选框,第⼆个区间有10个,第三个区间有5个,那这三个区间的采样概率就是
9/(3x20),9/(3x10),9/(3x5),这样的概率就能在三个区间分别都取3个,因为区间内候选框多,它被选中的概率⼩,最终体现各个区间都选这么多框。
实际代码做法是:⾸先按照iou分成k个区间,先尝试在不同区间进⾏随机采样采相同多数⽬的样本,如果不够就全部采样;进⾏⼀轮后,实际代码做法是
如果样本数不够,再剩下的样本中均匀随机采样。例如假设总共有1000个候选负样本(区间1:800个,区间2:120个,区间3:80个),分为3个区间,总共想取333个,那么理论上每个区间是111个,⾸先第⼀次在不同区间均匀采样,此时区间1可以采样得到111个,区间2也可以得到111个,区间3不够,所以全部保留;然后不够的样本数,在剩下的(800-111)+(120-111)+0个⾥⾯随机取31个,最终补齐333个。 核⼼代码如下: