想象你在一个古老的漫画修复工坊里工作。工坊的规矩很奇怪:不管什么漫画书送进来,都要先拆成一格格分镜画块,让每一位师傅轮流仔细端详每一块,然后在长桌旁大声交换各自的发现,最后合议出这本书的类别——是冒险故事,还是科幻小说?这,就是 ViT(Vision Transformer)的工作方式。 过去的图像识别(CNN)像一位用放大镜局部扫描的老学究,必须一层层从细节拼出全貌;而 ViT 更像那位拆书匠:它把整张图均匀切成小方块(patch),像读文字一样把它们排成一行,给每块编上序号,再让一屋子师傅同时交流、综合信息,最后读出书名。ViT 是第一个证明 Transformer 在图像领域能打败 CNN 的模型,它开创了视觉大模型的先河——如今的 SAM、DINOv2 等视觉基础模型,根子上都长在 ViT 这片土壤里。这篇内容,就是带你走进这间“漫画拼图工坊”,看看机器究竟是怎么把一张图片,当成一段文字读懂并分类的。
理解 ViT 是进入视觉大模型世界的通行证。掌握图像如何变成 token、位置编码如何保留空间信息,你就能看懂从 CLIP 到 SAM 等一系列前沿视觉架构的设计逻辑,为学习多模态大模型打下最坚实的根基。
目录
可视化演示
本节配有交互动效(进入视口后自动加载,约 3KB)。
Patch Embedding——图像分块 分块:224×224→14×14 patches 嵌入:每patch→1D向量 N=(H×W)/P², 每patch展平投影 图像转为token序列
模型背景:ViT从何而来
工坊里资历最老的师傅一直用放大镜慢慢扫视漫画的每一寸——他坚信只有从局部一点点看起,才能拼出全貌。这就是 CNN 的思路:用一个个小卷积核在图像上滑动,每次只“看”一小块,再靠层层堆叠扩大视野。但这种“局部扫描”有个天生的遗憾:想看到画面左上角和右下角之间的联系,必须穿过很多层网络,既慢又容易丢失线索。
2017 年,Transformer 在自然语言处理领域横空出世,它有一种神奇的能力:让序列中任意两个位置的词直接互相对话,一步就看全全局关系。这间工坊的新师傅们想:为什么不能把图像也变成“文字序列”呢?于是 2020 年,Google 团队的 ViT 论文《An Image is Worth 16x16 Words》诞生了——他们真的把一张 224×224 的图像变成了 196 个“词”,喂给纯 Transformer 网络,第一次在图像分类上击败了当时最强的 CNN。这一下,视觉领域的天花板被捅破了。
ViT 的核心设计逻辑可以概括为“万物皆可 token”。关键的第一步,是明确图像到底能拆成多少个 token,它由图像边长和 patch 边长共同决定:
工坊从此多了一位拆书匠:他不纠结于局部,而是先拆书,后面所有人围着拼图块平等交流。正是这个“从局部扫描到全局拼图”的范式转变,让 ViT 成了视觉大模型的新起点。
- 分子 H × W图像的高度与宽度相乘,得到整幅图像的总像素数。比如 224×224 的图像,总像素是 50176 个。
- 分母 P × P每个 patch 的边长 P 与自己相乘,得到单个 patch 占用的像素数。当 P=16 时,每块拼图包含 256 个像素。
- 相除取商总像素数除以单块像素数,就算出了 patch 的总数量 N。对 224×224 输入、P=16,N 正好是 196,这就是送入模型的 token 数量。
Patch切分:把漫画拆成整齐的拼图
拆书匠开工了。他拿来一张 224×224 像素的漫画书页,先在上面画好一张 16×16 的网格——不多不少,正好 14×14 个格子,每格就是一块 P×P 的拼图。这里的“拆”很有讲究:所有格子一模一样大,彼此紧紧挨着、绝不重叠,就像裁纸刀一刀一刀均匀切下去,保证每块拼图承载的信息量相当,也保留了它们在页面上的相对位置。
把每块拼图拿起来细看,它本身是一小块二维图像,有高、有宽、还有三个颜色通道(红绿蓝)。但 Transformer 的工坊只认一维的文字卡片,不认二维的图案。所以拆书匠要把每一块拼图“压平”:按行把像素一个个排成一长串。一块 16×16×3 的拼图,展平后就变成一根长度为 768 的向量——就像把一小块方地毯拆成一条长长的线头,线的顺序就是原来地毯的行走路径。
这个“压平”操作在数学上就是一个 reshape,把三维的小块变成一维的长向量:
拆完这一轮,漫画书页变成了 196 张窄长的“纸条”。但纸条之间的空间关系还没被编码,下一步,工坊要教这些纸条“记住”自己原本在页面上的位置。
- 原始块 I_{i,j}图像中第 i 行、第 j 列的那块 patch,它本身是三维的,形状是 P×P×C,即长、宽、颜色通道。
- 展平操作 Flatten按固定的行走顺序(第一行从左到右、第二行从左到右……)把所有像素依次排开,二维方块变成一维长串。
- 展平结果 x_p输出的向量长度为 P×P×C。当 P=16、C=3 时,每个 patch 变成 768 维的向量,这就是递给 Transformer 工坊的“卡片”。
PatchEmbedding:把拼图变成统一的卡片
196 张纸条长短不一规格混乱,有的写着 768 个数字,有的颜色通道分布不均匀,工坊的师傅们没法高效传递。拆书匠决定把它们全部做成统一规格的“工坊标准卡片”——这就是 Patch Embedding 的作用:通过一个可学习的线性投影矩阵,把每张 768 维的纸条压缩或映射成一个 D 维的嵌入向量(ViT 常用 D=768 或 1024)。
这个映射在数学上就是一次矩阵乘法。想象每张纸条上的 768 个数字排成一列,乘以一个形状为 768×D 的投影矩阵 E,得到一根 D 维的新向量。矩阵 E 里的每一个数字都是模型在训练中自动学出来的参数,它像一个“翻译官”,知道原始像素的哪些组合模式是有意义的——比如边缘、纹理、色块。经过这层映射,每个 patch 不再是原始像素的简单罗列,而是被提炼过的“语义卡片”。
整个过程用公式写出来非常简洁:
现在,196 张统一规格的卡片整整齐齐摆在工坊桌上。但这时有个严重的问题:卡片之间完全一样排序打乱也没区别——工坊没人知道哪张卡片原本在左上角、哪张在右下角。下一节,就该给卡片编上座位号了。
- 转置向量 x_p^T把展平后的 patch 向量转置成列向量的形式,方便与矩阵做乘法。
- 投影矩阵 E形状为 (P·P·C) × D 的可学习参数矩阵,它负责把 768 维的原始信息压缩/映射到 D 维的嵌入空间。E 里的每一列都可以看作一个“特征检测器”。
- 偏置项 b一个可学习的 D 维向量,给映射结果加一个偏移,让模型拟合能力更强。
- 输出 z_p最终得到 D 维的 patch 嵌入向量。全部 196 个 patch 完成相同变换后,图像就变成了一个长度为 196 的“卡片序列”。
位置编码:给拼图块编上序号
师傅们把 196 张标准卡片摊在长桌上,发现一个尴尬的事实:自注意力机制天生是“排列不变”的——就像一群只认卡片内容、不认卡片位置的助手,你把 3 号卡片和 7 号卡片换位置,他们的讨论结果完全一样。对文字来说,词语顺序就是语义的一部分;对图像来说,位置更是灵魂。一副拼图如果块块都正确但位置全乱,那将毫无意义。
解决之道是位置编码(Positional Encoding):为每一个位置准备一个可学习的“序号向量”,直接加到对应位置的 patch 嵌入上。ViT 用的不是三角函数那种固定的位置编码,而是一张可学习的参数矩阵 E_pos——它像一个座位表,每个座位都有自己专属的“气味标签”,助手们闻到标签就知道这张卡片原本坐在哪里。训练过程中,模型会自动学会如何编码“相邻”、“左上”、“中心”等空间关系。
在真正送入 Encoder 之前,还要做一件事:在序列最前面额外插一个特殊的 CLS token(后面会细讲)。把 CLS token 和 196 个 patch 卡片拼接,再整体加上位置编码:
有了位置编码这瓶“隐形墨水”,工坊长桌上的讨论终于有了空间秩序。不过,ViT 的位置编码有一个重要的脾气:它非常依赖大数据的喂养,训练数据不够时,这套座位表很难学好——这一点我们会在误区部分细说。
- 拼接操作 [x_cls; z_1……z_N]把 CLS 向量放在最前面,后面依次接上 196 个 patch 嵌入向量,组成一个长度为 197 的序列。CLS 是个可学习的向量,它一开始不携带任何图像信息。
- 位置编码矩阵 E_pos形状为 (N+1) × D 的可学习参数,每一行一个位置向量,与序列中对应位置的 token 一一配对。
- 逐元素相加 +位置编码向量直接加到 token 向量上。相加后每个 token 既携带了 patch 的像素语义,又携带了它在原图中的位置信息,二者融为一体。
Encoder编码:工坊里的传纸条大会
现在,197 张“带味”的卡片摆上了长桌。工坊的讨论规则分为两层:先是全体师傅同时传纸条——这就是多头自注意力(Multi-Head Self-Attention);然后每张卡片自己整理收到的所有纸条并做出总结——这就是 MLP 层。两层之间都加了“残差连接”(把原始卡片信息原封不动保留下来再叠加),并用 LayerNorm 稳定每一轮的信号强度,防止讨论越来越跑偏。
自注意力是这场大会的核心机制。每张卡片 x 都会生成三个角色:查询(Query,我想找谁)、键(Key,我是谁)、值(Value,我有什么信息)。任意两张卡片之间,用查询和键做点积算出“我们俩有多相关”,再用这个相关度对所有卡片的值做加权求和。这样一来,左上角的拼图块可以直接“看见”右下角的拼图块,一步跨越整个图像——这正是 CNN 梦寐以求的全局感受野。
多头版本则是把 768 维的卡片切成 H 个 64 维的“头”,每个头独立开一场讨论,关注不同维度的关系——有的头专门关心颜色相似性,有的头关心纹理延续性,最后把所有头的结果拼在一起。单头注意力的核心公式是:
一场传纸条大会下来,每张卡片都吸收了全场的信息,变成了“见过世面”的新卡片。但师傅们讨论得再热闹,最终还是要有人站出来宣布结论。工坊里那个一直不说话的 CLS 店长,终于要开口了。
- 查询矩阵 Q来自每个 token 的可学习变换,代表“我想找什么样的信息”。所有 token 的查询向量堆叠成矩阵。
- 键矩阵 K 与点积 QK^TK 代表“我能提供什么类型的线索”。Q 与 K 做点积,得到 N×N 的相似度矩阵,第 i 行第 j 列的值表示“token i 对 token j 的关注程度”。
- 缩放因子 √d_k除以键向量维度的平方根,防止点积结果过大导致 softmax 梯度消失——就像控制会场音量,防止大家喊得太响听不清细节。
- softmax 归一化把每一行的相似度分数变成总和为 1 的权重分布,让关注度可比。
- 加权求值 × V用归一化后的权重对值矩阵 V 加权求和,得到每个 token 融合全局信息后的新表示。
分类输出:店长读出书名
讨论进行了 12 轮(12 层 Encoder),长桌上的每张卡片都早已不是最初的模样——它们各自掌握了全书的全局信息。但工坊最终要交出一份结论:这本漫画属于哪个类别?这时候,序列最前面那个特殊的 CLS token 就派上了用场。它从一开始就被插在序列首位,不携带任何具体 patch 的信息,唯一的作用就是“旁听”:在每一轮注意力交换中,它都能看到所有卡片的信息,同时所有卡片也能看到它。
你可以把 CLS token 理解为一位从头到尾只做记录、不发表观点的店长。12 轮讨论结束后,店长手里等于握着全场所有拼图块交叉印证后的浓缩信息。现在只需把他的记录本——最后一层输出的 CLS 向量——交给分类头(一个全连接层),就能映射成每个类别的得分,再经过 softmax 变成概率分布:
整个工坊的训练模式也值得记住:先在超大数据集(如 JFT-300M)上预训练,让拆书匠和师傅们学会“通用的读图能力”,再到 ImageNet 等下游数据集上微调。预训练时还会用 1D 位置编码插值来适配更大尺寸的输入图像——这就是视觉大模型“先通读万卷书,再精读一本”的成长路径。
- 最后一层输出 z_L^cls经过 L 层 Encoder 后,序列第一个位置(CLS)对应的输出向量,它浓缩了全局分类信息。
- 分类权重 W_cls形状为 D × C 的可学习矩阵(C 是类别数),把 D 维的浓缩信息映射到 C 个类别的得分空间。
- softmax 概率化把所有类别的得分转换为总和为 1 的概率分布,取最大概率对应的类别作为预测结果。
AI 应用场景
医学影像分类:CT 切片是天然的“拼图书”
阶段:图像预处理与分类模型训练
解决的问题:医生每天要看数百张肺部 CT 切片,传统人工筛查费时且容易疲劳漏诊。CNN 方案虽然能用,但对大尺寸影像需要多次下采样,容易丢失微小病灶的全局上下文。ViT 把整张切片切块成 token,让模型每时每刻都能同时关注左肺和右肺的关联特征,对早期微小病灶的敏感度更高。
具体案例:某三甲医院放射科引入基于 ViT 的肺炎分类系统,将 512×512 的 CT 切片切成 32×32 的 patch 序列,在 5 万张标注切片上预训练后微调。系统对“病毒性肺炎 vs 细菌性肺炎”的分类准确率从 CNN 基线的 88% 提升到 94%,且对病灶位置的定位热力图更完整,帮助医生发现了 3 例早期被忽略的间质性病变。
卫星遥感地物分类:大片土地也能一眼看全局
阶段:遥感图像嵌入与分类
解决的问题:一张卫星图往往覆盖几十平方公里,农田、城市、水体、森林交错分布。传统方法要么用滑动窗口逐块分类导致边界割裂,要么整图缩放损失细节。ViT 把大图切块后做全局自注意力,天然适合这种“既要看每块地的细节,又要看地块之间的空间关系”的任务。
具体案例:某地理信息公司用 ViT 对高分二号卫星影像做土地利用分类,输入 1024×1024 的影像,patch 大小设为 32。相比 U-Net 和 ResNet 方案,ViT 对不规则地物边界的分割更平滑,农田与森林的混淆率降低了 37%,并且凭借全局感受野直接输出了整景影像的分类结果,不再需要复杂的后处理拼接。
电商商品图自动打标:小图快跑,大图精读
阶段:商品图像嵌入与多标签分类
解决的问题:电商平台每天新增数百万张商品图,需要自动识别品类、颜色、风格等多个标签。传统 CNN 需要为每个标签单独训练模型,维护成本高。ViT 的 CLS token 天然适合多标签分类——只需把分类头换成多个二分类头,一个模型就能同时输出数十个标签。
具体案例:某头部电商平台的商品审核系统采用 ViT-base 作为图像编码器,在 3000 万张商品图上预训练后进行多标签微调。系统同时预测“连衣裙/短裙/半身裙”、“红色/碎花/波点”等 50 个标签,单张图片推理耗时仅 8ms,准确率比此前 ResNet-50 方案高出 4.2 个百分点,人力审核量减少了 60%。
Python 演示
import torchimport torch.nn as nn class PatchEmbed(nn.Module): def __init__(self, img_size=224, patch_size=16, in_chans=3, embed_dim=192): super().__init__() 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 = self.proj(x) x = x.flatten(2) x = x.transpose(1, 2) return x class TransformerBlock(nn.Module): def __init__(self, embed_dim=192, num_heads=4, mlp_ratio=4.0): super().__init__() self.norm1 = nn.LayerNorm(embed_dim) self.attn = nn.MultiheadAttention(embed_dim, num_heads, batch_first=True) self.norm2 = nn.LayerNorm(embed_dim) hidden_dim = int(embed_dim * mlp_ratio) self.mlp_block = nn.Sequential( nn.Linear(embed_dim, hidden_dim), nn.GELU(), nn.Linear(hidden_dim, embed_dim), ) def forward(self, x): x = x + self.attn(self.norm1(x), self.norm1(x), self.norm1(x))[0] x = x + self.mlp_block(self.norm2(x)) return x class SimpleViT(nn.Module): def __init__(self, img_size=224, patch_size=16, num_classes=10, embed_dim=192, depth=6, num_heads=4): super().__init__() self.patch_embed = PatchEmbed(img_size, patch_size, 3, embed_dim) self.cls_token = nn.Parameter(torch.zeros(1, 1, embed_dim)) self.pos_embed = nn.Parameter( torch.zeros(1, self.patch_embed.num_patches + 1, embed_dim)) self.blocks = nn.ModuleList( [TransformerBlock(embed_dim, num_heads) for _ in range(depth)]) self.norm = nn.LayerNorm(embed_dim) self.head = nn.Linear(embed_dim, num_classes) def forward(self, x): B = x.shape[0] x = self.patch_embed(x) cls_tokens = self.cls_token.expand(B, -1, -1) x = torch.cat([cls_tokens, x], dim=1) x = x + self.pos_embed for blk in self.blocks: x = blk(x) x = self.norm(x) cls_out = x[:, 0] logits = self.head(cls_out) return logits if __name__ == "__main__": model = SimpleViT() dummy = torch.randn(2, 3, 224, 224) out = model(dummy) print("输出形状:", out.shape)
self.proj = nn.Conv2d(in_chans, embed_dim, kernel_size=patch_size, stride=patch_size)用步长等于卷积核大小的卷积实现 Patch Embedding,一举完成切块和线性投影。x.flatten(2).transpose(1, 2)把 [B, D, 14, 14] 展平为 [B, D, 196] 再转置成 [B, 196, D],让序列维度排第二。self.cls_token = nn.Parameter(torch.zeros(1, 1, embed_dim))定义可学习的 CLS token,初始化为零向量,训练中自动更新。torch.cat([cls_tokens, x], dim=1)把 CLS token 拼接到 196 个 patch token 前面,得到长度为 197 的序列。x = x + self.pos_embed把位置编码加到 token 序列上,注入空间位置信息。x + self.attn(self.norm1(x), ...)[0]残差连接套 LayerNorm 加多头自注意力,是 Transformer Block 的标准结构。cls_out = x[:, 0]取出序列第一个位置(CLS token)的输出,送入分类头。dummy = torch.randn(2, 3, 224, 224)构造一个批大小为 2、3 通道、224×224 的随机图像,验证前向传播通畅。
常见误区
误区“ViT 就是把图片拉成一长串像素,然后像读文本一样传给 Transformer,不需要任何预处理。”
正解如果真把 224×224×3=150528 个像素全部作为 token,序列长度是 15 万,自注意力的计算量是序列长度的平方,任何显卡都扛不住。ViT 的关键设计是先把图像切成 patch(比如 16×16),每个 patch 展平后通过线性投影变成一个 token,序列长度骤降到 197。这就像工坊师傅不会把书页撕成一个个字,而是按“格子”拆成拼图块——既保留局部结构,又控制讨论规模。
为何常见:Transformer 在 NLP 里确实是以词为单位,大家容易类比成“以像素为单位”,忽略了图像像素数量远大于文本词数这一关键差异。
误区“位置编码不就是告诉模型每个 patch 排第几吗?用一个整数编号就行,简单又直观。”
正解整数编号有两个致命问题:一是数字大小本身会误导模型(比如 100 号的位置是不是比 1 号重要 100 倍?);二是它带不来任何空间几何关系——编号 4 和编号 5 相邻,但编号 12 的图像位置与 4 也在同一行吗?ViT 用的是可学习的多维向量加在 token 上,模型在训练中自己学会“第 i 行第 j 列 ≈ 某组特定向量”的编码方式,这种柔性的向量编码远比硬编码整数信息丰富。
为何常见:人们自然地把“位置”理解成“序号”,但从 NLP 的 Word2Vec 到 ViT 的 E_pos,高维向量表示信息的能力远超单个标量,这是新手最容易低估的地方。
误区“patch 越小,每个 token 包含的像素越少,模型越能关注细节,准确率应该越高。”
正解patch 从 16×16 减到 8×8,token 数从 196 暴涨到 784,计算量增加约 4 倍(自注意力是 O(N²)),很多小显存显卡直接训练不起来。更重要的是,patch 太小意味着每个 token 的语义信息太薄,模型反而难以学到有意义的全局模式。ViT 论文的实验表明,patch 为 8 时在小数据集上表现反而略差(更容易过拟合),16 是精度和效率的最佳平衡点,32 则偏粗。这就像拼图块太小,师傅们看到的信息太琐碎,反而难以形成整体判断。
为何常见:直觉上“越精细越好”在 CNN 的卷积核设计里部分成立,但 Transformer 的 token 是全局交互的基本单元,token 过细导致序列过长,模型的学习负担和计算负担同时上升,这个 trade-off 违背直觉。
误区“ViT 这么厉害,直接在 ImageNet 上从零训练,效果肯定碾压 ResNet。”
正解恰恰相反,ViT 缺少 CNN 的内置归纳偏置(局部性、平移等变性),在中等规模数据集(如 ImageNet-1k,128 万张图)上从头训练,效果不如同量级的 ResNet。ViT 的真正威力需要海量数据来激发:论文在 JFT-300M(3 亿张图)上预训练后,再迁移到 ImageNet 才以明显优势超越 CNN。这就像一位只读过一本漫画的拆书匠,肯定不如深耕多年的老学究;但当他读完 3 亿本书后,眼界和判断力就完全不同了。
为何常见:媒体宣传只强调 ViT 的 SOTA 结果,很少提及它依赖大规模预训练这一前提,导致初学者误以为 ViT 是“即插即用”的万能模型。
误区“分类直接用所有 patch token 的均值池化就行,CLS token 是多余的'画蛇添足'设计。”
正解CLS token 是 ViT 架构中精心设计的“信息汇聚中心”。它在位置编码序列的最前端,通过 L 层自注意力与所有 patch 交互,最终输出一个全局向量。虽然理论上平均池化也能汇总信息,但实验证明 CLS token 的效果更稳定——它作为可学习的“旁听者”,不受任何具体 patch 的偏置影响,能更纯粹地学习“什么信息对分类最重要”。后续的 BERT、MAE 等模型也都沿用了这一设计,说明它经得起实践检验。
为何常见:CLS token 初始化为零向量、不携带图像信息,看起来像是“白占一个位置”,初学者容易低估它在深层网络中的信息汇聚作用。
面试题
Q1. ViT 中把图像切成的“基本单位”是什么?
- A.单个像素点
- B.固定大小的 patch← 正确答案
- C.整张图像
- D.颜色通道
答案:B。ViT 把图像切成固定大小的 patch(如 16×16),每个 patch 展平后映射为一个 token。单个像素点作为 token 会导致序列过长,而整张图像作为 token 又失去了局部信息,只有 patch 是平衡的粒度选择。
Q2. 当输入图像为 224×224、patch 大小为 16×16 时,ViT 会得到多少个 patch token?
- A.14
- B.49
- C.196← 正确答案
- D.224
答案:C。patch 数量 = (224/16)² = 14² = 196。加上一个 CLS token 后,实际送入 Encoder 的序列长度为 197。这就像一本漫画书按 16×16 的格子拆,正好能拆出 196 块拼图。
Q3. 位置编码在 ViT 中的核心作用是什么?
- A.加速模型训练
- B.保留 patch 的空间位置关系← 正确答案
- C.压缩模型参数量
- D.将图像转换为文字
答案:B。自注意力机制本身是排列不变的——把 token 顺序打乱,结果完全一样。位置编码给每个 token 注入“它原本在图像中的位置”信息,让模型能感知拼图块的相对空间关系,这是 ViT 能理解图像结构的关键。
Q4. ViT 中 CLS token 的最终输出向量主要用于什么?
- A.计算位置编码
- B.生成所有 patch 的均值
- C.作为分类头的输入← 正确答案
- D.初始化 patch embedding
答案:C。CLS token 经过 L 层 Encoder 后,其输出向量浓缩了全局分类信息,ViT 将它送入分类头(全连接层)得到类别概率。它就像工坊里一直旁听的店长,讨论结束后用笔记本来做最终判断。
Q5. 为什么 ViT 在中小规模数据集上从零训练时,效果往往不如 CNN?
- A.ViT 的网络深度不够
- B.ViT 缺少局部性与平移等变等归纳偏置← 正确答案
- C.Transformer 无法处理图像数据
- D.patch 切分会导致信息完全丢失
答案:B。CNN 自带局部感受野和平移等变的归纳偏置,天然适合图像;而 ViT 的全局自注意力没有这些先验,必须从数据中学习。数据量不足时,ViT 学不到这些模式,容易过拟合。这就像没有读过万卷书的拆书匠,经验还不如深耕多年的老师傅。
Q6. 在 ViT 中,Patch Embedding 最常用的实现方式是什么?
- A.全连接层直接作用在展平向量上
- B.步长等于卷积核大小的卷积操作← 正确答案
- C.随机像素采样
- D.滑动窗口平均池化
答案:B。虽然数学上 Patch Embedding 等价于线性投影,但工程实现中通常用 stride=kernel_size 的 Conv2d 一次完成切块和投影,效率最高。这就像用一台模压机,一步就把纸条上的信息变成标准卡片。
Q7. ViT Encoder 中残差连接的主要作用是什么?
- A.减少模型参数量
- B.缓解深层网络中的梯度消失与退化问题← 正确答案
- C.增加位置编码的维度
- D.替代 LayerNorm 的作用
答案:B。残差连接让梯度可以“抄近路”直接回传到浅层,缓解了层数加深带来的梯度消失和退化问题。它是 Transformer Block 能够堆叠 12 层甚至 24 层而不崩溃的基石。就像工坊讨论时,每位师傅都会保留自己最初的记录本,防止讨论多轮后丢失原始信息。
Q8. 以下哪些是 ViT 处理一张图像的标准步骤?
- A.将图像切成均匀的 patch 并展平← 正确答案
- B.通过线性投影将 patch 映射为 embedding← 正确答案
- C.加上可学习的位置编码← 正确答案
- D.用循环神经网络逐行扫描图像
答案:ABC。ViT 的四部曲是:切 patch → Patch Embedding 线性投影 → 加位置编码 → 送入 Transformer Encoder。RNN 逐行扫描是另一类模型的做法,ViT 完全没有使用循环结构,而是靠全局自注意力完成序列建模。
Q9. 关于 ViT 的位置编码,下列说法正确的有哪些?
- A.位置编码参数是可学习的← 正确答案
- B.位置编码直接加在 patch embedding 上← 正确答案
- C.位置编码必须是固定的三角函数形式
- D.位置编码帮助模型感知 patch 的空间顺序← 正确答案
答案:ABD。ViT 使用可学习的位置编码矩阵 E_pos,与 token 逐元素相加后送入 Encoder。原始 Transformer 论文用固定三角函数,但 ViT 选用可学习版本,实验效果更好。位置编码本质上是给模型提供空间顺序线索,没有它模型就是“盲拼图”。
Q10. 下列关于 ViT 的说法中,正确的有哪些?
- A.patch 越小,序列越长,自注意力计算量越大← 正确答案
- B.ViT 在 ImageNet-1k 上从头训练即能稳定超越 ResNet
- C.CLS token 是可学习的向量,初始不携带图像信息← 正确答案
- D.ViT 的位置编码一维向量也能隐含二维空间关系← 正确答案
答案:ACD。自注意力复杂度是 O(N²),patch 越小 token 越多计算量爆炸式增长,A 对。ViT 在中等数据集从头训练并不优于 CNN,需要大数据预训练,B 错。CLS token 初始化为可学习零向量,在深层网络中汇聚全局信息,C 对。ViT 用一维的位置编码排列二维 patch,模型可以自动学会行列关系,D 对。