涨点神器!重新标记ImageNet,让CNN涨点明显!代码已开源

点击上方“CVer”,选择加"星标"置顶

重磅干货,第一时间送达

涨点神器!重新标记ImageNet,让CNN涨点明显!代码已开源_第1张图片

本文提出ReLabel重新标记策略和LabelPooling训练策略,可让现有CNN涨点明显!如使得ResNet-50在ImageNet上Acc可以达到78.9% !
作者单位:NAVER AI Lab

论文地址:https://arxiv.org/abs/2101.05022

github地址:https://github.com/naver-ai/relabel_imagenet

1 问题发现

ImageNet可以说是最受欢迎的图像分类基准,但它也是label noise水平很高的基准。最近的研究表明,尽管被认为是单标签基准,但许多样本仍包含多个类别。因此,本文提出了将ImageNet预测转变为多标签任务的方法,因此每个图像都使用详尽的多标签标注。但是,由于标注成本高昂,所以没有固定训练集以供使用。

本文作者认为,单标签标注和有效多标签图像之间的不匹配在采用Random crops的训练中同样存在问题。如下图所示,使用单标签注释,图像的随机裁剪可能包含与Ground Truth情况完全不同的目标对象,从而在训练过程中引入噪声甚至错误的标签。

涨点神器!重新标记ImageNet,让CNN涨点明显!代码已开源_第2张图片

同时Random crops增强不仅对多目标类图像产生监督噪声。即使对于只有一个对象类的图像Random crops通常也有可能不包含前景对象。如下图所示,在标准ImageNet训练设置下有8%的Random crops与Ground Truth没有重叠。只有23.5%的Random crops在使用Ground Truth Box时具有大于50%的IoU。因此在ImageNet上训练模型不可避免地会存在大量的噪声干扰。

涨点神器!重新标记ImageNet,让CNN涨点明显!代码已开源_第3张图片

因此,本文提出了一种Re-Label策略,在ImageNet训练集上获得像素级标签 ,即Localized Multi-Labels。方法是使用在外部训练数据上训练的强分类器来生成这些标签。然后在最后的池化层之前的预测已经被使用。

本文还提出了一种新的基于密集标签训练分类器的训练方案LabelPooling。对于每个Random crops样本,通过计算Random crops的标签分数来计算多标签的Ground Truth。而ReLabel只需要一次计算即可为每个数据集生成标签映射,而不像知识蒸馏那样,每次训练迭代需要一个前向传递来生成监督信息。

实验结果表明,使用Localized Multi-Labels,ResNet-50在ImageNet上的Top-1分类精度达到78.9%,而通过CutMix正则化可以进一步提高到80.2%。实验结果显示,使用Localized Multi-labels训练的模型在迁移学习到目标检测和实例分割任务都有比较明显的提升。

2 相关工作

2.1 ImageNet上的Label问题

ImageNet俨然已经成为图像分类器的标准基准,而方法的优劣则取决于这些方法在这个基准上的性能。因此,基准本身的可靠性已成为仔细研究和分析的主题。

与许多其他数据集一样,ImageNet包含了很多标签噪声。在ImageNet上最持久的标签错误类型之一便是错误的单一标签,指的是一个图像中存在多个类别而只有一个类别被注释的情况。这样的错误很普遍,因为ImageNet包含许多带有多个类的图像。

Shankar等人已经为错误的单一标签确定了3个子类别:

  • 1)一幅图像包含多个对象类;

  • 2)存在多个同义或分层的标签,包括其他的标签;

  • 3)一幅图像固有的模糊性使得多个标签可能存在。

这些研究将验证集标签细化为多标签,建立了有效多标签图像的真实、公正的评价模型。然而,有部分学者工作的重点只是验证,而不是训练。也有学者在方法引入了一种清理方案,通过用强分类器的预测来验证它们标签的正确性,从而删除带有潜在错误标签的训练样本。

本文的工作重点是ImageNet培训标签的清理策略。利用强分类器来清理训练标签。本文纠正了错误的标签,而不是删除。同时本文的标签也是按区域给出的。本文方案也得到了更好的性能。

2.2 知识蒸馏

知识蒸馏则是利用教师网络产生的监督信息。同时知识蒸馏的研究也丰富了教师模型的选择,如特征映射蒸馏、关系蒸馏、集合蒸馏或迭代自蒸馏。

虽然这些研究追求更强的监督形式,但是这些方法比较繁重而复杂略显不切实际。

由于加入了Random crops数据增广,Teacher Model每次训练迭代都非常的繁琐而复杂。如下表所示LabelPooling的相似之处在于,该模型是在机器监督下训练的,但效率更高。

涨点神器!重新标记ImageNet,让CNN涨点明显!代码已开源_第4张图片

LabelPooling使用预先计算的标签映射来监督模型,而不是在训练期间通过Teacher Model为每一个Random crops动态生成标签。

2.3 ImageNet的训练Tricks

数据增强是一种简单而强大的ImageNet训练策略。传统的数据增强方法包括Random crops、Flipping和Color jittering。Random crops即在图像中根据Random crops坐标进行裁剪然后将其调整为固定大小。

本文的工作考虑了Localized Multi-Labels,使对每个Random crops的监管更加合理。对于训练分类器还有一些额外的训练技巧与ReLabel的训练数据正交。展示了这些技巧可以与ReLabel相结合以提高性能。

3 方法原理

3.1 Re-labeling ImageNet

本文实验注意到,尽管在ImageNet上使用单标签监督(softmax交叉熵损失)训练Machine Annotators,它们仍然倾向于对多类别图像进行多标签预测。作为说明,考虑具有两个正确类别0和1的图像x。

假设在训练过程中模型同时输入带有噪声的标签 和 。然后,交叉熵损失为:

化简后为:

其中, 是指index=c时的标签为1的One-Hot编码, 是 的预测向量。注意,函数 在 时取的最小值。因此,模型通过预测 使损失最小化。

因此,如果数据集中存在大量的标签噪声,使用单标签交叉熵损失训练的模型会倾向于预测多标签输出。

从分类器中获取标签的另一个好处是可以提取特定于位置的标签

涨点神器!重新标记ImageNet,让CNN涨点明显!代码已开源_第5张图片

本文方法去掉分类器的全局平均池化层,将后面的FC层变成1×1的卷积层,从而将分类器变成一个全卷积网络。模型的输出变成 。然后使用输出的 作为标签映射输出 。

本文利用EfficientNet-L2作为Machine Annotators分类器,其输入大小为475×475。对于所有训练图像,将它们调整为475×475而不进行裁剪,并通过前向传播来生成标签Maps。标签Map的Spatial大小为 ,d通道数量为5504个,C=类别数量为1000。

涨点神器!重新标记ImageNet,让CNN涨点明显!代码已开源_第6张图片

在上图中给出了几个标签映射的例子。在 标签Map中,这里只显示了分类器前2个类别的2个heatmap。heatmap为 ,其中 是前2名之一。如示例所示,top-1和top-2 heatmap位于每个物体的位置上。

import os

import torch
import torch.distributed
import torch.nn as nn
import torchvision
from torchvision.ops import roi_align
from torchvision.transforms import functional as torchvision_F


def get_labelmaps(label_maps_topk, num_batches):
    label_maps_topk_sizes = label_maps_topk[0].size()

    label_maps = torch.zeros([num_batches, 1000, label_maps_topk_sizes[2],
                              label_maps_topk_sizes[3]])
    for _label_map, _label_topk in zip(label_maps, label_maps_topk):
        _label_map = _label_map.scatter_(
            0,
            _label_topk[1][:, :, :].long(),
            _label_topk[0][:, :, :]
        )
    label_maps = label_maps.cuda()
    return label_maps


def get_relabel(label_maps, batch_coords, num_batches):
    target_relabel = roi_align(
        input=label_maps,
        boxes=torch.cat(
            [torch.arange(num_batches).view(num_batches,
                                            1).float().cuda(),
             batch_coords.float() * label_maps.size(3) - 0.5], 1),
        output_size=(1, 1))
    target_relabel = torch.nn.functional.softmax(target_relabel.squeeze(), 1)
    return target_relabel


class ComposeWithCoords(torchvision.transforms.Compose):
    def __init__(self, **kwargs):
        super(ComposeWithCoords, self).__init__(**kwargs)

    def __call__(self, img):
        coords = None
        for t in self.transforms:
            if type(t).__name__ == 'RandomResizedCropWithCoords':
                img, coords = t(img)
            elif type(t).__name__ == 'RandomCropWithCoords':
                img, coords = t(img)
            elif type(t).__name__ == 'RandomHorizontalFlipWithCoords':
                img, coords = t(img, coords)
            else:
                img = t(img)
        return img, coords


class RandomResizedCropWithCoords(torchvision.transforms.RandomResizedCrop):
    def __init__(self, **kwargs):
        super(RandomResizedCropWithCoords, self).__init__(**kwargs)

    def __call__(self, img):
        i, j, h, w = self.get_params(img, self.scale, self.ratio)
        coords = (i / img.size[1],
                  j / img.size[0],
                  h / img.size[1],
                  w / img.size[0])
        return torchvision_F.resized_crop(img, i, j, h, w, self.size,
                                 self.interpolation), coords


class ImageFolderWithCoordsAndLabelMap(torchvision.datasets.ImageFolder):
    def __init__(self, **kwargs):
        self.relabel_root = kwargs['relabel_root']
        kwargs.pop('relabel_root')
        super(ImageFolderWithCoordsAndLabelMap, self).__init__(**kwargs)

    def __getitem__(self, index):
        path, target = self.samples[index]
        score_path = os.path.join(
            self.relabel_root,
            '/'.join(path.split('/')[-2:]).split('.')[0] + '.pt')

        sample = self.loader(path)
        if self.transform is not None:
            sample, coords = self.transform(sample)
        else:
            coords = None
        if self.target_transform is not None:
            target = self.target_transform(target)

        score_maps = torch.load(score_path)

        return sample, target, coords, score_maps

3.2 LabelPooling for Training

通过前面的一系列操作我们可以得到稠密的多标签 ,那我们如何用它们来训练分类器?

为此,本文提出了一种新的训练方案,LabelPooling,它考虑了Localized Ground Truths。在下图中展示了LabelPooling和原始ImageNet训练之间的区别。

涨点神器!重新标记ImageNet,让CNN涨点明显!代码已开源_第7张图片

在一个标准的ImageNet训练中,对Random crops的监督是由每张图像给出的单一标签的Ground Truths给出的。

另一方面,LabelPooling加载一个预先计算好的标签Map,并对Random crops坐标对应的标签Map进行区域池化操作。

LabelPooling采用RoIAlign区域池化方式。对池化预测Maps进行全局平均池化和Softmax操作,然后得到多标签Ground-Truth向量用来训练模型。

伪代码如下:

涨点神器!重新标记ImageNet,让CNN涨点明显!代码已开源_第8张图片

4. 讨论

4.1 Space consumption

前面提到本文利用EfficientNet-L2作为Machine Annotators分类器,其输入大小为475×475。并通过前向传播来生成标签 。保存所有类别的整个标签映射将需要超过1tb的存储:128万张图片× ≈1.0TB。但是对于每个图像,超出几个top-k类的像素级预测基本上是零。因此,通过只存储每个图像的前5个预测结果来节省存储空间,结果是10个 GB标签Map数据。这相当于在原始ImageNet数据之上仅增加10%的额外空间。

4.2 Time consumption

ReLabel需要一次性的计算成本来通过Machine Annotators转发ImageNet训练图像。这个过程大约需要10小时,仅占ResNet-50整个训练时间的3.3%。对于每次训练迭代,LabelPooling在标准ImageNet监督之上执行标签映射加载和区域池化操作仅增加0.5%的训练时间。

请注意,ReLabel比知识蒸馏在计算效率上要高得多,知识蒸馏需要在每次迭代中向前通过Teacher Model。例如,KD使用EfficientNet-B7 Teacher Model所花费的训练时间是原来的4倍多。

4.3 Which machine annotator should we select?

理想情况下Machine Annotators可以为训练图像提供精确的标签。为此,本文作者考虑由几个最先进的分类器EfficientNetf-{B1、B3、B5、B7、B8}生成的ReLabel,使用JFT-300M训练EfficientNet-L2,以及使用InstagramNet-1B训练的ResNeXT_101_32x{32d,48d}。通过使用以上来自不同分类器的标签映射来训练ResNet-50。注意,ResNet-50在vanilla single labels训练时达到了top-1的验证精度77.5%。

涨点神器!重新标记ImageNet,让CNN涨点明显!代码已开源_第9张图片

如图所示,目标模型的总体性能遵循Machine Annotators的性能。当机器监督不够强时(如EfficientNet-B1),训练后的模型表现出严重的性能下降(76.1%)。因此最终选择了EfficientNet-L2作为Machine Annotators,使ResNet-50的性能达到最佳(78.9%)。

4.4 Factor analysis of ReLabel

ReLabel是multi-label和pixel-wise。为了检验这两种性质的必要性,进行了消融实验。考虑到RoIAlign区域池化后localized single labels是通过argmax 取代 操作获得 L_{loc,single}\in {0,1}^C。

对于全局multi-label,本文在标签映射上使用全局平均池化,而不是RoIAlign,从而产生标签 。

最后,通过先执行全局平均池化,再执行argmax操作便可以得到全局单标签$L_{loc,single}\in {0,1}^C;注意标签与原始ImageNet标签有相同的格式,只不过是由机器生成的。

涨点神器!重新标记ImageNet,让CNN涨点明显!代码已开源_第10张图片

这4个变量的结果如表所示。观察到78.9%的ReLabel性能,去除多标签和本地化标签分别导致下降0.5和0.4。

当两者都缺失时有1.4下降。因此,认为这2种因素对于良好的性能都是不可或缺的。还要注意,与原始ImageNet标签相比,机器生成的global, single labels不会带来任何收益。这进一步表明了上述属性从Machine Annotators中获得最大益处的重要性。

4.5 Confidence of ReLabel supervision

本文研究了在random crop和groundtruth bounding box的不同重叠水平下,ReLabel监督的置信度。

涨点神器!重新标记ImageNet,让CNN涨点明显!代码已开源_第11张图片

如图所示,绘制了5万个random crop样本。根据合并标签的最大分类概率来衡量ReLabel监督的置信度(即 ,其中 )。

涨点神器!重新标记ImageNet,让CNN涨点明显!代码已开源_第12张图片

结果如图所示。ReLabel整体的平均监督程度遵循对象存在的程度,特别是与对象区域重叠较小的情况(IoU<0.4)。

例如,当IoU为0时(即random crop在目标区域之外),则标签置信度低于0.6为训练模型提供了一些不确定性信号。

5 实验

5.1 与其他标签操作的比较

涨点神器!重新标记ImageNet,让CNN涨点明显!代码已开源_第13张图片

通过上表可以看出,与Label Smoothing和Label Clean相比,ReLabel提升比较明显。

涨点神器!重新标记ImageNet,让CNN涨点明显!代码已开源_第14张图片

由上表可以看出,通过在ResNet的基础模型上使用ReLabel可以有效的提升Top-1的精度,如果结合CutMix一起使用,提升也会更加的明显。

涨点神器!重新标记ImageNet,让CNN涨点明显!代码已开源_第15张图片

由上表可以看出,ReLabel方法具有一定的泛化性,不仅仅只在ResNet上有效,在EfficientNet和ResNeXT上依旧有效。

5.2 Transfer Learning

涨点神器!重新标记ImageNet,让CNN涨点明显!代码已开源_第16张图片

可以看出在检测任务上也有很好的性能。

涨点神器!重新标记ImageNet,让CNN涨点明显!代码已开源_第17张图片

可以看出在多类分类问题任务上也有很好的性能。

参考

[1].Re-labeling ImageNet:from Single to Multi-Labels, from Global to Localized Labels.

[2].https://github.com/naver-ai/relabel_imagenet

CV资源下载

后台回复:CVPR2020,即可下载代码开源的论文合集

后台回复:ECCV2020,即可下载代码开源的论文合集

后台回复:YOLO,即可下载YOLOv4论文和代码

后台回复:Trasnformer综述,即可下载两个最新的视觉Transformer综述PDF,肝起来!

重磅!CVer-细分垂直交流群成立

扫码添加CVer助手,可申请加入CVer-细分垂直方向 微信交流群,可申请加入CVer大群,细分方向已涵盖:目标检测、图像分割、目标跟踪、人脸检测&识别、OCR、姿态估计、超分辨率、SLAM、医疗影像、Re-ID、GAN、NAS、深度估计、自动驾驶、强化学习、车道线检测、模型剪枝&压缩、去噪、去雾、去雨、风格迁移、遥感图像、行为识别、视频理解、图像融合、图像检索、论文投稿&交流、TransformerPyTorch和TensorFlow等群。

一定要备注:研究方向+地点+学校/公司+昵称(如目标检测+上海+上交+卡卡),根据格式备注,才能通过且邀请进群

▲长按加微信群

▲长按关注CVer公众号

整理不易,请给CVer点赞和在看

你可能感兴趣的:(大数据,python,计算机视觉,机器学习,人工智能)