一、什么是Vision Transformers?
从2017年在《Attention is All You Need》中首次提出以来,Transformer模型已经成为自然语言处理(NLP)领域的最新技术。在2021年,论文《An Image is Worth 16x16 Words》成功地将Transformer应用于计算机视觉任务。从那时起,基于Transformer的各种架构陆续被提出用于计算机视觉。
Transformer是一种利用注意力机制作为主要学习机制的机器学习模型,它很快成为了序列到序列任务(如语言翻译)的最新技术。论文《An Image is Worth 16x16 Words》成功地改造了《Attention is All You Need》中中提出的Transformer,用于解决图像分类任务,创建了Vision Transformer(ViT)。ViT基于与《Attention is All You Need》中中的Transformer相同的注意力机制。然而,与用于NLP任务的Transformers包含编码器和解码器两个注意力分支不同(当然现在主流的NLP如GPT只使用Decoder),ViT仅使用编码器。编码器的输出随后传递给一个神经网络“头”,进行预测。
《An Image is Worth 16x16 Words》中ViT的缺点是其最佳性能需要在大规模数据集上进行预训练。表现最好的模型是在专有的JFT-300M数据集上预训练的。在较小的开源数据集ImageNet-21k上预训练的模型,其性能与最新的卷积神经网络ResNet模型相当。《Tokens-to-Token ViT: Training Vision Transformers from Scratch on ImageNet》尝试通过引入一种新的预处理方法,将输入图像转换为一系列token,从而消除这种预训练需求。在本文中,我们将重点介绍《An Image is Worth 16x16 Words》中实现的ViT。
二、模型详解
本文遵循《An Image is Worth 16x16 Words》中描述的模型结构。然而,这篇论文中的代码没有公开。最新的Tokens-to-Token ViT的代码可以在GitHub上找到。Tokens-to-Token ViT(T2T-ViT)模型在一个基础的ViT骨干网络前加上了一个Tokens-to-Token(T2T)模块。本文中的代码基于Tokens-to-Token ViT GitHub代码中的ViT组件。本文所做的修改包括但不限于:允许输入非正方形图像,并去除了dropout层。下面是ViT模型的示意图。
Vision Transformer (ViT) 工作流程(嵌入维度768):
1. Input Image(输入图像):
输入图像的尺寸是 60 x 100
像素。
2. Image Tokens(图像Token):
将输入图像分割成多个 20 x 20
像素的块。图像的高度被分割成 60 / 20 = 3
行块。图像的宽度被分割成 100 / 20 = 5
列块。因此,总的块数为 3 * 5 = 15
个块。每个块被展平成一个长度为 20 * 20 = 400
的向量,所以我们有15个长度为400的图像Token。
3. Linearly Embed Patches(线性嵌入块):
将每个长度为400的图像Token通过一个线性变换映射到一个嵌入空间,生成长度为768的嵌入向量。768是经过Token化后的每个Token的维度或长度。在Vision Transformer (ViT) 中,每个图像块(Patch)在被展平并通过线性变换后,都会被映射到一个长度为768的嵌入向量。这意味着每个Token的表示是在768维的嵌入空间中。
这样,每个块就被表示为一个长度为768的嵌入向量。
4. Prediction Token(预测Token):
初始化一个全零的预测Token,长度为768(与每个图像Token的长度相同)。
5. Concatenate(拼接):
将预测Token与15个图像Token拼接在一起,形成一个包含16个Token的序列。序列的形式为:[预测Token, 图像Token1, 图像Token2, ..., 图像Token15],每个Token的长度为768。
6. Position Embedding and All Tokens(位置嵌入和所有Token):
为16个Token(包括预测Token和图像Token)添加位置嵌入。位置嵌入是一个与Token序列长度相同的向量,用于表示每个Token在序列中的位置。位置嵌入的维度也是768。添加位置嵌入后的序列仍然是16个Token,每个Token的长度为768。这一步确保所有Token(包括预测Token和图像Token)都已经添加了位置信息,并且准备好进行下一步的编码块处理。
7. Encoding Block(编码块):
这些Token序列通过一系列的编码块进行处理。在你的代码示例中,编码块的数量是12(由depth
参数指定)。每个编码块包含以下组件:
-
Norm(规范化层):对输入进行规范化,确保输入数据在不同维度上的分布更加均匀。
-
Attention(注意力层):应用多头自注意力机制来捕捉Token之间的关系。注意力机制允许每个Token与其他Token交换信息,从而捕捉图像的全局特征。
-
Norm(规范化层):再次进行规范化,确保在经过注意力层之后的数据继续保持均匀分布。
-
NN(神经网络):一个小型的前馈神经网络,由一个全连接层、一个激活层和另一个全连接层组成。前馈神经网络进一步处理和转换Token信息。
经过12个编码块的处理后,每个Token(包括预测Token)都被充分处理和转换,捕捉到了输入图像的丰富特征信息。
8. Seperate(分离):
从编码块输出的16个Token序列中分离出预测Token和图像Token。此时,预测Token已经通过多个编码块获取了输入图像的信息。分离操作通常是通过索引来实现的,例如:
# 从编码块输出的Token序列中提取预测Token
prediction_token = encoded_tokens[:, 0]
# 提取图像Token
image_tokens = encoded_tokens[:, 1:]
通过这种方式,我们可以得到一个包含预测信息的预测Token和15个图像Token。
9. Prediction Token(预测Token):
提取后的预测Token,已经从编码块中获取了输入图像的信息。这个Token包含了用于最终预测的所有必要信息。由于预测Token在多个编码块中与其他图像Token进行了交互,它已经聚合了整个图像的全局特征。
10. Linear Layer(线性层):
预测Token通过一个线性层来生成最终的预测结果。这个线性层将预测Token映射到输出空间,输出形状根据具体的学习任务进行设置。例如:
-
对于分类任务,输出是一个长度为类数的向量,每个元素表示对应类别的概率。
-
对于回归任务,输出是一个或多个预测值。
# 假设我们有一个线性层用于分类任务
linear_layer = nn.Linear(768, num_classes)
prediction = linear_layer(prediction_token)
11. Prediction(预测结果):
最终的预测结果。例如&#