ViT 与 VLM 中视觉 Token 的关系学习笔记

一、核心结论

可以先记住最重要的一句话:

普通 ViT 和 VLM 中使用的 ViT,本质上的视觉编码过程非常相似。

主要区别在于:

普通 ViT 做分类时,通常只取 CLS Token 作为整张图片的全局特征。

VLM 通常保留大量 Patch Token,将这些视觉 Token 经过 Projector 后送入 LLM。

可以简单表示为:

普通 ViT 分类:

Image

-> ViT

-> B, N+1, D_vision

-> 取 CLS

-> B, D_vision

-> 分类器

VLM:

Image

-> ViT / CLIP-ViT

-> B, N+1, D_vision

-> 去掉 CLS,保留 Patch Token

-> B, N, D_vision

-> Projector

-> B, N, D_llm

-> LLM


二、ViT 为什么会产生很多 Token

ViT 不直接把整张图片作为一个整体处理,而是先将图片切成 Patch。

假设:

图片大小 = 224 × 224

Patch Size = 16 × 16

那么:

每边 Patch 数量 = 224 / 16 = 14

总 Patch 数量:

N = 14 × 14 = 196

因此一张图片会被转换成:

196 个 Patch

每个 Patch 进一步转换成一个视觉 Token。

所以:

Image

-> 196 个 Patch

-> 196 个 Patch Token


三、CLS Token 是什么

传统 ViT 通常还会额外加入一个可学习的 CLS Token。

因此:

196 个 Patch Token

再加:

1 个 CLS Token

最终进入 Transformer 的 Token 数量:

196 + 1 = 197

所以 ViT 内部常见的特征 Shape 是:

B, 197, D

其中:

B = Batch Size

197 = 1 个 CLS Token + 196 个 Patch Token

D = ViT Hidden Dimension

例如 ViT-B/16:

B, 197, 768


四、B, 197, 768 每个维度是什么意思

假设:

x.shape = B, 197, 768

第一个维度 B:

表示一个 Batch 中有多少张图片。

例如:

B = 8

表示一次输入 8 张图片。

第二个维度 197:

表示视觉 Token 数量。

其中:

Token 0 = CLS Token

Token 1 ~ Token 196 = Patch Token

第三个维度 768:

表示每一个视觉 Token 的特征维度。

因此可以理解为:

一张图片被表示成 197 个 Token。

每个 Token 是一个 768 维向量。


五、普通 ViT 为什么只取 CLS Token

假设 ViT 输出:

B, 197, 768

分类任务通常只需要回答:

这张图片属于什么类别?

例如:

汽车

飞机

因此没有必要把 196 个 Patch Token 全部送入分类头。

通常直接取:

x:, 0, :

也就是第 0 个 Token:

CLS Token

Shape 从:

B, 197, 768

变成:

B, 768

然后:

B, 768

-> Linear Classifier

-> B, num_classes

例如:

B, 768

-> Linear

-> B, 1000

就可以完成 ImageNet 1000 类分类。


六、CLS Token 为什么可以代表整张图片

CLS Token 刚开始只是一个可学习参数。

一开始它本身并不包含图片内容。

但是进入 Transformer 后:

CLS Token

会和:

Patch 1

Patch 2

Patch 3

...

Patch 196

通过 Self-Attention 不断进行信息交换。

经过多层 Transformer 后:

CLS Token 会融合整张图片的信息。

因此可以把最终 CLS Token 理解为:

整张图片的全局摘要向量。

例如:

CLS Feature = 0.12, -0.28, 0.76, ..., 0.15

这个向量可能包含:

图片大概是什么场景

主要物体是什么

整体语义是什么

因此很适合用于:

图像分类

全局图像表示

图文相似度


七、为什么 VLM 不只使用 CLS Token

VLM 面临的任务比普通分类复杂得多。

例如用户可能问:

图片左下角的人手里拿着什么?

图片中的第三辆车是什么颜色?

右上角有什么物体?

图片上的文字写了什么?

这些问题需要大量局部细节。

如果只把整张图片压缩成一个 CLS Token:

Image

-> ViT

-> CLS

-> LLM

相当于:

整张图片的大量信息

被压缩成一个向量。

这样很容易损失:

局部位置

小目标

细粒度纹理

文字

空间关系

多个物体之间的关系

因此 VLM 通常会保留大量 Patch Token。


八、VLM 中的 ViT 输出

假设视觉编码器输出:

B, 197, 1024

其中:

第 0 个 Token:

CLS Token

Shape:

B, 1, 1024

剩下 196 个:

Patch Token

Shape:

B, 196, 1024

很多 VLM 会执行类似:

x = x:, 1:, :

也就是删除 CLS。

最终得到:

B, 196, 1024

这就是常说的:

视觉 Token。


九、为什么是 B, 196, 1024

这里的三个维度分别表示:

B:

Batch Size

196:

视觉 Patch Token 数量

1024:

Vision Encoder 的 Hidden Dimension

例如:

B, 196, 1024

意味着:

每张图片由 196 个视觉 Token 表示。

每个视觉 Token 是一个 1024 维向量。

可以直观理解为:

Image

-> 196 个区域

-> 每个区域得到一个 1024 维视觉表示


十、Patch Token 是否只包含局部信息

不是。

这一点很重要。

刚进入 ViT 时:

Patch 1 主要对应图片的某个局部区域。

Patch 2 对应另一个局部区域。

但是经过多层 Self-Attention 后:

Patch 1 可以关注 Patch 2、Patch 3、...、Patch N。

所以最终的 Patch Token 不只是:

"这个局部区域有什么"

还包含:

这个区域和其他区域是什么关系

周围的上下文是什么

整张图的部分全局信息

因此更准确地说:

Patch Token 是以局部空间位置为锚点,同时融合全局上下文的视觉表示。


十一、为什么 VLM 要保留 Patch Token

假设图片中:

左上角 = 天空

右上角 = 篮球框

中央 = 球员

右下角 = 篮球

ViT 经过编码后,某些 Token 可能主要对应这些区域。

虽然实际一个 Patch 不一定严格对应一个完整物体,但可以帮助理解为:

Visual Token 1 -> 左上区域信息

Visual Token 30 -> 篮球框相关信息

Visual Token 100 -> 球员相关信息

Visual Token 180 -> 篮球相关信息

如果用户问:

"右下角是什么?"

LLM 可以通过 Attention 更关注右下角对应的一些 Visual Tokens。

如果只有一个 CLS:

CLS = 整张图片全局摘要

就更难保留这种细粒度空间信息。


十二、普通 ViT 与 VLM 最核心区别

普通 ViT 分类:

ViT 输出:

B, 197, 768

然后:

只取:

B, 768

也就是 CLS Token。

最终:

CLS

-> Classifier

-> 分类结果

VLM:

ViT 输出:

B, 197, 1024

然后:

去掉 CLS

得到:

B, 196, 1024

保留全部或大部分 Patch Token。

再把它们送给语言模型。


十三、为什么还需要 Projector

Vision Encoder 与 LLM 的 Hidden Dimension 往往不同。

例如:

ViT Hidden Dimension:

1024

LLM Hidden Dimension:

4096

那么:

B, 196, 1024

不能直接当成 LLM 的 Token Embedding。

因为 LLM 希望每个 Token 都是:

4096 维。

因此需要一个 Projector:

B, 196, 1024

-> Projector

-> B, 196, 4096

Projector 的作用就是:

将视觉特征空间映射到 LLM 的特征空间。


十四、Projector 可以是什么结构

最简单可以是一层 Linear:

1024 -> 4096

也可以使用 MLP:

1024

-> Linear

-> 中间维度

-> 激活函数

-> Linear

-> 4096

例如:

Visual Feature

1024 维

-> Linear

4096 维

或者:

1024

-> 4096

-> GELU

-> 4096

最终得到与 LLM Hidden Dimension 相同的视觉 Token。


十五、Projector 前后 Shape

假设:

Vision Encoder 输出:

B, 196, 1024

Projector:

1024 -> 4096

那么:

Projector 前:

B, 196, 1024

Projector 后:

B, 196, 4096

需要注意:

通常 Projector 只改变最后一个 Hidden Dimension。

不会自动改变 Token 数量。

因此:

196 一般保持不变。


十六、视觉 Token 如何进入 LLM

假设视觉部分:

B, 196, 4096

用户输入:

"图片里面有什么?"

Tokenizer 之后假设有 T 个文本 Token。

经过 LLM Embedding:

B, T, 4096

因为现在两边最后一维都是:

4096

所以可以组合成同一个 Token 序列。

例如:

Visual Tokens:

B, 196, 4096

Text Tokens:

B, T, 4096

组合后:

B, 196 + T, 4096

然后整体送入 LLM Transformer。


十七、一个简单完整例子

假设:

输入图片大小:

224 × 224

Patch Size:

16

Vision Encoder Hidden Dimension:

1024

LLM Hidden Dimension:

4096

第一步:Patchify

224 / 16 = 14

14 × 14 = 196

得到:

196 个 Patch

第二步:加 CLS

Token 数:

196 + 1 = 197

第三步:ViT 编码

ViT 输出:

B, 197, 1024

第四步:删除 CLS

得到:

B, 196, 1024

第五步:Projector

1024 -> 4096

得到:

B, 196, 4096

第六步:文本 Token

假设问题经过 Tokenizer 后有 10 个 Token。

文本 Embedding:

B, 10, 4096

第七步:组合

视觉:

B, 196, 4096

文本:

B, 10, 4096

最终:

B, 206, 4096

送入 LLM。


十八、196 并不是固定的

不能把 VLM 固定理解成:

B, 196, 1024

更通用的表示应该是:

B, N, D_vision

其中:

N = 视觉 Token 数量

D_vision = Vision Encoder Hidden Dimension

视觉 Token 数量 N 和以下因素有关:

输入图片分辨率

Patch Size

是否使用 CLS

是否使用特殊 Token

是否进行 Token Pooling

是否进行 Token Merge

是否使用 Resampler


十九、视觉 Token 数量如何计算

如果图片尺寸是:

H × W

Patch Size:

P × P

假设 H 和 W 都能被 P 整除。

那么 Patch 数量:

N = (H / P) × (W / P)

例如:

224 × 224 图片

Patch = 16

那么:

N = 14 × 14 = 196

如果图片:

336 × 336

Patch = 14

那么:

336 / 14 = 24

N = 24 × 24 = 576

所以视觉 Token 可能变成:

B, 576, D_vision

而不是:

B, 196, D_vision


二十、为什么视觉 Token 太多会导致 VLM 很慢

Visual Tokens 最终会作为 LLM 上下文的一部分。

例如:

文本只有:

100 Tokens

图片却产生:

576 Visual Tokens

那么 LLM 实际输入序列可能变成:

676 Tokens

如果两张图片:

2 × 576 = 1152 Visual Tokens

再加 100 个文本 Token:

1252 Tokens

因此视觉 Token 数量会直接影响:

LLM Prefill 时间

Attention 计算量

显存占用

KV Cache

端侧推理速度


二十一、为什么很多 VLM 要压缩视觉 Token

假设原始 ViT 输出:

B, 576, 1024

如果全部送入 LLM,成本比较高。

于是可以使用:

Token Merge

Pooling

Resampler

Q-Former

Token Compression

将:

576 个 Visual Tokens

压缩为:

256

128

64

甚至更少的 Token。

例如:

B, 576, 1024

-> Resampler

-> B, 64, 1024

-> Projector

-> B, 64, 4096

-> LLM

目标是:

尽量保留视觉信息

同时减少 LLM 输入长度。


二十二、CLS Token 与 Patch Token 的区别

CLS Token:

主要用于汇总整张图片的全局信息。

典型 Shape:

B, 1, D

适合:

图像分类

全局语义表示

图文整体匹配

Patch Token:

保留更多空间和局部信息。

典型 Shape:

B, N, D

适合:

VLM

视觉问答

细粒度图片理解

OCR

目标关系理解

空间推理


二十三、普通 ViT 和 VLM 的 Shape 对比

以一个假设模型为例。

普通 ViT:

输入:

B, 3, 224, 224

Patchify:

196 Patch

加入 CLS:

197 Tokens

ViT 输出:

B, 197, 768

分类:

取 CLS:

B, 768

分类头:

B, num_classes


VLM:

输入:

B, 3, 224, 224

Patchify:

196 Patch

加入 CLS:

197 Tokens

Vision Encoder 输出:

B, 197, 1024

删除 CLS:

B, 196, 1024

Projector:

B, 196, 4096

与文字 Token 拼接:

B, 196 + T, 4096

送入 LLM。


二十四、最容易出现的误区

误区 1

"普通 ViT 输出就是 B, 768。"

不准确。

ViT Transformer 内部通常仍然会产生:

B, N+1, D

只是在分类时只拿 CLS:

B, D


误区 2

"VLM 的 ViT 天生输出 B, 196, 1024。"

不准确。

更可能是:

ViT 原始输出:

B, 197, 1024

然后:

去掉 CLS

得到:

B, 196, 1024


误区 3

"视觉 Token 就等于图片分类结果。"

不是。

视觉 Token 是视觉特征。

例如:

B, 196, 1024

仍然只是连续特征向量。

它不是:

汽车

这样的类别编号。


误区 4

"Projector 负责理解图片。"

不完全正确。

真正主要负责提取视觉信息的是:

Vision Encoder / ViT。

Projector 更主要负责:

特征空间转换和视觉---语言接口连接。


误区 5

"一个 Patch Token 只包含一个小区域。"

不完全正确。

Patch Token 最开始来自一个局部区域。

但经过多层 Self-Attention 后,会融合其他 Patch 的上下文信息。

所以最终 Patch Token 同时具有:

局部空间信息

一定程度的全局上下文。


二十五、最通用的 VLM Shape 写法

不要死记:

B, 196, 1024

更推荐记住:

Vision Encoder 输出:

B, N, D_vision

Projector 后:

B, N, D_llm

文本 Token:

B, T, D_llm

组合后:

B, N + T, D_llm

其中:

B = Batch Size

N = Visual Token Number

T = Text Token Number

D_vision = Vision Encoder Hidden Dimension

D_llm = LLM Hidden Dimension


二十六、最核心的理解

普通 ViT:

把图片转换成很多视觉 Token。

但分类任务通常只使用 CLS Token:

B, N+1, D

->

B, D

VLM:

为了保留更多局部视觉信息,通常使用大量 Patch Token:

B, N, D_vision

然后通过 Projector:

B, N, D_llm

再作为 LLM 的输入 Token。

因此一句话总结:

ViT 负责把图片变成视觉 Token;

普通分类只取其中的全局 CLS;

VLM 则通常保留大量 Patch Token,让 LLM 能够看到更加完整和细粒度的视觉信息。

相关推荐
cxr8281 小时前
D2E 深度剖析 时序工具链
人工智能·架构
陆枫Larry1 小时前
从 Agent = Model + Harness 说起:重新看看 Cursor、Claude Code 和 Codex区别
人工智能
问天_观心1 小时前
虚拟环境WSL之Ubuntu的安装
人工智能·ubuntu
狂奔蜗牛(bradley)1 小时前
搭建RKNN Toolkit2开发环境
人工智能
jikemaoshiyanshi1 小时前
企业内部 AI 使用分散时,哪些云上 AI 平台适合统一模型访问、成本追踪和安全治理?——AWS 统一模型网关方案更适合作为治理起点
人工智能
a1122998211 小时前
团体标准 T/CGCC 119-2026 正式实施:如何利用合规框架重构企业的 AI 可见性考核标准?
人工智能·重构
欧特克_Glodon1 小时前
OpenCV计算机视觉开发入门与实践<七>:OpenCV 界面编程之窗口
c++·人工智能·opencv·计算机视觉
樊小肆1 小时前
DeepSeeker-Code源码导读01-agentNudges
人工智能·agent
Anhty1 小时前
2026 实测 4 款 AI 变声器|QQ 聊天伪装声线,告别僵硬假声
人工智能·功能测试·ios·智能手机·安卓