文章目录
传送门:
作者介绍的另一篇论文:《Intriguing Properties of Vision Transformer》(Vision Transformer的一些有趣特性)如下图所示:

上述例子中,卷积神经网络很难判断到底是一个什么物体,但是对于所有的这些例子Vision Transformer都能够处理的很好。
在VIT之前,self-attention在CV领域的应用很有限,要么和卷积一起使用,要么就是把CNN里面的某些模块替换成self-attention,但是整体架构不变。
VIT的出现,打破了AlexNet出现以来CNN网络在CV领域的统治地位。VIT表明,在图片分类任务中,只使用纯的Vision Transformer结构也可以取的很好的效果(最佳模型在ImageNet1K上能够达到88.55%的准确率)开启CV新时代。而且 VIT将CV直接当做NLP来做,还打破了CV和NLP的模型壁垒,推进了多模态领域的发展。
下图
Ours-JFT表示在在Google自家的JFT数据集上进行了预训练,Ours-I21K表示在ImageNet 21K上预训练,再在ImageNet 1K上测试。实验分数也可以在paperwithcode的Dataset排行榜上看到。
在这篇文章中,作者主要拿ResNet、ViT(纯Transformer模型)以及Hybrid(卷积和Transformer混合模型)三个模型进行比较,所以本博文除了讲ViT模型外还会简单聊聊Hybrid模型。
基于self-attention的模型架构,特别是Transformer,在NLP领域几乎成了必选架构。现在的主流方式就是:在大型语料库上训练一个大模型,然后迁移到小的数据集上进行微调。多亏了Transformer的高效性和可扩展性,现在已经可以训练超过1000亿参数的大模型,随着模型和数据集的增长,还没有看到性能饱和的现象。 (英伟达和微软联合推出的大型语言生成模型Megatron-Turing,有5300亿参数,还能在各种任务上大幅度提升性能,而没有达到性能饱和)
Transformer是对输入序列做self-attention,其复杂度是 O ( n 2 ) O(n^2) O(n2),现在支持的最大序列长度一般就是几百几千。如果直接把图片每个像素值拉平当做输入序列,那么序列就太长了。所以在CV领域CNN一直占主导地位。
受NLP启发,很多工作尝试将CNN和self-attention结合起来。那怎么降低输入序列把它用到CV领域呢?
Stand-Alone Axial-Attention来处理。具体的说,不是输入整张图,而是在一个local window(局部的小窗口)中计算attention。窗口的大小可以控制,复杂度也就大大降低。(类似卷积的操作) 所以,自注意力早已经在计算机视觉里有所应用,而且已经有完全用自注意力去取代卷积操作的工作了。
这些模型虽然理论上是非常高效的,但事实上因为这个自注意力操作都是一些比较特殊的自注意力操作(除了上面举例的最后一篇),要很复杂的工程去加速算子,所以就导致很难训练出一个大模型。因此在大规模的图像识别上,传统的残差网络还是效果最好的。
本文是被transformer在NLP领域的可扩展性所启发,本文想要做的就是直接应用一个标准的transformer作用于图片,尽量做少的修改。好处是可以直接使用NLP中成熟的Transformer架构,不需要再魔改模型,而且Transformer这么多年有很多高效的实现。具体的处理方式见下一节。
上面举例的例4模型,从技术上讲就是
Vision Transformer。但是作者认为二者的区别,是本文证明了,使用一个标准的Transformer endoder(类似BERT,不需要任何特殊改动)在大规模的数据集上做预训练的话,就能取得比现在最好的卷积神经网络差不多或者还好的结果。(这是本文的主要论证工作,在1.4.2和1.4.3章节都有体现 )另外就是二者可处理图片的分辨率不同(32×32对比224×224)。
引言的最后部分放出了结论:
inductive bias,是指一种先验知识或者说是一种提前做好的假设)。CNN的归纳偏置一般来说有两种:
locality:CNN是以滑动窗口的形式一点一点地在图片上进行卷积的,所以假设图片上相邻的区域会有相邻的特征,靠得越近的东西相关性越强;translation equivariance(平移等变性或平移同变性):写成公式就是f(g(x))=g(f(x)),不论是先做 g 这个函数,还是先做 f 这个函数,最后的结果是不变的;其中f代表卷积操作,g代表平移操作。(因为在卷积神经网络中,卷积核就相当于是一个模板,不论图片中同样的物体移动到哪里,只要是同样的输入进来,然后遇到同样的卷积核,那么输出永远是一样的)
简单介绍了一下Transformer在NLP领域应用最广的两大分支BERT和GPT,都是基于自监督的训练方式(MLM任务和Next word prediction)。
直接将图片的像素作为序列输入Transformer是不可行的,所以作者介绍了一下之前的相关处理方式(类似上面引言提到的几个模型)。
第三段介绍了,有一些工作研究了用比ImageNet更大的数据集去做预训练,效果会更好,比如说ImageNet-21k和JFT300M。最终作者也是在这两个数据集上预训练模型。
下图是原论文中给出的关于Vision Transformer(ViT)的模型框架。简单而言,模型由三个模块组成:
Embedding层(线性投射层Linear Projection of Flattened Patches)Transformer Encoder(图右侧有给出更加详细的结构)MLP Head(最终用于分类的层结构)
如上图所示:
embedding层(图片输入)
patchs,然后这些patchs一个个输入线性投射层得到Pacth embedding。比如ViT-L/16表示每个patchs大小是16×16。class token作为这些patchs全局输出,相当于transformer中的CLS(这里的加是concat拼接)。position embedding(这里的加是直接向量相加,不是concat)。Pacth embedding+position embedding+class token一起输入Transformer Encoder层得到其输出。MLP Head得到分类结果。(VIT只做分类任务)整体上看,VIT的模型结构还是很简洁的,难点就是如何将图片转为token输入网络。
对于标准的Transformer模块,要求输入的是token(向量)序列,即二维矩阵[num_token, token_dim]。对于图像数据而言,其数据为[H, W, C]格式的三维矩阵,明显不是Transformer想要的。所以需要先通过一个Embedding层来对数据做个变换。
ViT-B/16为例(后面都是以此模型举例),将输入图片(224x224)按照16x16大小的Patch尺寸进行划分,划分后会得到
(
224
/
16
)
2
=
196
(224/16)^2=196
(224/16)2=196个Patches。[16, 16, 3] -> [768]在代码实现中,直接通过一个卷积层来实现。卷积核大小为16x16,步距为16,卷积核个数为768。通过卷积
[224, 224, 3] -> [14, 14, 768],然后把H以及W两个维度展平即可[14, 14, 768] -> [196, 768],此时正好变成了一个二维矩阵,正是Transformer想要的。
如果模型更大的话,Pacth embedding可以映射到更大的维度,也就是论文中提到的参数D。

3. 加上[class]token以及Position Embedding。
在原论文中,作者说参考BERT,添加一个[class]token(用来表示序列特征),然后与之前从图片中生成的tokens拼接在一起,Cat([1, 768], [196, 768]) -> [197, 768]
这里的Position Embedding采用的是一个可训练的参数(1D Pos. Emb.),是直接叠加在tokens上的(add),所以shape要一样,也是[197, 768]。
关于为什么使用[class]token和1D Pos. Emb,在本文1.5.1消融试验部分会讲到。
Transformer Encoder其实就是重复堆叠Encoder Block L次,主要由以下几部分组成:
[197, 768] -> [197, 3072],第二个全连接层会还原回原节点个数[197, 3072] -> [197, 768],原来跟transformer中做法一样。Encoder Block。ViT-B/16模型结构图 上面通过Transformer Encoder后输出的shape和输入的shape是保持不变的,以ViT-B/16为例,输入的是[197, 768]输出的还是[197, 768]。对于分类,我们只需要提取出[class]token生成的对应结果就行,即[197, 768]中抽取出[class]token对应的[1, 768]。
接着我们通过MLP Head得到我们最终的分类结果。MLP Head原论文中说在训练ImageNet21K时是由Linear+tanh激活函数+Linear组成。但是迁移到ImageNet1K上或者你自己的数据上时,只定义一个Linear即可。
下面是小绿豆绘制的ViT-B/16模型结构图:(Pre-Logits就是Linear+tanh,一般迁移学习是可以不用的。)

作者在论文3.1 VIT部分,对整个过程用数学公式描述了一次:

在CNN中,locality(局部性)和translate equivariance(平移等变性)是在模型的每一层中都有体现的,这个先验知识相当于贯穿整个模型的始终。
但是对于ViT来说,只有MLP层是局部而且平移等变性的,其它的自注意力层是全局的,这种图片的2d信息ViT基本上没怎么使用。
就是只有刚开始将图片切成patch的时候和加位置编码的时候用到了,除此之外,就再也没有用任何针对视觉问题的归纳偏置了,而且位置编码也是随机初始化的1-D信息。所以在中小数据集上ViT不如CNN是可以理解的。
既然transformer全局建模的能力比较强,卷积神经网络又比较data efficient(不需要太多的训练数据),那么自然想到去搞一个前面层是CNN后面层是transformer的混合网络,也就是Hybrid混合模型。Hybrid不再直接将图片打成一个个patch,而是直接送入CNN得到embedding,比如经过Resnet50,最后一个stage输出特征图是14×14,拉直了也是196维向量。这部分细节参考文本1.4实验部分。
之前的工作有表明,使用更大的图片输入尺寸往往模型效果会更好。但是使用一个预训练好的vision transformer,其实是不太好去调整输入尺寸的。如果还是将patch size保持一致,但是图片扩大了,那么序列长度就增加了,提前预训练好的位置编码有可能就没用了。
这个时候位置编码该如何使用?作者发现其实做一个简单的2d的插值就可以了(使用torch官方自带的interpolate函数就完成)。但这只是一个临时的解决方案,如果需要从一个很短的序列变成一个很长的序列时,简单的插值操作会导致最终的效果下降(比如256→512)。这也算是vision transformer在微调的时候的一个局限性。
因为使用了图片的位置信息进行插值,所以这块的尺寸改变和抽图像块是vision transformer里唯一用到2d信息的归纳偏置的地方。
在论文的4.1章节的Table1中有给出三个模型(Base/ Large/ Huge,对应BERT)的参数,在源码中除了有Patch Size为16x16的外还有32x32的。其中:
Layers:Transformer Encoder中重复堆叠Encoder Block的次数Hidden Size:对应通过Embedding层后每个token的dim(向量的长度)MLP size:Transformer Encoder中MLP Block第一个全连接的节点个数(是Hidden Size的四倍)Heads:代表Transformer中Multi-Head Attention的heads数(多头注意力有几个头)。
对比VIT的几个不同配置模型和BiT-L,以及Noisy模型。最终效果提升不大,但是ViT训练时间短很多。(的后面还有其它的对比试验支持作者的这个观点)
TPU-v3-core-days 2.5k:表示最大的ViT-H/14模型在TPU-v3上只需要训练2500天。

vision trasformer预训练需要多大的数据规模?(重要论证) 下图展示了在不同大小的数据集上预训练后,BiTt和VIT到底在ImageNet的微调效果如何。
BiT,上下两条线分别表示使用ResNet50和ResNet152结构;其它五个
∙
\bullet
∙就是不同配置的ViT。ImageNet、ImageNet 21K、JFT-300M三种规模的数据集上训练的结果,三种数据集规模分别是1.2Million,14M和300MJFT数据集上分别采样不同规模子集的实验结果,这里ViT用作特征提取器而不是微调。(去除了训练时的强约束,比如说dropout、weight decay、label smoothing;而且不同规模的数据集来自同一分布,更能看出模型本身的特性)
ViT,那么得至少是在ImageNet-21k这种规模的数据集上预训练(数据量14M),否则还不如用CNN。下图再次论证作者观点(VIT训练更便宜):
Average-5就是他在五个数据集(ImageNet real、pets、flowers、CIFAR-10、CIFAR-100)上做了验证后的平均结果ImageNet 上的验证结果JFT-300M上预训练号的模型
ViT比BiT效果要好,这也说明ViT训练比CNN更便宜Hybrid混合模型比其它两者效果都要好Hybrid精度慢慢的跟ViT差不多了,甚至还不如在同等计算条件下的ViT。为什么卷积神经网络抽出来的特征没有帮助ViT更好的去学习?这里作者对此也没有做过多的解释。ViT和BiT都没有性能饱和的迹象。统一见本文1.6 可视化部分。
这部分放在正文而不是负类中,是因为作者认为:在NLP领域,Transformer这个模型确实起到了很大的推动作用,但另外一个真正让Transformer火起来的原因其实是大规模的自监督训练,二者缺一不可。
NLP中自监督方式是MLM任务或者Next word prediction,本文模仿的是BERT,所以作者考虑构造专属于ViT的目标函数Mask patch prediction。具体来说,给定一张图片,将它打成很多patch,然后将某些patch随机抹掉,然后通过这个模型将这些patch重建出来。
但是最后ViT-Base/16在ImageNet只能达到80的左右的准确率,比最好的有监督方式训练,还是差了四个点,所以作者后面的工作是考虑引入对比学习。
对比学习是所有自监督学习中表现最好的,紧接着出现的
ViT MoCo v3和DINO就是在ViT的基础上使用了对比学习。
这部分内容在论文附录的D Additional Analyses部分
虽然最终VIT采用的[CLS]token和1D-Position Embedding都和BERT是一样的,但是作者在论文实验部分也都对此作了很多消融试验。比如:
[CLS]token是从NLP领域借鉴的,但是之前的CNN网络用于图片分类的特征并非这么做。
Pacth embedding中不加入[CLS]token,而是在最后Transformer Encoder输出序列向量时,用一个GAP来得到最终全局表征向量,最终结果和使用[CLS]token的效果几乎差不多 。[CLS]token,因为本文目的是跟原始的Transformer尽可能地保持一致,不想大家觉得效果好可能是因为某些trick或者某些针对cv的改动而带来的,作者就是想证明, 一个标准的Transformer照样可以做视觉。Position Embedding作者也有做一系列对比试验,在源码中默认使用的是1-D Pos. Emb.,对比不使用Position Embedding准确率提升了大概3个点,和2-D Pos. Emb.以及Rel. Pos. Emb.比起来没太大差别。
2-D Pos. Emb.(2D位置编码)就是用patch的横纵坐标表示其位置,而不是一个一维的序号。其中横坐标有D/2的维度,纵坐标也有D/2的维度,两者拼接到得到了一个D维的向量。
Rel. Pos. Emb.:相对位置编码。两个patch之间的距离可以使用绝对位置编码,也可以使用相对位置编码,最终结果差不多。
作者对此解释是:ViT是直接在图像块上做的,而不是在原来全局尺度的像素块上做的,所以在排列组合这种小块或者想要知道这些小块之间相对位置信息的时候,还是相对比较容易的,所以使用任意的位置编码都无所谓。
在论文4.1章节的Model Variants中有比较详细的讲到,就是将传统CNN特征提取和Transformer进行结合。下图绘制的是以ResNet50作为特征提取器的混合模型Hybrid,但这里的Resnet与之前讲的Resnet有些不同。
StdConv2d不是传统的Conv2d,然后将所有的BatchNorm层替换成GroupNorm层。如果有stage4就是下采样32倍,改为只有stage3就是下采样16倍,这样224×224的图片输出的就是14×14大小。
通过ResNet50 Backbone进行特征提取后,得到的特征矩阵shape是[14, 14, 1024],接着再输入Patch Embedding层,注意Patch Embedding中卷积层Conv2d的kernel_size和stride都变成了1,只是用来调整channel。
后面的部分和前面ViT中讲的完全一样,就不在赘述。
简单说,ViT是图片经过Conv2d卷积层得到Patchs,而Hybrid是多加了一步,图片经过ResNet50 Backbone进行特征提取后,经过卷积得到Patchs。然后都是加上class token和位置向量输入Transformer Encoder,得到class token都是输出。再经过MLP得到分类结果。

下表是论文用来对比ViT,Resnet(和刚刚讲的一样,使用的卷积层和Norm层都进行了修改)以及Hybrid模型的效果。通过对比发现,在训练epoch较少时Hybrid优于ViT,但当epoch增大后ViT优于Hybrid。

分析完训练成本以后,作者也做了一些可视化,希望通过这些可视化能够分析一下vit内部的表征。

Mean attention distance

ViT-L/16有24层,所以横坐标网络深度是从0到24 。ViT-L/16有16个头,每一列其实就是16个点。Mean attention distance(平均注意力的距离:图上两个像素点的真实距离乘以他们之间的attention weights,因为自注意力是全局都在做,所以平均注意力的距离就能反映模型到底能不能注意到两个很远的像素)Mean attention distance从10几到100多,有的近有的远,这也就证明了自注意力能够在网络最底层,也就是刚开始的时候就已经能够注意到全局上的信息了,而不是像卷神经网络一样,逐步提升感受野。output token的自注意力折射回原来的输入图片,可以发现模型确实是学习到了这些概念。
Vision Transformer和NLP领域标准的Transformer的自注意力机制区别在于:除了在刚开始抽图像块的时候,还有位置编码用了一些图像特有的归纳偏置,除此之外就再也没有引入任何图像特有的归纳偏置了。这样的好处就是可以直接把图片当做NLP中的token,拿NLP中一个标准的Transformer就可以做图像分类了。
这个策略扩展性非常好,和大规模预训练结合起来的时候效果也出奇的好,而且训练起来还相对便宜。
另外作者在这里对Vision Transformer还做了一些展望:
除以上几点之外,作者还在
多模态领域挖了一个大坑。CV和NLP大一统之后,是不是这些任务都可以用一个Transformer取解决呢?后续这一块也是推进的很快。
class PatchEmbed(nn.Module):
"""
2D Image to Patch Embedding
"""
def __init__(self, img_size=224, patch_size=16, in_c=3, embed_dim=768, norm_layer=None):
super().__init__()
img_size = (img_size, img_size)
patch_size = (patch_size, patch_size)
self.img_size = img_size
self.patch_size = patch_size
self.grid_size = (img_size[0] // patch_size[0], img_size[1] // patch_size[1])
self.num_patches = self.grid_size[0] * self.grid_size[1] # 在VIT-B/16中就是16*16
self.proj = nn.Conv2d(in_c, embed_dim, kernel_size=patch_size, stride=patch_size)
# 默认不传入norm_layer, nn.Identity()表示不做任何操作
self.norm = norm_layer(embed_dim) if norm_layer else nn.Identity()
def forward(self, x):
B, C, H, W = x.shape # x就表示传入的图片
# 需要注意的是,VIT模型不像传统的CNN模型那样,可以更改图片的入网尺寸。
assert H == self.img_size[0] and W == self.img_size[1], \
f"Input image size ({H}*{W}) doesn't match model ({self.img_size[0]}*{self.img_size[1]})."
# flatten: [B, C, H, W] -> [B, C, HW],最后两个维度拉平
# transpose: [B, C, HW] -> [B, HW, C],后两个维度交换
x = self.proj(x).flatten(2).transpose(1, 2)
x = self.norm(x) # 得到 Patch Embedding
return x
class Attention(nn.Module):
def __init__(self,
dim, # 输入token的dim
num_heads=8, # 多头注意力使用几个head
qkv_bias=False, # 生成qkv时是否使用偏置
qk_scale=None,
attn_drop_ratio=0., # dropout概率,下同
proj_drop_ratio=0.):
super(Attention, self).__init__()
self.num_heads = num_heads
head_dim = dim // num_heads # 每个head的维度,一般要求dim能整除num_heads
self.scale = qk_scale or head_dim ** -0.5 # 不传入qk_scale时,self.scale=根号dk
self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias) # 使用一个全连接层得到qkv
self.attn_drop = nn.Dropout(attn_drop_ratio)
self.proj = nn.Linear(dim, dim) # 多头拼接后用Wo映射,Wo就是全连接层实现
self.proj_drop = nn.Dropout(proj_drop_ratio)
def forward(self, x):
# [batch_size, num_patches + 1, total_embed_dim]
# num_patches + 1就是196+1(class token),total_embed_dim=768
B, N, C = x.shape
# qkv(): -> [batch_size, num_patches + 1, 3 * total_embed_dim]
# reshape: -> [batch_size, num_patches + 1, 3, num_heads, embed_dim_per_head]
# permute: -> [3, batch_size, num_heads, num_patches + 1, embed_dim_per_head]
qkv = self.qkv(x).reshape(B, N, 3, self.num_heads, C // self.num_heads).permute(2, 0, 3, 1, 4)
# [batch_size, num_heads, num_patches + 1, embed_dim_per_head]
q, k, v = qkv[0], qkv[1], qkv[2] # make torchscript happy (cannot use tensor as tuple)
# transpose: -> [batch_size, num_heads, embed_dim_per_head, num_patches + 1]
# @: multiply -> [batch_size, num_heads, num_patches + 1, num_patches + 1]
attn = (q @ k.transpose(-2, -1)) * self.scale
attn = attn.softmax(dim=-1)
attn = self.attn_drop(attn)
# @: multiply -> [batch_size, num_heads, num_patches + 1, embed_dim_per_head]
# transpose: -> [batch_size, num_patches + 1, num_heads, embed_dim_per_head]
# reshape: -> [batch_size, num_patches + 1, total_embed_dim]
x = (attn @ v).transpose(1, 2).reshape(B, N, C)
x = self.proj(x)
x = self.proj_drop(x)
return x
参考:
本文算法在2.3章节!!!
自从Vision Transformer将标准的transformer成功的应用到CV上面以来,就出现了很多相关性的工作,MAE就是其中的一篇。本文是2021.11.11发布在Arxiv上的文章,主要工作是在Vision Transformer基础上,引入自监督训练,相当于将BERT应用到CV领域。通过完形填空来获取对于图片的理解,把整个训练拓展到没有标号的数据上面 ,使得transformer在CV上的应用更加普及。
最终MAE只需要Vision Transformer百分之一规模的数据集上预训练,就能达到同样的效果。而且在目标检测、实例分割、语义分割等任务上,效果都很好。
本文标题中的
Autoencoders,是‘自’而非自动的意思,表示类似自回归这一类模型的特点, 即标号和样本(y和x)来自于同一个东西。比如说在语言模型中,每一次用前面的次去预测下一个词。而对于MAE,则表明模型的标号也是图片本身。
MAE的自监督训练实现途径非常简单,随机地mask图片中地一些patches(块),然后再去重构the missing pixels.,这个思想来自于BERT中的带掩码的语言模型。
在MAE中,自监督训练还有两个核心的设计:
非对称的编-解码器架构,非对称体现在两个方面:
高掩码率:比如mask 75%,才能得到一个比较好的自监督训练效果(否则只需要插值还原)。这等于只编码1/4的图片,训练速度加快了四倍,所以MAE可以扩展到更大的模型。
最终作者只使用一个最简单的ViT-Huge模型,在ImageNet-1K上预训练,精度也能达到87.8%。
下面是作者展示的一些模型重构效果图:


在导言一开始,作者大意就说自监督学习很香,使得Transformer在NLP领域的应用非常火。尽管也有一些工作将BERT应用到CV领域,比如Denoising Autoencoder是在一个图片中加入很多噪音,然后通过去噪来学习对这个图片的理解,但最终这些效果都不及NLP。
MAE也是一种类似去噪 的模型,mask一些patches,也相当于往模型中加入很多噪音
为何masked自编码模型在CV和NLP领域应用不一样呢?
msaked patches单独剔除,导致后面不好将图片还原(Transformer中可以将masked token直接去掉,和其他词区分开来)。但是ViT成功将Transformer应用到图片分类,所以这个问题不再有了。75%),就可以大大降低图片的冗余性。这样就压迫模型必须学习全局信息,也就提高了模型学习的难度。将图片中一大片都去掉, 剩下的块离得比较远,就没那么冗余了。否则模型仅仅学一个局部模型就可以进行插值还原。
关于此点论证,看上面图2.3.4就可以发现:仅仅一些局部的,很稀疏的块,就可以重构全局图片。
解码差异
masked tokens,而token本身就是一种比较高级一些的语义表示。而来自编码器的特征也是高度语义的,与需要解码的目标之间的 gap 较小,所以只需要一个简单的全连接层就可以解码这些tokens。(ViT最后需要的是图片特征,所以也只需要MLP就可以解码)the missing pixels,这些像素是一个很基础的特征。要将自编码器的高级语义特征解码至低级语义层级,所以可能需要一个比较复杂的转置卷积网络才能完成解码。正是基于以上分析,作者才提出本文的两个核心设计:高掩码率以及非对称编-解码器。
在导言最后一部分,作者说MAE可以只在ImageNet 1K上就能预训练ViT-Large/-Huge模型(得到很好的效果)。类比ViT,相同效果后者需要在近100倍规模的数据集上训练才能达到。
另外,在目标检测、语义分割和实例分割上,MAE比之前所有模型(包括有监督训练模型)效果都要好,而且加大模型会有显著的收益。
MAE使用编码器将观察到的信号映射到潜在表示,再使用一个解码器从潜在表示重构原始信号。与经典的自动编码器不同,我们采用了一种非对称设计,允许编码器仅对部分观察信号(无掩码标记)进行操作,模型设计图如下:

ViT:)
Pacth embedding+position embedding一起输入Transformer Encoder层得到其输出。position embeddings信息)。decoder,解码器会尝试将里面的像素信息全部重构回来,使之成为原始图片。endoder,将图片切成Patches后编码得到特征,然后用来处理自己的任务就行。(此时不需要掩码,也就不需要解码器)说明:上图中编码器比解码器更宽,表示模型的主要计算部分在编码器(最重要的就是编码像素得到特征)
shuffle),然后取前25%完成采样,输入encoder层。(后面75%就是做mask处理)ViT一样,不再赘述,唯一不同的是,被mask的块不进行编码。masked tokens不是通过mask 掉的 patch 经过 embedding 转换而来,而是通过一个共享的可学习向量来表示,也就是说每一个被mask的块都表示成同样的向量。position emebdding进行区分。unmask tokens;decoder处理所有tokens,但是结构轻量;通过这种非对称设计,使得整体结构十分高效,大大减少了预训练时间。masked tokens(在最开始 mask 掉 patches 的时候可以先记录下这些 masked 部分的索引)normalization(减均值除方差),这样数据更稳定。将以上讲解的全部串联起来就是:
patches:(B,C,H,W)->(B,N,PxPxC);embedding(实质是通过全连接层),生成 tokens,并加入位置信息(position embeddings):(B,N,PxPxC)->(B,N,dim);unmask tokens 输入 Encoder,另一部分“扔掉”(mask 掉);tokens 与 masked tokens( 加入位置信息) 按照原先在 patch 形态时对应的次序拼在一起,然后喂给 Decoder 玩。
unshuffle操作,还原到原来的顺序。微调层数对比
我们知道,预训练模型做微调的效果是比只做特征提取的效果更好的,但是训练时间会更长。所以作者试验了一下,微调不同的层数,模型的效果如何(见下图)。

1. ImageNet实验
下图是在 ImageNet-1K验证集上的top-1结果。(详见附录A1)

scratch,original:ViT-L/16模型正常地从头训练,效果其实不是很稳定。(200epoch)scratch,our impl.:ViT-L/16加上比较强的正则(详见附录A2)baseline MAE:在ImageNet上预训练,然后在ImageNet-1K上微调50epoch。2. decoder/mask策略/数据增强

上图展示的是MAE使用ViT-L/16结构,在ImageNet-1K数据集上的acc精度。下面一个个来看:
ft: fine-tuning微调lin:linear probing,只训练最后一个线性层的参数,相当于MAE只做特征提取- 最终
decoder的默认深度是8 blocks,宽度是512 dim,与VIT-L相比,计算量只有前者的9%.。
表a:展示不同的decoder深度,可见堆叠8个transformer block效果最好。(其实对微调来说,都差不多)
表b:decoder宽度,每个token表示成一个512维的向量,效果最好。
表c:是否编码masked tokens。结果是不编码精度更高,且计算量更少(编码的Flops是不编码的3.3倍)
表d:重建目标对比.。
MAE现行做法normalization,效果最好。PCA降维BEiT的做法,通过vit把每一块映射到一个离散的token上面再做预测。表e:数据增强。结果显示,做简单的随机大小裁剪,效果就不错
fixed size和 rand size分别表示裁剪成固定大小,和裁剪成随机大小。color jit 是加入颜色变换,none就是不使用数据增强了。
表f:采样策略。随机采样方式最简单,效果也最好。
random/block/grid分别表示随机采样、按块采样(mask大块)、按网格采样。下面有进一步的说明图:

3. mask比例
综合ft和lin考虑,masking ratio=75%时效果最好。(图就不放了)
1. 自监督模型效果对比
下表是在ImageNet-1K训练集上预训练后的微调结果:

在COCO数据集上的效果对比:

over
简单且拓展性好的算法,是整个深度学习的核心。
- 简单:是指
MAE在ViT模型上加了一些简单的扩展,但是模型本身是不简单的。- 拓展性好:是指你有钱就可以无限的加数据了,毕竟MAE不需要标号,你可以训练更大的模型。
自监督学习在最近几年是比较火的,但是在计算机视觉中,还是主要用有标号的数据来训练 。本文在ImageNet数据集上通过自编码器学习到可以媲美有标号训练的效果,使得CV领域的自监督学习可能走上与NLP类似的轨迹。
另一方面,图像和语言是不同类型的信息,要谨慎处理这种差异。
Broader impacts:MAE是个生成模型,可以生成不存在的内容,类似GAN,所以使用要注意。
Swin transformer是微软研究院于2021年3月25日发表在ICCV的一篇文章(ICCV 2021最佳论文),利用transformer架构处理计算机视觉任务,在图像分割,目标检测各个领域已经霸榜。比如打开其官网代码可以看到:(这排名不是卷死?)

首先看论文题目。Swin Transformer: Hierarchical Vision Transformer using Shifted Windows。即:Swin Transformer是一个用了移动窗口的层级式Vision Transformer(Hierarchical是层级式的意思)。
所以Swin来自于 Shifted Windows , 它能够使Vision Transformer像卷积神经网络一样,做层级式的特征提取,这样提取出来的特征具有多尺度的概念 ,这也是 Swin Transformer这篇论文的主要贡献。
本文提出了一个新的 Vision Transformer 叫做 Swin Transformer,它可以被用来作为计算机视觉领域一个通用的骨干网络 。
标准的Transformer直接用到视觉领域有一些挑战,即:
基于这两点,本文提出了 hierarchical Transformer,通过移动窗口来学习特征。
W-MSA(Window Multi-Self-Attention)。W-MSA大大降低了降低了计算复杂度。同时通过Shiting(移动)的操作可以使相邻的两个窗口之间进行交互,也因此上下层之间有了cross-window connection,从而变相达到了全局建模的能力。
Vision Transformer:进行MSA(多头注意力)计算时,任何一个patch都要与其他所有的patch都进行attention计算,计算量与图片的大小成平方增长。Swin Transformer:采用了W-MSA,只对window内部计算MSA,当图片大小增大时,计算量仅仅是呈线性增加。
在摘要后部分作者也说了,Swin Transformer能够提取多尺度特征之后,在多种视觉处理任务上都有很好的效果。比如ImageNet-1K 上准确度达到87.3%;在 COCO mAP刷到58.7%(比之前最好的模型提高2.7);在ADE上语义分割任务也刷到了53.5(提高了3.2个点 )
另外对于 MLP 的架构用 shift window 的方法也能提升,这一点在MLP Mixer中就有体现。
在这部分作者对比了Vision Transformer和Swin Transformer的结构区别,如下图所示:

可以看出主要区别有两个:
Vision Transformer中是一开始就直接下采样16倍,这样模型自始至终都是处理的16倍下采样率过后的特征,这样在处理需要多尺寸特征的任务时,效果不够好。Swin Transformer 使用patch merging,可以把相邻的四个小的patch合成一个大的patch,提高了感受野,这样就能获取多尺度的特征(类似CNN中的池化效果)。这些特征通过FPN结构就可以做检测,通过UNet结构就可以做分割了。Swin Transformer使用窗口(Window)的形式将特征图划分成了多个不相交的区域,并且只在每个窗口内进行多头注意力计算,大大减少计算量。locality。(在本帖1.1.3中讲过)。locality:CNN是以滑动窗口的形式一点一点地在图片上进行卷积的,所以假设图片上相邻的区域会有相邻的特征,靠得越近的东西相关性越强
- 在
Swin Transformer里,默认每个窗口有49个patch,第一层每个patch尺寸是4*4。locality进一步说明:对于图片来说,语义相近的不同物体还是大概率会出现在相连的地方,所以即使是在一个小范围的窗口内计算自注意力也是差不多够用的,全局计算自注意力对于视觉任务来说,其实是有点浪费资源的。W-MSA虽然减少了计算量,但也会隔绝不同窗口之间的信息传递。所以在论文中作者又提出了SW-MSA的概念,通过此方法能够让信息在相邻的窗口中进行传递,后面会细讲。
原论文中给出的关于Swin Transformer(Swin-T)网络的架构图如下:

ViT一样将图片分割成一个个4*4大小的patch([224,224,3]—>[56,56,48])Linear Embeding层:将每个像素的channel数调整为C,并对每个channel做一次Layer Norm。([56,56,48]—>[56,56,96])
- 假设输入的是RGB三通道图片,那么每个patch就有4x4=16个像素,然后每个像素有R、G、B三个值,所以展平后是16x3=48。
- swin-transformer有T、S、B、L等不同大小,其C的值也不同,比如
Swin-Tiny中,C=96。- 在源码中
Patch Partition和Linear Embeding就是直接通过一个卷积层实现的,和之前Vision Transformer中讲的 Embedding层结构一模一样。(kernel size=4×4,stride=4,num_kernel=48)
将每49个patch划分为一个窗口,后续只在窗口内进行计算。
通过四个Stage构建不同大小的特征图。其中后三个stage都是先通过一个Patch Merging层进行2倍的下采样。([56,56,96]—>[28,28,192]—>[14,14,384]—>[7,7,768])
每个stage中,重复堆叠Swin Transformer Block偶数次(结构见上图右侧,分别使用W-MSA和SW-MSA,两个结构成对出现)。
如果是分类任务,后面还会接上一个Layer Norm层、全局池化层以及全连接层得到最终输出。[7,7,768]—>[1,768]—>[1,num_class](也就是做序列的全局平均,类似CNN的做法,而不是加上CLS做分类)
- 如果不划分窗口,以
Swin-Tiny举例,Linear Embeding层输出矩阵为[56,56,96]。如果计算全局注意力的话,输入序列长度为56*56=3136,每个元素是96维,这个序列就太长了。- 引入
Shifted Windows后,每个序列长度固定为49。- 与ViT还有一点不同的是:
ViT在输入时会给embedding加上1D-位置编码。而Swin-T这里则是作为一个可选项(self.ape)。另外Swin-T在计算Attention时用的是相对位置编码。
看完整个前向过程之后,就会发现 Swin Transformer 有四个 stage,还有类似于池化的 patch merging 操作,自注意力还是在小窗口之内做的,以及最后还用的是全局平均池化 。所以可以说 Swin Transformer是披着Transformer皮的卷积神经网络,将二者进行了完美的结合。
接下来,在分别对Patch Merging、W-MSA、SW-MSA以及使用到的相对位置偏置(relative position bias)进行详解。

上面讲了,在每个Stage中首先要通过一个Patch Merging层进行下采样(Stage1除外)。
如上图所示,假设输入的是一个4x4大小的单通道特征图(feature map),分割窗口大小为2×2,Patch Merging操作如下:
可以看出,通过Patch Merging层后,feature map的高、宽会减半,深度翻倍。
W-MSA全称是window Multi-heads Self-attention。普通的Multi-heads Self-attention会对feature map中的每个像素(或称作token)都要计算Self-Attention。而W-MSA模块,首先将feature map按照MxM大小划分成一个个Windows,然后单独对每个Windows内部进行Self-Attention。
目的:减少计算量(下图可以看出两种方式分别是多少计算量)
缺点:窗口之间无法进行信息交互,等于减少了感受野,无法看到全局信息

具体的计算过程可以参考:太阳花的小绿豆帖子《Swin-Transformer网络结构详解》第三章
与W-MSA不同的地方在于这个模块存在窗口滑动,所以叫做shifted window。滑动距离是window_size//2,方向是向右和向下。
滑动窗口是为了解决W-MSA计算attention时,窗口与窗口之间无法进行信息传递的问题。如下图所示,左侧是网络第L层使用的W-MSA模块,右侧是第L+1层使用SW-MSA模块。对比可以发现,窗口(Windows)发生了偏移。
比如在L+1层特征图上,对于第一行第2列的2x4的窗口,它能够使第L层的第一排的两个窗口信息进行交流。再比如,第二行第二列的4x4的窗口,他能够使第L层的四个窗口信息进行交流,其他同理。

但是这样也有一个问题:偏移后,窗口数由原来的4个变成了9个,后面又要对每个窗口内部进行MSA,非常麻烦。为此,作者又提出了一种更加高效的计算方法——masked MSA(后面会讲)。
下图左侧是刚刚通过偏移窗口后得到的新窗口,右侧是为了方便大家理解,对每个窗口加上了一个标识。





Efficient batch computation for shifted configuration简单说,就是通过移动合并,将9个窗口还是变为原来的4个窗口,再进行Masked MSA计算。计算量和普通的MSA一样,只是多了个mask。
Masked MSA是为了解决合并窗口中各个窗口应该单独计算的问题。使用Masked MSA,将不同窗口元素计算的attention score-100,等价于屏蔽掉不同窗口元素的attention结果。最终达到了4个窗口同时进行MSA计算,又保证得到只在在窗口内进行计算的效果。
结果见下图左侧:
ImageNet-1K上预训练然后在ImageNet-1K上微调的结果(测试集)ImageNet-22K上预训练然后在ImageNet-1K上微调的结果(测试集)ViT在小规模数据集上效果并不好,在足够大的数据集上效果明显提升,和之前论文中的结论是一样的。
结果见上图右侧:
ResNet-50 和Swin-Tiny作为backbone的结果对比。(二者参数量和计算量相近)Mask R-CNN做检测模型,然后替换不同的backbone。效果好
论文中还提到,使用相对位置偏置后给够带来明显的提升。(下图公式中的B就是偏置,ADE20k是图片分割数据集)

下面具体讲解什么是
Relative Position Bias(假设特征图大小为2×2)
- 计算相对位置索引:比如蓝色像素,在蓝色像素使用q与所有像素k进行匹配过程中,是以蓝色像素为参考点。然后用蓝色像素的绝对位置索引与其他位置索引进行相减,就得到其他位置相对蓝色像素的相对位置索引,同理可以得到其他位置相对蓝色像素的相对位置索引矩阵(第一排四个位置矩阵)。
- 展平拼接:将每个相对位置索引矩阵按行展平,并拼接在一起可以得到第二排的这个4x4矩阵。
- 索引转换为一维:在源码中作者为了方便把二维索引给转成了一维索引。
- 首先在原始的相对位置索引上加上M-1(M为窗口的大小,在本示例中M=2),加上之后索引中就不会有负数了。
- 接着将所有的行标都乘上2M-1
- 最后将行标和列标进行相加。这样即保证了相对位置关系,而且不会出现直接相加后位置重叠的问题。(0±1和-1+0结果都一样,但其实其位置不一样)
- 取出相对位置偏置参数。真正使用到的可训练参数B 是保存在relative position bias table表里的,其长度是等于 ( 2 M − 1 ) × ( 2 M − 1 ) (2M-1) \times (2M-1) (2M−1)×(2M−1)。相对位置偏置参数B,是根据相对位置索引来查relative position bias table表得到的,如下图所示。
为啥表长是 ( 2 M − 1 ) × ( 2 M − 1 ) (2M-1) \times (2M-1) (2M−1)×(2M−1)?考虑两个极端位置,(0,0)能取到的相对位置极值为(-1,-1),(-1,-1)能取到的极值是(1,1),即行和列都能取到(2M-1)个数。考虑到所有的排列组合,表的长度就是 ( 2 M − 1 ) × ( 2 M − 1 ) (2M-1) \times (2M-1) (2M−1)×(2M−1)
模型结构和参数如下:

以Swin-T举例:
concat4×4,96d,LN表示宽高都下采样4倍,调整后channel数为96,再经过一个Layer Norm层。Swin Transformer Block,其中:
win. sz. 7x7表示使用的窗口的大小(window size)为7×7dim表示这个层输出的feature map的channel深度(或者说token的向量长度)head表示多头注意力模块中head的个数W-MSA和SW-MSA。 本文最关键的一个贡献就是基于 Shifted Window 的自注意力,它对很多视觉的任务,尤其是对下游密集预测型的任务是非常有帮助的 。所以未来工作的重点就是把Shifted Window 用到NLP任务中,推进模型的大一统(多模态)。
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
这里是Ruby新手。完成一些练习后碰壁了。练习:计算一系列成绩的字母等级创建一个方法get_grade来接受测试分数数组。数组中的每个分数应介于0和100之间,其中100是最大分数。计算平均分并将字母等级作为字符串返回,即“A”、“B”、“C”、“D”、“E”或“F”。我一直返回错误:avg.rb:1:syntaxerror,unexpectedtLBRACK,expecting')'defget_grade([100,90,80])^avg.rb:1:syntaxerror,unexpected')',expecting$end这是我目前所拥有的。我想坚持使用下面的方法或.join,
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
基础版云数据库RDS的产品系列包括基础版、高可用版、集群版、三节点企业版,本文介绍基础版实例的相关信息。RDS基础版实例也称为单机版实例,只有单个数据库节点,计算与存储分离,性价比超高。说明RDS基础版实例只有一个数据库节点,没有备节点作为热备份,因此当该节点意外宕机或者执行重启实例、变更配置、版本升级等任务时,会出现较长时间的不可用。如果业务对数据库的可用性要求较高,不建议使用基础版实例,可选择其他系列(如高可用版),部分基础版实例也支持升级为高可用版。基础版与高可用版的对比拓扑图如下所示。优势 性能由于不提供备节点,主节点不会因为实时的数据库复制而产生额外的性能开销,因此基础版的性能相对于
Transformers开始在视频识别领域的“猪突猛进”,各种改进和魔改层出不穷。由此作者将开启VideoTransformer系列的讲解,本篇主要介绍了FBAI团队的TimeSformer,这也是第一篇使用纯Transformer结构在视频识别上的文章。如果觉得有用,就请点赞、收藏、关注!paper:https://arxiv.org/abs/2102.05095code(offical):https://github.com/facebookresearch/TimeSformeraccept:ICML2021author:FacebookAI一、前言Transformers(VIT)在图
我使用irb。下面是我写的代码。“斧头”..“bc”我期待"ax""ay""az""ba"bb""bc"但结果只是“斧头”..“bc”我该如何纠正?谢谢。 最佳答案 >puts("ax".."bc").to_aaxayazbabbbc 关于ruby-从结束值创建一系列字符串,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7617092/
使用RubyonRails,我使用给定的增量(例如每30分钟)用时间填充“选择”。目前我正在YAML文件中写出所有的可能性,但我觉得有一种更巧妙的方法。我想我想提供一个开始时间、一个结束时间、一个增量,并且目前只提供一个名为“关闭”的选项(想想“business_hours”)。所以,我的选择可能会显示:'Closed'5:00am5:30am6:00am...[allthewayto]...11:30pm谁能想出更好的方法,或者只是将它们全部“拼写”出来的最佳方法? 最佳答案 此答案基于@emh的答案。defcreate_hour
有道无术,术尚可求,有术无道,止于术。本系列SpringBoot版本3.0.4本系列SpringSecurity版本6.0.2本系列SpringAuthorizationServer版本1.0.2源码地址:https://gitee.com/pearl-organization/study-spring-security-demo文章目录前言1.OAuth2AuthorizationServerMetadataEndpointFilter2.OAuth2AuthorizationEndpointFilter3.OidcProviderConfigurationEndpointFilter4.N
CSDN优秀解读:https://blog.csdn.net/jiaoyangwm/article/details/1266387752021https://arxiv.org/pdf/2103.14259.pdf关键解读在目标检测中标签分配的最新进展主要寻求为每个GT对象独立定义正/负训练样本。在本文中,我们创新性地从全局的角度重新审视标签分配,并提出将分配程序制定为一个最优传输(OT)问题——优化理论中一个被充分研究的课题。具体来说,我们将每个需求方(锚框)和供应商(GT标签)的单位传输成本定义为他们的分类和回归损失加权之和。在公式化后,找到最好的分配方案即为最小传播成本解决最优传输方案,
今天想要跟着沐神学习一下循环神经网络,在跑代码的时候,d2l出现了问题,这里记录一下解决的过程,方便以后查阅。李沐《动手学深度学习》d2l——安装和使用安装d2l解决Import“...“couldnotberesolved问题PermissionError:[WinError5]拒绝访问。:'..\\\data'安装d2l下载whl:https://www.cnpython.com/pypi/d2l/dl-d2l-0.15.1-py3-none-any.whl将下载的文件放到这里:在这个文件中右键,选择“在终端中打开”在终端中输入如下命令:condaactivatepytorch_envpi