MAE–transformer模型预训练

假设我们想从图像中识别出不同种类的椅子,然后将购买链接推荐给用户。一种可能的方法是先找出100种常见的椅子,为每种椅子拍摄1,000张不同角度的图像,然后在收集到的图像数据集上训练一个分类模型。这个椅子数据集虽然可能比Fashion-MNIST数据集要庞大,但样本数仍然不及ImageNet数据集中样本数的十分之一。这可能会导致适用于ImageNet数据集的复杂模型在这个椅子数据集上过拟合。同时,因为数据量有限,最终训练得到的模型的精度也可能达不到实用的要求。

为了应对上述问题,一个显而易见的解决办法是收集更多的数据。然而,收集和标注数据会花费大量的时间和资金。例如,为了收集ImageNet数据集,研究人员花费了数百万美元的研究经费。虽然目前的数据采集成本已降低了不少,但其成本仍然不可忽略。

另外一种解决办法是应用迁移学习(transfer learning),将从源数据集学到的知识迁移到目标数据集上。例如,虽然ImageNet数据集的图像大多跟椅子无关,但在该数据集上训练的模型可以抽取较通用的图像特征,从而能够帮助识别边缘、纹理、形状和物体组成等。这些类似的特征对于识别椅子也可能同样有效。

本节我们介绍迁移学习中的一种常用技术:微调(fine tuning)。如图9.1所示,微调由以下4步构成。

  1. 在源数据集(如ImageNet数据集)上预训练一个神经网络模型,即源模型。
  2. 创建一个新的神经网络模型,即目标模型。它复制了源模型上除了输出层外的所有模型设计及其参数。我们假设这些模型参数包含了源数据集上学习到的知识,且这些知识同样适用于目标数据集。我们还假设源模型的输出层跟源数据集的标签紧密相关,因此在目标模型中不予采用。
  3. 为目标模型添加一个输出大小为目标数据集类别个数的输出层,并随机初始化该层的模型参数。
  4. 在目标数据集(如椅子数据集)上训练目标模型。我们将从头训练输出层,而其余层的参数都是基于源模型的参数微调得到的。

当目标数据集远小于源数据集时,微调有助于提升模型的泛化能力。

代码实现微调:

pretrained_net = models.resnet18(pretrained=True)
pretrained_net.load_state_dict(torch.load('/home/kesci/input/resnet185352/resnet18-5c106cde.pth'))

下面打印源模型的成员变量fc。作为一个全连接层,它将ResNet最终的全局平均池化层输出变换成ImageNet数据集上1000类的输出。

print(pretrained_net.fc)

输出:Linear(in_features=512, out_features=1000, bias=True)

可见此时pretrained_net最后的输出个数等于目标数据集的类别数1000。所以我们应该将最后的fc成修改我们需要的输出类别数:

pretrained_net.fc = nn.Linear(512, 2)
print(pretrained_net.fc)

此时,pretrained_netfc层就被随机初始化了,但是其他层依然保存着预训练得到的参数。由于是在很大的ImageNet数据集上预训练的,所以参数已经足够好,因此一般只需使用较小的学习率来微调这些参数,而fc中的随机初始化参数一般需要更大的学习率从头训练。PyTorch可以方便的对模型的不同部分设置不同的学习参数,我们在下面代码中将fc的学习率设为已经预训练过的部分的10倍。

output_params = list(map(id, pretrained_net.fc.parameters()))
feature_params = filter(lambda p: id(p) not in output_params, pretrained_net.parameters())

lr = 0.01
optimizer = optim.SGD([{'params': feature_params},
                       {'params': pretrained_net.fc.parameters(), 'lr': lr * 10}],
                       lr=lr, weight_decay=0.001)

记录: 在MAE的微调训练中,提供了两种 微调

  1. Linear probing: 锁死transformer的参数,只训练CIFAR10的那个Linear层。
  2. Fine-tuning: 接着训练transformer的参数,同时也训练CIFAR10的那个Linear。

论文做了MAE各个部分的不同设置对比实验,这些实验能够揭示MAE更多的特性。首先是masking ratio,从下图可以看到,最优的设置是75%的masking ratio,此时linear probing和finetune效果最好,这比之前的研究要高很多,比如BEiT的masking ratio是40%。另外也可以看到linear probing和finetune的表现不一样,linear probing效果随着masking ratio的增加逐渐提高直至一个峰值后出现下降,而finetune效果在不同making ratio下差异小,masking ratio在40%~80%范围内均能表现较好。 ​

preview

ESPCN 图像超分辨率方法

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

代码:https://github.com/leftthomas/ESPCN

Real-Time Single Image and Video Super-Resolution Using an Efficient Sub-Pixel Convolutional Neural Network

ESPCN 是在2016年在CVPR上发表的一片论文,中提出的一种实时的基于卷积神经网络的图像超分辨率方法。

这篇论文主要就是提出了一种新的亚像素卷积层(sub-pixel convolutional layer),以往的方法,为了生成高分辨率的输出,一般是先对输入进行上采样扩大图像分辨率,得到与高分辨率图像同样的大小,再作为网络输入,意味着卷积操作在较高的分辨率上进行,相比于在低分辨率的图像上计算卷积,会降低效率。 ESPCN(Real-Time Single Image and Video Super-Resolution Using an Efficient Sub-Pixel Convolutional Neural Network,CVPR 2016)提出一种在低分辨率图像上直接计算卷积得到高分辨率图像的高效率方法。

如果想最后的分辨率从 n 到 rn,ESPCN会生成r*r个通道,再进行sub-pixel convolutional,生成高分辨率的图片。假设是9通道 混合,这里的通道混合是将每个通道对应位置的元素重新排列成3*3的图像。这个变换虽然被称作sub-pixel convolution, 但实际上并没有卷积操作。

通过使用sub-pixel convolution, 图像从低分辨率到高分辨率放大的过程,插值函数被隐含地包含在前面的卷积层中,可以自动学习到。只在最后一层对图像大小做变换,前面的卷积运算由于在低分辨率图像上进行,因此效率会较高。

ESPCN激活函数采用tanh替代了ReLU。损失函数为均方误差。

pytorch中已经集成了 sub-pixel convolution :

nn.PixelShuffle(upscale_factor)

以四维输入(N,C,H,W)为例,Pixelshuffle会将为(∗,r 2 C r^2Cr2C,H,W)的Tensor给reshape成(∗,C,rH,rW)的Tensor

Upsample:

对给定多通道的1维(temporal)、2维(spatial)、3维(volumetric)数据进行上采样。

对volumetric输入(3维——点云数据),输入数据Tensor格式为5维:minibatch x channels x depth x height x width
对spatial输入(2维——jpg、png等数据),输入数据Tensor格式为4维:minibatch x channels x height x width
对temporal输入(1维——向量数据),输入数据Tensor格式为3维:minibatch x channels x width

此算法支持最近邻,线性插值,双线性插值,三次线性插值对3维、4维、5维的输入Tensor分别进行上采样(Upsample)。

RepVGG: Making VGG-style ConvNets Great Again

论文下载地址:https://arxiv.org/abs/2101.03697
官方源码(Pytorch实现):https://github.com/DingXiaoH/RepVGG

这篇论文对于我来说最大的用处是提出了结构的重重参数化:

在推理时将三个并行分支合并成单个分支,并保证输出输出不变。

结构重参数化主要分为两步,第一步主要是将Conv2d算子和BN算子融合以及将只有BN的分支转换成一个Conv2d算子,第二步将每个分支上的3x3卷积层融合成一个卷积层。

1、Conv2d和BN 这个已经是非常常见的,因为卷积核bn都是线性运算,所以可以进行合并。

这里假设输入的特征图(Input feature map)如下图所示,输入通道数为2,然后采用两个卷积核(图中只画了第一个卷积核对应参数)。

在这里插入图片描述

接着计算一下输出特征图(Output feature map)通道1上的第一个元素,即当卷积核1在输入特征图红色框区域卷积时得到的值(为了保证输入输出特征图高宽不变,所以对Input feature map进行了Padding)。其他位置的计算过程类似这里就不去演示了。

在这里插入图片描述

然后再将卷积层输出的特征图作为BN层的输入,这里同样计算一下输出特征图(Output feature map)通道1上的第一个元素,按照上述BN在推理时的计算公式即可得到如下图所示的计算结果。

在这里插入图片描述

代码

Conv2d+BN融合实验(Pytorch)
下面是参考作者提供的源码改的一个小实验,首先创建了一个module包含了卷积和BN模块,然后按照上述转换公式将卷积层的权重和BN的权重进行融合转换,接着载入到新建的卷积模块fused_conv中,最后随机创建一个Tensor(f1)将它分别输入到module以及fused_conv中,通过对比两者的输出可以发现它们的结果是一致的。

from collections import OrderedDict

import numpy as np
import torch
import torch.nn as nn


def main():
    torch.random.manual_seed(0)

    f1 = torch.randn(1, 2, 3, 3)

    module = nn.Sequential(OrderedDict(
        conv=nn.Conv2d(in_channels=2, out_channels=2, kernel_size=3, stride=1, padding=1, bias=False),
        bn=nn.BatchNorm2d(num_features=2)
    ))

    module.eval()

    with torch.no_grad():
        output1 = module(f1)
        print(output1)

    # fuse conv + bn
    kernel = module.conv.weight 
    running_mean = module.bn.running_mean
    running_var = module.bn.running_var
    gamma = module.bn.weight
    beta = module.bn.bias
    eps = module.bn.eps
    std = (running_var + eps).sqrt()
    t = (gamma / std).reshape(-1, 1, 1, 1)  # [ch] -> [ch, 1, 1, 1]
    kernel = kernel * t
    bias = beta - running_mean * gamma / std
    fused_conv = nn.Conv2d(in_channels=2, out_channels=2, kernel_size=3, stride=1, padding=1, bias=True)
    fused_conv.load_state_dict(OrderedDict(weight=kernel, bias=bias))

    with torch.no_grad():
        output2 = fused_conv(f1)
        print(output2)

    np.testing.assert_allclose(output1.numpy(), output2.numpy(), rtol=1e-03, atol=1e-05)
    print("convert module has been tested, and the result looks good!")


if __name__ == '__main__':
    main()

repVGG中大量运用conv+BN层,我们知道将层合并,减少层数能提升网络性能,下面的推理是conv带有bias的过程:

这其实就是一个卷积层,只不过权重考虑了BN的参数 我们令:

最终的融合结果即为:

相关融合代码如下图所示:

def _fuse_bn_tensor(self, branch):
        if branch is None:
            return 0, 0
        if isinstance(branch, nn.Sequential):
            kernel = branch.conv.weight
            running_mean = branch.bn.running_mean
            running_var = branch.bn.running_var
            gamma = branch.bn.weight
            beta = branch.bn.bias
            eps = branch.bn.eps
        else:
            ...
        std = (running_var + eps).sqrt()
        t = (gamma / std).reshape(-1, 1, 1, 1)
        return kernel * t, beta - running_mean * gamma / std

2、如何将不同分支合并:

作者这里首先将不同分支的卷积核都变成3*3:

2.1 将1×1卷积转换成3×3卷积
这个过程比较简单,如下图所示,以1×1卷积层中某一个卷积核为例,只需在原来权重周围补一圈零就行了,这样就变成了3×3的卷积层,注意为了保证输入输出特征图高宽不变,此时需要将padding设置成1(原来卷积核大小为1×1时padding为0)。最后按照上述2.1中讲的内容将卷积层和BN层进行融合即可。

在这里插入图片描述

2.2将BN转换成3×3卷积
对于只有BN的分支由于没有卷积层,所以我们可以先自己构建出一个卷积层来。如下图所示,构建了一个3×3的卷积层,该卷积层只做了恒等映射,即输入输出特征图不变。既然有了卷积层,那么又可以按照上述2.1中讲的内容将卷积层和BN层进行融合。

在这里插入图片描述

2.3 多分支融合
在上面的章节中,我们已经讲了怎么把每个分支融合转换成一个3×3的卷积层,接下来需要进一步将多分支转换成一个单路3×3卷积层。

在这里插入图片描述

合并的过程其实也很简单,直接将这三个卷积层的参数相加即可,具体推理过程就不讲了,如果不了解的可以自己动手算算。

总的来说,这篇论文的目标是Simple is Fast, Memory-economical, Flexible,提出了很多想法去实现上述目标,对于当前我的工作还是比较有启发的,尤其是最后对网络进行合并以及量化部分。下一步要好好学习下torch的量化QAT (torch.quantization.prepare_qat)

Flowformer: Linearizing Transformers with Conservation Flows (任务通用的主干网络-线性复杂度的transformers)

【导读】近年来,Transformer方兴未艾,但是其内在的二次复杂度阻碍了它在长序列和大模型上的进一步发展。清华大学软件学院机器学习实验室从网络流理论出发,提出任务通用的线性复杂度主干网络Flowformer,在长序列、视觉、自然语言、时间序列、强化学习五大任务上取得优秀效果。

任务通用是基础模型研究的核心目标之一,同时也是深度学习研究通向高级智能的必经之路。
近年来,得益于注意力机制的通用关键建模能力,Transformer在众多领域中表现优异,逐渐呈现出通用架构的趋势。但是随着序列长度的增长,标准注意力机制的计算呈现二次复杂度,严重阻碍了其在长序列建模与大模型中的应用。

为此,来自清华大学软件学院的团队深入探索了这一关键问题,提出了任务通用的线性复杂度主干网络Flowformer,在保持标准Transformer的通用性的同时,将其复杂度降至线性,论文被ICML 2022接受。

作者列表:吴海旭,吴佳龙,徐介晖,王建民,龙明盛

链接:https://arxiv.org/abs/2202.06258

代码:https://github.com/thuml/Flowformer相比于标准Transformer,本文提出的Flowformer模型,具有以下特点:

  • 线性复杂度,可以处理数千长度的输入序列;
  • 没有引入新的归纳偏好,保持了原有注意力机制的通用建模能力;
  • 任务通用,在长序列、视觉、自然语言、时间序列、强化学习五大任务上取得优秀效果。

本文深入研究了注意力机制存在的二次复杂度问题,通过将网络流中的守恒原理引入设计,自然地将竞争机制引入到注意力计算中,有效避免了平凡注意力问题。

我们提出的任务通用的骨干网络Flowformer,实现了线性复杂度,同时在长序列、视觉、自然语言、时间序列、强化学习五大任务上取得优秀效果。

在长序列建模应用上,如蛋白质结构预测、长文本理解等,Flowformer具有良好的应用潜力。此外,Flowformer中“无特殊归纳偏好”的设计理念也对通用基础架构的研究具有良好的启发意义。

Vision MLP系列–MLP-Mixer: An all-MLP Architecture for Vision

MLP-Mixer是ViT团队的另一个纯MLP架构的尝试。如果MLP-Mixer重新引领CV领域主流架构的话,那么CV领域主流架构的演变过程就是MLP->CNN->Transformer->MLP? 要回到最初的起点了吗???( Transformer移除了注意力以后就剩MLP了)

这篇论文提出了一种”纯“MLP结构的视觉架构。

先将输入图片拆分成patches,然后通过Per-patch Fully-connected将每个patch转换成feature embedding,然后送入N个Mixer Layer,最后通过Fully-connected进行分类。

Mixer分为channel-mixing MLP和token-mixing MLP两类。channel-mixing MLP允许不同通道之间进行交流;token-mixing MLP允许不同空间位置(tokens)进行交流。这两种类型的layer是交替堆叠的,方便支持两个输入维度的交流。每个MLP由两层fully-connected和一个GELU构成。

从上图我们可以看出,MLP -Mixer 首先使用图片分成很多个小正方形的patch,每个patch的大小定义为patch_size。论文中实现这一步骤使用的是前面提到的卷积,卷积核的大小和步长均patch_size。论文中给的参数,也是2的幂。
网络不再使用传统的RELU激活函数,而是使用了GELU激活函数。

将图片分成小块后,在将它转换为一维结构。如图:

在这里插入图片描述

然后将每一个patch进行转换,如下图所示:

在这里插入图片描述

通过这样一种方式呢,就将一张图片转换为了一个大矩阵,就可以输入到Mixer Layer 中进行计算。

MLP 是两个全连接层的感知机,W1,W2,对应token_mixer中两个全连接的权重,W3,W4则表示channel_mixer两个全连接的权重。σ表示GELU激活函数。那么公示就很简单了,输入X经过Layer Normalize,再乘以W1,再经过激活函数后乘以W2,再加上X。第二个公式也是相同的计算过程。
将前面通过编码得到的矩阵经过Layer Norm 在将矩阵进行旋转(T 表示旋转)连接MLP1,MLP1 就是文章token_mixer 用来寻找像素与像素之间的关系,其中,MLP1中的权值共享。计算完之后,再将矩阵旋转回来,通过Layer Norm 后再接一个channel_mixer 用于寻找通道与通道之间的关系。其中MixerLayer 还启用了ResNet中的跨连结构,跨连结构的作用可以参考[ResNet原理讲解和复现],看到这里,是不是感觉它跟卷积的原理很类似。
从上图可以看出Mixer Layer的输入维度和输出维度相同,并且通过MLP的方式来寻找图片像素与像素,通道与通道的关系。
这就是MLP-MIXER的网络结构了

实现的难点在于,矩阵旋转,我们使用einops中的Rearrange实现矩阵旋转

使用Rearrange 实现旋转

Rearrange(‘b n d -> b d n’) #这里是[batch_size, num_patch, dim] -> [batch_size, dim, num_patch]

#定义多层感知机
import torch
import numpy as np
from torch import nn
from einops.layers.torch import Rearrange
from torchsummary import summary
import torch.nn.functional as F

class FeedForward(nn.Module):
    def __init__(self,dim,hidden_dim,dropout=0.):
        super().__init__()
        self.net=nn.Sequential(
            #由此可以看出 FeedForward 的输入和输出维度是一致的
            nn.Linear(dim,hidden_dim),
            #激活函数
            nn.GELU(),
            #防止过拟合
            nn.Dropout(dropout),
            #重复上述过程
            nn.Linear(hidden_dim,dim),

            nn.Dropout(dropout)
        )
    def forward(self,x):
        x=self.net(x)
        return x


class MixerBlock(nn.Module):
    def __init__(self,dim,num_patch,token_dim,channel_dim,dropout=0.):
        super().__init__()
        self.token_mixer=nn.Sequential(
            nn.LayerNorm(dim),
            Rearrange('b n d -> b d n'),   #这里是[batch_size, num_patch, dim] -> [batch_size, dim, num_patch]
            FeedForward(num_patch,token_dim,dropout),
            Rearrange('b d n -> b n d')    #[batch_size, dim, num_patch] -> [batch_size, num_patch, dim]

         )
        self.channel_mixer=nn.Sequential(
            nn.LayerNorm(dim),
            FeedForward(dim,channel_dim,dropout)
        )
    def forward(self,x):

        x=x+self.token_mixer(x)

        x=x+self.channel_mixer(x)

        return x

class MLPMixer(nn.Module):
    def __init__(self,in_channels,dim,num_classes,patch_size,image_size,depth,token_dim,channel_dim,dropout=0.):
        super().__init__()
        assert image_size%patch_size==0
        self.num_patches=(image_size//patch_size)**2
        #embedding 操作,用卷积来分成一小块一小块的
        self.to_embedding=nn.Sequential(nn.Conv2d(in_channels=in_channels,out_channels=dim,kernel_size=patch_size,stride=patch_size),
            Rearrange('b c h w -> b (h w) c')
        )
        #经过Mixer Layer 的次数
        self.mixer_blocks=nn.ModuleList([])
        for _ in range(depth):
            self.mixer_blocks.append(MixerBlock(dim,self.num_patches,token_dim,channel_dim,dropout))
        self.layer_normal=nn.LayerNorm(dim)

        self.mlp_head=nn.Sequential(
            nn.Linear(dim,num_classes)
        )
    def forward(self,x):
        x=self.to_embedding(x)
        for mixer_block in self.mixer_blocks:
            x=mixer_block(x)
        x=self.layer_normal(x)
        x=x.mean(dim=1)

        x=self.mlp_head(x)

        return x

MLP-Mixer用Mixer的MLP来替代ViT的Transformer,减少了特征提取的自由度,并且巧妙的可以交替进行patch间信息交流和patch内信息交流,从结果上来看,纯MLP貌似也是可行的,而且省去了Transformer复杂的结构,变的更加简洁,有点期待后续ViT和MLP-Mixer如何针锋相对的,感觉大组就是东挖一个西挖一个的,又把尘封多年的MLP给挖出来了

Patches Are All You Need?

———– ConvMixer 网络

论文地址:https://openreview.net/pdf?id=TVHS5Y4dNvM
Github 地址:https://github.com/tmp-iclr/convmixer

ConvMixer is now integrated into the timm framework itself. You can see the PR here.

Conv Mixer 这篇文章提出的初衷是想去弄清楚,ViT系列模型表现优越,到底是图片分块的功劳 还是网络中Attention的功劳。于是作者就根据深度可分离卷积,在ViT 和 MLP Mixer 的启发中 设计了Conv Mixer。并且在表现上超越了一些ViT (某些ViT结构),MLP Mixer 和 ResNet。文章本身并没去追求模型的速度,和表现能力。

在这里插入图片描述
网络结构

网络结构详解:

1、 Patch embedding

这里的Patch embedding实际上是使用一个卷积层 实现的

nn.Conv2d(3,dim,kernel_size=patch_size,stride=patch_size)

其中 kernel_size 就是patch的大小

2、GELU激活函数(高斯误差线性单元)

这个是最近很多模型都在用的函数(dert、高斯误差线性单元激活函数在最近的 Transformer 模型)GELUs正是在激活中引入了随机正则的思想,是一种对神经元输入的概率描述,直观上更符合自然的认识,同时实验效果要比Relus与ELUs都要好。

GELUs其实是 dropout、zoneout、Relus的综合,GELUs对于输入乘以一个0,1组成的mask,而该mask的生成则是依概率随机的依赖于输入。假设输入为X, mask为m,则m服从一个伯努利分布(Φ ( x ) \Phi(x)Φ(x), Φ ( x ) = P ( X < = x ) , X 服 从 标 准 正 太 分 布 \Phi(x)=P(X<=x), X服从标准正太分布Φ(x)=P(X<=x),X服从标准正太分布),这么选择是因为神经元的输入趋向于正太分布,这么设定使得当输入x减小的时候,输入会有一个更高的概率被dropout掉,这样的激活变换就会随机依赖于输入了。

看得出来,这就是某些函数(比如双曲正切函数 tanh)与近似数值的组合。没什么过多可说的。有意思的是这个函数的图形:

GELU 激活函数。

可以看出,当 x 大于 0 时,输出为 x;但 x=0 到 x=1 的区间除外,这时曲线更偏向于 y 轴。

优点:

  • 似乎是 NLP 领域的当前最佳;尤其在 Transformer 模型中表现最好;
  • 能避免梯度消失问题。

3、ConvMixerLayer

class ConvMixerLayer(nn.Module):
    def __init__(self,dim,kernel_size = 9):
        super().__init__()
        #残差结构
        self.Resnet =  nn.Sequential(
            nn.Conv2d(dim,dim,kernel_size=kernel_size,groups=dim,padding='same'),
            nn.GELU(),
            nn.BatchNorm2d(dim)
        )
        #逐点卷积
        self.Conv_1x1 = nn.Sequential(
            nn.Conv2d(dim,dim,kernel_size=1),
            nn.GELU(),
            nn.BatchNorm2d(dim)
        )
    def forward(self,x):
        x = x +self.Resnet(x)
        x = self.Conv_1x1(x)
        return 

在ConvMixer Layer 中, 使用了深度可分离卷积,GELU 激活函数,逐点卷积。
论文中将图中红色部 称为 “channel wise mixing” 蓝色部分称为 “spatial mixing”
论文得到的结论是当深度可分离卷积部分的卷积核越大,模型的性能越好。文章中的使用的是9×9的卷积核,因为卷积核越大表现越好

文章最后也认为,ViT 表现如此优越 是因为patch embedding (图片分块)的原因。
作者认为 patch embedding 操作就能完成神经网络的所有下采样过程,降低了图片的分辨率,增加了感受野,更容易找到远处的空间信息。从而模型表现良好

论文阅读——合集(持续更新)

文献链接

图像分类(Classification)

目标检测(Object Detection)

语义分割(Semantic Segmentation)

实例分割(Instance Segmentation)

关键点检测(Keypoint Detection)

自然语言处理

Others

CVPR 2022 | 重新审视池化:你的感受野不是最理想的

作者丨简单来源丨CV技术指南

本文提出了一种简单而有效的动态优化池操作( Dynamically Optimized Pooling operation),称为DynOPool,它通过学习每一层感受野的最佳大小和形状来优化特征映射的端到端比例因子。

前言

本文提出了一种简单而有效的动态优化池操作( Dynamically Optimized Pooling operation),称为DynOPool,它通过学习每一层感受野的最佳大小和形状来优化特征映射的端到端比例因子。深度神经网络中任何类型的调整大小模块都可以用DynOPool操作以最小的成本替换。此外,DynOPool通过引入一个限制计算成本的附加损失项来控制模型的复杂性。

Pooling Revisited: Your Receptive Field is Suboptima

论文:https://arxiv.org/abs/2205.15254

公众号后台回复“DynOPool”获取论文PDF

背景

尽管深度神经网络在计算机视觉、自然语言处理、机器人、生物信息学等各种应用中取得了前所未有的成功,但最优网络结构的设计仍然是一个具有挑战性的问题。而感受野的大小和形状决定了网络如何聚集本地信息,并对模型的整体性能产生显著影响。神经网络中的许多组成部分,例如用于卷积和池化运算的内核大小和步长,都会影响感受野的配置。然而,它们仍然依赖于超参数,现有模型的感受野会导致形状和大小不理想

本文通过介绍固定大小和形状的传统感受野是次优的问题,讨论了DynOPool如何通过CIFAR-100上的VGG-16玩具实验解决这个问题。

固定大小和形状的传统感受野存在的问题:

1.不对称分布的信息

最佳感受野形状会根据数据集中固有的空间信息不对称性而改变。而大多数情况下固有的不对称性是不可测量的。此外,通常用于预处理的输入大小调整有时也会导致信息不对称。在人工设计的网络中,图像的长宽比经常被调整以满足模型的输入规格。然而,这种网络中的感受野不是用来处理操作的。

为了验证所提出的方法,作者在CIFAR-stretch-V上进行实验,如图1(a)所示,相较于人工设计模型,形状通过DynOPool动态优化的特征映射通过在水平方向上提取更具有价值的信息提高性能。

图片

图1  用来自CIFAR-100的三个不同的合成数据集进行玩具实验:(a)随机裁剪垂直拉伸的图像 (b)在4×4网格中平铺缩小的图像 (c)放大缩小的图像。

2.密集分布或稀疏分布信息

局部性是设计最优模型的组成部分。CNN通过级联的方式聚合局部信息来学习图像的复杂表示。而局部信息的重要性很大程度上取决于每个图像的属性。例如,当一个图像被模糊化时,大多数有意义的微观模式,如物体的纹理,都会被抹去。在这种情况下,最好在早期层中扩展感受野,集中于全局信息。另一方面,如果一幅图像在局部细节中包含大量类特定的信息,例如纹理,则识别局部信息将会更加重要。

为了验证假设,作者构建了CIFAR-100数据集的两个变体,CIFAR-tile和CIFAR-large,如图1(b)和(c)所示。作者模型在很大程度上优于人工设计的模型。

贡献

为了缓解人工构建的体系结构和操作的次优性,作者提出了动态优化池操作(DynOPool),这是一个可学习的调整大小模块,可以替代标准的调整大小操作。该模块为在数据集上学习的操作找到感受野的最佳比例因子,从而将网络中的中间特征图调整为适当的大小和形状。

论文的主要贡献:

1、解决了深度神经网络中现有尺度算子依赖于预定超参数的局限性。指出了在中间特征图中寻找最佳空间分辨率和感受野的重要性。

2、提出了一个可学习的调整尺寸大小的模块DynOPool,它可以找到中间特征图的最佳比例因子和感受域。DynOPool使用学习到的比例因子识别某一层的最佳分辨率和感受野,并将信息传播到后续层,从而在整个网络中实现规模优化。

3、证明了在图像分类和语义分割任务中,使用DynOPool的模型在多个数据集和网络架构上优于基线算法。它还显示了精度和计算成本之间的理想权衡。

方法

1.动态优化池(DynOPool)

图片

图2 DynOPool中的调整大小模块

模块通过优化一对输入和输出特征映射之间的比例因子r来优化查询点q的位置以及获得中间特征映射的最佳分辨率。DynOPool在不影响其他算子的情况下,自适应控制较深层接收域的大小和形状。

图片

图3 DynOPool整个的优化过程

针对比例因子r梯度不稳定,会产生梯度爆炸导致训练过程中分辨率发生显著变化的问题,使用a重新参数化r如下:

图片

2.模型复杂性约束

为了最大化模型的精度,DynOPool有时会有较大的比例因子,增加了中间特征图的分辨率。因此,为了约束计算代价,减少模型规模,引入了一个额外的损失项LGMACs,它由每次训练迭代t的分层GMACs计数的简单加权和给出,如下所示:

图片

实验

图片

表1 人工设计模型与使用DynOPool模型的精度(%)和GMACs比较

图片

图4 在VGG-16上使用人工设计的Shape Adaptor与使用DynOPool的训练模型可视化

图片

表2 在CIFAR-100数据集上DynOPool和Shape Adaptor的比较

图片

表3 在ImageNet数据集上EfficientNet-B0+DynOPool的性能

图片

表4 基于PascalVOC的HRNet-W48语义分割结果

结论

作者提出了一种简单而有效的动态优化池操作(DynOPool),它通过学习每个层中感受野的理想大小和形状来优化端到端的特征映射的比例因子,调整中间特征图的大小和形状,有效提取局部细节信息,从而优化模型的整体性能;

DynOPool还通过引入一个额外的损失项来限制计算成本,从而控制模型的复杂性。实验表明,在多个数据集上,该模型在图像分类和语义分割方面均优于基线网络。

IEEE论文投稿流程

摘自 BeyondSelf

这是一篇节省你翻论坛、查资料的文章。

我将把每一步尽量写的清楚,能够让新手按照这篇文章进行完整的投稿

即使你从未投过稿,完全不了解IEEE的投稿流程,希望按照这篇文章,能够帮助你流畅无误的投稿

这是针对本科生和低年级研究生,对投稿流程还不清楚,或者在初次投稿时可以参考的文章。

(零)预备:账号注册

这一步是为了注册ORCID和IEEE的账号,已经有账号的可以忽略不看

对于IEEE的不同杂志,是由不同的投稿账号的,这一点需要注意

1.注册ORCID,ORCID类似于你的身份证号码,即使你的名字改变,但是号码是不变的。

(1)进入orcid官网ORCID​orcid.org/

(2)选择右上方的SIGN IN/REGISTER

(3)依次填入所需的信息

2.注册IEEE账号

(1)进入IEEE查文献的主页https://ieeexplore.ieee.org/Xplore/home.jsp​ieeexplore.ieee.org/Xplore/home.jsp

(2)搜索期刊名字,会展示如下画面,这里以IEEE Transactions on communications 举例:

点击你想要投稿的期刊

(3)找到Submit Manusript,这个选项几乎所有的期刊都有。

(4)点击创建账户

(5)点击Associate your existing ORCID id

(6)在弹出页面中点击授权

(7)依次填入姓名和邮箱,只填必须项即可

之后就是输入地址和密码,按实际情况填写即可

(一)论文写作

1.下载模板

IEEE的期刊都会给一个模板,但是不同期刊会共用同一套模板。下载模板的网址为:https://journals.ieeeauthorcenter.ieee.org/create-your-ieee-journal-article/authoring-tools-and-templates/tools-for-ieee-authors/ieee-article-templates/​journals.ieeeauthorcenter.ieee.org/create-your-ieee-journal-article/authoring-tools-and-templates/tools-for-ieee-authors/ieee-article-templates/

IEEE Article Templates – IEEE Author Center JournalsIEEE Article Templates – IEEE Author Center Journals​journals.ieeeauthorcenter.ieee.org/create-your-ieee-journal-article/authoring-tools-and-templates/tools-for-ieee-authors/ieee-article-templates/

(0)点击 IEEE Template Selector 进入模板下载页面

(1)首先会让选择要写的文章类型,给了三个选项:

如果写常规的文章的话,就选第一个,包含trans和letter。会议的话,就选第三个。Magazine一般是指总结或者科普类的文章,影响因子高,但是一般你的第一篇文章,导师不会让你写这个。

(2)其次选择期刊的名字

这里直接输入即可,如“IEEE Transactions on Communications”.

(3)之后会依次选择文章的类型和格式,这里可供选择的格式有Latex和Word,首选Latex,一方面是因为格式好调,另一方面是因为敲公式快一些

(4)下载好模板之后,就可以开始写作了

2.论文写作准备

有了模板之后,还需要知道该期刊对于文章的要求,比如说页数,单栏还是双栏。这里不同期刊的要求不一样,对于新手来说,由于网页的设置,找到它并不容易。我这里来详细介绍下。

(1)进入IEEE查文献的主页https://ieeexplore.ieee.org/Xplore/home.jsp​ieeexplore.ieee.org/Xplore/home.jsp

(2)搜索期刊名字,会展示如下画面,这里以IEEE Transactions on communications 举例:

点击你想要投稿的期刊

(3)找到Submit Manusript,这个选项几乎所有的期刊都有。

(4)点进去之后,发现左下角有一个Journal Home,点击

(5)在上述网页中,找到你想要投稿的期刊(当然,你也可以跳过上述步骤,直接进入到这里~之所以要经过这些步骤,是因为接下来会用到其中一些步骤)

在出现的页面中,会有submission guidelines:

这里就说明,此期刊提交的时候要求单栏,12号字,不超过30页

这里教大家一个小技巧,如果整个网页页面太长的话,直接按Ctrl+F 搜索column关键词,因为所有的期刊都会要求单栏还是双栏,所以主要要求就在这个附近

(6)在第(4)步中,如果页面的右边已经有guidelines,那么就不需要再进入journal home了

对TPAMI杂志来说,直接点击红线所示,就可以得到文章要求,双栏,不超过12页

对于IEEE trans系列的杂志,基本上模板都是差不多的,如果在官网上找不到,也可以直接百度搜索一个模板

(二)论文投稿

在得到模板以及文章的要求之后,就可以开始论文写作了。当然,如果在上述步骤中找不到期刊的具体要求也没事,可以先写,一些格式问题可以之后再说,在文章正式发表前,编辑还会进行修改。这里假设你的论文已经写完,开始进入投稿环节

1.进入想要投稿期刊的主页,点击submit mannusript

2. 这里会要求你登入账号,一般是用导师的账号或者自己注册。投稿的账号一般就是通信作者

3.登录成功后,点击Author

4.点击Start New Submission中的Begin Submission,会出现如下信息

依次填入文章的类型、上传文件、作者等相关信息,就可以完成整篇文章的上传。这里以IEEE transactions on communications 举例,展示提交的流程

Step 1:

(1)首先选择类型,一般的话,就选常规的

(2)然后输入题目和摘要

Step 2:上传文件,一般是上传PDF

Step 3:输入关键字,下拉列表找到最贴合论文的,点击添加

Step 4:输入作者信息,与论文保持一致

Step 5 :选择审稿人,如果没有想选的话,可以跳过

Step 6 :是一些与文章相关的细节,可以按文章情况填写。

Step 7 :检查环节,确认无误后就可以正式提交了

注:邮箱是最重要的联系方式,之后会通过邮件联系你,请及时查看,而且对于修改等是有截止日期的。

(三)等待

论文会首先分配编辑,然后分配审稿人。可能会给你返回的状态有:Reject,Reject(Resubmission Allowed),Major,Minor,Accept

1.Reject并且不允许重投的话,说明就凉了

2.Reject且允许重投的话,也还凑合,重投的话可能被接受

3.Major大修,一般Major的话,如果修改没问题的话,大概率被接收

4.Minor小修,这样子的话基本也没问题

5.Accept是最好的,但不会刚投稿就这样,起码得有个minor,都得为难你一下

(四)接收后

当文章被接收后,编辑会给你发一个邮件,让你填一些内容,大概是著作权之类的。这些就按照要求来即可

之后会有一个校对环节,你需要在编辑给你发送的PDF上修改,而不能再重新提交PDF。此时的文章状态一般是Early Access,如果没有挂arxiv的话,在这个阶段,你就可以搜到自己的文章,并且也可以被引用了。再过一段时间,状态就会更新为Publish,就说明正式发表了。

IEEE 会议模板介绍

IEEE会议模板中提供了latex格式要求。

模板下载

一般在所投期刊和会议的官网上都会给出投稿模板或者给出投稿模板的链接。以IEEE的会议模板页面为例

我们可以在页面中下载自己想要的模板。一般分为LATEX版本和Microsoft Word版本,为了适应大部分读者朋友,本文我们以Microsoft Word版的A4为例进行讲解(A4和美国信纸的版本主要在于纸张大小和页边距不同,一般选用A4版)。点击链接可以下载模板打开之后如下:

可以看到,模板中已经有很多内容了。主要为对模板的介绍,示例以及一些注意事项。我一般是将自己的内容复制进去再用格式刷刷一遍来保证排版正确。下面我们开始介绍一下各部分的注意事项。

title

标题除了要使用样式表中的“title”之外,需要注意是不能使用副标题的。此外不可以使用符号,特殊字符,脚注或数学元素。

除非不可避免,不要在title中使用缩写。

如果uses可以准确替代using,则u大写,否则小写。

Author

模板可以有(但不限于)六位作者。所有的会议文章至少要有一位作者。作者名称从左到右列出,然后到下一行。作者序列将在以后的引用和索引服务中使用。

对于作者超过六名的论文:水平添加作者姓名。如果作者超过八名,请写到第三行。
对于作者少于六个的论文按以下步骤调整:

  • 选择:强调所有的作者和隶属行
  • 更改列数:从工具栏中选择列图标,然后选择正确的列数
  • 删除:删除多余作者的作者和隶属行

对于作者信息的书写,第一行是姓名,第二三行是组织名称,第四行是城市和国家,第五行是email或ORCID。请确保组织隶属关系尽可能简洁(例如,不要在同一组织的部门之间进行区分)。

Abstract

不可以使用符号,特殊字符,脚注或数学。

Keywords

无明确要求,一般写5个左右。

Heading

除非不可避免,不要在heading中使用缩写。

在混入式标题中,例如摘要需要用斜体区分标题和文本。

包含两种component heads 和text heads.

component heads包括Acknowledgments 和References ,使用Heading 5样式。

text heads按照关系、层级组织。有“Heading 1”,“Heading 2”,“Heading 3”和“Heading 4”的样式。

Text

分离文本和图形文件。只在段落末尾使用一个回车。不要在任何位置使用用任何分页。不要给文本标题加上数字,这些由模板来做。

缩写

即使在摘要中已经定义了缩写和首字母缩写,也要在正文首次使用时进行定义。不必定义诸如IEEE,SI,MKS,CGS,sc,dc和rms之类的缩写。

单位

使用SI(MKS)或CGS作为主要单位(鼓励使用SI单位)。英语单位可在括号中标注作为辅助单位。使用英文单位作为交易中的标识符除外,如“3.5英寸磁盘驱动器”。

避免同时使用SI和CGS单位,如以安培为单位的电流和以奥斯特为单位的磁场。如果必须使用混合单位,请说明方程中使用的每个数量的单位。

不要混用单位的完整拼写和缩写:“Wb/m2”或“webers per square meter”是正确的的,但“webers/m2”是错误的。当文本中出现单位时,将它们拼写出来:“. . . a few henries”,而非“. . . a few H”。

小数点之前的零不要省略:“0.25”而不是“.25”。使用“cm3”,而不是“cc”。

公式

请确定公式使用的是Times New Roman或者Symbol字体。要创建多级公式,可以将公式做成图形,然后将其插入文本中。

对公式使用连续编号。括号内的方程式编号右对齐。为了使用公式更紧凑,可以使用“/”,exp函数或者适当的指数。数量或变量使用 Italicize Roman symbols,而不是 Greek symbols。使用长破折号而不是连字符来表示减号。当公式是句子的一部分时,记得使用逗号或句号。

注意,公式是使用中心制表符来居中的。要确保在公式之前或之后立即定义公式中的符号。使用“(1)“,而不是“Eq. (1)”或“equation (1)”。除非是在句子开头时,使用“Equation (1) is”的描述。

图要放在列的顶部或者底部,避免将它们放在列的中间。大图可以跨越两列。在文本中引入后将其插入。即使在句子开头,也要使用缩写“Fig. 1”。

图的标签要使用8号Times New Roman字体,编写标签时使用单词而不是符号或缩写。如果在标签中包含单位,请在括号内标注。不要仅用单位标注轴。不要以数量和单位的比例标记轴。

图的标题放在图的下方,使用figure caption样式。

建议使用文本框插入图,此方法比直接插入图片更稳定。将文本框的颜色和相同安排选择为无填充和无线条。

表要放在列的顶部或者底部,避免将它们放在列的中间。大表可以跨越两列。在文本中引入后将其插入。

表的标题放在表的上方,使用table head样式。

如需使用脚注请用字母。

脚注

在上标中分别编号。将实际脚注放在引用该脚注的列的底部。

在这里插入图片描述

ACKNOWLEDGMENT

在美式英语中acknowledgment中g后没有e。赞助致谢请放在第一页无编号脚注中。

REFERENCES

在方括号[1]中连续编号参考文献。句子标点在方括号之后。使用“in [3]”而不是“Ref. [3]” 或者“reference [3]”,除非在句子开头可用“Reference [3] was the first …”

不要放置脚注。

除非有六位以上的作者,否则给出所有作者的名字,不要使用et al.。尚未发表的论文,即使已经提交发表,也应该引用为“unpublished”。已被接收发表的论文应引用为“in press”。出专有名词和元素符号外,仅将论文标题中的第一个单词大写。

对于在翻译期刊上发表的论文,请先给出英文引文,然后再给出外语原文。

最后要做的

模板用于撰写和格式化论文。在提交之前,请确保从文件中删除了所有模板文本,否则将会导致论文无法发表。