Skip to content

ViT关键问题

约 923 字大约 3 分钟

visiontransformer

2026-03-05

为什么要将图像划分为 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 = 768

  • Token 总数:
    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 网格大小。