文章目录

    • 一、Vision Transformer论文精读
      • 1.1 引言
        • 1.1.1 前言
        • 1.1.2 摘要
        • 1.1.3 引言
      • 1.2 相关工作
      • 1.3 ViT
        • 1.3.1 整体结构
        • 1.3.2 Embedding层结构详解
        • 1.3.3 Transformer Encoder详解
        • 1.3.4 MLP Head和`ViT-B/16`模型结构图
        • 1.3.5 归纳偏置
        • 1.3.6 Hybrid混合模型试验
        • 1.3.7 更大尺寸上的微调
      • 1.4 实验部分
        • 1.4.1 ViT三个尺寸模型参数对比
        • 1.4.2 对比其它最新模型
        • 1.4.3 `vision trasformer`预训练需要多大的数据规模?(重要论证)
        • 1.4.5 ViT可视化
        • 1.4.6 自监督训练
      • 1.5 附录
        • 1.5.1 [CLS]token和1D-Position Embedding消融实验
        • 1.5.2 Hybrid混合模型试验(不感兴趣可跳过)
      • 1.6 可视化
      • 1.7 论文结论
      • 1.8 PyTorch代码实现
        • 1.8.1 PatchEmbed层
        • 1.8.2 Attention层(实现多头注意力Multi-Head Attention)
        • 1.8.3 待续
    • 二、MAE论文精读
      • 2.1 导言
        • 2.1.1 前言
        • 2.1.2 摘要
        • 2.1.3 导言: 自编码模型为何在CV领域应用不及NLP?
      • 2.2 相关工作(都是老故事,略)
      • 2.3 算法
        • 2.3.1 MAE主要结构
        • 2.3.2 具体实现
        • 2.3.3 简单实现
      • 2.4 实验部分
        • 2.4.1 MAE超参数实验
        • 1.4.2 对比其它模型
      • 2.5 结论&讨论
    • 三、Swin-Transformer论文精读
      • 3.1 导言
        • 3.1.1前言
        • 3.1.2 摘要
        • 3.1.3 导言
      • 3.2 相关工作(略)
      • 3.3 算法
        • 3.3.1 模型结构
        • 3.3.2 Patch Merging
        • 3.3.3 W-MSA
        • 3.3.4 SW-MSA(Shifted Windows Multi-Head Self-Attention)
        • 3.3.5 Masked MSA(技术细节,选看)
      • 3.4 实验
        • 3.4.1 ImageNet
        • 3.4.2 COCO数据集
        • 3.4.3 语义分割数据集ADE20K
        • 3.4.4移动窗口和相对位置编码
        • 3.4.5 模型详细配置参数
      • 3.5 结论
      • 3.6 代码讲解

传送门:

一、Vision Transformer论文精读

  • 论文名称: An Image Is Worth 16x16 Words: Transformers For Image Recognition At Scale、论文源码、Pytorch官方源码、 ViT PytorchAPI、
  • 参考李沐《ViT论文逐段精读》、笔记《ViT全文精读》
  • 小绿豆《Vision Transformer详解》及bilibili视频讲解
  • transformer原理可参考我的博文《多图详解attention和mask。从循环神经网络、transformer到GPT2》

1.1 引言

1.1.1 前言

  作者介绍的另一篇论文:《Intriguing Properties of Vision Transformer》(Vision Transformer的一些有趣特性)如下图所示:
李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer

  上述例子中,卷积神经网络很难判断到底是一个什么物体,但是对于所有的这些例子Vision Transformer都能够处理的很好。

1.1.2 摘要

  在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排行榜上看到。
李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer
  在这篇文章中,作者主要拿ResNetViT(纯Transformer模型)以及Hybrid(卷积和Transformer混合模型)三个模型进行比较,所以本博文除了讲ViT模型外还会简单聊聊Hybrid模型。

1.1.3 引言

  基于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领域呢?

  1. Non-local Neural Networks(CVRP,2018):将原始图片中间层输出的特征图作为输入序列,来传入Transformer(比如ResNet50在最后一个Stage的特征图size=14×14)。
  2. 《Stand-Alone Self-Attention in Vision Models》(NeurIPS,2019):使用孤立注意力Stand-Alone Axial-Attention来处理。具体的说,不是输入整张图,而是在一个local window(局部的小窗口)中计算attention。窗口的大小可以控制,复杂度也就大大降低。(类似卷积的操作)
  3. 《Axial-DeepLab: Stand-Alone Axial-Attention for Panoptic Segmentation》(ECCV,2020a):将图片的2D的矩阵想办法拆成2个1D的向量。等于是先在高度的维度上做一次self-attention,然后再在宽度的维度上再去做一次self-attention,大幅度降低了计算的复杂度。
  4. 《On the Relationship between Self-Attention and Convolutional Layers》( ICLR, 2020.):在相关工作中,作者介绍了,和本文最相似的工作是这一篇文章。其作者从输入图片中抽取2×2的图片patch,然后一样的做self-attention(只在CIFAR-10数据集上做了实验,其数据集大小为32×32,所以patch size=2×2就行)
  5. image GPT:在相关工作中,作者也说到image GPT和本文很相近。但是image GPT是一个生成模型,虽然用了Transformer,但最终结果差很多(ImageNet上的最高的分类准确率也只能到72)。不过受此启发,后面出现了MAE,用一个自监督模式训练的生成式的模型,做出了比之前判别式的模型更好的效果(分类和检测)。

  所以,自注意力早已经在计算机视觉里有所应用,而且已经有完全用自注意力去取代卷积操作的工作了。
  这些模型虽然理论上是非常高效的,但事实上因为这个自注意力操作都是一些比较特殊的自注意力操作(除了上面举例的最后一篇),要很复杂的工程去加速算子,所以就导致很难训练出一个大模型。因此在大规模的图像识别上,传统的残差网络还是效果最好的。

  本文是被transformer在NLP领域的可扩展性所启发,本文想要做的就是直接应用一个标准的transformer作用于图片,尽量做少的修改。好处是可以直接使用NLP中成熟的Transformer架构,不需要再魔改模型,而且Transformer这么多年有很多高效的实现。具体的处理方式见下一节。

  上面举例的例4模型,从技术上讲就是Vision Transformer。但是作者认为二者的区别,是本文证明了,使用一个标准的Transformer endoder(类似BERT,不需要任何特殊改动)在大规模的数据集上做预训练的话,就能取得比现在最好的卷积神经网络差不多或者还好的结果。(这是本文的主要论证工作,在1.4.2和1.4.3章节都有体现 )另外就是二者可处理图片的分辨率不同(32×32对比224×224)。

引言的最后部分放出了结论:

1.2 相关工作

  简单介绍了一下Transformer在NLP领域应用最广的两大分支BERT和GPT,都是基于自监督的训练方式(MLM任务和Next word prediction)。
  直接将图片的像素作为序列输入Transformer是不可行的,所以作者介绍了一下之前的相关处理方式(类似上面引言提到的几个模型)。
  第三段介绍了,有一些工作研究了用比ImageNet更大的数据集去做预训练,效果会更好,比如说ImageNet-21k和JFT300M。最终作者也是在这两个数据集上预训练模型。

1.3 ViT

1.3.1 整体结构

下图是原论文中给出的关于Vision Transformer(ViT)的模型框架。简单而言,模型由三个模块组成:

李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer
如上图所示:

  1. embedding层(图片输入)

    • 一张图片先分割成n个patchs,然后这些patchs一个个输入线性投射层得到Pacth embedding。比如ViT-L/16表示每个patchs大小是16×16。
    • 在所有tokens前面加一个新的class token作为这些patchs全局输出,相当于transformer中的CLS(这里的加是concat拼接)。
    • 和transformer一样,引入位置信息。VIT的做法是在每个token前面加上位置向量,即position embedding(这里的加是直接向量相加,不是concat)。
      self-attention本身没有考虑输入的位置信息,无法对序列建模。而图片切成的patches也是有顺序的,打乱之后就不是原来的图片了。
  2. Pacth embedding+position embedding+class token一起输入Transformer Encoder层得到其输出。
  3. class token的输出当做整个图片的特征,经过MLP Head得到分类结果。(VIT只做分类任务)
  4. 整个模型是使用有监督的训练(相对于NLP中,transformer类模型很多都是无监督训练)

整体上看,VIT的模型结构还是很简洁的,难点就是如何将图片转为token输入网络。

1.3.2 Embedding层结构详解

  对于标准的Transformer模块,要求输入的是token(向量)序列,即二维矩阵[num_token, token_dim]。对于图像数据而言,其数据为[H, W, C]格式的三维矩阵,明显不是Transformer想要的。所以需要先通过一个Embedding层来对数据做个变换。

  1. 如下图所示,首先将一张图片按给定大小分成一堆Patches。以ViT-B/16为例(后面都是以此模型举例),将输入图片(224x224)按照16x16大小的Patch尺寸进行划分,划分后会得到
    (
    224
    /
    16
    )
    2
    =
    196
    (224/16)^2=196
    (224/16)2=196
    个Patches。
  2. 接着通过线性映射将每个Patch映射到一维向量中。具体的,每个Patche数据shape为[16, 16, 3],通过映射得到一个长度为768的向量(token)。[16, 16, 3] -> [768]

  在代码实现中,直接通过一个卷积层来实现。卷积核大小为16x16,步距为16,卷积核个数为768。通过卷积[224, 224, 3] -> [14, 14, 768],然后把H以及W两个维度展平即可[14, 14, 768] -> [196, 768],此时正好变成了一个二维矩阵,正是Transformer想要的。
  如果模型更大的话,Pacth embedding可以映射到更大的维度,也就是论文中提到的参数D

李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer
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]token1D Pos. Emb,在本文1.5.1消融试验部分会讲到。

1.3.3 Transformer Encoder详解

Transformer Encoder其实就是重复堆叠Encoder Block L次,主要由以下几部分组成:

1.3.4 MLP Head和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,一般迁移学习是可以不用的。)
李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer

作者在论文3.1 VIT部分,对整个过程用数学公式描述了一次:
李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer

1.3.5 归纳偏置

  在CNN中,locality(局部性)和translate equivariance(平移等变性)是在模型的每一层中都有体现的,这个先验知识相当于贯穿整个模型的始终。
  但是对于ViT来说,只有MLP层是局部而且平移等变性的,其它的自注意力层是全局的,这种图片的2d信息ViT基本上没怎么使用。

  就是只有刚开始将图片切成patch的时候和加位置编码的时候用到了,除此之外,就再也没有用任何针对视觉问题的归纳偏置了,而且位置编码也是随机初始化的1-D信息。所以在中小数据集上ViT不如CNN是可以理解的。

1.3.6 Hybrid混合模型试验

  既然transformer全局建模的能力比较强,卷积神经网络又比较data efficient(不需要太多的训练数据),那么自然想到去搞一个前面层是CNN后面层是transformer的混合网络,也就是Hybrid混合模型。Hybrid不再直接将图片打成一个个patch,而是直接送入CNN得到embedding,比如经过Resnet50,最后一个stage输出特征图是14×14,拉直了也是196维向量。这部分细节参考文本1.4实验部分。

1.3.7 更大尺寸上的微调

  之前的工作有表明,使用更大的图片输入尺寸往往模型效果会更好。但是使用一个预训练好的vision transformer,其实是不太好去调整输入尺寸的。如果还是将patch size保持一致,但是图片扩大了,那么序列长度就增加了,提前预训练好的位置编码有可能就没用了。
  这个时候位置编码该如何使用?作者发现其实做一个简单的2d的插值就可以了(使用torch官方自带的interpolate函数就完成)。但这只是一个临时的解决方案,如果需要从一个很短的序列变成一个很长的序列时,简单的插值操作会导致最终的效果下降(比如256→512)。这也算是vision transformer在微调的时候的一个局限性。
  因为使用了图片的位置信息进行插值,所以这块的尺寸改变和抽图像块是vision transformer里唯一用到2d信息的归纳偏置的地方。

1.4 实验部分

1.4.1 ViT三个尺寸模型参数对比

  在论文的4.1章节的Table1中有给出三个模型(Base/ Large/ Huge,对应BERT)的参数,在源码中除了有Patch Size为16x16的外还有32x32的。其中:

李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer

1.4.2 对比其它最新模型

  对比VIT的几个不同配置模型和BiT-L,以及Noisy模型。最终效果提升不大,但是ViT训练时间短很多。(的后面还有其它的对比试验支持作者的这个观点)

TPU-v3-core-days 2.5k:表示最大的ViT-H/14模型在TPU-v3上只需要训练2500天。

李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer

1.4.3 vision trasformer预训练需要多大的数据规模?(重要论证)

  下图展示了在不同大小的数据集上预训练后,BiTtVIT到底在ImageNet的微调效果如何。

下图再次论证作者观点(VIT训练更便宜):

1.4.5 ViT可视化

统一见本文1.6 可视化部分。

1.4.6 自监督训练

  这部分放在正文而不是负类中,是因为作者认为:在NLP领域,Transformer这个模型确实起到了很大的推动作用,但另外一个真正让Transformer火起来的原因其实是大规模的自监督训练,二者缺一不可。
  NLP中自监督方式是MLM任务或者Next word prediction,本文模仿的是BERT,所以作者考虑构造专属于ViT的目标函数Mask patch prediction。具体来说,给定一张图片,将它打成很多patch,然后将某些patch随机抹掉,然后通过这个模型将这些patch重建出来。
  但是最后ViT-Base/16在ImageNet只能达到80的左右的准确率,比最好的有监督方式训练,还是差了四个点,所以作者后面的工作是考虑引入对比学习。

  对比学习是所有自监督学习中表现最好的,紧接着出现的ViT MoCo v3DINO就是在ViT的基础上使用了对比学习。

1.5 附录

1.5.1 [CLS]token和1D-Position Embedding消融实验

这部分内容在论文附录的D Additional Analyses部分

  虽然最终VIT采用的[CLS]token1D-Position Embedding都和BERT是一样的,但是作者在论文实验部分也都对此作了很多消融试验。比如:

  1. [CLS]token是从NLP领域借鉴的,但是之前的CNN网络用于图片分类的特征并非这么做。

    • 比如ResNet50模型,是在最后一个stage5上输出的特征图(size=14×14)上做一个全局平均池化(GAP),拉直为一个一维向量,来作为整个图片的全局特征。最后用这个特征去做分类。
    • 作者也试验了在Pacth embedding中不加入[CLS]token,而是在最后Transformer Encoder输出序列向量时,用一个GAP来得到最终全局表征向量,最终结果和使用[CLS]token的效果几乎差不多 。
    • 下图表示CLS和GAP最后收敛结果差不多,只是学习率会不一样。最终作者还是使用了[CLS]token,因为本文目的是跟原始的Transformer尽可能地保持一致,不想大家觉得效果好可能是因为某些trick或者某些针对cv的改动而带来的,作者就是想证明, 一个标准的Transformer照样可以做视觉。
  2. 对于Position Embedding作者也有做一系列对比试验,在源码中默认使用的是1-D Pos. Emb.,对比不使用Position Embedding准确率提升了大概3个点,和2-D Pos. Emb.以及Rel. Pos. Emb.比起来没太大差别。
    李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer

  2-D Pos. Emb.(2D位置编码)就是用patch的横纵坐标表示其位置,而不是一个一维的序号。其中横坐标有D/2的维度,纵坐标也有D/2的维度,两者拼接到得到了一个D维的向量。
  Rel. Pos. Emb.:相对位置编码。两个patch之间的距离可以使用绝对位置编码,也可以使用相对位置编码,最终结果差不多。
  作者对此解释是:ViT是直接在图像块上做的,而不是在原来全局尺度的像素块上做的,所以在排列组合这种小块或者想要知道这些小块之间相对位置信息的时候,还是相对比较容易的,所以使用任意的位置编码都无所谓。

1.5.2 Hybrid混合模型试验(不感兴趣可跳过)

  在论文4.1章节的Model Variants中有比较详细的讲到,就是将传统CNN特征提取和Transformer进行结合。下图绘制的是以ResNet50作为特征提取器的混合模型Hybrid,但这里的Resnet与之前讲的Resnet有些不同。

  1. 首先这里的ResNet50的卷积层采用的StdConv2d不是传统的Conv2d,然后将所有的BatchNorm层替换成GroupNorm层。
  2. 在原Resnet50网络中,stage1重复堆叠3次,stage2重复堆叠4次,stage3重复堆叠6次,stage4重复堆叠3次,但在这里的ResNet50中,把stage4中的3个Block移至stage3中,所以stage3中共重复堆叠9次。

  如果有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得到分类结果。
李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer
  下表是论文用来对比ViT,Resnet(和刚刚讲的一样,使用的卷积层和Norm层都进行了修改)以及Hybrid模型的效果。通过对比发现,在训练epoch较少时Hybrid优于ViT,但当epoch增大后ViT优于Hybrid。
李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer

1.6 可视化

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

  1. patch embedding可视化
    • 下图左侧展示了E(第一层linear projection layer)是如何对图片像素进行embedding。
    • 只展示了开头28个token的可视化结果,可以看到结果类似CNN,都是提取的一些颜色和纹理这样的底层特征,作者说它们可以用来描述每一个图像块的底层的结构。
  2. position embedding可视化
    • 下图中间部分展示了不同patch之间,位置编码的cos相似性,越接近1 表示越相似。
    • 可以看到黄色(最相似)出现位置和patch本身所处位置对应,说明1D编码已经学习到2D的位置信息,所以换成2D位置编码效果几乎不变。
      李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer
  3. 自注意力是否起作用了?
    为了了解ViT如何利用self-attention来整合图像中的信息,我们分析了不同层的Mean attention distance
    李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer
    李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer
  1. out token输出
    • 在本文的4.5实验部分,作者对上面attention的结果又进行了一次验证。
    • 作者用output token的自注意力折射回原来的输入图片,可以发现模型确实是学习到了这些概念。
    • 因为输出的token是融合了所有的信息(全局的特征),模型已经可以关注到与最后分类有关的图像区域
      李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer

1.7 论文结论

  Vision Transformer和NLP领域标准的Transformer的自注意力机制区别在于:除了在刚开始抽图像块的时候,还有位置编码用了一些图像特有的归纳偏置,除此之外就再也没有引入任何图像特有的归纳偏置了。这样的好处就是可以直接把图片当做NLP中的token,拿NLP中一个标准的Transformer就可以做图像分类了。
  这个策略扩展性非常好,和大规模预训练结合起来的时候效果也出奇的好,而且训练起来还相对便宜。
  另外作者在这里对Vision Transformer还做了一些展望:

  1. 将VIT从分类扩展到目标检测和分割,所以后面出现了一系列将Transformer应用在在视觉领域的模型:
    • ViT-FRCNN
    • SETR,即Segmentation Transformer
    • DETR,即Detection Transformer
    • 2021年3月Swin-Transformer横空出世,将多尺度的设计融合到了Transformer中,更加适合做视觉的问题了。
  2. 探索一下自监督的预训练方案(NLP领域常用做法)。
    本文也做了一些初始实验,证明了用这种自监督的训练方式也是可行的,但是跟有监督的训练比起来还是有不小的差距。
  3. 将Vision Transformer做得更大,效果应该会更好。
    半年后,本文作者团队又出了一篇Scaling Vision Transformer,训练出更大的VIT网络,即ViT-G,将ImageNet图像分类的准确率提高到了90以上。

  除以上几点之外,作者还在多模态领域挖了一个大坑。CV和NLP大一统之后,是不是这些任务都可以用一个Transformer取解决呢?后续这一块也是推进的很快。

1.8 PyTorch代码实现

项目代码github地址、B站代码讲解《使用pytorch搭建Vision Transformer(vit)模型》

1.8.1 PatchEmbed层

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

1.8.2 Attention层(实现多头注意力Multi-Head Attention)

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

1.8.3 待续

二、MAE论文精读

参考:

  • 论文《Masked Autoencoders Are Scalable Vision Learners》
  • 李沐《MAE 论文逐段精读【论文精读】》、笔记《MAE 论文逐段精读》
  • 知乎《别再无聊地吹捧了,一起来动手实现 MAE(Masked Autoencoders Are Scalable Vision Learners) 玩玩吧!》

本文算法在2.3章节!!!

2.1 导言

2.1.1 前言

  自从Vision Transformer将标准的transformer成功的应用到CV上面以来,就出现了很多相关性的工作,MAE就是其中的一篇。本文是2021.11.11发布在Arxiv上的文章,主要工作是在Vision Transformer基础上,引入自监督训练,相当于将BERT应用到CV领域。通过完形填空来获取对于图片的理解,把整个训练拓展到没有标号的数据上面 ,使得transformer在CV上的应用更加普及。
  最终MAE只需要Vision Transformer百分之一规模的数据集上预训练,就能达到同样的效果。而且在目标检测、实例分割、语义分割等任务上,效果都很好。

  本文标题中的Autoencoders,是‘’而非自动的意思,表示类似自回归这一类模型的特点, 即标号和样本(y和x)来自于同一个东西。比如说在语言模型中,每一次用前面的次去预测下一个词。而对于MAE,则表明模型的标号也是图片本身

2.1.2 摘要

  MAE的自监督训练实现途径非常简单,随机地mask图片中地一些patches(块),然后再去重构the missing pixels.,这个思想来自于BERT中的带掩码的语言模型。

在MAE中,自监督训练还有两个核心的设计:

  最终作者只使用一个最简单的ViT-Huge模型,在ImageNet-1K上预训练,精度也能达到87.8%

下面是作者展示的一些模型重构效果图:
李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer

李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer

2.1.3 导言: 自编码模型为何在CV领域应用不及NLP?

  在导言一开始,作者大意就说自监督学习很香,使得Transformer在NLP领域的应用非常火。尽管也有一些工作将BERT应用到CV领域,比如Denoising Autoencoder是在一个图片中加入很多噪音,然后通过去噪来学习对这个图片的理解,但最终这些效果都不及NLP。

MAE也是一种类似去噪 的模型,mask一些patches,也相当于往模型中加入很多噪音

  为何masked自编码模型在CV和NLP领域应用不一样呢?

  1. 架构差异
    之前的CV领域都是用的CNN网络,而CNN中的卷积,是不好做掩码操作的。
      因为卷积核滑动时,不好将msaked patches单独剔除,导致后面不好将图片还原(Transformer中可以将masked token直接去掉,和其他词区分开来)。但是ViT成功将Transformer应用到图片分类,所以这个问题不再有了。
  2. 信息密度(information density)不同。
    • 在自然语言中,一个词就是一个语义的实体,比如说字典中对一个词的解释就是很长的一段话,所以一句话中很难去去掉几个词(这样做完形填空才有意义)。
    • 在图片中,像素是比较冗余的,取决于相机的分辨率有多大。所以如果只是简单去掉一些块的话,很容易进行插值还原。
    • 作者的做法是,mask很高比例的像素块(比如75%),就可以大大降低图片的冗余性。这样就压迫模型必须学习全局信息,也就提高了模型学习的难度。

  将图片中一大片都去掉, 剩下的块离得比较远,就没那么冗余了。否则模型仅仅学一个局部模型就可以进行插值还原。
  关于此点论证,看上面图2.3.4就可以发现:仅仅一些局部的,很稀疏的块,就可以重构全局图片。

  1. 解码差异

    • NLP中需要预测masked tokens,而token本身就是一种比较高级一些的语义表示。而来自编码器的特征也是高度语义的,与需要解码的目标之间的 gap 较小,所以只需要一个简单的全连接层就可以解码这些tokens。(ViT最后需要的是图片特征,所以也只需要MLP就可以解码)
    • MAE中需要还原the missing pixels,这些像素是一个很基础的特征。要将自编码器的高级语义特征解码至低级语义层级,所以可能需要一个比较复杂的转置卷积网络才能完成解码。

  正是基于以上分析,作者才提出本文的两个核心设计:高掩码率以及非对称编-解码器

  在导言最后一部分,作者说MAE可以只在ImageNet 1K上就能预训练ViT-Large/-Huge模型(得到很好的效果)。类比ViT,相同效果后者需要在近100倍规模的数据集上训练才能达到。
  另外,在目标检测、语义分割和实例分割上,MAE比之前所有模型(包括有监督训练模型)效果都要好,而且加大模型会有显著的收益。

2.2 相关工作(都是老故事,略)

2.3 算法

2.3.1 MAE主要结构

  MAE使用编码器将观察到的信号映射到潜在表示,再使用一个解码器从潜在表示重构原始信号。与经典的自动编码器不同,我们采用了一种非对称设计,允许编码器仅对部分观察信号(无掩码标记)进行操作,模型设计图如下:
李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer

  说明:上图中编码器比解码器更宽,表示模型的主要计算部分在编码器(最重要的就是编码像素得到特征)

2.3.2 具体实现

2.3.3 简单实现

将以上讲解的全部串联起来就是:

  1. 将图像划分成 patches:(B,C,H,W)->(B,N,PxPxC);
  2. 对各个 patch 进行 embedding(实质是通过全连接层),生成 tokens,并加入位置信息(position embeddings):(B,N,PxPxC)->(B,N,dim);
  3. 根据预设的掩码比例,进行随机均匀采样。unmask tokens 输入 Encoder,另一部分“扔掉”(mask 掉);
  4. 编码后的 tokensmasked tokens( 加入位置信息) 按照原先在 patch 形态时对应的次序拼在一起,然后喂给 Decoder 玩。
    • 整个序列是通过unshuffle操作,还原到原来的顺序。
    • 如果 Encoder 编码后的 token 的维度与 Decoder 要求的输入维度不一致,则需要先经过 linear projection 将维度映射到符合 Decoder 的要求
  5. Decoder 解码后取出 masked tokens 对应的部分送入到全连接层,对 masked patches 的像素值进行预测,最后将预测结果(B,N’,PxPxC)与 masked patches 进行比较,计算 MSE loss。

2.4 实验部分

微调层数对比
  我们知道,预训练模型做微调的效果是比只做特征提取的效果更好的,但是训练时间会更长。所以作者试验了一下,微调不同的层数,模型的效果如何(见下图)。
李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer

2.4.1 MAE超参数实验

1. ImageNet实验

下图是在 ImageNet-1K验证集上的top-1结果。(详见附录A1)
李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer

2. decoder/mask策略/数据增强
李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer

上图展示的是MAE使用ViT-L/16结构,在ImageNet-1K数据集上的acc精度。下面一个个来看:

  • ft: fine-tuning微调
  • lin:linear probing,只训练最后一个线性层的参数,相当于MAE只做特征提取
  • 最终decoder的默认深度是8 blocks,宽度是512 dim,与VIT-L相比,计算量只有前者的9%.。

3. mask比例
综合ft和lin考虑,masking ratio=75%时效果最好。(图就不放了)

1.4.2 对比其它模型

1. 自监督模型效果对比

下表是在ImageNet-1K训练集上预训练后的微调结果:
李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer
在COCO数据集上的效果对比:
李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer

over

2.5 结论&讨论

简单且拓展性好的算法,是整个深度学习的核心。

  • 简单:是指MAEViT模型上加了一些简单的扩展,但是模型本身是不简单的。
  • 拓展性好:是指你有钱就可以无限的加数据了,毕竟MAE不需要标号,你可以训练更大的模型。

  自监督学习在最近几年是比较火的,但是在计算机视觉中,还是主要用有标号的数据来训练 。本文在ImageNet数据集上通过自编码器学习到可以媲美有标号训练的效果,使得CV领域的自监督学习可能走上与NLP类似的轨迹。
  另一方面,图像和语言是不同类型的信息,要谨慎处理这种差异

Broader impacts:MAE是个生成模型,可以生成不存在的内容,类似GAN,所以使用要注意。

三、Swin-Transformer论文精读

  • 论文名称:Swin Transformer: Hierarchical Vision Transformer using Shifted Windows、官方开源代码
  • 李沐《Swin Transformer论文精读视频》、视频笔记
  • 参考:太阳花的小绿豆帖子《Swin-Transformer网络结构详解》、讲解视频
  • Pytorch实现代码及Swin Transformer API、Tensorflow2实现代码

3.1 导言

3.1.1前言

  Swin transformer是微软研究院于2021年3月25日发表在ICCV的一篇文章(ICCV 2021最佳论文),利用transformer架构处理计算机视觉任务,在图像分割,目标检测各个领域已经霸榜。比如打开其官网代码可以看到:(这排名不是卷死?)
李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer
  首先看论文题目。Swin Transformer: Hierarchical Vision Transformer using Shifted Windows。即:Swin Transformer是一个用了移动窗口的层级式Vision Transformer(Hierarchical是层级式的意思)。
  所以Swin来自于 Shifted Windows , 它能够使Vision Transformer像卷积神经网络一样,做层级式的特征提取,这样提取出来的特征具有多尺度的概念 ,这也是 Swin Transformer这篇论文的主要贡献。

3.1.2 摘要

  本文提出了一个新的 Vision Transformer 叫做 Swin Transformer,它可以被用来作为计算机视觉领域一个通用的骨干网络 。

标准的Transformer直接用到视觉领域有一些挑战,即:

  1. 多尺度问题:比如一张图片里的各种物体尺度不统一,NLP中没有这个问题;
  2. 分辨率太大:如果将图片的每一个像素值当作一个token直接输入Transformer,计算量太大,不利于在多种机器视觉任务中的应用。

基于这两点,本文提出了 hierarchical Transformer,通过移动窗口来学习特征。

  • 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中就有体现。

3.1.3 导言

在这部分作者对比了Vision Transformer和Swin Transformer的结构区别,如下图所示:
李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer
可以看出主要区别有两个:

  1. 层次化构建方法(Hierarchical feature maps) :Swin Transformer使用了类似卷积神经网络中的层次化构建方法。

    • 对于计算机视觉的下游任务,尤其是密集预测型的任务(检测、分割),有多尺寸的特征至关重要的。(比如目标检测里的FPN、分割里面的UNet等等)
    • Vision Transformer中是一开始就直接下采样16倍,这样模型自始至终都是处理的16倍下采样率过后的特征,这样在处理需要多尺寸特征的任务时,效果不够好。
    • Swin Transformer 使用patch merging,可以把相邻的四个小的patch合成一个大的patch,提高了感受野,这样就能获取多尺度的特征(类似CNN中的池化效果)。这些特征通过FPN结构就可以做检测,通过UNet结构就可以做分割了。
  2. 使用W-MSA ,好处有两点:

    • Swin Transformer使用窗口(Window)的形式将特征图划分成了多个不相交的区域,并且只在每个窗口内进行多头注意力计算,大大减少计算量。
    • 获得了和CNN一样的归纳偏置特性——locality。(在本帖1.1.3中讲过)。
      归纳偏置:一种先验知识或者说提前的假设
      locality:CNN是以滑动窗口的形式一点一点地在图片上进行卷积的,所以假设图片上相邻的区域会有相邻的特征,靠得越近的东西相关性越强
  • Swin Transformer里,默认每个窗口有49个patch,第一层每个patch尺寸是4*4。
  • locality进一步说明:对于图片来说,语义相近的不同物体还是大概率会出现在相连的地方,所以即使是在一个小范围的窗口内计算自注意力也是差不多够用的,全局计算自注意力对于视觉任务来说,其实是有点浪费资源的。
  • W-MSA虽然减少了计算量,但也会隔绝不同窗口之间的信息传递。所以在论文中作者又提出了 SW-MSA的概念,通过此方法能够让信息在相邻的窗口中进行传递,后面会细讲。

3.2 相关工作(略)

3.3 算法

3.3.1 模型结构

  原论文中给出的关于Swin Transformer(Swin-T)网络的架构图如下:
李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer

  1. Patch Partition层:类似ViT一样将图片分割成一个个4*4大小的patch([224,224,3]—>[56,56,48]
  2. 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 PartitionLinear Embeding就是直接通过一个卷积层实现的,和之前Vision Transformer中讲的 Embedding层结构一模一样。(kernel size=4×4,stride=4,num_kernel=48)
  1. 将每49个patch划分为一个窗口,后续只在窗口内进行计算。

  2. 通过四个Stage构建不同大小的特征图。其中后三个stage都是先通过一个Patch Merging层进行2倍的下采样。([56,56,96]—>[28,28,192]—>[14,14,384]—>[7,7,768]

  3. 每个stage中,重复堆叠Swin Transformer Block偶数次(结构见上图右侧,分别使用W-MSASW-MSA,两个结构成对出现)。

  4. 如果是分类任务,后面还会接上一个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 MergingW-MSASW-MSA以及使用到的相对位置偏置(relative position bias)进行详解。

3.3.2 Patch Merging

李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer

  上面讲了,在每个Stage中首先要通过一个Patch Merging层进行下采样(Stage1除外)。
如上图所示,假设输入的是一个4x4大小的单通道特征图(feature map),分割窗口大小为2×2,Patch Merging操作如下:

  1. 分割:Patch Merging会将每个2x2的相邻像素划分为一个patch,然后将每个patch中相同位置(同一颜色)像素给拼在一起,得到了4个feature map。
  2. 拼接:将这四个feature map在深度方向进行concat拼接
  3. 归一化:进行LayerNorm处理
  4. 改变通道数:最后通过一个全连接层对每个像素的channel进行改变,将feature map的深度由C变成C/2。

可以看出,通过Patch Merging层后,feature map的高、宽会减半,深度翻倍。

3.3.3 W-MSA

  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。

目的:减少计算量(下图可以看出两种方式分别是多少计算量)
缺点:窗口之间无法进行信息交互,等于减少了感受野,无法看到全局信息
李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer

具体的计算过程可以参考:太阳花的小绿豆帖子《Swin-Transformer网络结构详解》第三章

3.3.4 SW-MSA(Shifted Windows Multi-Head Self-Attention)

  与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层的四个窗口信息进行交流,其他同理。

李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer
  但是这样也有一个问题:偏移后,窗口数由原来的4个变成了9个,后面又要对每个窗口内部进行MSA,非常麻烦。为此,作者又提出了一种更加高效的计算方法——masked MSA(后面会讲)。

3.3.5 Masked MSA(技术细节,选看)

  下图左侧是刚刚通过偏移窗口后得到的新窗口,右侧是为了方便大家理解,对每个窗口加上了一个标识。

  1. 将区域A和C移到最下方
    李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer
  2. 再将区域A和B移至最右侧
    李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer
  3. 分成4个4x4的窗口
    如下图所示,移动完后,4是一个单独的窗口;5和3合并成一个窗口;7和1合并成一个窗口;8、6、2和0合并成一个窗口。这样又和原来一样是4个4x4的窗口了,所以能够保证计算量是一样的。
    李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer
  4. Masked MSA计算。
    上图这样划分之后,还有个问题,就是合并的窗口本身是不相邻的,比如5和3,如果直接进行MSA计算,是有问题的。我们希望是能够单独计算区域3和区域5各自区域内的MSA,论文中给的方法是Masked MSA,来隔绝不同区域的信息。
    李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer
      如上图,区域5和区域3为例。对于该窗口内的每一个像素,都要先生成对应的query,key和value,然后与每一个像素进行attention计算。设
    α
    ,
    \alpha _{0,0}
    α0,0
    代表
    q
    q^0
    q0
    与像素0对应的
    k
    k^0
    k0
    进行匹配得到的attention score,同理可以得到
    α
    ,
    1
    \alpha _{0,1}
    α0,1

    α
    ,
    15
    \alpha _{0,15}
    α0,15

      接下来就是SoftMax操作,但是对于Masked MSA,不同区域之间的像素计算的attention score会减去100(attention score∈[0,1],减去100是一个很大的负数,经过softmax之后基本等于0了,后续加权求和结果也是0),这样等于不同区域之间的像素计算的attention被置为0,被屏蔽了。最终像素0计算的attention结果,还是和本区域5各个像素计算之后的结果。
      注意:在计算完后还要把数据给挪回到原来的位置上(例如上述的A,B,C区域)

  Efficient batch computation for shifted configuration简单说,就是通过移动合并,将9个窗口还是变为原来的4个窗口,再进行Masked MSA计算。计算量和普通的MSA一样,只是多了个mask。
  Masked MSA是为了解决合并窗口中各个窗口应该单独计算的问题。使用Masked MSA,将不同窗口元素计算的attention score-100,等价于屏蔽掉不同窗口元素的attention结果。最终达到了4个窗口同时进行MSA计算,又保证得到只在在窗口内进行计算的效果。

3.4 实验

3.4.1 ImageNet

结果见下图左侧:

3.4.2 COCO数据集

结果见上图右侧:

3.4.3 语义分割数据集ADE20K

效果好

3.4.4移动窗口和相对位置编码

  论文中还提到,使用相对位置偏置后给够带来明显的提升。(下图公式中的B就是偏置,ADE20k是图片分割数据集)
李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer

  下面具体讲解什么是Relative Position Bias(假设特征图大小为2×2)
李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer

  1. 计算相对位置索引:比如蓝色像素,在蓝色像素使用q与所有像素k进行匹配过程中,是以蓝色像素为参考点。然后用蓝色像素的绝对位置索引与其他位置索引进行相减,就得到其他位置相对蓝色像素的相对位置索引,同理可以得到其他位置相对蓝色像素的相对位置索引矩阵(第一排四个位置矩阵)。
  2. 展平拼接:将每个相对位置索引矩阵按行展平,并拼接在一起可以得到第二排的这个4x4矩阵。
  3. 索引转换为一维:在源码中作者为了方便把二维索引给转成了一维索引。
    - 首先在原始的相对位置索引上加上M-1(M为窗口的大小,在本示例中M=2),加上之后索引中就不会有负数了。
    - 接着将所有的行标都乘上2M-1
    - 最后将行标和列标进行相加。这样即保证了相对位置关系,而且不会出现直接相加后位置重叠的问题。(0±1和-1+0结果都一样,但其实其位置不一样)
    李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer

    李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer

  4. 取出相对位置偏置参数。真正使用到的可训练参数B 是保存在relative position bias table表里的,其长度是等于
    (
    2
    M

    1
    )
    ×
    (
    2
    M

    1
    )
    (2M-1) \times (2M-1)
    (2M1)×(2M1)
    。相对位置偏置参数B,是根据相对位置索引来查relative position bias table表得到的,如下图所示。
    李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer
      为啥表长是
    (
    2
    M

    1
    )
    ×
    (
    2
    M

    1
    )
    (2M-1) \times (2M-1)
    (2M1)×(2M1)
    ?考虑两个极端位置,(0,0)能取到的相对位置极值为(-1,-1),(-1,-1)能取到的极值是(1,1),即行和列都能取到(2M-1)个数。考虑到所有的排列组合,表的长度就是
    (
    2
    M

    1
    )
    ×
    (
    2
    M

    1
    )
    (2M-1) \times (2M-1)
    (2M1)×(2M1)

3.4.5 模型详细配置参数

模型结构和参数如下:
李沐论文精读系列二:Vision Transformer、MAE、Swin-Transformer

Swin-T举例:

3.5 结论

  本文最关键的一个贡献就是基于 Shifted Window 的自注意力,它对很多视觉的任务,尤其是对下游密集预测型的任务是非常有帮助的 。所以未来工作的重点就是把Shifted Window 用到NLP任务中,推进模型的大一统(多模态)。

3.6 代码讲解

  • 太阳花的小绿豆:代码地址、代码讲解视频
  • 《Swin Transformer 论文详解及程序解读》

发表回复