YOLOV4各个创新功能模块技术分析(三)

YOLOV4各个创新功能模块技术分析(三)

 八.数据增强相关-Stylized-ImageNet

论文名称:ImageNet-trained cnns are biased towards texture; increasing shape bias improves accuracy and robustness

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

论文摘要

为了提高卷积神经网络分类器的性能,提出了区域下降策略。事实证明,可以有效地引导模型关注对象中不易区分的部分(例如,腿而不是人头),从而使网络更好地进行泛化,并具有更好的对象定位能力。另一方面,当前的区域性丢失方法通过叠加一块黑色像素或随机噪声来去除训练图像上的信息像素。这种删除是不可取的,因为会导致信息丢失和培训效率低下。因此,提出了CutMix增强策略:在训练图像中剪切和粘贴面片,其中地面真值标签也与面片的面积成比例地混合。通过有效利用训练像素和保持区域退学的正则化效果,CutMix在CIFAR和ImageNet分类任务以及ImageNet弱监督定位任务中始终优于最新的增强策略。此外,与以前的增强方法不同,CutMix训练的ImageNet分类器在用作预训练模型时,在Pascal检测和MS-COCO图像字幕基准方面获得了一致的性能增益。证明了CutMix提高了模型对输入腐败的鲁棒性及其分布外检测性能。

     本文非常有意思,得到的结论非常有意义,可以指导对于某些场景测试失败的分析。本质上本文属于数据增强论文,做的唯一一件事就是:对ImageNet数据集进行风格化。

    本文结论是:CNN训练学习到的实际是纹理特征(texture bias)而不是形状特征,这和人类的认知方式有所区别,如论文题目所言,存在纹理偏置。而本文引入风格化imagenet数据集,平衡纹理和形状偏置,提高泛化能力。

    本文指出在ImageNet上训练的CNN强烈的偏向于识别纹理而不是形状,这和人的行为是极为不同的,存在纹理偏差,所以提出了Stylized-ImageNet数据,混合原始数据训练就可以实现既关注纹理,也关注形状(也就是论文标题提到的减少纹理偏向,增加形状偏向)。从而不仅更适合人类的行为,更惊讶的是提升了目标检测的精度,以及鲁棒性,更加体现了基于形状表示的优势。

    文章从一只披着象皮的猫究竟会被识别为大象还是猫这个问题入手,揭示了神经网络根据物体的texture进行识别而非以为的根据物体的形状。

    作者准备了6份数据,分别是正常的图片,灰色图,只包含轮廓的,只包含边缘的,只有纹理没有形状,纹理和形状相互矛盾(大象的纹理,猫的形状),对于第六份数据(纹理和形状冲突的数据),作者采用Stylized-ImageNet随机地将物体的纹理替换掉(也就是本文创新点),如下(c)所示:

 

 

     采用了4个主流网络,加上人类直观评估。原图其实是作者除了物体外,其余都是白色背景的数据集,目的是去除干扰。

    对于前面5份数据,采用原图和灰度图,神经网络都可以取得非常高的准确率,而对于只包含轮廓和只包含边缘的图片,神经网络的预测准确率则显著降低。更有意思的是,对于只包含纹理的图片,神经网络取得特别高的准确率。因而不难推断出,神经网络在识别中,主要是参考纹理信息而不是形状信息。

    作者先构造数据集,然后再进行后面的深入实验,IN就是指的ImageNet,SIN是指的风格化的ImageNet,如下所示

  SIN的特点是保留shape,但是故意混淆掉纹理信息。

 

 从上的第一行可以看出,在原始图片IN上训练的模型不能适应去除纹理SIN的图片(IN-SIN),而使用去除纹理的图片进行训练和测试效果会差于使用原始图片进行训练和测试(SIN-SIN),这说明纹理信息在图像识别中确实起到了一定的作用,去除了纹理信息会提高模型识别的难度。最后,当使用去除纹理的图片进行训练而在原图进行测试的时候(SIN-IN),效果比在去除纹理的图片上面效果好(SIN-SIN)。

    后面三行的实验采用的是第一行resnet的网络结构,其主要特征是限制模型的感受野,从而让模型无法学习到空间的信息,其对应的感受野分别是33*33,17*17,9*9,对于训练原始的图片,其结果测试误差跟没有加上感受野限制的误差差别不大,从而说明纹理信息起到主导作用(IN-IN),而对应去除掉纹理信息的图片,其测试结果下降十分明显(SIN-SIN),说明形状信息起到主要的作用,证明了SIN的模型确实在学习形状的信息而不是纹理的信息。这个实验是要说明提出的SIN数据集由于强制抹掉了固定纹理,网络训练难度增大,在没有限制感受野情况下可以学的蛮好,但是一旦限制了感受野就不行了,说明SIN模型学习到的不仅仅是纹理(因为纹理是局部的,如果依靠纹理来分类,那么准确率应该下降不了这么多),更多的是依靠shape分类,因为感受野外限制了,导致无法看到整个shape,并且通过更加限制感受野,SIN-SIN准确率下降更多可以发现。也就是说SIN数据集由于替换掉了纹理,迫使网络学习shape和纹理,达到了本文目的。SIN上训练的ResNet50展示出更强的形状偏向,符合人类常理。

    增强形状偏向也改变了表示,那么影响了CNN的性能和鲁棒性了吗?设置了两个训练方案:

    1 同时在SIN和IN上训练
    2 同时在SIN和IN上训练,在IN上微调。称为Shape-ResNet。

 

     作者把去掉纹理的数据和原图一起放进去模型中进行训练,最后用原图进行finetune,发现这种方法可以提高模型的性能。Shape-ResNet超过了原始ResNet的准确率,说明SIN是有用的图像增强。

    总结:CNN识别强烈依赖于纹理,而不是全局的形状,但是这是不好的,为了突出形状bias,可以采用本文的SIN做法进行数据增强,SIN混合原始数据训练就可以实现既关注纹理,也关注形状,不仅符合人类直观,也可以提高各种任务的准确率和鲁邦性。所以本文其实是提出了一种新的数据增强策略。是不是很有意思的结论?

九.数据增强相关-label smooth

论文题目:Rethinking the inception architecture for computer vision

论文摘要

卷积网络是最先进的计算机视觉解决方案的核心,可用于各种各样的任务。自2014年以来,非常深的卷积网络开始成为主流,在各种基准上产生了巨大的收益。尽管增加的模型大小和计算成本往往会转化为大多数任务的即时质量增益(只要为培训提供足够的标记数据),但计算效率和低参数计数仍然是各种用例(如移动视觉和大数据场景)的有利因素。探索如何通过适当的因子化卷积和积极的正则化来尽可能有效地利用增加的计算量来扩大网络。在ILSVRC 2012分类挑战验证集上进行了基准测试,结果表明,与最新技术相比,本文方法取得了显著的进步:使用一个计算成本为50亿乘加/推断和使用少于2500万个参数的网络进行单帧评估时,最大误差为21.2%,最大误差为5.6%。通过4个模型的集成和多作物评估,报告了验证集上3.5%的前5个错误(测试集上3.6%的错误)和验证集上17.3%的前1个错误。

    label smooth是一个非常有名的正则化手段,防止过拟合,想基本上没有人不知道,故不详说了,核心就是对label进行soft操作,不要给0或者1的标签,而是有一个偏移,相当于在原label上增加噪声,让模型的预测值不要过度集中于概率较高的类别,把一些概率放在概率较低的类别。

十.特征增强相关-DropBlock

论文题目:DropBlock: A regularization method for convolutional networks
论文地址:https://arxiv.org/abs/1810.12890
开源代码:https://github.com/miguelvr/dropblock

论文摘要

当深度神经网络被过度参数化,并在大量噪声和正则化(如权值衰减和丢失)的情况下进行训练时,它们通常能很好地工作。虽然漏失被广泛地用作全连通层的正则化技术,但对于卷积层,它通常不太有效。卷积层漏失的这种不成功可能是由于卷积层中的激活单元在空间上是相关的,因此尽管漏失,信息仍然可以通过卷积网络流动。因此,需要一种结构形式的辍学来正则化卷积网络。在本文中,我们引入DropBlock,这是一种结构化的dropout形式,其中特征映射的相邻区域中的单元被放在一起。我们发现,除了卷积层外,在跳跃连接中应用DropbBlock可以提高精确度。此外,在训练过程中,逐渐增加的下降单位的数量会导致更好的准确性和对超参数选择的鲁棒性。大量实验表明,DropBlock在卷积网络的正则化中比dropout有更好的性能。在ImageNet分类上,ResNet-50架构与DropBlock实现              78.13%准确度,超过1.6%基线改善。在COCO检测中,DropBlock提高了视网膜的平均精度              36.8%到38.4% 。      

    由于dropBlock其实是dropout在卷积层上的推广,故很有必须先说明下dropout操作。

    dropout,训练阶段在每个mini-batch中,依概率P随机屏蔽掉一部分神经元,只训练保留下来的神经元对应的参数,屏蔽掉的神经元梯度为0,参数不参数与更新。而测试阶段则又让所有神经元都参与计算。

    dropout操作流程:参数是丢弃率p
    1)在训练阶段,每个mini-batch中,按照伯努利概率分布(采样得到0或者1的向量,0表示丢弃)随机的丢弃一部分神经元(即神经元置零)。用一个mask向量与该层神经元对应元素相乘,mask向量维度与输入神经一致,元素为0或1。
    2)然后对神经元rescale操作,即每个神经元除以保留概率1-P,也即乘上1/(1-P)。
    3)反向传播只对保留下来的神经元对应参数进行更新。
    4)测试阶段,Dropout层不对神经元进行丢弃,保留所有神经元直接进行前向过程。

    为啥要rescale呢?是为了保证训练和测试分布尽量一致,或者输出能量一致。可以试想,如果训练阶段随机丢弃,那么其实dropout输出的向量,有部分被屏蔽掉了,可以等下认为输出变了,如果dropout大量应用,那么其实可以等价为进行模拟遮挡的数据增强,如果增强过度,导致训练分布都改变了,那么测试时候肯定不好,引入rescale可以有效的缓解,保证训练和测试时候,经过dropout后数据分布能量相似

     dropout方法多是作用在全连接层上,在卷积层应用dropout方法意义不大。文章认为是因为每个feature map的位置都有一个感受野范围,仅仅对单个像素位置进行dropout并不能降低feature map学习的特征范围,也就是说网络仍可以通过该位置的相邻位置元素去学习对应的语义信息,也就不会促使网络去学习更加鲁邦的特征。

    既然单独的对每个位置进行dropout并不能提高网络的泛化能力,那么很自然的,如果按照一块一块的去dropout,就自然可以促使网络去学习更加鲁邦的特征。思路很简单,就是在feature map上去一块一块的找,进行归零操作,类似于dropout,叫做dropblock。

 

     绿色阴影区域是语义特征,b图是模拟dropout的做法,随机丢弃一些位置的特征,但是作者指出这做法没啥用,因为网络还是可以推断出来,(c)是本文做法。

 

     dropblock有三个比较重要的参数,一个是block_size,用来控制进行归零的block大小;一个是γ,用来控制每个卷积结果中,到底有多少个channel要进行dropblock;最后一个是keep_prob,作用和dropout里的参数一样。

 

     M大小和输出特征图大小一致,非0即1,为了保证训练和测试能量一致,需要和dropout一样,进行rescale。

    上述是理论分析,在做实验时候发现,block_size控制为7*7效果最好,对于所有的feature map都一样,γ通过一个公式来控制,keep_prob则是一个线性衰减过程,从最初的1到设定的阈值(具体实现是dropout率从0增加到指定值为止),论文通过实验表明这种方法效果最好。如果固定prob效果好像不好。实践中,并没有显式的设置的值,而是根据keep_prob(具体实现是反的,是丢弃概率)来调整。

 

    DropBlock in ResNet-50 DropBlock加在哪?最佳的DropBlock配置是block_size=7,在group3和group4上都用。将DropBlock用在skip connection比直接用在卷积层后要好,具体咋用,可以看代码。

 

classDropBlock2D(nn.Module):    r"""Randomly zeroes 2D spatial blocks of the input tensor.
    As described in the paper    `DropBlock: A regularization method for convolutional networks`_ ,    dropping whole blocks of feature map allows to remove semantic    information as compared to regular dropout.
    Args:        drop_prob (float): probability of an element to be dropped.        block_size (int): size of the block to drop
    Shape:        - Input: `(N, C, H, W)`        - Output: `(N, C, H, W)`
    .. _DropBlock: A regularization method for convolutional networks:       https://arxiv.org/abs/1810.12890
    """
    def__init__(self, drop_prob, block_size):        super(DropBlock2D, self).__init__()
        self.drop_prob = drop_prob        self.block_size = block_size
    defforward(self, x):        # shape: (bsize, channels, height, width)
        assert x.dim() == 4,             "Expected input with 4 dimensions (bsize, channels, height, width)"
        ifnot self.training or self.drop_prob == 0.:            return x        else:            # get gamma value            gamma = self._compute_gamma(x)
            # sample mask            mask = (torch.rand(x.shape[0], *x.shape[2:]) < gamma).float()
            # place mask on input device            mask = mask.to(x.device)
            # compute block mask            block_mask = self._compute_block_mask(mask)
            # apply block mask            out = x * block_mask[:, None, :, :]
            # scale output            out = out * block_mask.numel() / block_mask.sum()
            return out
    def_compute_block_mask(self, mask):        # 比较巧妙的实现,用max pool来实现基于一点来得到全0区域        block_mask = F.max_pool2d(input=mask[:, None, :, :],                                  kernel_size=(self.block_size, self.block_size),                                  stride=(1, 1),                                  padding=self.block_size // 2)
        if self.block_size % 2 == 0:            block_mask = block_mask[:, :, :-1, :-1]
        block_mask = 1 - block_mask.squeeze(1)
        return block_mask
    def_compute_gamma(self, x):        return self.drop_prob / (self.block_size ** 2)

    联合线性调度一起使用,如下所示:

 

 

 

 

原文地址:https://www.cnblogs.com/wujianming-110117/p/12954617.html