论文阅读:(CVPR 2020 Oral)针对长尾分布识别任务的双边分支网络BBN

目录

      • 引言
      • 论文方法介绍
      • 论文效果展示
      • 参考资料

引言

  • 因为之前相关研究工作涉及到细粒度图像分类任务,这就难免会遇到数据集的长尾分布问题。
  • 数据的长尾分布指的是数据集中某些类下图像数据特别多,而某些类图像数据特别少,如果从图像上来看的话,横轴为类别数目,纵轴为每一类下对应的图像数目( 如BBN所画示意图),则该数据集有着长长的尾巴(long-tail),因此形象称为长尾分布。
    论文阅读:(CVPR 2020 Oral)针对长尾分布识别任务的双边分支网络BBN_第1张图片
  • 本次介绍的论文为旷世南京研究院的成果,初次看到本文作者,看到了魏秀参老师,很是亲切。魏老师做细粒度图像分类方面的工作很多,很优秀。该论文为2020年CVPR会议的Oral。这是很大的殊荣,同时也表达了对该篇工作的认可。

论文方法介绍

论文工作主要有四个:

  • 探索了长尾分布下类型再平衡机制(re-balancing)的作用。其中,re-balancing主要包括两个方面,例如,re-weighting (RW)和re-sampling (RS)。关于这两个常用的类别平衡方法,等着我再写一篇专题,再来介绍吧。下面主要介绍一下论文中讨论的情况。
    • 作者将神经网络的训练过程分为了两个阶段,第一阶段是图像特征学习,在文中指的是学习除神经网络后面分类器层之外前面的神经网路;第二阶段是分类器学习,指的是固定第一阶段学到了提取图像特征的网络权重,从头开始学习分类器层的权重参数。
    • 关于探索不同再平衡方法效果的结果图如下,其中横轴为第一阶段的图像特征学习,纵轴为分类器学习,图中数字为分类错误率,CE为只采用交叉熵损失(Cross Entropy)学习,RW为Re-Weghting,重新赋予不同类别的不同权重,RS为Re-Sampling,重新对数据集采样。
    • 从上往下看结果图,可以看到在固定了第一阶段图像特征学习情况下,RS/RW都比CE要好,这就说明再平衡机制可以提升分类器的性能
    • 但是如果从左向右看,在固定了分类器学习情况下,CE都要比RW/RS要好,这就说明再平衡机制会损坏图像特征学习的性能
      论文阅读:(CVPR 2020 Oral)针对长尾分布识别任务的双边分支网络BBN_第2张图片
  • 在重采样分支中,提出了反采样方法, 对于反向采样器来说,每个类的采样可能性与其样本量的倒数成正比,即一个类中的样本越多,该类的采样可能性就越小。
    • 具体来讲,定义第 i i i类的样本数为 N i N_i Ni,所有类中,具有最多的样本的定义为 N m a x N_{max} Nmax。可以分为三步,完成反采样。
    1. 按照以下公式,计算第 i i i类的类别概率 P i P_i Pi
      P i = w i ∑ j = 1 C w j P_{i}=\frac{w_i }{\sum_{j=1}^{C}{w_j}} Pi=j=1Cwjwi,
      其中, w i = N m a x N i w_i = \frac{N_{max}}{N_i} wi=NiNmax
    2. 按照 P i P_i Pi的值,随机采样一个类
    3. 均匀地从第 i i i类中提取一个样本并进行替换。
    • 对应源码(选取主要代码段):
      def __getitem__(self, index):
      """
      Args:
          index (int): Index
      
      Returns:
          tuple: (image, target) where target is index of the target class.
      """
      if self.cfg.TRAIN.SAMPLER.TYPE == "weighted sampler" and self.train:
          assert self.cfg.TRAIN.SAMPLER.WEIGHTED_SAMPLER.TYPE in ["balance", "reverse"]
      
          if  self.cfg.TRAIN.SAMPLER.WEIGHTED_SAMPLER.TYPE == "balance":
              sample_class = random.randint(0, self.cls_num - 1)
      
          elif self.cfg.TRAIN.SAMPLER.WEIGHTED_SAMPLER.TYPE == "reverse":
              sample_class = self.sample_class_index_by_weight()
      # ================================================
      def sample_class_index_by_weight(self):
            rand_number, now_sum = random.random() * self.sum_weight, 0
              for i in range(self.cls_num):
                  now_sum += self.class_weight[i]
                  if rand_number <= now_sum:  # 这里暂时没有看明白
                      return i
      # ================================================
       def get_weight(self, annotations, num_classes):
      	   num_list = [0] * num_classes
      	   cat_list = []
      	   # Count the number of each category.
      	   for anno in annotations:
      	       category_id = anno["category_id"]
      	       num_list[category_id] += 1
      	       cat_list.append(category_id)
      	   max_num = max(num_list)
      	   class_weight = [max_num / i for i in num_list]
      	   sum_weight = sum(class_weight)
      	   return class_weight, sum_weight
      
  • 提出了BBN模型(Bilateral-Branch Network)来顾及网络前部分提取图形特征学习和后面的全连接层的分类器学习。
    • 整体网络结构图如下,整体来看网络结构清晰,简单有效。
    • 关于具体网络结构源码和普通CNN结构一样,这里就不再给出相关源码。
      论文阅读:(CVPR 2020 Oral)针对长尾分布识别任务的双边分支网络BBN_第3张图片
  • 提出了一种新的累积学习策略,这类似于一种注意力机制,通过动态调节 α \alpha α,来控制不同阶段下,模型的注意力关注那个。
    • 虽然图像特征学习和分类器学习应该有着同等地位,但是BBN在学习过程中从关注图像特征学习逐渐到分类器学习,这样可以保证在训练过程中,不同目标的两个分支都能在整个训练过程中不断更新,这样可以避免两个过程中的相互影响。
    • 关于 α \alpha α的动态调节公式为:
      α = 1 − ( T T m a x ) 2 , \alpha = 1 - (\frac{T}{T_{max}})^2, α=1(TmaxT)2
      其中 T T T为当前训练代数, T m a x T_{max} Tmax为总体训练代数。
    • 简单画出草图为以下:论文阅读:(CVPR 2020 Oral)针对长尾分布识别任务的双边分支网络BBN_第4张图片
    • 对应源码(选取主要代码段):
    def bbn_mix(self, model, criterion, image, label, meta, **kwargs):
    
       image_a, image_b = image.to(self.device), meta["sample_image"].to(self.device)
       label_a, label_b = label.to(self.device), meta["sample_label"].to(self.device)
    
       feature_a, feature_b = (
           model(image_a, feature_cb=True),
           model(image_b, feature_rb=True),
       )
    
       l = 1 - ((self.epoch - 1) / self.div_epoch) ** 2  # parabolic decay
    
       mixed_feature = 2 * torch.cat((l * feature_a, (1-l) * feature_b), dim=1)
       output = model(mixed_feature, classifier_flag=True)
       loss = l * criterion(output, label_a) + (1 - l) * criterion(output, label_b)
    
       now_result = torch.argmax(self.func(output), 1)
       now_acc = (
               l * accuracy(now_result.cpu().numpy(), label_a.cpu().numpy())[0]
               + (1 - l) * accuracy(now_result.cpu().numpy(), label_b.cpu().numpy())[0]
       )
    

论文效果展示

  • 论文中探索了很多结果,这里就不一一展示,只挑选比较有意义的结果。
  • 探索了在不平衡数据集上不同采样方法的效果比较:
    论文阅读:(CVPR 2020 Oral)针对长尾分布识别任务的双边分支网络BBN_第5张图片
  • 探索了不同的动态调整 α \alpha α的方法:
    论文阅读:(CVPR 2020 Oral)针对长尾分布识别任务的双边分支网络BBN_第6张图片

参考资料

  • 旷视提双边分支网络BBN:攻坚长尾分布的现实世界任务 | CVPR 2020 Oral
  • CVPR 2020 Oral | 旷视研究院提出双边分支网络BBN:攻坚长尾分布的现实世界任务
  • PyTorch源码
  • 论文PDF

你可能感兴趣的:(论文)