
1. ViT的设计原点一次“违背直觉”的尝试2020年之前你要是跟一个搞计算机视觉的人说图像识别可以完全不用卷积神经网络只用Transformer那套自注意力机制他大概率会觉得你在开玩笑。因为在当时卷积网络统治视觉领域已经快十年了从AlexNet到ResNet再到EfficientNet每一代经典模型都在用局部感受野、权重共享、平移等变性这些“归纳偏置”来处理图像。归纳偏置是什么意思它就是你在让模型学东西之前先人为告诉它一些先验规则——比如“图像里的特征跟位置有关相邻的像素大概率关系更紧密”卷积核就是这么设计的用一个小的滑动窗口扫过整张图天然就把局部性刻进了骨子里。而Vision Transformer简称ViT做的事情恰恰是反着来的。它把一张图像切成一个一个的小方块我们叫它Patch然后把每个Patch当作一个“词”送进标准的Transformer编码器里。这里没有任何滑动窗口没有局部感受野没有卷积操作纯粹靠全局自注意力去挖掘图像里每个区域之间的关系。第一次看到这个方案的时候我的第一反应是和不少人一样这能好吗一张图片可能有几百个Patch每个Patch都要跟所有其他Patch计算关联计算量先不说关键是它真的能学到有意义的视觉特征吗但结果大家也知道了。ViT在大规模数据集上做预训练之后跑到ImageNet分类任务上准确率第一次超过了同时代的卷积网络。这件事的意义不在某个数字上而是它证明了一个更根本的问题卷积网络那些“祖传”的归纳偏置或许并不是视觉理解的必需品至少在数据量足够大的时候模型完全可以从零开始自己学出比人工先验更有效的模式。这篇博文想聊的就是ViT从诞生到现在这将近十年时间里的演进脉络。我会从它的核心设计思路讲起说说它后续在效率、结构、训练范式上走过的几条关键路线再结合我自己实际训练和部署ViT模型踩过的坑给你一份真正能用的经验总结。内容偏向工程实践和认知复盘适合已经在用深度学习方法做视觉任务、或者对Transformer架构有基本了解的朋友。1.1 从“图像当作句子”这个隐喻说起要理解ViT先要理解它最重要的一步操作Patch Embedding。假设输入是一张224×224的RGB图像ViT先把它切成16×16大小的Patch那就会得到(224/16)² 196个Patch。每个Patch展平之后是一个16×16×3 768维的向量然后通过一个可学习的线性投影把维度映射到Transformer的隐藏层维度D这个过程就相当于给每个Patch做了一个“词嵌入”。再叠加一个位置编码Position Embedding因为Transformer本身没有顺序概念必须把Patch的位置信息显式加进去这样每个Patch就带上了它在图像中的坐标语义。比较经典的实现里位置编码通常会用一个可学习的1×196的向量矩阵训练过程中自己更新。也有研究者后来尝试用2D形式的相对位置编码效果在某些任务上会更好。这一步的直观理解是你把一张照片拆成196块拼图每块拼图上标注“它在整张图的哪个位置”然后一股脑丢给一个擅长处理序列的模型。图像信息就这样被彻底序列化了原本二维的空间结构被压缩成一维的顺序模型需要靠注意力来重建“哪块和哪块属于同一个物体”这种空间关系。这里有个经常被忽略的细节为什么是16×16而不是8×8或者32×32Patch的大小其实是一个权衡。Patch越小序列长度越长注意力计算量指数上升因为自注意力的复杂度是O(n²)n是序列长度。Patch越大序列越短计算量小了但每个Patch内的空间细节会在展平之后丢失掉毕竟一个32×32的Patch里不同物体边缘的细粒度信息被粗暴压缩成了一个向量。ViT原文对多个Patch大小做过对比最终16×16被选为一个在计算量和性能之间比较均衡的折中方案。后来一些轻量级模型比如MobileViT也会用更小的3×3或者4×4 Patch配合卷积来做局部建模那是另一套思路了后面讲到演进的时候会再展开。1.2 全局注意力带来的范式变化ViT真正区别于CNN的地方是它利用自注意力机制构建了全局上下文关联。卷积操作的感受野是局部且有限的想看到更大的范围只能靠加深网络层数让高层特征慢慢“看到”更大视野这种方式是隐式的、渐进的。而Transformer在第一层就直接计算所有Patch之间的两两关系每个位置从一开始就能获得全图的全局信息这种能力是显式的、一步到位的。听起来很美好但代价也很明显。标准Transformer编码器里每一层的自注意力计算量和内存占用都是序列长度的平方。对一张224×224图像而言196个Patch还算能接受可一旦换成高分辨率输入比如384×384Patch数量就变成576个计算量直接涨了近9倍。再往后如果要做目标检测、语义分割这类密集预测任务经常需要输入分辨率达到1024×1024甚至更高序列长度会膨胀到几千纯ViT结构在这种场景下几乎不可用。正因如此ViT早期被很多人诟病“训练不稳定、需要超大规模数据、推理速度慢”。这个批评有一定道理但也促成了后续一系列重要的演进方向要么想办法降低注意力的计算复杂度比如窗口注意力、稀疏注意力要么从结构上做改变比如引入多尺度金字塔设计要么换个训练范式比如用自监督预训练来缓解对大数据集的依赖。这些也都是我这篇博文后面要重点展开的内容。2. 演进的第一条线数据效率问题ViT最初的效果其实非常依赖预训练数据规模。论文里直接使用了包含数亿张图片的私有数据集做预训练才能让ViT超过CNN。这在我们普通工程师的日常项目里几乎不现实谁会为了一个分类任务去准备几亿张图于是“怎么用更少的数据把ViT训好”就成了最紧迫的问题这个方向也催生了几个关键进展。第一个绕不开的工作是DeiTData-efficient Image Transformers。它提出了一套实用训练策略核心手段是知识蒸馏。具体做法是在训练过程中引入一个已经训练好的卷积网络作为教师模型让学生模型——也就是ViT——去模仿教师的输出分布而不仅仅是学习硬标签。简单说硬标签只能告诉模型“这张图是猫”而教师模型的软输出会额外暗示“这张图有75%像猫20%像狗5%像狐狸”这种具有模糊性的信息对提升学生模型泛化能力帮助很大。在DeiT的实验中他们发现用了蒸馏之后ViT在ImageNet上只需要约120万张训练图就能达到相当不错的性能。这个量级对很多团队來說已经是可以承受的了。我当时照着DeiT的训练配置复现过一遍最有感触的一个细节是整组训练策略里最重要的一环并不是模型结构本身而是数据增强。DeiT把当时图像分类领域里一堆有效增强手段——RandAugment、Mixup、CutMix、随机擦除——全部叠加了进去。如果训练ViT的时候只带基础增强性能下滑非常明显。我后来在生产环境里做一个小规模图像分类模型就是直接沿用了这套训练配方效果比我自己组合的增强方案稳定很多准确率上有三四个点的差距这在很多业务里是决定性的差异了。第二条线是Swin Transformer。前面提到纯ViT的序列长度问题Swin给出的解法是引入滑动窗口注意力Shifted Window Attention。它先把图像分成长方形网格每个网格内部的Patch只在本地做自注意力这样就相当于把全局注意力限定到局部窗口范围内。然后每隔一层Transformer窗口位置会偏移一半Shift这样不同层的窗口互相错开信息可以在层与层之间传递弥补局部窗口带来的感受野受限问题。更重要的是Swin引入了类似CNN金字塔的结构不同阶段输出不同分辨率的特征图从高分辨率到低分辨率逐层下采样。这意味着Swin可以直接套用到检测、分割等需要多尺度特征的任务上比如检测框架里的特征金字塔网络FPN在Swin上工作得很顺利。ViT虽然全局建模能力更强但因为它输出的是单一分辨率的序列迁移到密集预测任务时就特别别扭往往得额外设计一个专门的特征提取头才行。从演进逻辑看Swin不是推翻ViT而是用工程化的方式把ViT的核心优势——全局建模能力——保留下来同时通过结构设计绕开计算瓶颈。这个思路后来延伸出了很多变体比如PVT、Twins、Focal Transformer等等大家本质上都在做同一件事如何在保持Transformer优点的同时让它对多尺度特征和密集预测更友好。2.1 自监督预训练带来了什么改变数据效率问题还有一个更大的破局点那就是自监督预训练。2021年末到2022年初MAEMasked Autoencoder的出现让视觉Transformer的训练方式彻底改变了格局。MAE的思路是把输入图像的75% Patch全部遮盖掉只留25%的Patch喂给ViT编码器然后在解码器端重建被遮住的像素。模型要完成这个任务就必须真正理解被遮挡区域的语义内容而不是仅仅做表面纹理匹配。这个玩法很像自然语言处理里BERT的掩码语言建模但它更激进——遮盖比例高达75%。为什么可以遮这么多因为图像本身存在大量空间冗余不像语言每个词都承载着稠密的语义。相邻Patch之间的内容相关性非常强如果不遮得多一些模型只需要“抄”邻近可见Patch的内容就能轻松完成重建根本学不到高层次特征。MAE最让我惊艳的地方在于它让ViT的预训练不再依赖人工标注一个视觉模型在海量无标注图片上先学一遍通用表征然后下游任务只需要少量微调效果就能和从头训练甚至超过。这个范式对实际工程影响非常大。之前训练一个大模型做垂直场景任务你首先得找标注团队花几个月标数据然后模型训练出来可能因为数据量不够还是欠拟合。有了自监督预训练直接用无标注的行业图片做MAE预训练把通用视觉表征学好再用仅有的少量标注数据做下游微调整个流程又快又省人力。我见过好几个垂直领域的项目比如工业质检里只带了几千张缺陷图的场景之前用CNN做分类总是过拟合换用MAE预训练的ViT骨干之后泛化能力一下提升了不少。3. 演进的第二条线结构设计的进化如果说数据效率是让ViT“活下来”的关键那么结构设计上的持续进化就是让它从能用到好用的过程。这里我梳理出了几个我认为对ViT演进非常重要的结构分支每个分支都在解决不同的问题。3.1 金字塔多尺度结构前面提到的Swin是金字塔结构的一种实现但它的核心亮点其实是窗口注意力代替全局注意力来降低复杂度。在Swin之前PVTPyramid Vision Transformer提出了一种更“CNN化”的Transformer结构它把编码器分成多个阶段每个阶段内做全局自注意力但阶段之间做空间下采样同时通道数递增。这样从第一阶段到第四阶段特征图尺寸从原始的H/4逐渐变成H/32和ResNet系列骨干的层级结构完全对应。这种结构的最大价值在于兼容性。目标检测和语义分割的框架里几乎都会用到从骨干网络提取多尺度特征的过程像特征金字塔、PANet这些模块的设计就是假设输入是多尺度的。PVT和Swin因为输出特征图本身就是多尺度的所以能无缝替换掉原来的CNN骨干不需要改动检测或分割框架的任何模块。而单纯的ViT只能输出H/16大小的单一特征想要用它做检测还得专门设计一套极其繁琐的适配流程。我自己的实践感受是如果项目需要做检测或者分割且希望用Transformer架构尽量直接选金字塔设计的变体不要拿着原始的ViT硬上。你把时间花在解决ViT的序列长度适配问题上远不如选一个本来就设计好的金字塔结构来得高效。3.2 混合架构与局部建模另一个非常值得关注的方向是CNN与Transformer的混合架构。代表性的工作包括 MobileViT、LocalViT、以及后来的下一代架构如 ConvNeXt 和 FastViT。这类工作的核心动机是Transformer虽然全局建模强但缺少CNN天然具备的局部归纳偏置比如边缘特征、纹理特征的提取而局部细节对视觉任务来说往往很重要不能完全依赖全局注意力。我举个例子MobileViT的设计非常巧妙。它把图像按通道维度分成几个小组每个组内先用一个3×3卷积提取局部空间特征然后把每个空间位置看作一个序列再做一次全局注意力。这样既保留了卷积网络的局部建模能力和计算效率又引入了全局上下文信息整个模型的参数量小、推理速度快非常适合移动端部署。我在一个手机端图像分类项目里试过MobileViT模型体量只有三四百万参数但准确率比同体量CNN高好几个点推理时间也没有明显增加。沿着混合架构的方向2022年之后出现了一类很有意思的“ConvNeXt化”趋势就是把CNN结构按照Transformer的设计哲学重新审视和改造。比如ConvNeXt模型本质上是一个纯卷积网络但它的设计规格从ResNet逐步向Swin Transformer靠拢——更大的卷积核、更少的激活函数、更深的倒瓶颈结构——最终在ImageNet上实现了和Swin相当甚至更好的效果。这其实是对“Transformer一定比CNN好”这个判断的有力反思很多时候出色的性能并不来自特定的某个算子而是更大规模计算配合更优结构设计带来的整体效果。3.3 注意力计算效率当模型规模越来越大处理图像分辨率越来越高时自注意力的O(n²)复杂度就成了绕不开的瓶颈。怎么解决各路研究者做了很多尝试总结下来大致有这么几条路线。一是稀疏注意力。既然每个Patch没必要跟所有Patch都做全连接计算那我人为选择一部分有意义的关联来计算就行。Swin的窗口注意力就是一种稀疏化它的计算被限制在固定的局部窗口内。长距离依赖则通过窗口偏移来间接实现。另一种实现是轴向注意力Axial Attention分别对行和列做注意力计算复杂度从O(n²)降到了O(n√n)虽然降低了精度上限但在高分辨率场景下性价比非常高。二是低秩近似。Linear Transformer、Performer这类工作通过核技巧或者随机特征映射把注意力计算近似成一个低秩矩阵乘法复杂度降低到线性。听起来很美好但实际工程中往往需要配合更复杂的数值处理如果实现不好精度损失会比较明显。我在一些实际任务上测过Performer大模型上性能退化在可接受范围小模型上则非常明显这就限制了它的工程普及度。三是减少序列长度。这在多模态模型里很常见。图像经过一个预训练ViT提取特征后通常会产生大量Patch Token为了跟文本序列拼接到一起时节省计算量研究者会设计Token Merging或Token Pruning的方法把冗余的Patch合并或者直接剪掉。比如有个实现叫ToMeToken Merging它通过计算每对Token之间的相似度每层合并掉最相似的那几对可以在几乎不损失精度的前提下把序列长度压缩约50%。我试过一次推理速度提升明显尤其在高分辨率输入、批量处理场景下效果更好。4. 演进的主战场多模态与统一建模要说最近这两年ViT最活跃的应用方向必须提多模态。从2021年CLIP开始视觉Transformer已经不再局限于图像分类这个单一任务而是和文本模型一起构成图文理解乃至视频理解系统的骨干。CLIP的核心思想是用对比学习把图片和文本映射到同一个向量空间正样本对图片和其匹配的描述之间的距离拉近负样本对之间的距离推远。训练完成之后你不需要针对具体任务重新训练只需要给模型一段文字描述比如“一只在草地上奔跑的柴犬”模型就能直接检索出最匹配的图片。这种Zero-shot能力在多模态检索和内容理解场景里非常受欢迎。CLIP用的视觉编码器就是ViT这背后有个非常特别的设计考虑为什么选ViT而不是CNN因为CLIP需要视觉编码器的输出Token与文本编码器的Token做联合建模。文本Token天生是“序列化”的如果视觉编码器能输出同样格式的Patch Token序列那两个模态在特征融合时就能站在一个更统一的接口上进行交互。后续像Flamingo、LLaVA等视觉语言模型更进一步让语言模型在推理时动态地读取ViT输出Token把视觉信息直接当作“外部记忆”提供给文本生成过程。这种做法带来了一个完全不同的训练节奏。传统视觉模型需要先预训练、再微调、然后面对每一个新任务还要重新出数据。多模态时代这个大模型可以通过一个统一接口去理解视觉世界和语言的边界任务的迁移不需要再为每个下游任务设计单独的模型头。我当时第一次用CLIP做商品图文匹配时内心是有一点震撼的你只需要把图文对整理成统一格式丢给对比学习训练一下检索准确率比以往辛辛苦苦设计的多模态融合模型还高而且训练过程不需要任何人工标注。4.1 视频理解与ViT的时空扩展除了静态图像ViT在视频领域也有重要扩展。视频本质上是一个有很多帧的图像序列把ViT从空间维度扩展到时空维度可以通过在输入阶段就把多个连续帧Patch拼接到一起把时间维度和空间维度统一序列化或者直接替换注意力机制让自注意力能同时覆盖空间和时间范围这就是Video Vision Transformer系列的工作方向。空间上每一帧被切成Patch时间上不同帧的相同空间位置Token会被打包到同一时间注意力窗口中。经过多层的空间时间注意力交叉之后模型能够同时识别物体的外观变化和运动轨迹。用ViT做视频理解的明显优势是它不依赖预设的光流等手工运动特征能从数据中直接学出“运动意味着什么”。我在一个用户行为视频分类项目里实验过直接把预训练好的基于图像的ViT权重复用到视频模型中做初始化再用小规模视频数据微调效果远超从零训练的CNN视频模型而且收敛得特别快。这说明ViT在时空联合建模上的学习效率确实高只要初始化得当。4.2 长尾与细粒度场景中的挑战当然ViT的演进并不只有高光时刻。在真实场景里长尾分布问题和细粒度分类问题至今依然是ViT的一大软肋。所谓长尾分布就是数据集中绝大多数类别拥有大量样本而尾部类别只拥有极少样本这在真实业务中几乎随处可见。ViT因为依赖全局注意力模型对数据分布的敏感度比CNN更高在数据不均匀时尾部类别的性能会掉得很厉害。细粒度分类则与之相反类别之间的差异非常细微比如不同品种的鸟类、不同缺陷类型的工业表面缺陷这种任务要求模型对微小局部差异极其敏感而ViT的Patch化输入和全局注意力并不天然擅长这种高精度局部特征建模。针对这些缺陷工业界和学术界想了不少办法。解决长尾问题比较有效的思路是在训练时使用重采样或者重加权策略同时利用预训练模型在大数据上学到的通用特征做迁移。另一个思路是把ViT和CNN做局部特征融合用CNN在细粒度图像上提取局部细节用ViT做全局上下文语义补充。这种做法在医学影像和工业质检的场景里特别实用。我自己在表面缺陷检测项目里的体会是把Swin骨干和ResNet骨干做双分支融合会比单纯用任何一种主干网络在细粒度缺陷样本上的表现都更稳定。5. 十年视野下的路线回顾与技术选型建议回顾从ViT提出至今的演进路径我会把它分成三个阶段。第一阶段大约是2020年前后是“证明阶段”大家集中精力证明“纯注意力架构可以用于视觉并且能达到业界顶级水平”。第二阶段2021到2022年是“工程化阶段”焦点转向效率和数据DeiT、Swin、MAE等一系列工作让它从论文走向工程可用。第三阶段2023年之后是“泛化阶段”ViT不再只是图像模型而是成为多模态乃至通用人工智能模型的核心视觉骨干同时它也在与CNN、状态空间模型等其他架构持续融合。走到现在如果你让我给一个技术选型的建议我不会像一些极端观点那样说“ViT已经全面取代CNN了”。真实情况是二者各有各的适用场景。分类任务上如果数据量有限、算力有限CNN仍然是可靠的起点。如果数据规模很大、或者任务本身涉及大量长距离依赖的建模——比如场景理解、跨模态检索、高分辨率图像理解——ViT及它的各种变体则更有优势。如果做视频理解或多模态任务ViT几乎是你绕不开的选择。5.1 训练一个ViT模型的实操要点如果你决定尝试用ViT做一个新项目我这里有几条实践经验可以分享。第一条不要从零训练。除非你有千万级别的标注数据否则几乎注定欠拟合。一定要用在大规模数据上预训练好的权重作为初始化这个步骤能给你的模型带来10个点以上的跨越。行业内许多开源仓库都提供了在ImageNet-21K甚至更大规模数据上训练好的模型权重直接拿来做下游任务的骨干就行。第二条一定要重视优化器设置。ViT对学习率的敏感性比CNN高得多。AdamW加上cosine学习率衰减是比较稳妥的通用配方。初始学习率通常在1e-4到5e-4之间具体看你批量大小。Batch size翻倍时学习率可以按比例调大但增幅不要超过2倍。此外warmup阶段必不可少根据模型规模从500步到5000步不等用来稳定训练初期避免损失震荡。第三条数据增强要认真对待。这一点前面提到过再强调一次Mixup、CutMix、RandAugment这些手段对ViT的提升效果通常非常显著。我之前试过一组对照实验同样的模型和数据集带全套增强比只带基础裁剪翻转的版本精度高出接近5个百分点而且泛化能力明显更好。5.2 推理部署中的工程经验模型训练好了部署阶段又是一个新战场。ViT模型在GPU上推理时并行度高但在CPU或者边缘设备上就比较吃亏因为它缺乏CNN那种天然的局部计算结构推理库很难针对自注意力做太激进的重排优化。如果要在边缘设备上跑ViT我试过两条比较有效的路径。一是使用支持注意力的推理框架和编译器比如一些专门优化Transformer推理的运行时通过算子融合、内存复用等手段把性能拉上去。二是用ONNX导出配合量化感知训练。ViT对INT8量化的敏感度比CNN更高盲目的后训练量化经常会有明显性能下降所以必须做量化感知训练让模型在训练阶段就适应低精度计算。我在一个移动端分类项目中通过量化感知训练加注意力融合优化最终在设备上跑到了接近实时帧率效果和浮点模型相比只掉了一个点以内。如果推理场景对延迟极其敏感还有一个思路是直接选择轻量级架构比如MobileViT或者Mobile-Former它们在设计阶段就考虑了部署效率比直接压缩一个标准ViT要省事得多。5.3 下一个方向的个人判断到现在这个阶段我认为ViT的演进远未结束但它的形态会和前几年大不一样。一个明显的趋势是架构融合CNN擅长局部高频细节提取ViT擅长建模全局低频依赖两者优势互补未来必然有更多统一架构出现。另一个趋势是蒸馏与自监督训练的普及让大规模预训练的成本不断降低垂直领域的小团队也能训练出自己的“通用视觉模型”。还有一个方向是高效注意力机制的持续精进配合更强大的硬件我相信高分辨率实时视觉理解会在不久将来走入更多生产系统。我在实际项目中反复验证过的一件事是不要迷信任何一种架构选型永远要跟着任务走。ViT很强但它的强项需要数据和算力支撑CNN很稳但在数据量大到一定程度时上限确实不如Transformer。把每种架构的局限和优势都摸清楚你才算真正理解了过去十年视觉模型演进的精髓。