ViT 为什么只取第一个位置作为输出:CLS Token 特征聚合完整解析
ViT 为什么只取第一个位置作为输出:CLS Token 特征聚合完整解析
【免费下载链接】visionDatasets, Transforms and Models specific to Computer Vision项目地址: https://gitcode.com/gh_mirrors/vi/vision
在 PyTorch Vision 库里跑 ViT(Vision Transformer)时你会发现一个细节:编码器输出的特征序列很长,但模型只截取第一个位置送入分类头,最终 logits 形状是 [B, 768]。为什么偏偏是"第一个位置"?📌 这篇文章从输出形状出发,把 CLS Token 特征聚合这套设计讲清楚。
从 [B, 768] 说起:输出形状是怎么来的
先看代码。在 torchvision/models/vision_transformer.py 的forward里,有两行非常直白:
x = x[:, 0] # 取序列第一个位置 x = self.heads(x)此时x的形状是 [B, 197, 768]:197 是序列长度,768 是特征维度。而分类头是一个把 768 维映射到 1000 类的线性层,它只接受"一张图一个向量",无法直接处理 197 个向量。问题于是变成:197 个位置里,哪一个最适合代表整张图?模型设计给出的答案就是第一个位置。
CLS Token:一个刻意插入的"汇总槽位"
CLS(Classification)Token 的思路来自 NLP 领域的 BERT:在序列开头放一个特殊 token,经过多层自注意力(self-attention,即序列中每个元素都能看到其他所有元素并据此更新自己)后,它的最终表示会汇聚全局信息,供分类使用。
PyTorch Vision 的实现同样是"预置槽位 + 靠注意力填充":
batch_class_token = self.class_token.expand(n, -1, -1) x = torch.cat([batch_class_token, x], dim=1)CLS Token 是一个可学习参数,被拼接到所有 patch 特征之前。关键在于:它刚进场时对图像一无所知,只能通过自注意力"向"196 个 patch 提问。每一层它都在关注全部 patch,层层堆叠后,这个向量的内容就是经过注意力加权蒸馏出的全局摘要。
从图像到序列:CLS Token 走过的完整路径
以 ViT-B/16 为例,图像到序列的变化分四步:
- 切 patch 并投影:224×224 的图像被 16×16 的卷积切成 14×14=196 个 patch,每个 patch 经线性投影变成 768 维向量(即 patch embedding);
- 加位置编码:编码器为每个 token 加上表示空间位置的向量,让模型能区分 patch 的先后位置;
- 多层编码器:自注意力 + MLP 反复交互,所有 token 互相"交流";
- 只取第一个位置:输出仍是 197 个 token,但分类只读取 CLS 位置,得到 [B, 768] 的分类特征。
也就是说,197 个 token 并行地"读懂"了图像,而输出时只读出预留的汇总槽位。
CLS Token 与全局平均池化:两种特征聚合的差异
CLS Token 的本质是特征聚合——把 196 个 patch 特征压成一个向量。全局平均池化(GAP)是常见的替代做法,差异如下:
| 对比维度 | CLS Token | 全局平均池化 |
|---|---|---|
| 聚合方式 | 注意力加权,权重由学习决定 | 所有 patch 等权平均 |
| 重点区域 | 可动态聚焦关键 patch | 局部信息被等比例稀释 |
| 推理成本 | 读取单向量,几乎无额外开销 | 需对整条序列做一次平均 |
| 适用场景 | 分类任务的标准做法 | 也常配合 patch 特征用于密集任务 |
此外还有多 Token 融合的思路:把 CLS 输出与 GAP 拼接或相加,可能提升鲁棒性,但计算与调参成本更高。
开发者如何选择与修改聚合方式
- 标准分类任务:直接用 PyTorch Vision 的默认实现,CLS Token 聚合已经被大量预训练权重验证,不需要动;
- 微调或换分类头:只替换
heads即可,"取第一个位置"的逻辑保持不变; - 检测、分割等需要局部信息的任务:CLS 位置没有空间含义,应改用 patch 特征序列(即丢弃第 0 位)接入下游模块;
- 做消融实验:可把
x[:, 0]换成x[:, 1:].mean(dim=1)即 GAP,对比两者在自己数据集上的表现,这是很常见的对照实验。
一句话总结:ViT 只取第一个位置,是因为 CLS Token 从输入阶段就被放在那里充当汇总槽位,多层自注意力把所有 patch 的全局信息蒸馏进了这个向量。至于聚合策略,它只是分类头前一个可替换的组件,按任务特点选择即可。
【免费下载链接】visionDatasets, Transforms and Models specific to Computer Vision项目地址: https://gitcode.com/gh_mirrors/vi/vision
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考