1.概述
误检是目标检测领域的一大难点,现有的检测算法都存在误检情况.
误检一般分成两类
1.固定特征的误检.误检对象与正样本存在相似的特征,如将集装箱误检为卡车.
2.没有规律的误检.这类误检没有什么特征可寻,具有一定的随意性,如将地面/天空误检为汽车.
对于第一类误检,我们经常采用的方法是将相应的负样本加入到训练数据集中;这一做法对于yolo系列的算法改善效果较明显【需要保证一定量的负样本】,但在实际应用中,我们发现:
通过添加负样本来优化误检问题这一策略对Rcnn系列的算法的改进效果并不明显
对于漏检问题,比如特定场景下的车辆或行人等,通过增加相应的样本数据同样能够实现较好的优化,而且这个策略对yolo系列和RCNN系列的算法都适应,即:
通过添加正样本来优化漏检问题这一策略对Rcnn系列的算法的改进效果较明显
×××说明:对于数据分布不均匀导致的明显漏检问题,添加样本能够起到较好的优化效果;但不是所有的漏检都能够通过增加样本来解决,如小目标问题、遮挡问题等,这些还是得从算法的角度进行优化;
继续我们关于rcnn误检的思考,总结起来有两个问题:
- 为什么yolo加负样本好使而rcnn却反应不佳????
- 同样是加样本,为什么rcnn对漏检的改善效果明显,但对误检的改善却不行???
关于这两个问题,我从算法的角度进行了一些解读和理解【个人观点】,其主要原因还是在于两者对正负样本的处理有所区别;anchor_base系列的目标检测算法,如yolov3、faster_rcnn等,在正负样本的处理过程中都会涉及两个重要的步骤:
- **assigner:**为每一个先验框[anchor]分配属性,即这个anchor是正样本、负样本还是忽略不计
- **sampler:**采取某种策略[如随机采样]从分配好的正负样本中选出对应数量的正负样本进行训练
关于assigner和sampler的理解以及更多正负样本的匹配策略,可以参考目标检测之正负样本详解,此处不再展开;
首先关于为什么yolo加负样本好使而rcnn却反应不佳?
我们知道,yolo和faster_rcnn在模型训练过程中会生成很多的anchor,通过assigner这一步操作,这些anchor被分成了正样本、负样本或忽略不计的样本,在正负样本中,负样本的数量往往远远超过正样本的数量,因此我们会再通过sampler操作筛选出一点数量的负样本送到网络中进行训练和学习,也就是说并不是所有的负样本都会送到网络中学习;
图像中的误检目标实际是一个负样本,如果在训练过程中关于这个误检目标的负样本anchor并没有送到网络中,那网络自然也就学不到这个背景特征,而且负样本的数量往往很多,而送去学习的负样本却很少,所以如果采用随机抽样的方法进行选取,误检目标做为负样本被送进网络学习的概率很低;
在实际训练中,关于rpn参数的设置如下【可以自己调整】:
rpn=dict(
assigner=dict(
type='MaxIoUAssigner', #采用的Assigner策略
pos_iou_thr=0.7,
neg_iou_thr=0.3,
min_pos_iou=0.2,
ignore_iof_thr=0.3),
sampler=dict(
type='RandomSampler',#采用的samplerc策略,此处为随机抽样
num=256, #送到网络学习的样本总数,包括正样本和负样本
pos_fraction=0.5, #送去训练的正样本占实际样本的比例【一般达不到】
neg_pos_ub=-1,
add_gt_as_proposals=False),
allowed_border=128,
pos_weight=-1,
debug=False),
class RandomSampler(BaseSampler):
def __init__(self,
num,
pos_fraction,
neg_pos_ub=-1,
add_gt_as_proposals=True,
**kwargs):
super(RandomSampler, self).__init__(num, pos_fraction, neg_pos_ub,
add_gt_as_proposals)
@staticmethod
def random_choice(gallery, num):
"""Random select some elements from the gallery.
It seems that Pytorch's implementation is slower than numpy so we use
numpy to randperm the indices.
"""
assert len(gallery) >= num
if isinstance