前言

​ 虽然 Transformer 架构已成为自然语言处理任务的事实标准,但它在计算机视觉领域的应用仍然有限。在视觉领域,注意力要么与卷积网络结合使用,要么用来替换卷积网络的某些组件,同时保持其整体结构不变。论文中表明,这种对 CNN 的依赖是不必要的,直接应用于图像块序列的纯 Transformer 可以在图像分类任务中表现得非常好。当对大量数据进行预训练并转移到多个中型或小型图像识别基准(ImageNet、CIFAR-100、VTAB 等)时,与最先进的卷积网络相比,Vision Transformer (ViT) 取得了出色的结果,同时训练所需的计算资源却少得多。消融实验结果如下:

image-20241018181547156

模型理解

Vision Transformer理解

image-20241018181753453

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

  • Linear Projection of Flattened Patches(Embedding层)
  • Transformer Encoder(图右侧有给出更加详细的结构)(论文Attention Is All You Need中的结构)
  • MLP Head(多层感知机头,最终用于分类的层结构)

Embedding层结构理解

image-20241019150503871

Patch+Position Embedding的作用主要是对输入进来的图片进行分块处理,每隔一定的区域大小划分图片块。然后将划分后的图片块组合成序列

论文中是使用卷积实现该操作。在VIT中,我们常设置这个卷积的卷积核大小为$16 \times 16$,步长也为16,卷积核个数为768。此时,卷积就会每隔16像素点对图片进行特征提取,图像块的特征提取就不会重叠。对于大小为$224 \times 224\times 3 $的图片而言,会生成一个$14\times 14\times 768$的特征层。

为什么这个操作实现了图像分块?

因为在$14 \times 14$的特征矩阵中,每一个$1\times 1$的格子中的数,代表的就是原图像中$16\times 16$像素的图像块的特征(卷积操作)。

下一步就是将这个特征层组合成序列,组合的方式非常简单,就是将高宽维度进行平铺,[14, 14, 768]在高宽维度平铺后,获得一个[196, 768]的特征层。平铺完成后,我们会在图片序列中添加上Cls Token,该Token会作为一个单位的序列信息一起进行特征提取,图中的这个0*就是Cls Token,我们此时获得一个197, 768的特征层。(Cls Token是concat到[196, 768]的特征层上的。)

[196, 768]的特征矩阵应该是什么样子?

结构概述

  • 行数(197):这个矩阵的行数由两个部分组成:
    • 1 行cls_token,用于捕捉整个图像的全局特征。
    • 196 行:每个图像块的特征向量,表示图像被划分为 $16 \times 16 $的块后,提取的特征。
  • 列数(768):每一行的特征维度是 768,通常与 Transformer 中的隐藏层维度相对应。

    示例表示

假设 cls_token 和图像块特征都用随机值填充,那么矩阵的示例表示如下:

image-20241019153255469

解释

  • 第一行cls_token):是一个向量,表示整个图像的全局信息,它的值会在训练过程中更新,以便更好地捕捉图像的特征。
  • 后196行(图像块特征):每一行对应一个图像块的特征,反映该块在图像中的局部信息。这些特征是通过卷积操作提取的,通常采用的是滑动窗口方法,对图像进行分块处理后得到。

    使用位置嵌入

在输入到 Transformer 之前,这个矩阵通常还会与位置嵌入相加,以提供每个元素在序列中的位置信息。这可以帮助模型理解各个块之间的相对位置关系。

Cls Token的作用

Cls Token的查询向量也会与其他图像块的键向量进行点积。

如果 cls_token 的查询向量与某个图像块特征的键向量点积的结果较高,表示 cls_token 对该图像块特征的信息非常关注,这个图像块在整个图像中扮演了重

要角色。反之,较低的点积结果表示 cls_token 对该图像块的关注较少,可能这个图像块的信息对整体分类影响不大。

Transformer Encoder层结构理解

参考:1.Vision Transformer详解-CSDN博客

​ 2.神经网络学习小记录67——Pytorch版 Vision Transformer(VIT)模型的复现详解_vit复现代码-CSDN博客

​ 3.Transformer 模型详解_transformer模型-CSDN博客

MLP Head层结构理解

在 Vision Transformer (ViT) 中,MLP Head 是多层感知机(Multilayer Perceptron, MLP)用于最终的分类任务。它的主要功能是将 cls_token 的输出特征向量转换为最终的分类结果。

cls_token 的最终输出

经过 ViT 的多层 Transformer 处理后,cls_token 的特征被不断与图像块的特征交互,最终生成了一个表示全局图像信息的向量,形状为 B×768B \times 768B×768,其中:

  • BBB 是批量大小。
  • 768 是特征的维度(这是 Transformer 的输出维度)。

MLP Head 的结构

MLP Head 通常包括以下几层:

  • 全连接层:将 768 维特征向量映射到类别数(如 1000 个类别),用线性变换处理。
  • 激活函数:可能使用激活函数(如 ReLU 或 GELU),引入非线性。
  • 输出层:另一个全连接层,最终输出分类 logits(未归一化的分类分数)。

具体来说,MLP Head 的结构通常如下:

1
2
3
4
5
6
7
python class MLPHead(nn.Module):
def __init__(self, num_features=768, num_classes=1000):
super(MLPHead, self).__init__()
self.fc1 = nn.Linear(num_features, num_classes) # 768 -> num_classes

def forward(self, x):
return self.fc1(x) # 输出分类 logits

具体流程

假设我们使用 ViT 来分类图片,整个 MLP Head 的具体使用过程如下:

得到 cls_token 的特征

在 ViT 的前向传播过程中,经过自注意力机制的多层处理,cls_token 的输出是一个全局特征向量。假设其形状是 B×768B \times 768B×768(批量大小为 BBB,每个特征向量的维度为 768)。

1
2
#cls_token 经过 transformer 输出
cls_token_output = transformer_output[:, 0, :] # 取出 cls_token 的特征,shape: [B, 768]

cls_token 输入 MLP Head

cls_token_output 作为 MLP Head 的输入,使用全连接层将其转换为分类的 logits。假设类别数为 1000,输出的形状为 $B \times 1000$,其中每个值表示对应类别的未归一化分数。

1
2
# 经过 MLP Head
logits = mlp_head(cls_token_output) # logits 的 shape 是 [B, 1000]

分类和计算损失

  • 在训练时,logits 通常会与真实标签进行比较,计算损失(例如交叉熵损失)。
  • 在推理时,logits 会通过 Softmax 转换为类别概率,从而得到最终的分类结果。
1
2
# 通过 Softmax 计算概率
probs = torch.softmax(logits, dim=-1) # shape 仍为 [B, 1000]

MLP Head 的作用

MLP Head 的核心作用是通过全连接层将高维特征(768 维)转换为具体的类别预测结果。由于 cls_token 已经聚合了所有图像块的信息,它代表了全局图像的特征。MLP Head 只需要对这个全局特征进行处理,并将其映射到具体类别上。