跳转至

Vision Transformer(ViT)

ViT(Vision Transformer)把图像当作一串 patch token 来处理,让 Transformer 从“处理文字序列”扩展到“处理图像序列”。它是现代 VLM、VLA、图像生成和视觉基础模型的重要骨架。


一句话理解

文本 Transformer 的输入是:

一句话 -> 分词 -> token embedding -> Transformer

ViT 的输入是:

一张图 -> 切成 patch -> patch embedding -> Transformer Encoder

也就是说,ViT 把图像中的小块当成“视觉词”。

核心直觉

CNN 用卷积核在局部窗口里提特征,然后逐层扩大感受野;ViT 先把图像切成 patch,再用 self-attention 让任意两个 patch 直接建立联系。


模型整体结构: 20260704145219

1. 图像如何变成 Token?

设输入图像为:

\[ x \in \mathbb{R}^{H \times W \times C} \]

其中 \(H,W\) 是高和宽,\(C\) 是通道数。把图像切成大小为 \(P \times P\) 的 patch,patch 数量为:

\[ N = \frac{H \times W}{P^2} \]

例如一张 \(224 \times 224\) 的 RGB 图像,如果 patch size 是 \(16 \times 16\)

\[ N = \frac{224 \times 224}{16^2} = 196 \]

所以这张图会变成 196 个视觉 token。


2. Patch Embedding

每个 patch 的原始形状是:

\[ P \times P \times C \]

把它展平成向量:

\[ x_p \in \mathbb{R}^{P^2C} \]

再用一个线性层映射到 Transformer 的隐藏维度 \(D\)

\[ z_p = x_p W_E + b_E \]

其中:

  • \(x_p\):展平后的 patch
  • \(W_E \in \mathbb{R}^{P^2C \times D}\):patch embedding 矩阵
  • \(z_p \in \mathbb{R}^{D}\):视觉 token embedding

20260704150807 工程上,patch embedding 通常可以用一个卷积层实现,使用卷积层实现只是因为在特定参数下,卷积可以实现和上面一样的效果,方便实现,真实线性网络映射的w和b转换到了卷积核中,在卷积完成后进行展平就是一样的效果:

Conv2d(in_channels=3, out_channels=D, kernel_size=P, stride=P)

这个卷积层不会像普通 CNN 那样滑动重叠窗口,而是刚好每 \(P\) 个像素取一个 patch。


3. Class Token 与位置编码

3.1 Class Token

ViT 通常在 patch token 前面加一个可学习的 [CLS] token:

[CLS], patch_1, patch_2, ..., patch_N

经过 Transformer 后,[CLS] 的输出向量被当作整张图的全局表示,用于分类或下游任务。

在 VLM/VLA 中,不一定只用 [CLS]。很多模型会保留全部 patch token,因为机器人需要知道目标物体在哪,而不是只知道整张图是什么。

3.2 位置编码

Transformer 本身不知道 token 的空间位置。对图像来说,patch 的顺序非常重要,所以要加位置编码,ViT 的位置编码数值最开始通常是随机初始化的,然后通过反向传播学习;但是它加到哪个 Patch 上并不是随机的,而是严格按照 Patch 展平后的顺序一一对应。:

\[ z_0 = [z_{\text{cls}}; z_1; z_2; ...; z_N] + E_{\text{pos}} \]

位置编码告诉模型:

  • 这个 patch 在左上角还是右下角。
  • 哪些 patch 在空间上相邻。
  • 图像中物体的布局关系。

没有位置编码会怎样?

如果没有位置编码,Transformer 只知道“有哪些 patch”,不知道“它们在哪里”。一张图被打乱 patch 顺序后,模型可能仍觉得差不多,这对视觉任务是灾难。


4. Transformer Encoder Block

ViT 使用的是 Transformer Encoder。一个标准 block 包含:

graph LR
    A[输入 Token] --> B[LayerNorm]
    B --> C[Multi-Head Self-Attention]
    C --> D[残差连接]
    D --> E[LayerNorm]
    E --> F[MLP]
    F --> G[残差连接]

4.1 Self-Attention

每个 token 会生成 Query、Key、Value:

\[ Q = XW_Q,\quad K = XW_K,\quad V = XW_V \]

注意力计算:

\[ \text{Attention}(Q,K,V)=\text{softmax}\left(\frac{QK^T}{\sqrt{d}}\right)V \]

直观理解:

  • Query:我想找什么信息?
  • Key:我有什么信息可供匹配?
  • Value:如果被关注,实际传递什么内容?

对于图像来说,一个杯子边缘 patch 可以关注杯身、杯口、桌面、夹爪附近的 patch,从而理解整体结构。

4.2 Multi-Head

多头注意力让模型从不同角度看图像:

可能关注
head 1 局部边缘
head 2 颜色相似区域
head 3 物体部件关系
head 4 远距离空间关系

这不是严格固定的解释,但有助于理解多头为什么有用。

4.3 MLP

Attention 负责 token 之间的信息交换,MLP 负责对每个 token 内部的特征做非线性变换。一个常见结构是:

\[ \text{MLP}(x)=W_2 \cdot \text{GELU}(W_1x) \]

5. ViT 的计算量

Self-attention 的复杂度和 token 数量平方相关:

\[ O(N^2D) \]

其中 \(N\) 是 patch token 数量,\(D\) 是隐藏维度。

如果图像分辨率变大或 patch size 变小,token 数会急剧增加:

图像大小 Patch size Token 数
\(224 \times 224\) 16 196
\(224 \times 224\) 14 256
\(448 \times 448\) 16 784
\(448 \times 448\) 14 1024

从 196 到 784 token,attention 矩阵大小会增加约 16 倍。这也是 VLM/VLA 经常需要控制图像分辨率和视觉 token 数的原因。


6. ViT vs CNN

维度 CNN ViT
基本单元 卷积核 patch token
信息交互 局部到全局 全局 self-attention
归纳偏置 强:局部性、平移等变 弱:更依赖数据学习
数据需求 小中数据也能训练 通常需要大规模预训练
长距离关系 需要堆很多层 一层 attention 即可建模
空间细节 局部纹理强 patch 太大时细节会损失

归纳偏置是什么?

归纳偏置就是模型先天带着的假设。CNN 假设图像有局部结构、相邻像素关系重要;ViT 的假设更少,所以数据足够大时上限高,但小数据训练更难。


7. 为什么 ViT 适合 VLM/VLA?

VLM/VLA 很喜欢 ViT,原因有三点:

7.1 输出天然是 token 序列

LLM 处理的是 token 序列。ViT 也输出 token 序列,因此很容易接到 LLM:

图像 patch token + 文本 token -> LLM

7.2 全局关系建模强

机器人任务经常需要理解远距离关系:

  • 目标物体和容器之间的相对位置。
  • 夹爪和物体之间的距离。
  • “左边的杯子”和“右边的托盘”的关系。

Self-attention 可以直接建模这些关系。

7.3 适合大规模预训练

CLIP、SigLIP、DINOv2 等现代视觉编码器大量使用 ViT。VLA 可以继承这些预训练视觉能力,而不是从少量机器人数据里从零学视觉。


8. ViT 的常见变体

模型 关键思想 为什么重要
DeiT 用蒸馏和数据增强提升小数据训练 让 ViT 更数据高效
Swin Transformer 窗口注意力 + 层级结构 降低高分辨率图像计算量
MAE 随机遮住大量 patch,让模型重建 自监督视觉预训练经典方法
CLIP ViT 图文对齐训练 VLM/VLA 常用视觉塔
DINOv2 ViT 自监督通用视觉特征 对局部特征、几何和 dense prediction 友好

9. 新手检查清单

学完 ViT 后,你应该能回答:

  • 一张图如何被切成 patch token?
  • patch size 变小会带来什么影响?
  • 为什么要加位置编码?
  • [CLS] token 和 patch token 分别有什么用?
  • self-attention 如何让远距离 patch 交互?
  • ViT 为什么通常需要大规模预训练?
  • 为什么 VLA 更关心 patch token,而不只是图像分类结果?

10. 参考资料