Transformer、Swin Transformer、VIT、TimeS-former

一、Transformer(Attention is all you need)

1.1 Transformer 结构

在这里插入图片描述
Transformer是一个基于Encoder-Decoder框架的模型,其结构拆解开来,主要分为图上4个部分,其中最重要的就是2和3Encoder-Decoder部分。

1.2 输入

1.2.1 Input Embedding

Transformer的输入往往是一段文本,文本序列经过处理后输入网络模型:
文本序列→拆分词元,建立字典→序列转变为词元在字典中所对应的索引→将索引转变为词向量,可以是word2vec,GloVe,one-hot编码。

1.2.2 Positional Encoding

没有 Position embedding 的 Transformer 模型并不能捕捉序列的顺序,交换单词位置后 attention map 的对应位置数值也会进行交换,并不会产生数值变化,即没有词序信息。所以想要将词序信息加入到模型中就需要进行位置编码。
在这里插入图片描述pos是位置,i是维度,位置编码的每个维度对应一个正弦信号
将positional encoding与 Input Embedding相加输入编码器

1.3 编码器

Encoder block是由6个encoder堆叠而成,Nx=6。

一个encoder由Multi-Head Attention 和 全连接神经网络Feed Forward Network构成。

1.3.1 自注意力机制

在这里插入图片描述
在这里插入图片描述
其中dk就是K的维度

1.3.2 多头自注意力机制

将输入x按通道数平均分成多份,每一份使用同样的注意力机制进行计算。

1.3.3 Add:残差连接

1.3. 4 Norm

层归一化,能够加快训练的速度,提高训练的稳定性,LN是在同一个样本中不同神经元之间进行归一化,而BN是在同一个batch中不同样本之间的同一位置的神经元之间进行归一化。

BN是对于相同的维度进行归一化,但是NLP中输入的都是词向量,一个300维的词向量,单独去分析它的每一维是没有意义地,因此这里选用的是LN。

1.3.5 Feed-Forward Networks

先线性变换,然后ReLU非线性,再线性变换,这里的x是Multi-Head Attention的输出Z。经过Add&Normalize,输入下一个encoder中,经过6个encoder后输入到decoder中
在这里插入图片描述

1.4 解码器

1.4.1 Decoder的输入

训练时的输入:准备好的对应的target数据
预测时的输入:一开始输入的是起始符,然后每次输入是上一时刻Transformer的输出。

1.4.2 Masked Multi-Head Attention

基于自注意力
与Encoder的Multi-Head Attention计算原理一样,只是多加了一个mask码。mask 表示掩码,它对某些值进行掩盖,使其在参数更新时不产生效果。Transformer 模型里面涉及两种 mask,分别是 padding mask 和 sequence mask。

  1. padding mask
  • 因为每个批次输入序列长度是不一样的,要对输入序列进行对齐。
  • 具体来说,就是给在较短的序列后面填充 0。但是如果输入的序列太长,则是截取左边的内容,把多余的直接舍弃。
  • 填充的位置没有意义,attention机制不应该把注意力放在这些位置上,所以需要进行一些处理。
  • 具体的做法是,把这些位置的值加上一个非常大的负数(负无穷),这样的话,经过 softmax,这些位置的概率就会接近0!
  1. sequence mask
  • sequence mask 是为了使得 decoder 不能看见未来的信息。
  • 对于一个序列,在 time_step 为 t 的时刻,我们的解码输出应该只能依赖于 t 时刻之前的输出,而不能依赖 t 之后的输出。 因此需要把 t 之后的信息给隐藏起来。
  • 这在训练的时候有效,因为训练的时候每次是将target数据完整输入进decoder中,预测时不需要,预测的时候只能得到前一时刻预测出的输出。
  • 具体做法:产生一个上三角矩阵,上三角的值全为0。把这个矩阵作用在每一个序列上,就可以达到目的。

在Encoder中的Multi-Head Attention也是需要进行mask地,只不过Encoder中只需要padding mask即可,而Decoder中需要padding mask和sequence mask

1.4.3 基于Encoder-Decoder 的Multi-Head Attention

  • Encoder中的Multi-Head Attention基于Self-Attention
  • Decoder中的第二个Multi-Head Attention就只是基于Attention
  • 它的输入query来自于Masked Multi-Head Attention的输出,Keys和Values来自于Encoder中最后一层的输出。

为什么Decoder中要搞两个Multi-Head Attention

  • 第一个Masked Multi-Head Attention是为了得到之前已经预测输出的信息,相当于记录当前时刻的输入之间的信息。
  • 第二个Multi-Head Attention是为了通过当前输入的信息得到下一时刻的信息,也就是输出的信息。是为了表示当前的输入与经过encoder提取过的特征向量之间的关系来预测输出。

数据经过了第二个Multi-Head Attention和Feed Forward Network,输出进入下一个decoder,如此经过6层decoder之后到达最后的输出层。

1.5 输出

在这里插入图片描述
首先经过一次线性变换,然后Softmax得到输出的概率分布,然后通过词典,输出概率最大的对应的单词作为我们的预测输出。

二、ViT: An Image Is Worth 16x16 Words: Transformers For Image Recognition At Scale

2.1 ViT结构

在这里插入图片描述
模型由三个模块组成:

  • Linear Projection of Flattened Patches(Embedding层)
  • Transformer Encoder(图右侧)
  • MLP Head(最终用于分类的层结构)

2.1 Patch

对于标准的Transformer模块,要求输入的是token(向量)序列,即二维矩阵[num_token, token_dim]

对于图像数据而言,其数据格式为[H, W, C]是三维矩阵。

首先将一张图片按给定大小分成一堆Patches。

以ViT-B/16为例,将输入图片(224x224)按照16x16大小的Patch进行划分,划分后会得到(224/16)^2=196 个Patches。

通过线性映射将每个Patch映射到一维向量中,以ViT-B/16为例,每个Patche数据shape为[16, 16, 3]通过映射得到一个长度为768的向量(后面都直接称为token)。[16, 16, 3] -> [768]

在代码实现中,直接通过一个卷积层来实现。 以ViT-B/16为例,直接使用一个卷积核大小为16x16,步距为16,卷积核个数为768的卷积来实现。通过卷积[224, 224, 3] -> [14, 14, 768],然后把H以及W两个维度展平即可[14, 14, 768] -> [196, 768],此时正好变成了一个二维矩阵,正是Transformer想要的。

2.2 [class]token以及Position Embedding

2.1.1 [class]token

  • 在刚刚得到的一堆tokens中插入一个专门用于分类的[class]token

  • 这个[class]token是一个可训练的参数,数据格式和其他token一样都是一个向量,以ViT-B/16为例,就是一个长度为768的向量,与之前从图片中生成的tokens拼接在一起,Cat([1, 768], [196, 768]) -> [197, 768]。

2.2.2 Position Embeddi

  • 这里的Position Embedding采用的是一个可训练的参数(1D Pos. Emb.),是直接叠加在tokens上的(add),所以shape要一样。
  • 以ViT-B/16为例,刚刚拼接[class]token后shape是[197, 768],那么这里的Position Embedding的shape也是[197, 768]。

对于Position Embedding作者实验了无位置编码、1D位置编码、2D位置编码以及相对位置编码,在源码中默认使用的是1D Pos. Emb.,对比不使用Position Embedding准确率提升了大概3个点,和2D Pos. Emb.比起来没太大差别。
在这里插入图片描述

2.3 Transformer Encoder

Transformer Encoder其实就是重复堆叠Encoder Block L次,主要由以下几部分组成:
在这里插入图片描述

  • Layer Norm
  • Multi-Head Attention
  • Dropout/DropPath
  • MLP Block:就是全连接+GELU激活函数+Dropout,需要注意的是第一个全连接层会把输入节点个数翻4倍[197, 768] -> [197, 3072],第二个全连接层会还原回原节点个数[197, 3072] -> [197, 768]

3.3 MLP Head

  • 上面通过Transformer Encoder后输出的shape和输入的shape是保持不变的,以ViT-B/16为例,输入的是[197, 768]输出的还是[197, 768]。
  • 在Transformer Encoder后其实还有一个Layer Norm没有画出来。
  • 这里我们只是需要分类的信息,所以我们只需要提取出[class]token生成的对应结果就行,即[197, 768]中抽取出[class]token对应的[1, 768]。
  • 接着通过MLP Head得到最终的分类结果。
  • MLP Head原论文中说在训练ImageNet21K时是由Linear+tanh激活函数+Linear组成。但是迁移到ImageNet1K上或者你自己的数据上时,只用一个Linear即可。在这里插入图片描述

3.4 模型配置

论文给出了三个模型(Base/ Large/ Huge)的参数,在源码中除了有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数。
    在这里插入图片描述

三、Swin Transformer: Hierarchical Vision Transformer using Shifted Windows

在论文中,作者指出之前的Transformer模型从NLP迁移到CV没有大放光彩的主要原因是:

  • 两个领域涉及的scale不同,NLP的scale是标准固定的,而CV的scale变化范围非常大,相对于文本,视觉实体的尺度区别很大,例如车辆和人
  • CV比起NLP需要更大的分辨率,而且CV中使用Transformer的计算复杂度是图像尺度的平方,这会导致计算量过于庞大。

那么本篇论文作者为了解决该问题所用的方法有:

  • 引入CNN中常用的层次化构建方式Hierarchical feature maps)构建层次化Transformer
  • 提出了 Shifted Windows Multi-Head Self-Attention(SW-MSA)的概念,通过此方法能够让信息在相邻的窗口中进行传递

3.1 Swin Transformer vs ViT

在这里插入图片描述

  • Swin Transformer使用了类似卷积神经网络中的层次化构建方法(Hierarchical feature maps),比如特征图尺寸中有对图像下采样4倍的,8倍的以及16倍的,这样的backbone有助于在此基础上构建目标检测,实例分割等任务。
  • ViT是一开始就直接下采样16倍,后面的特征图也是维持这个下采样率不变,这样对于多尺寸特征的获得会弱一些。
  • Swin-Transformer使用窗口多头自注意力,将特征图划成多个不相交的区域,然后在每个窗口里进行自注意力计算,只要窗口大小固定,自注意力的计算复杂度也是固定的,那么总的计算复杂度就是图像尺寸的线性倍。
  • ViT对整个特征图进行全局自注意力计算,这样就减少了计算量,但是也隔绝了不同窗口之间的信息交流。随之Swin Transformer提出后文的移动窗口自注意力计算(Shifted Windows Multi-Head Self-Attention(SW-MSA))

3.2 网络架构图

在这里插入图片描述

  • 首先将图片输入到Patch Partition模块中进行分块,即每4x4相邻的像素为一个Patch,然后在channel方向展平(flatten)。

假设输入的是RGB三通道图片,那么每个patch就有4x4=16个像素,然后每个像素有R、G、B三个值所以展平后是16x3=48,所以通过Patch Partition后图像shape由 [H, W, 3]变成了 [H/4, W/4, 48]。

  • 再通过Linear Embeding层对每个像素的channel数据做线性变换,由48变成C。

图像shape再由 [H/4, W/4, 48]变成了 [H/4, W/4, C]

  • 然后就是通过四个Stage构建不同大小的特征图,除了Stage1中先通过一个Linear Embeding层外,剩下三个stage都是先通过一个Patch Merging层进行下采样(后面会细讲)。
  • 再通过重复堆叠的Swin Transformer Block。

这里的Block其实有两种结构,如图(b)中所示,这两种结构的不同之处仅在于一个使用了W-MSA结构,一个使用了SW-MSA结构。而且这两个结构是成对使用的,先使用一个W-MSA结构再使用一个SW-MSA结构。所以你会发现堆叠Swin Transformer Block的次数都是偶数(因为成对使用)。

  • 最后对于分类网络,后面还会接上一个Layer Norm层、全局池化层以及全连接层得到最终输出。图中没有画,但源码中是这样做的。

3.3 Patch Merging

  • 每个Stage中首先要通过一个Patch Merging层进行下采样(Stage1除外)。
  • 如下图所示,假设输入Patch Merging的是一个4x4大小的单通道特征图(feature map),Patch Merging会将每个2x2的相邻像素划分为一个patch,然后将每个patch中相同位置(同一颜色)像素给拼在一起就得到了4个feature map。
  • 接着将这四个feature map在深度方向进行concat拼接,然后在通过一个LayerNorm层。
  • 最后通过一个全连接层在feature map的深度方向做线性变化,将feature map的深度由C变成2C。
  • 通过Patch Merging层后,feature map的高和宽会减半,深度会翻倍。

在这里插入图片描述

3.4 W-MSA

  • 引入Windows Multi-head Self-Attention(W-MSA)模块是为了减少计算量。
  • 如下图所示,左侧使用的是普通的Multi-head Self-Attention(MSA)模块,对于feature map中的每个像素(或称作token,patch)在Self-Attention计算过程中需要和所有的像素去计算。
  • 但在图右侧,在使用Windows Multi-head Self-Attention(W-MSA)模块时,首先将feature map按照MxM(例子中的M=2)大小划分成一个个Windows,然后单独对每个Windows内部进行Self-Attention。

在这里插入图片描述
原论文中给出的计算量比较:
在这里插入图片描述

在这里插入图片描述

3.5 SW-MSA

  • 采用W-MSA模块时,只会在每个窗口内进行自注意力计算,所以窗口与窗口之间是无法进行信息传递的。
  • 为了解决这个问题,作者引入了Shifted Windows Multi-Head Self-Attention(SW-MSA)模块,即进行偏移的W-MSA。
  • 如下图所示,左侧使用的是刚刚讲的W-MSA(假设是第L层),那么根据之前介绍的W-MSA和SW-MSA是成对使用的,那么第L+1层使用的就是SW-MSA(右侧图)。
  • 根据左右两幅图对比能够发现窗口(Windows)发生了偏移(可以理解成窗口从左上角分别向右侧和下方各偏移了⌊M/2⌋ 个像素)。
    在这里插入图片描述
    根据上图,可以发现通过将窗口进行偏移后,由原来的4个窗口变成9个窗口了。后面又要对每个窗口内部进行MSA,这样做感觉又变麻烦了。为了解决这个麻烦,作者又提出而了Efficient batch computation for shifted configuration,一种更加高效的计算方法。下面是原论文给的示意图。
    在这里插入图片描述
    变换顺序:先将AC移动到最下方,再将AB移动到最右方
    在这里插入图片描述
    四个窗口的模板如下图:

在这里插入图片描述

3.6 Relative Position Bias

3.6.1 相对位置偏置加在哪

在这里插入图片描述
B即为相对位置偏置

3.6.2 相对位置偏置如何计算

  • 如下图,假设输入的feature map高宽都为2,那么首先我们可以构建出每个像素的绝对位置(左下方的矩阵)

对于每个像素的绝对位置是使用行号和列号表示的
蓝色的像素对应的是第0行第0列,所以绝对位置索引是(0,0)

  • 相对位置索引:首先看下蓝色的像素,在蓝色像素使用q与所有像素k进行匹配过程中,是以蓝色像素为参考点,然后用蓝色像素的绝对位置索引与其他位置索引进行相减,就得到其他位置相对蓝色像素的相对位置索引。

例如黄色像素的绝对位置索引是(0,1),则它相对蓝色像素的相对位置索引为(0,0)−(0,1)=(0,−1)
同理可以得到其他位置相对蓝色像素的相对位置索引矩阵。
同样,也能得到相对黄色,红色以及绿色像素的相对位置索引矩阵。

  • 接下来将每个相对位置索引矩阵按行展平,并拼接在一起可以得到下面的4x4矩阵
    在这里插入图片描述
    这里描述的一直是相对位置索引,并不是相对位置偏置参数。后面会根据相对位置索引去取对应的参数。

比如说黄色像素是在蓝色像素的右边,所以相对蓝色像素的相对位置索引为(0,−1)。
绿色像素是在红色像素的右边,所以相对红色像素的相对位置索引为(0,−1)。
这两者的相对位置索引都是(0,−1),所以他们使用的相对位置偏执参数都是一样的。

在源码中作者为了方便把二维索引给转成了一维索引:

  1. 在原始的相对位置索引上加上M-1(M为窗口的大小,在本示例中M=2),加上之后索引中就不会有负数了。
    在这里插入图片描述

  2. 接着将所有的行标都乘上2M-1在这里插入图片描述

  3. 最后将行标和列标进行相加。
    在这里插入图片描述
    注意:

  • 之前计算的是相对位置索引,并不是相对位置偏执参数。

  • 真正使用到的可训练参数是保存在relative position bias table表里的,这个表的长度是等于(2M−1)×(2M−1)。

  • 只要窗口大小是固定的,relative position index表就是固定的,根据表中的index去relative position bias table中取数据

  • 训练的是relative position bias table中的参数
    在这里插入图片描述

3.7 模型配置

T(Tiny),S(Small),B(Base),L(Large),其中:

  • win. sz. 7x7表示使用的窗口(Windows)的大小
  • dim表示feature map的channel深度(或者说token的向量长度)
  • head表示多头注意力模块中head的个数
    在这里插入图片描述

四、TimeS-former:Is Space-Time Attention All You Need for Video Understanding?

这篇论文是在vision transformer的基础上,在时间维度进行了attention,将图像分类拓展到了视频分类。这也是第一个完全抛弃CNN,只用transformer搭建整个网络的视频分类模型。

作者在文中说到,之所以进行这种只用transformer的尝试,是有三点原因:
(1)tranformer在NLP领域取得了巨大的成功,视频和文本一样,某些动作需要有上下文才能进行准确的分类;
(2)CNN有很强的inductive bias

  • 其一,卷积利用卷积核的方式告诉了卷积网络,每个像素点和它周围的像素点有很大的关联
  • 其二,卷积核权重共享的机制告诉了卷积网络,图像当中的物体移动之后,仍旧是相同的物体
  • transformer其实也有一些inductive biases,比如必须要根据相似度来融合信息,但这种biases比较weak。

同时CNN只能处理感受野之内的信息,如果需要看图片的全局信息,就必须要用很深的网络,而很深的网络又需要大量的数据和大量的算力。

(3)transformer需要的算力小,而且可以适用于比较长的视频,比如1分钟以上的,甚至是7分钟左右的。

在将空间维度的transformer和时间维度的transformer进行结合时,作者也尝试了很多方法,最终发现将时间和空间和attention分开计算的"divided space-time attention"是效果最好的。

4.1 模型输入

模型的输入为从视频片段中等分抽取的F帧,表示为X,X的shape为H×W×3×F。

比如一个2s,fps为24的视频片段,当F=8时,就会取[0,6,12,18,24,30,36,42]这几帧作为一个序列来输入。F在论文中的取值是[8,32,64,96]这几种,没有特殊说明的话,就是F=8

输入的每一帧会先经过resize和crop成为一个预先设置好的模型接受的输入尺寸,一般是224×224。
然后每一帧都会被切成多个patches。

每个patch的尺寸为P×P,P一般取16。
切成多个patches之后的图像就如图2-2中的图片示意的那样,一共会被切成N个patch,N=HW/(P^2)

切割后的每一个patch可以表示为x(p,t),其中p=1,…,N表示属于一帧中的第几个patch,t=1,…,F表示第几帧。

最后,每个patch会经过一层embedding,得到
在这里插入图片描述
在这里插入图片描述

4.2 attention模块

首先,要得到每个patch的query,key和value。在这里插入图片描述

  • LN()表示LayerNorm
  • a=1,…,A表示第a个head
  • Dh表示每个head的维度
  • p=1…N
  • t=1…F
  • l应该是指层数

然后开始attention,这里相比图片的transformer多了时间的维度,所以如果直接全都做attetion的话,计算量会非常大,需要计算N×F+1次attention

问题:+1从哪里来的
来自于之前加入的应该可学习的向量

在这里插入图片描述

  • SM表示softmax
  • Dh =D/A表示每个head分到的维度,D是embedding的维度
  • 中括号里的k表示k的可选集合

为了减小attention的计算量,作者想出了如下图所示的多种attention的方式
在这里插入图片描述
以第t帧的左上角蓝色patch做attention为例,用到的前后帧及自身的patch的如图所示

在这里插入图片描述

两个问题:

  • 第四种方法:先局部后整体,是否每一帧蓝色patch都是先和局部的3个patch做注意力,再和整体的3个patch做注意力,这样的话就没有利用时间维度上的信息了?
  • 究竟是选择patch做自注意力,还是不同patch做注意力?:每个patch做自注意力

中间这种将时间的attention和空间的attention分开计算的方式,效果最好,也是作者最后使用的,称为"divided space-time attention"。这种方法只需要计算N+F+2次attention即可。

注意:
+2和之前+1的原理一样
使用的是多头自注意力机制,这只是其中一个头的计算

在这里插入图片描述

有了attention之后,结合value可以得到一个attention的最终输出
在这里插入图片描述

问题:前半部分是什么?

使用了多头注意力,这个输出再经过一个MLP,加上残差,就得到了一层的输出在这里插入图片描述

根据效果来看,在时间、空间上分别做注意力最好
在这里插入图片描述

4.3 分类模块

当得到所有层的输出之后,分类用的就是用的之前在输入中加的特殊的向量对应的输出。
在这里插入图片描述
拿y去过分类器就行了,分类器可以是一个全连接

细节:

在预测的时候,作者用了三种不同crop(top-left、center和bottom-right)的方式,过模型之后取平均。

这一步是在模型输入的时候做的。比如把图片resize到256×256之后,再用这种方式crop到224×224。

  • 29
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值