ViT关键问题
为什么要将图像划分为 patch?
将图像划分为固定大小的 patch,并将每个 patch 映射为 embedding 向量,是为了将图像表示为一组离散的视觉 token,从而构建一个序列建模问题。
其本质目的不是“将二维变为一维”,而是:
- 控制 token 数量,降低自注意力的计算复杂度;
- 将视觉输入离散化为与序列模型兼容的 token 表示。
若以像素作为 token,224×224 图像将产生 50176 个 token,自注意力复杂度为 O(N²),在计算上不可接受。
Patch 数量与维度计算
对于输入尺寸 224×224×3,patch 大小为 16×16:
Patch 数量:
224 / 16 = 14
总 patch 数量 = 14 × 14 = 196每个 patch 展开后维度:
16 × 16 × 3 = 768Token 总数:
196 + 1(CLS token)= 197
每个 patch 会先 reshape 为 768 维向量,再通过线性投影映射到 D 维 embedding 空间。
Position Embedding 的作用
Self-attention 本身是排列不变(permutation-invariant)的。
如果不引入位置编码:
- 模型无法区分 token 的空间排列;
- 任意打乱 patch 顺序都会产生相同输出;
- 无法建模图像的空间结构。
Position Embedding 的作用是引入空间位置信息,使模型能够区分不同 patch 的相对和绝对位置。
为什么需要 CLS Token?
CLS token 是一个可学习的全局表示向量,用于聚合所有 token 的信息。
其与全局平均池化(GAP)的本质区别在于:
- CLS token 通过自注意力机制主动、选择性地聚合信息;
- GAP 是对特征进行无参数的均值统计。
因此,CLS token 是参数化、可学习的全局信息聚合方式。
Linear Projection 的本质
ViT 中的 Linear Projection 等价于:
- kernel size = patch size
- stride = patch size
- 输出通道数 = embedding dimension
的一层卷积操作。
因此,patch embedding 本质上可以视为一次非重叠卷积。
为什么 ViT 更“数据饥渴”?
ViT 缺乏卷积网络中的归纳偏置(inductive bias),例如:
- 局部性(locality)
- 平移不变性(translation invariance)
这些结构性偏置需要通过数据学习得到,因此:
ViT 通常需要更大规模的数据集才能达到甚至超过 CNN 的效果。
计算复杂度来源
ViT 的计算复杂度主要来自自注意力机制。
若 token 数量为 N,embedding 维度为 D:
- 自注意力复杂度为:O(N²D)
其中 N² 来自 token 两两之间的相关性计算。
Patch Size 从 16 改为 8 会发生什么?
若 patch size 减半:
- token 数量增加 4 倍
- 自注意力计算量增加 16 倍(因为 N²)
- 表达能力增强(更细粒度建模)
但计算与显存开销显著增加。
为什么 ViT 可以看作“全局卷积”?
在自注意力机制中:
- 任意两个 token 之间都可以直接进行信息交互;
- 第一层即可获得全局感受野(global receptive field)。
因此,ViT 在建模上具有天然的全局性。
CNN 为什么也能获得全局感受野?为何 ViT 更强?
CNN 通过多层卷积堆叠逐步扩大感受野:
- 感受野是渐进式增长;
- 理论感受野 ≠ 有效感受野(effective receptive field 通常较小)。
而 ViT:
- 单层即可建模全局依赖;
- 所有 token 之间的注意力路径长度为 1;
- 全局依赖建模更直接。
输入分辨率变化时如何处理 Position Embedding?
对于 learnable position embedding:
- 需要在空间维度上进行双线性插值(bilinear interpolation);
- 将原有 embedding resize 到新的 patch 网格大小。
