为什么16x16的图像块,成了视觉Transformer颠覆CNN的起点?
几年前,如果有人告诉你,把一张图片简单地切成一个个16x16像素的小方块,然后像处理句子里的单词一样去处理它们,就能在图像识别任务上超越深耕数十年的卷积神经网络,你可能会觉得这想法过于天真。然而,这正是Vision Transformer(ViT)在2020年横空出世时所做的事情。它没有使用任何卷积操作,仅仅依靠标准的Transformer编码器,就在大规模图像分类任务上取得了令人瞩目的成绩,甚至在某些场景下“吊打”了当时的顶尖CNN模型。这背后,那个看似简单的“16x16图像块”策略,绝非随意选择,而是融合了计算效率、模型容量与数据驱动哲学的精妙设计。对于技术决策者和研究者而言,理解这个设计背后的“魔力”,远比单纯比较准确率数字更有价值。它关乎我们如何重新思考计算机视觉模型的根本架构,以及在什么条件下,一种全新的范式能够脱颖而出。
1. 从序列到图像:ViT核心思想的重构
传统的卷积神经网络(CNN)其强大之处在于其内置的归纳偏置——即模型对数据所做的先验假设。例如,卷积核的局部连接特性假设了图像中相邻像素间的关系更为重要,权重共享则假设了某种平移不变性。这些偏置在数据量有限时极为有效,它引导模型快速学习到图像的本质特征,避免了在浩瀚的像素空间里盲目搜索。
而Transformer架构,最初为自然语言处理设计,其核心是自注意力机制。它没有对数据的局部性做任何先验假设,而是让模型通过训练,自行发现序列中任意两个元素(单词)之间的关系。这种“关系发现”的能力是全局的、动态的。
ViT所做的,是一次大胆的“降维打击”式重构。它抛弃了CNN的卷积滑动窗口,选择了一条更直接的路径:
- 图像分块:将输入图像(例如224x224分辨率)分割成固定大小(如16x16)的非重叠网格。每个网格块包含16x16x3=768个像素值(假设是RGB三通道)。
- 线性投影:将每个图像块展平为一个向量,并通过一个可训练的线性层(全连接层)映射到一个固定的维度D(例如768)。这个过程,相当于为每个“视觉单词”学习了一个嵌入表示。
- 构建序列:将所有图像块的嵌入向量,加上一个额外的可学习的
[class]token嵌入和一个可学习的位置嵌入,按顺序排列,就构成了一个长度为N+1的序列(N为图像块数量)。这个序列可以直接输入标准的Transformer编码器。
# 一个简化的ViT图像分块与嵌入过程示意(使用PyTorch风格)
import torch
import torch.nn as nn
class PatchEmbed(nn.Module):
def __init__(self, img_size=224, patch_size=16, in_chans=3, embed_dim=768):
super().__init__()
self.img_size = img_size
self.patch_size = patch_size
self.num_patches = (img_size // patch_size) ** 2
# 使用一个卷积层同时完成分块和线性投影
self.proj = nn.Conv2d(in_chans, embed_dim, kernel_size=patch_size, stride=patch_size)
def forward(self, x):
# x: [B, C, H, W]
x = self.proj(x) # [B, embed_dim, H/patch_size, W/patch_size]
x = x.flatten(2).transpose(1, 2) # [B, num_patches, embed_dim]
return x
# 假设输入为一批224x224的RGB图像
batch_size = 4
x = torch.randn(batch_size, 3, 224, 224)
patch_embed = PatchEmbed()
patches = patch_embed(x) # 输出形状: [4, 196, 768]
print(f"将图像分割为 {patches.shape[1]} 个图像块,每个块嵌入维度为 {patches.shape[2]}")
这个流程的关键在于,它将二维的空间结构问题,转化为了一个一维的序列建模问题。模型不再需要理解“上下左右”的二维关系(这部分信息由位置嵌入隐式提供),而是专注于学习图像块之间的语义关联。这种转换,使得NLP领域最强大的序列建模工具——Transformer,得以在视觉领域大展拳脚。
注意:这里的“单词”类比是理解ViT的绝佳切入点,但它与NLP中的单词有本质不同。图像块是连续信号的低级表示,缺乏自然语言中离散的、高层次的语义。ViT需要从这些低级“视觉词根”开始,自底向上地构建语义理解。
2. 16x16:一个权衡计算、信息与性能的甜蜜点
为什么是16x16?而不是8x8、32x32,或者像CNN那样多尺度的感受野?这个选择是ViT设计中最具工程智慧的一环,它是在模型表达能力、计算复杂度和信息保留之间反复权衡后的结果。
首先,我们从计算复杂度的角度来分析。 Transformer自注意力机制的计算复杂度与输入序列长度的平方成正比。对于一个分辨率为 H x W 的图像,当使用 P x P 的分块大小时,生成的序列长度 N = (H*W) / (P*P)。
| 分块大小 (P) | 序列长度 (N, 对于224x224) | 自注意力复杂度 (相对值,O(N²)) |
|---|---|---|
| 8x8 | 784 | 非常高 (~614,656) |
| 16x16 | 196 | 中等 (~38,416) |
| 32x32 | 49 | 低 (~2,401) |
从上表可以清晰看出,16x16的分块策略将序列长度控制在了196这个相对合理的数量级。如果采用8x8,序列长度激增至784,自注意力的计算和内存开销将变得难以承受。而如果采用32x32,序列长度骤降至49,虽然计算效率极高,但每个图像块过大,丢失了过多的细粒度空间信息,相当于在建模的起点就进行了强烈的下采样,不利于模型捕捉细节特征。
其次,分块大小直接影响每个“视觉单词”的信息含量。 一个16x16的块,包含了768个原始像素值。这个尺寸的块,已经可以承载一些有意义的局部模式,比如一小段边缘、一个角点,或者纹理的一部分。它既不像8x8那样过于琐碎(信息原子化,增加了序列建模的难度),也不像32x32那样过于粗糙(可能已经包含了多个物体部件,失去了局部性)。
提示:在原始ViT论文的实验中,作者们对比了不同分块大小(如32x32, 16x16, 14x14等)。结果表明,在相同模型容量和计算预算下,16x16通常能取得最佳的性能平衡。更小的分块(如14x14)有时能在顶级数据集上带来微幅提升,但计算成本增加显著,性价比不高。
最后,这个选择与Transformer的架构特性深度耦合。 Transformer擅长建模长程依赖,但对序列中每个元素(图像块)的初始表示要求较高。16x16的块经过线性投影后,其嵌入向量能够编码一个相对完整、信息密度适中的局部视觉特征。这为后续的多头自注意力层进行全局信息交互提供了一个良好的“讨论素材”。
我们可以通过一个简单的思想实验来理解:如果把整张224x224的图片作为一个“单词”,Transformer将无从下手,因为单个向量无法表达复杂的空间结构。如果把每个像素作为一个“单词”,序列过长且每个“单词”信息量太低。16x16,正是在“整体”与“原子”之间找到的那个平衡点,它让Transformer既能处理一个长度可控的序列,又能让序列中的每个元素本身具备一定的表征能力。
3. 位置编码:让Transformer“看见”空间结构
将图像切成网格并打平成序列后,一个最严重的问题出现了:模型完全丧失了二维空间位置信息。在原始序列中,第10个块和第11个块在模型看来只是索引不同,但模型并不知道它们在原始图像中是相邻的。这对于需要理解空间布局的图像任务(如分类、检测)是致命的。
ViT解决这个问题的方式,是引入了位置编码。具体来说,它为序列中的每一个位置(包括[class] token和每一个图像块的位置)分配一个与嵌入维度相同的可学习向量,然后直接加到对应的嵌入向量上。
输入Transformer的向量 = 图像块嵌入 + 位置嵌入
这个操作看似简单,却至关重要。它相当于在告诉模型:“这个向量所代表的视觉内容,位于图像的(x, y)坐标处。” 模型通过训练,可以学会如何利用这些位置信息。
有趣的是,ViT论文中发现,学习到的位置编码展现出了清晰的二维空间结构。 研究人员通过计算不同位置编码之间的余弦相似度发现:
- 空间距离近的图像块,其位置编码也更相似。
- 同行或同列的图像块,其位置编码也表现出聚类特性。
- 在某些情况下,甚至能观察到类似正弦波的结构。
这表明,尽管模型没有显式地被灌输“二维邻域”的概念,但它通过数据驱动的方式,自己从任务中学习到了图像固有的空间拓扑关系。这也解释了为什么在ViT中,使用更复杂的手工设计的位置编码(如二维正弦编码)并没有带来显著的性能提升——模型自己已经学得足够好了。
# 位置编码的简单示意
class VisionTransformer(nn.Module):
def __init__(self, num_patches, embed_dim):
super().__init__()
# 可学习的位置嵌入,形状为 [1, num_patches+1, embed_dim]
self.pos_embed = nn.Parameter(torch.zeros(1, num_patches + 1, embed_dim))
# [class] token
self.cls_token = nn.Parameter(torch.zeros(1, 1, embed_dim))
def forward(self, x):
# x: [B, num_patches, embed_dim]
B = x.shape[0]
cls_tokens = self.cls_token.expand(B, -1, -1) # 扩展到batch维度
x = torch.cat((cls_tokens, x), dim=1) # 拼接[class] token
x = x + self.pos_embed # 加上位置编码
# ... 后续输入Transformer编码器
return x
位置编码是ViT中为数不多的、注入图像特定归纳偏置的地方。另一个地方是在微调更高分辨率图像时,对预训练位置嵌入进行双线性插值,以适应新的网格尺寸。这两个设计点非常克制,却有效地弥补了纯Transformer架构在视觉任务上的先天不足。
4. 与CNN的终极对决:归纳偏置 vs. 数据驱动
ViT与CNN的核心差异,归根结底是哲学上的差异:强归纳偏置引导 vs. 弱归纳偏置下的数据驱动学习。
CNN像一个经验丰富的老师,从一开始就告诉学生:“看图片,要先看局部,再看整体;一个特征无论在图片的哪个位置出现,它都是同一个特征。” 这种强引导在数据少的时候非常高效,学生能快速上手。
ViT则像一个采用探索式教学法的老师,它给学生一堆打乱的拼图块(图像块),然后说:“你们自己讨论,找出它们之间的关系,并告诉我整幅画是什么。” 这个过程初期可能更慢、更混乱,需要更多的“讨论”(计算)和更丰富的“案例”(数据)。但一旦学生(模型)通过海量案例学会了如何有效讨论,其形成的理解可能更加灵活和深入。
这种差异在实验数据上体现得淋漓尽致:
- 小数据场景(如只在ImageNet-1K上训练):CNN(如ResNet)显著优于ViT。因为数据不足以让ViT从头开始学习所有视觉模式(如边缘、纹理)和空间关系,它容易过拟合。而CNN的卷积归纳偏置起到了强大的正则化作用,引导模型走向正确的学习方向。
- 大数据场景(如在JFT-300M上训练):ViT的性能开始反超,并且模型越大,优势越明显。当数据量足够庞大时,ViT能够从数据中自动学习到甚至比卷积核更优的特征提取方式,其全局注意力机制也能捕捉到CNN感受野难以触及的长距离依赖关系。此时,CNN的强归纳偏置反而可能成为一种限制。
下表概括了ViT与典型CNN(如ResNet)在几个关键维度的对比:
| 特性维度 | Vision Transformer (ViT) | 卷积神经网络 (CNN,如ResNet) |
|---|---|---|
| 核心操作 | 全局自注意力 | 局部卷积、池化 |
| 归纳偏置 | 极弱(仅位置编码、分块) | 极强(局部性、平移等变性、层次结构) |
| 感受野 | 第一层即可达到全局 | 随网络深度逐层扩大 |
| 数据效率 | 较低,需要海量数据预训练 | 较高,中等规模数据即可有效训练 |
| 计算效率 | 序列长度平方级复杂度,对长序列不友好 | 计算高效,与图像大小呈线性关系 |
| 可解释性 | 注意力图可直接显示模型关注区域 | 特征图可解释,但高层语义融合复杂 |
| 扩展性 | 模型规模(深度、宽度、注意力头)扩展性极佳 | 扩展受梯度消失/爆炸等问题限制,需精心设计 |
这个对比揭示了ViT成功的必要条件:大规模预训练。没有海量数据,ViT的“数据驱动”优势就无法发挥,其弱点(数据效率低)就会暴露。这也正是为什么ViT论文的标题强调“At Scale”(大规模)。它不是用来替代所有场景下的CNN,而是在数据充裕的新时代,为我们提供了一种更强大、更灵活的视觉建模新范式。
5. 超越分类:ViT分块策略的泛化与工程实践
理解了16x16分块的精髓后,我们自然会问:这个策略是普适的吗?在实际工程中,我们该如何应用和调整?
首先,分块大小并非一成不变。 对于不同分辨率、不同任务的数据,最优分块尺寸可能需要调整。
- 高分辨率图像:对于医疗影像、卫星图片等,输入分辨率可能达到512x512甚至更高。直接使用16x16分块会导致序列长度剧增(如1024)。常见的做法是增大分块尺寸(如32x32),或者在骨干网络前端加入一个轻量的“ Stem ”网络(由少量卷积层组成)进行初步下采样,再分块输入Transformer。
- 计算资源受限:在边缘设备上,为了降低延迟,可以使用更大的分块(如32x32)来显著减少序列长度,虽然会损失一些精度,但能换来实时的推理速度。
- 密集预测任务:在目标检测、语义分割等任务中,需要像素级或区域级的高分辨率特征图。单纯的ViT分块会丢失细节。衍生模型如Swin Transformer引入了层级结构和滑动窗口注意力,它在不同阶段进行块合并,形成特征金字塔,同时将计算限制在局部窗口内,既保持了Transformer的全局建模能力,又获得了CNN的多尺度特征优势。
其次,混合架构的探索从未停止。 最初的ViT论文也探索了“混合模型”,即用CNN(如ResNet)的中间特征图作为ViT的输入序列。这种架构试图结合两者的优点:CNN早期层高效提取低级特征,ViT后期层进行全局关系建模。实验发现,在中等计算预算下,混合模型有时能略胜一筹,但当模型和数据规模都变得非常大时,纯ViT的优势更加明显。这暗示着,在足够的数据和算力下,Transformer有能力从原始信号中学习到从低级到高级的全部特征,无需CNN作为前置特征提取器。
在实际部署ViT类模型时,有几个工程细节值得关注:
- 位置编码插值:当在ImageNet-1K(224x224)上预训练的ViT,需要应用到更高分辨率(如384x384)的下游任务时,直接推理会因位置编码数量不匹配而失败。标准的做法是对预训练的位置嵌入进行二维双线性插值,使其适应新的网格布局。这是一个简单却至关重要的技巧。
- 计算优化:自注意力的O(N²)复杂度是瓶颈。除了使用更大的分块,还可以采用线性注意力、分块局部注意力、因子化注意力等近似算法来加速。此外,像FlashAttention这样的IO感知精确注意力算法,能极大优化GPU内存访问,提升训练和推理速度。
- 知识蒸馏:大型ViT模型参数多、推理慢。可以通过知识蒸馏,将一个大ViT(教师模型)的知识压缩到一个更小的ViT或CNN(学生模型)中,在保持大部分性能的同时大幅降低部署成本。
ViT及其后续变体的出现,不仅仅是带来了一个新的SOTA模型,更重要的是它拓宽了计算机视觉的架构设计思路。它证明了,即使在视觉这种具有强空间结构的数据上,基于纯粹注意力机制的、弱归纳偏置的模型,只要给予足够的数据和计算资源,同样可以取得卓越的性能,甚至在某些方面超越基于卷积的经典范式。这鼓励研究者们去探索更多非卷积的视觉基础模型,也促使我们重新审视那些曾被我们视为“理所当然”的架构先验。对于技术决策者来说,选择ViT还是CNN,不再是一个简单的“谁更好”的问题,而是一个需要综合考量数据规模、计算预算、任务需求和部署环境的战略决策。在数据为王的时代,ViT无疑为我们提供了一把打开更高性能之门的钥匙,而理解其16x16分块的设计哲学,则是握住这把钥匙的第一步。
499



被折叠的 条评论
为什么被折叠?



