RCNN 的 Hard Negative Mining的原理

文章目录

  • 一、为何难例挖掘? Why Hard Example Mining
  • 二、R-CNN中的hard negative mining
  • 参考博客

一、为何难例挖掘? Why Hard Example Mining

        难例挖掘与非极大值抑制 NMS 一样,都是为了解决目标检测老大难问题(样本不平衡+低召回率)及其带来的副作用。

非极大值抑制(NMS)的详解与实现
        首先,目标检测与图像分类不同,图像分类往往只有一个输出,但目标检测的输出个数却是未知的。除了Ground-Truth(标注数据)训练时,模型永远无法百分百确信自己要在一张图上预测多少物体。

     所以目标检测问题的老大难问题之一就是如何提高召回率。召回率(Recall)是模型找到所有某类目标的能力(所有标注的真实边界框有多少被预测出来了)。检测时按照是否检出边界框与边界框是否存在,可以分为下表四种情况:
RCNN 的 Hard Negative Mining的原理_第1张图片
        是所有某类物体中被检测出的概率,并由下式给出:
在这里插入图片描述
        为了提高这个值,很直观的想法是“宁肯错杀一千,绝不放过一个”。因此在目标检测中,模型往往会提出远高于实际数量的区域提议(Region Proposal,SSD等one-stage的Anchor也可以看作一种区域提议)。但此时就会遇到一个问题,因为区域提议实在太多,导致在训练时绝大部分都是负样本,这导致了大量无意义负样本的梯度“淹没”了有意义的正样本。根据Focal Loss[1]论文的统计,通常包含少量信息的“easy examples”(通常是负例),与包含有用信息的“hard examples”(正例+难负例)之比为100000:100!这导致这些简单例的损失函数值将是难例损失函数的40倍!RCNN 的 Hard Negative Mining的原理_第2张图片
        因此,为了让模型正常训练,我们必须要通过某种方法抑制大量的简单负例,挖掘所有难例的信息,这就是难例挖掘的初衷。

        难负例挖掘(Hard Negative Mining)就是在训练时,尽量多挖掘些难负例(hard negative)加入负样本集,这样会比easy negative组成的负样本集效果更好。

二、R-CNN中的hard negative mining

对于现在的我们,首先遇到难负例挖掘应该是R-CNN的论文,论文关于hard negative mining的部分引用了两篇论文:

  • Object detection with discriminatively trained part based models
  • Example-based learning for viewbased humanface detection
  • 作者:薰风初入弦
    链接:https://www.zhihu.com/question/46292829/answer/794749025
    来源:知乎
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

        Bootstrapping methods train a model with an initial subset of negative examples, and then collect negative examples that are incorrectly classified by this initial model to form a set of hard negatives. A new model is trained with the hard negative examples, and the process may be repeated a few times.
        we use the following “bootstrap” strategy that incrementally selects only those “nonface” patterns with high utility value:

  1. Start with a small set of “nonface” examples in the training database.
  2. Train the MLP classifier with the current database of examples.
  3. Run the face detector on a sequence of random images. Collect all the “nonface” patterns that the current system wrongly classifies as “faces” (see Fig. 5b).Add these “nonface” patterns to the training database as new negative examples.
  4. Return to Step 2.
    +而R-CNN中的难负例挖掘就是采用了这种自举法(bootstrap)的方法:
    +先用初始的正负样本训练分类器(此时为了平衡数据,使用的负样本也只是所有负样本的子集)
  • 用(1)训练好的分类器对样本进行分类,把其中错误分类的那些样本(hard negative)放入负样本子集,
  • 再继续训练分类器,
  • 如此反复,直到达到停止条件(比如分类器性能不再提升).
    也就是说,R-CNN的Hard Negative Mining相当于给模型定制一个错题集,在每轮训练中不断“记错题”,并把错题集加入到下一轮训练中,直到网络效果不能上升为止。
    R-CNN中Hard Negative Mining的实现代码:
    rcnn/rcnn_train.m at master · rbgirshick/rcnnLine:214开始的函数定义
    在源文件rcnn_train.m中函数 sample_negative_feature用于采样负例特征,对函数定义的关键代码稍作解释。
d.feat = rcnn_pool5_to_fcX(d.feat, opts.layer, rcnn_model); %将pool5层特征前向传播到fc7层特征
d.feat = rcnn_scale_features(d.feat, opts.feat_norm_mean); % 缩放特征norm值,具体参见源码注释
neg_ovr_thresh = 0.3;
if first_time     % 首次直接取 最大IOU < 0.3 的region作为负例,用于后面训练SVM
  for cls_id = class_ids
    I = find(d.overlap(:, cls_id) < neg_ovr_thresh);
    X_neg{cls_id} = d.feat(I,:);
    keys{cls_id} = [ind*ones(length(I),1) I];
  end
else   % 非首次负例采样
 % 先用当前更新过的SVM 预测region,即,应用SVM到 fc7的特征上,y'=w*x+b
  zs = bsxfun(@plus, d.feat*rcnn_model.detectors.W, rcnn_model.detectors.B);
  for cls_id = class_ids % 每个分类独立使用SVM
    z = zs(:, cls_id);   % 对当前分类,获取 SVM 计算值 y'
 % 下一行代码是关键
    I = find((z > caches{cls_id}.hard_thresh) & ...
             (d.overlap(:, cls_id) < neg_ovr_thresh));
% Avoid adding duplicate features
    keys_ = [ind*ones(length(I),1) I];
    if ~isempty(caches{cls_id}.keys_neg) && ~isempty(keys_)
      [~, ~, dups] = intersect(caches{cls_id}.keys_neg, keys_, 'rows');
      keep = setdiff(1:size(keys_,1), dups);
      I = I(keep);
    end
% Unique hard negatives
    X_neg{cls_id} = d.feat(I,:);
    keys{cls_id} = [ind*ones(length(I),1) I];
  end
end

上述代码片段中,非首次负例采样时,要筛选出 难负例example,需要满足两个条件:

  • 负例,即最大IOU 小于 阈值 d.overlap(:, cls_id) < neg_ovr_thresh
  • 分类错误,既然是负例,那么SVM计算值wx+b 应该小于 1
    以下图简单的回顾一下SVM:
    RCNN 的 Hard Negative Mining的原理_第3张图片位于H1和H2超平面上的实例就称为支持向量机对于y=1的正例点,有H1: wx + b =1
    对于y=-1的负例点,H2: wx + b = -1
    分类正确时应满足,
    1)wx+b>=1, if y = 1
    2)wx+b <=-1, if y = -1
    但是,SVM为了处理非严格线性可分的数据集,引入了松弛变量,于是如下图,RCNN 的 Hard Negative Mining的原理_第4张图片
    于是 只要 wx+b>-1,都可以认为是正例,只不过 wx+b越小,置信度越低。
    在inference阶段,同样是这个思路,比如rcnn_detect.m文件中
thresh = -1
scores = bsxfun(@plus, feat*rcnn_model.detectors.W, rcnn_model.detectors.B);
for i = 1:num_classes
  I = find(scores(:, i) > thresh);
  scored_boxes = cat(2, boxes(I, :), scores(I, i));
  keep = nms(scored_boxes, 0.3); 
  dets{i} = scored_boxes(keep, :);
end

参考博客

Hard negative mining
rcnn中的Hard negative mining方法是如何实现的?

你可能感兴趣的:(目标检测,深度学习,人工智能)