前言
在前面三篇文章中,我们已经完成了 ViT 的三个基础铺垫:
01 为什么 Vision Transformer 会出现?
02 Transformer 基础:Self-Attention 原理详解
03 图像如何变成 Token:Patch Embedding 详解
现在,我们终于可以正式进入 ViT 的原始论文:
An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale
这篇论文提出了后来非常经典的 Vision Transformer,简称 ViT。ViT 的核心思想非常直接:
把图像切成固定大小的 patch,把每个 patch 当成一个 token,然后直接输入标准 Transformer Encoder。
这句话看起来很简单,但它的意义非常大。在 ViT 之前,计算机视觉任务长期被 CNN 主导。即使有一些工作尝试把 attention 引入视觉任务,也大多是把 attention 和 CNN 结合起来,或者用 attention 替换 CNN 中的一部分模块。而 ViT 这篇论文想回答一个更直接的问题:
能不能尽量不依赖卷积,直接把标准 Transformer 用到图像识别中?
论文给出的答案是:
可以,但前提是要有足够大规模的数据预训练。
ViT 原论文于 2020 年提交到 arXiv,后续作为 ICLR 2021 论文发表;论文明确指出,纯 Transformer 直接作用于图像 patch 序列,在大规模预训练后可以在多个图像识别基准上取得很强的迁移性能。
1. 论文基本信息
论文题目:
An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale
中文可以理解为:
一张图像相当于许多个 16×16 的"视觉单词":用于大规模图像识别的 Transformer
论文作者来自 Google Research / Google Brain 团队,作者包括 Alexey Dosovitskiy、Lucas Beyer、Alexander Kolesnikov、Dirk Weissenborn、Xiaohua Zhai、Neil Houlsby 等。
这篇论文的核心贡献可以概括为一句话:
它证明了不依赖 CNN 主干网络,直接把图像切成 patch 序列并输入标准 Transformer,也可以在图像识别任务中取得非常强的结果。
论文提出的模型就是:
Vision Transformer,简称 ViT
2. 这篇论文想解决什么问题?
在 ViT 之前,Transformer 已经在自然语言处理领域取得了巨大成功。在 NLP 中,文本天然就是序列:
word_1, word_2, word_3, ..., word_n
Transformer 可以直接处理这些 token,并通过 self-attention 建模 token 之间的关系。但是图像不是一维序列,而是二维结构:
height × width × channels
所以视觉领域长期依赖 CNN,因为 CNN 天然适合处理图像的局部空间结构。在 ViT 出现之前,视觉任务中使用 attention 的方式大致有几类:
在 CNN 中加入 attention 模块;
用 attention 替换 CNN 中的一部分卷积;
在 CNN 提取的特征图上再使用 Transformer;
针对图像设计专门的局部 attention 或稀疏 attention。
这些方法都没有完全摆脱 CNN 或视觉特定结构。ViT 论文想做的事情更加直接:
尽量少做图像任务专用设计,直接把标准 Transformer 用到图像分类任务中。
论文中的一个重要设计理念是:
尽可能保持 Transformer 原始结构不变。
也就是说,ViT 并不是重新设计一个复杂的视觉专用 Transformer,而是把图像转成 patch token 序列之后,直接使用标准 Transformer Encoder。论文也强调,这种简单设置的一个好处是可以比较直接地复用 NLP 中成熟的 Transformer 架构和高效实现。
3. ViT 的核心思想是什么?
ViT 的核心思想可以用一句话概括:把图像切成 patch,把 patch 当成 token,然后输入 Transformer。假设输入图像大小为:
224 × 224 × 3
如果 patch size 是:
16 × 16
那么这张图像可以被切成:
14 × 14 = 196
个 patch。每个 patch 被展平后,通过一个线性层映射成固定维度的向量,也就是 patch embedding。于是,图像就变成了一个 token 序列:
patch_1, patch_2, patch_3, ..., patch_196
再加上一个用于分类的 class token,最终输入 Transformer Encoder 的序列长度就是:197
这个过程可以概括为:
图像
↓
切分成 patch
↓
patch 展平
↓
线性投影得到 patch embedding
↓
加入 class token
↓
加入 position embedding
↓
输入 Transformer Encoder
↓
使用 class token 做分类
这就是 ViT 最核心的流程。
ViT 的关键并不是某一个复杂模块,而是它把图像任务重新组织成了 Transformer 可以处理的序列建模问题。论文中的模型图也说明了这一点:图像先被切成固定大小的 patch,每个 patch 被线性嵌入,然后加入位置编码,再送入标准 Transformer Encoder;为了进行分类,模型在序列前加入一个可学习的 classification token。
4. Patch Embedding:图像如何输入 Transformer?
Patch Embedding 是 ViT 的第一步,也是图像和 Transformer 之间的接口。
假设输入图像为:X ∈ R^{H × W × C}
H:图像高度
W:图像宽度
C:通道数
patch size 为:P×P
那么 patch 数量为:
N = HW / P²
对于 ViT-B/16:
H = 224
W = 224
C = 3
P = 16
所以:N = 224 × 224 / 16² = 196。
每个 patch 的大小是:16 × 16 × 3 = 768。
展平后,每个 patch 是一个 768 维向量。然后通过一个线性映射,把它变成 Transformer 的 embedding 维度。如果 embedding dim 是 768,那么输出就是:[196, 768]
这一步的作用是:把图像的局部小块转换成 Transformer 可以处理的 token embedding
5. Class Token 和 Position Embedding
有了 patch embedding 之后,ViT 还需要加入两个重要信息:
Class Token
Position Embedding
5.1 Class Token:整张图像的代表
ViT 借鉴了 BERT 中 [CLS] token 的思想。在 patch token 序列前面,ViT 会加入一个可学习的 class token。原本 patch token 是:
patch_1, patch_2, ..., patch_196
加入 class token 后变成:
cls_token, patch_1, patch_2, ..., patch_196
序列长度从:196。变成:197。
经过 Transformer Encoder 后,class token 会和所有 patch token 进行 self-attention 交互。
可以简单理解为:class token 像一个信息汇总员,它会不断从所有 patch token 中收集信息,最后代表整张图像用于分类。
论文中也说明,ViT 在序列前加入一个可学习的 embedding,其在 Transformer Encoder 输出处的状态作为图像表示,并在其上接分类头。
5.2 Position Embedding:告诉模型 patch 在哪里
Transformer 本身并不知道 token 的空间位置。如果只输入 patch embedding,模型知道每个 patch 的内容,但不知道:
这个 patch 在左上角还是右下角;
哪些 patch 是相邻的;
哪些 patch 在同一行;
哪些 patch 在同一列。
因此,ViT 需要加入 position embedding。对于 ViT-B/16,输入 token 数量是 197,embedding dim 是 768,所以 position embedding 的形状是:
1, 197, 768
输入 Transformer 前:
x = patch_embedding + position_embedding
更准确地说,是:
x = [cls_token; patch_embeddings] + position_embeddings
可以这样理解:
Patch Embedding:告诉模型这个 patch 里面有什么;
Position Embedding:告诉模型这个 patch 位于哪里。
论文中使用的是可学习的一维位置编码,并指出更复杂的二维位置编码在其实验中没有带来明显性能收益。
6. Transformer Encoder 在 ViT 中的作用
完成 patch embedding、class token 和 position embedding 后,输入就可以送入 Transformer Encoder。ViT 中的 Transformer Encoder 基本沿用了标准 Transformer 的结构。每个 Transformer block 主要包含:
1. LayerNorm
2. Multi-Head Self-Attention
3. Residual Connection
4. LayerNorm
5. MLP
6. Residual Connection
可以写成:
x = x + MSA(LN(x))
x = x + MLP(LN(x))
其中:
MSA:Multi-Head Self-Attention
MLP:前馈神经网络
LN:LayerNorm
在 ViT 中,Self-Attention 的作用是让所有 patch token 之间进行信息交互。对于一张 224×224 的图像,ViT-B/16 有 196 个 patch token,再加上 1 个 class token,共 197 个 token。每一层 Self-Attention 都会计算一个 token-to-token 的关系矩阵。如果有 12 个 attention head,那么每层都会得到类似:
[12, 197, 197]
这样的 attention 权重矩阵。这意味着:
每个 head 都可以从一个特征子空间中观察所有 token 之间的关系。
与 CNN 相比,ViT 的全局信息交互更加直接。CNN 通常通过多层卷积逐步扩大感受野,而 ViT 在 Self-Attention 中可以让任意两个 patch token 直接发生联系。
7. ViT-B/16、ViT-L/16、ViT-H/14 有什么区别?
ViT 论文中定义了多个不同规模的模型。其中最常见的是:
ViT-Base
ViT-Large
ViT-Huge
论文中的模型配置如下:
模型 Transformer 层数 Hidden Size MLP Size Heads 参数量
ViT-Base 12 768 3072 12 86M
ViT-Large 24 1024 4096 16 307M
ViT-Huge 32 1280 5120 16 632M
这里几个指标的含义是:
Layers:Transformer Encoder block 的数量;
Hidden size:token embedding 的维度;
MLP size:Transformer block 中 MLP 隐藏层维度;
Heads:多头注意力中的 attention head 数量;
Params:模型参数量。
模型名称中的 /16 或 /14 表示 patch size。例如:
ViT-B/16:Base 模型,patch size = 16 × 16
ViT-L/16:Large 模型,patch size = 16 × 16
ViT-H/14:Huge 模型,patch size = 14 × 14
patch size 越小,token 数量越多,计算量越大,但图像细节保留得也更多。论文中也指出,Transformer 的序列长度与 patch size 的平方成反比,因此更小 patch size 的模型计算代价更高。
8. ViT 对后续视觉模型的影响
ViT 的影响非常大它不只是提出了一个图像分类模型,而是打开了视觉 Transformer 研究的大门。
后续很多工作都可以看作是在回答 ViT 留下的问题。
8.1 如何减少 ViT 对大规模数据的依赖?
代表工作:
DeiT
DeiT 通过更强的数据增强、训练策略和蒸馏方法,让 ViT 可以在 ImageNet-1K 上更高效地训练。
这条路线主要解决:
ViT 数据需求过高的问题。
8.2 如何让 ViT 适合检测和分割?
代表工作:
PVT
Swin Transformer
SegFormer
这些方法引入金字塔结构、窗口注意力、多尺度特征等设计,让 Transformer 更适合密集预测任务。这条路线主要解决:
原始 ViT 缺少多尺度层次结构的问题。
8.3 如何让 ViT 适合自监督学习?
代表工作:
MAE
BEiT
DINO
DINOv2
这些方法利用 masked image modeling、自蒸馏或对比学习等方式,让 ViT 学习更通用的视觉表示。这条路线主要解决:
如何让 ViT 从无标签数据中学习强视觉特征。
8.4 如何让 ViT 走向多模态和基础模型?
代表工作:
CLIP
SigLIP
SAM
ViT 的 token 化表示和 Transformer 结构天然适合与文本、提示、mask 等其他模态结合。这也是它在视觉基础模型中被广泛使用的重要原因。
8.5 如何让 ViT 更高效?
代表方向:
Token Pruning
Attention Head Pruning
MLP Pruning
Efficient ViT
Mobile ViT
Window Attention
Linear Attention
ViT 的计算瓶颈主要来自 token 数量、attention 计算和 MLP 参数量。因此,后续大量研究都在尝试提升 ViT 的推理效率和部署友好性。这也和我们后续专栏中的 ViT 剪枝、压缩和部署内容密切相关。