[论文理解] Making Convolutional Networks Shift-Invariant Again

Making Convolutional Networks Shift-Invariant Again

Intro

本文提出解决CNN平移不变性丧失的方法,之前说了CNN中的downsample过程由于不满足采样定理,所以没法确保平移不变性。信号处理里面解决这样的问题是利用增大采样频率或者用抗混叠方法,前者在图像处理里面设置stride 1就可实现,但stride 1已经是极限,本文着重于后者,使用抗混叠使得CNN重新具有平移不变性。

混叠是在采样频率不满足采样定理时出现的一种现象,抗混叠通过抗混叠滤波器消除混叠,即先用低通滤波器处理,然后再去采样,这样可以消除高频信号造成的不满足采样定理的情况。那么在图像处理里,理论上avg pooling就可以减小高频影响,但是有相关研究表明max-pooling在结果上要优于avg pooling(不考虑平移不变性只考虑分类等结果),但是max-pooling是不满足采样定理的,这就很尴尬。

Methods

先解释两个概念
平移不变性:指的是输入平移一定距离,最终的结果不变,分类里面就是分类的概率结果是不变的。
平移同变形:指的是输入平移一定距离,其对应的feature也做同样的平移。
本文主要是针对特征的平移同变性去解决问题,而实际上实现了特征的平移同变形,后面接的是fc层,最后一层的平移不变性是等价于平移同变性的,所以实现了特征的平移同变性就是实现了整个网络输出的平移不变性。例如,vgg网络的最后两层是fc层和softmax,显然fc层的spatial dim只有唯一一个元素(高维向量),所以平移不变性和平移等变性在这一层是等价的。

作者认为,max-pooling的过程可以分为两个过程,max操作和采样操作,其中max操作是平移等变的,因为max操作是利用滑动窗口实现的(stride 1),然后进行最大采样,就实现了下采样,而在采样过程中保留了高频部分(采样频率又相对较低),所以会导致不满足采样定理。为了使max-pooling满足采样定理,对采样之前的信号用低通滤波处理,即可实现混叠。低通滤波加上采样操作,作者成为BlurPool。

对于stride 2 conv,同样地,卷积过程其实也分为两个过程,对采样前的信号低通滤波处理即可:conv(stride k)-relu替换为conv(stride 1)-relu-BlurPool(k)。avg pooling同理。

操作如图所示。

Coding

import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
class Downsample(nn.Module):
    def __init__(self, pad_type='reflect', filt_size=3, stride=2, channels=None, pad_off=0):
        super(Downsample, self).__init__()
        self.filt_size = filt_size
        self.pad_off = pad_off
        self.pad_sizes = [int(1.*(filt_size-1)/2), int(np.ceil(1.*(filt_size-1)/2)), int(1.*(filt_size-1)/2), int(np.ceil(1.*(filt_size-1)/2))]
        self.pad_sizes = [pad_size+pad_off for pad_size in self.pad_sizes]
        self.stride = stride
        self.off = int((self.stride-1)/2.)
        self.channels = channels
        if(self.filt_size==1):
            a = np.array([1.,])
        elif(self.filt_size==2):
            a = np.array([1., 1.])
        elif(self.filt_size==3):
            a = np.array([1., 2., 1.])
        elif(self.filt_size==4):
            a = np.array([1., 3., 3., 1.])
        elif(self.filt_size==5):
            a = np.array([1., 4., 6., 4., 1.])
        elif(self.filt_size==6):
            a = np.array([1., 5., 10., 10., 5., 1.])
        elif(self.filt_size==7):
            a = np.array([1., 6., 15., 20., 15., 6., 1.])

        filt = torch.Tensor(a[:,None]*a[None,:])
        filt = filt/torch.sum(filt)
        self.register_buffer('filt', filt[None,None,:,:].repeat((self.channels,1,1,1)))

        self.pad = get_pad_layer(pad_type)(self.pad_sizes)

    def forward(self, inp):
        if(self.filt_size==1):
            if(self.pad_off==0):
                return inp[:,:,::self.stride,::self.stride]
            else:
                return self.pad(inp)[:,:,::self.stride,::self.stride]
        else:
            return F.conv2d(self.pad(inp), self.filt, stride=self.stride, groups=inp.shape[1])
class AntialiasNet(nn.Module):
    def __init__(self,num_classes = 10):
        super(AntialiasNet,self).__init__()
        self.net = nn.Sequential(
            nn.Conv2d(1,32,3,stride = 1),
            nn.BatchNorm2d(32),
            nn.ReLU(inplace = True),

            nn.Conv2d(32,64,3,stride = 1),
            nn.BatchNorm2d(64),
            nn.ReLU(inplace = True),
            Downsample(channels = 64),

            nn.Conv2d(64,128,3,stride = 1),
            nn.BatchNorm2d(128),
            nn.ReLU(inplace = True),

            nn.Conv2d(128,256,3,stride = 1),
            nn.BatchNorm2d(256),
            nn.ReLU(inplace = True),
            Downsample(channels = 256),
                    )
        self.avg_pool = nn.AdaptiveAvgPool2d((7,7))
        self.classifier = nn.Sequential(
            nn.Linear(256 * 7 * 7, 4096),
            nn.ReLU(True),
            nn.Dropout(),
            nn.Linear(4096, 4096),
            nn.ReLU(True),
            nn.Dropout(),
            nn.Linear(4096, num_classes),
        )
    def forward(self,x):
        return self.classifier(self.avg_pool(self.net(x)).view(-1,256*7*7))

def get_pad_layer(pad_type):
    if(pad_type in ['refl','reflect']):
        PadLayer = nn.ReflectionPad2d
    elif(pad_type in ['repl','replicate']):
        PadLayer = nn.ReplicationPad2d
    elif(pad_type=='zero'):
        PadLayer = nn.ZeroPad2d
    else:
        print('Pad type [%s] not recognized'%pad_type)
    return PadLayer
if __name__ == "__main__":
    x = torch.randn(3,1,28,28)
    net = AntialiasNet()

    print(net(x))

原文地址:https://www.cnblogs.com/aoru45/p/12230117.html

时间: 2024-10-07 22:56:00

[论文理解] Making Convolutional Networks Shift-Invariant Again的相关文章

[论文理解]Region-Based Convolutional Networks for Accurate Object Detection and Segmentation

Region-Based Convolutional Networks for Accurate Object Detection and Segmentation 概括 这是一篇2016年的目标检测的文章,也是一篇比较经典的目标检测的文章.作者介绍到,现在表现最好的方法非常的复杂,而本文的方法,简单又容易理解,并且不需要大量的训练集. 文章的大致脉络如图. 产生region proposal 文章提到了滑窗的方法,由于滑窗的方法缺点非常明显,就是每次只能检测一个aspect ratio,所以确

论文: Deformable Convolutional Networks

论文: Deformable Convolutional Networks CNN因为其内部的固定的网络结构,对模型几何变换的识别非常有限. 本paper给出了两个模块deformable convolution 和 deformable ROI-Pooling来提高CNN的模型变换能力. 过去的办法解决几何变换的方法,一,使用data Augmentation来增大不同几何形状的object,二,使用sift 或者 sliding windows这样的方法来解决. 本paper主要针对三个mo

[论文理解] CBAM: Convolutional Block Attention Module

CBAM: Convolutional Block Attention Module 简介 本文利用attention机制,使得针对网络有了更好的特征表示,这种结构通过支路学习到通道间关系的权重和像素间关系的权重,然后乘回到原特征图,使得特征图可以更好的表示. Convolutional Block Attention Module 这里的结构有点类似与SENet里的支路结构. 对于Channel attention module,先将原feature map分别做global avg pool

[论文理解] Why do deep convolutional networks generalize so poorly to small image transformations?

Why do deep convolutional networks generalize so poorly to small image transformations? Intro CNN的设计初衷是为了使得模型具有微小平移.旋转不变性,而实际上本文通过实验验证了现在比较流行的神经网络都已经丧失了这样的能力,甚至图像只水平移动一个像素,预测的结果都将会发生很大的变化.之所以如此,作者认为CNN的下采样背离了隆奎斯特采样定理,就连augmentation也并不能缓解微小变化不变性的丧失. I

[论文理解] Learning Efficient Convolutional Networks through Network Slimming

Learning Efficient Convolutional Networks through Network Slimming 简介 这是我看的第一篇模型压缩方面的论文,应该也算比较出名的一篇吧,因为很早就对模型压缩比较感兴趣,所以抽了个时间看了一篇,代码也自己实现了一下,觉得还是挺容易的.这篇文章就模型压缩问题提出了一种剪枝针对BN层的剪枝方法,作者通过利用BN层的权重来评估输入channel的score,通过对score进行threshold过滤到score低的channel,在连接的

Fully Convolutional Networks for semantic Segmentation(深度学习经典论文翻译)

摘要 卷积网络在特征分层领域是非常强大的视觉模型.我们证明了经过端到端.像素到像素训练的卷积网络超过语义分割中最先进的技术.我们的核心观点是建立"全卷积"网络,输入任意尺寸,经过有效的推理和学习产生相应尺寸的输出.我们定义并指定全卷积网络的空间,解释它们在空间范围内dense prediction任务(预测每个像素所属的类别)和获取与先验模型联系的应用.我们改编当前的分类网络(AlexNet [22] ,the VGG net [34] , and GoogLeNet [35] )到完

VERY DEEP CONVOLUTIONAL NETWORKS FOR LARGE-SCALE IMAGE RECOGNITION 这篇论文

由Andrew Zisserman 教授主导的 VGG 的 ILSVRC 的大赛中的卷积神经网络取得了很好的成绩,这篇文章详细说明了网络相关事宜. 文章主要干了点什么事呢?它就是在在用卷积神经网络下,在采用小的卷积核与小的移动步长的情况下,探索一下网络的深度对目标识别率的影响. 网络的大体结构 网络的输入为224*224的RGB图片,后面跟卷积层,卷积核的大小基本都为3*3有最小的可以保留图片空间分瓣率的卷积核,步长为1个像素,偶尔会有1*1的卷积核,这就相当于加入了一个非线性变换而已.再往后接

论文笔记《Fully Convolutional Networks for Semantic Segmentation》

<Fully Convolutional Networks for Semantic Segmentation>,CVPR 2015 best paper,pixel level, fully supervised. 主要思路是把CNN改为FCN,输入一幅图像后直接在输出端得到dense prediction,也就是每个像素所属的class,从而得到一个end-to-end的方法来实现image  semantic segmentation. 我们已经有一个CNN模型,首先要把CNN的全连接层

目标检测论文阅读:Deformable Convolutional Networks

https://blog.csdn.net/qq_21949357/article/details/80538255 这篇论文其实读起来还是比较难懂的,主要是细节部分很需要推敲,尤其是deformable的卷积如何实现的一步上,在写这篇博客之前,我也查阅了很多其他人的分享或者去github找代码,当然也不敢说完全了解了这种特殊的卷积--仅仅做一点自己的阅读心得与体会吧.这是一篇很有意义的工作,但是和深度学习很多论文一样,在读完之后内心也不免有着种种疑云. Deformable Convoluti