VIT — 用于大规模图像识别的 Transformer
论文题目:AN IMAGE IS WORTH 16X16 WORDS:TRANSFORMERS FOR IMAGE RECOGNITION AT SCALE。
官方代码:https://github.com/google-research/vision_transformer
引言与概述
Vision Transformer(ViT)是一种基于注意力机制的深度学习模型,它是由 Google 提出的,旨在将Transformer架构应用到计算机视觉任务中。它的提出证明了: Transformer 在CV领域的可行性。
Transformers在之前可以和CNN结合起来用增强特征图的方式用于分类和检测。
-
而在vision Transform中没有使用到深度的2d卷积,完全使用Transform中的多头自注意力机制,与Encode结构进行实现的
-
输入的patches的结构经过一个vit块后的结构保持不变,因此可以用来直接对vit块进行N次的堆叠操作。
Vision Transformer(ViT)模型架构是一种基于 Transformer 架构的深度学习模型,用于处理计算机视觉任务(最主要的是会应用到分类的任务中)。下面是 Vision Transformer 的模型框架。
-
Linear Projection of Flattened Patches模块(Embedding层):将输入的图像数据转换为可以输入到 Transformer 编码器中的序列化表示,其中包括了patch+position+learnable embedding。
-
Transformer encoder (Transformer编码层):向量表示被输入到 Transformer 编码器中。每个 Transformer 编码器包含多头自注意力机制和前馈神经网络,用于捕捉全局信息和学习特征表示。这一部分是 Vision Transformer 中最关键的组件。
-
MLP Head(用于分类的全连接层):在经过一系列 Transformer 编码器之后,模型的输出会被送入一个包含多层感知机(MLP)的输出层中,用于最终的分类或其他计算机视觉任务。
处理流程
-
输入阶段: 首先将输入的原始图像按照给定大小切分成固定大小的图像块(patches),每个图像块包含图像中的局部信息。 每个图像块通过一个线性变换(通常是一个卷积层)映射到一个低维的特征空间,得到Patch Embeddings。同时,为每个Patch Embedding加入位置编码(Positional Embedding)和可学习嵌入(learnable Embedding) 以综合考虑图像的空间位置和全局信息。
-
输入到Transformer: 将经过嵌入层处理的序列化表示作为输入,传入到多层Transformer Encoder来对序列化表示进行处理。
-
输出分类结果: 经过一系列Transformer编码器的处理后,模型的最后一层输出向量经过全连接层或其他分类层进行分类任务。
图像处理与前向传播
在论文中提到过,在Vit Transform提出之前,其实就有人使用过将图像中的每一个像素看作是一个序列数据,本质上就是将图像的像素数据进行一个展平操作=WxHx3个像素,就会导致图像得到的序列数据过长从而影响整个的运算。
作者就针对这一个问题提出了使用Transformer receives as input a 1D
sequence of token embeddings. To handle 2D images, we reshape the image x ∈ RH×W×C into asequence of flattened 2D patches xp ∈ RN×(P2·C)(使用patch方法将2d的数据转换为1d的数据,但是是切分为多个小的patch块进行的。)
Patch Embedding
Patch Embedding 是指将输入的图像划分为固定大小的图像块(patches)后,将每个图像块映射成一个向量表示,最终所有的图像块被变换成满足transformer输入的一维表示。
将输入为224x224的图像,切分为196个16x16的Patch图像块。
我们从50176个token转变为了196个token从而降低了序列的长度。
-
图像划分为图像块: 输入的原始图像被切分成大小相同的图像块,每个图像块通常是不重叠的固定大小的方形区域。这样做的目的是为了将图像信息分割为局部区域,使得模型能够处理不同尺寸的图像。 例:以ViT-B/16为例,将输入图片(224x224)按照16x16大小的Patch进行划分,划分后会得到 ( 224 / 16 ) 2 = 196 ( 224 / 16 )^2 = 196 (224/16)2=196个Patches,每个Patche数据shape为[16, 16, 3]。
-
映射为向量表示: 对于每个图像块,通过一个线性变换(一个卷积层)将其映射成一个一维特征向量,也称为 Patch Embedding。这个过程可以理解为将图像块中的像素信息转换为一个固定维度的向量,以表示该图像块的特征。 例:每个Patche数据通过映射得到一个长度为768的向量,即[16, 16, 3] -> [768]
- 串联所有 Patch Embedding: 将所有图像块经过 Patch Embedding 后得到的向量表示串联在一起,形成一个序列化的特征矩阵。这个矩阵作为Transformer的输入,传入Transformer编码器进行处理。 例:将196个Patchs串联起来,最终组成[196,768]的二维token向量,token的个数是196,token维度是768
Class token + Positional Embedding
Class token
在ViT模型的原论文中,作者模仿BERT模型,为ViT 模型中引入一个专门用于分类的 [class] token。这个 [class] 是一个可训练的参数,其数据格式和其他 token 一样都是一个向量,例如在 ViT-B/16 模型中,这个向量的长度是768
其中引入的class token代表的是一个可以学习的张量。
引入了class token之后就需要和经过Linear Projection of Flattened Patches展平之后得到的向量进行一个cat
的操作。
下面给出运算步骤的一个示意图。‘
我们最后得到的信息就是,批次数 + (196+1)[经过cat连接操作] +768(论文中D的长度)
向量拼接: 将 [class] token 的向量与之前从图片中生成的 tokens 拼接在一起。例如,原先有 196 个 tokens,每个 token 长度为 768,则token embeddding变为Cat([1, 768], [196, 768]) -> [197, 768],注意, [ c l a s s ] [class] [class] token插在开头。
之后我们还需要加入位置编码就可以对位置信息进行编码从而输入序列数据进入Transform的多头自注意力机制模块。
ViT的Position Embedding采用的是一个可学习/训练的 1-D 位置编码嵌入,是直接叠加在tokens上的(add), 例: position embedding的shape应该是[197,768],直接position embedding + [ c l a s s ] [class] [class] token embedding=[197,768]
相加的操作不改变整体的一个维度信息。
使用什么样的位置编码对结果的影响不是特别的大。
Transformer encode
Transformer encoder在代码中有时是打包在Block里面的。
Transformer Encoder 是用来处理输入序列的部分,它由多个 Transformer Block 组成。每个 Transformer Block 都包括两个主要组件:多头自注意力层和前馈神经网络。
包括了两个残差连接的部分所组成。
-
Multi-head Self-Attention Layer: 在每个 Transformer Block 中,输入特征首先被送入一个多头自注意力层。这个层用来计算输入序列中每个位置对应的注意力权重,以捕捉不同位置之间的关系。
-
Feed-Forward Neural Network: 在经过多头自注意力层后,每个位置的特征会通过一个前馈神经网络进行处理。这个前馈神经网络通常由两个全连接层和激活函数组成,用来对每个位置的特征进行非线性变换和映射。
-
Residual Connection & Layer Normalization: 在每个 Transformer Block 的多头自注意力层和前馈神经网络中都会包含残差连接和层归一化操作,这有助于缓解梯度消失问题和加速训练过程。
多个Transformer encode模块进行堆叠,ViT 模型能够有效地学习输入图像的复杂特征和结构信息。(代码中好像是连续堆叠三次)多头注意力部分使用之前的类进行单独的定义。
论文中给出的一个前向传播的基本的公式形式。
等式 1:由 图像块嵌入
x
p
i
E
x_p^iE
xpiE,类别向量
x
c
l
a
s
s
x_{class}
xclass,位置编码
E
p
o
s
E_{pos}
Epos构成 输入向量
z
0
z_0
z0
等式 2:由 多头注意力机制、层归一化和跳跃连接构成的 MSA Block,可重复L个,最后一个输出为
z
l
‘
z_l^{‘}
zl‘
等式 3:由 前馈网络、层归一化 和 跳跃连接构成的 MLP Block,可重复L个,最后一个输出为
z
l
z_l
zl
等式 4:由 层归一化 和 分类头 (MLP or FC) 输出 图像表示
y
y
y
MLP Head
先进行一个4倍的扩增,之后在通过一个线性层进行下采样的一个操作,使得输入输出的大小保持不变。(隐藏层拓为4倍)
注意和之前还有做一次残差连接的操作。
MLP Head 是指位于模型顶部的全连接前馈神经网络模块,用于将提取的图像特征表示转换为最终的分类结果或其他预测任务输出。MLP Head 通常跟在 Transformer Encoder 的输出之后,作为整个模型的最后一层。
具体来说,当我们只需要分类信息时,只需要提取出 [ c l a s s ] [class] [class]token生成的对应结果就行,即[197, 768]中抽取出[class] token对应的[1, 768]。接着我们通过MLP Head得到我们最终的分类结果。MLP Head原论文中说在训练ImageNet21K时是由Linear+tanh激活函数+Linear组成。但是迁移到ImageNet1K上或者你自己的数据上时,只用一个Linear即可。
取出class token对应的那一部分代码信息,(197-1)
维度变换总结
总结:
-
输入图像的input shape=[1,3,224,224],1是batch_size,3是通道数,224是高和宽输入图像经过patch Embedding,其中Patch大小是14,卷积核是768,则经过分块后,获得的块数量是 196,每个块的维度被转换为768,即得到的patch embedding的shape=[1,196,768]
-
将可学习的[class] token embedding拼接到patch embedding前,得到shape=[1,197,768]
-
将position embedding加入到拼接后的embedding中,组成最终的输入嵌入,最终的输入shape=[1,197,768]
-
输入嵌入送入到Transformer encoder中,shape并不发生变化
-
最后transformer的输出被送入到MLP或FC中执行分类预测,选取[class] token作为分类器的输入,以表示整个图像的全局信息,假设分类的类目为K,最终的shape=[1,768]*[768,K]=[1,K] K也就是分类的类别数目。
最后总结的VIT-b/16模型所对应的结构示意图如图所示。
论文中还给出了通过训练之后得到的位置编码直接的余弦相似度的示意图。