跳转到内容
English

Qwen3-VL:从图像 patch 到 DeepStack

交互教程

追踪一张图像经过视觉编码器、空间 merger 和三次残差特征注入。

前置阅读:多模态模型中的视觉 tokenizer 总览 · RoPE-ViT

预训练视觉编码器可为每个 patch 返回一个连续特征;语言模型需要自身隐藏宽度的向量,以及可处理的序列长度。Merger 负责这些接口差异。它不是图像解码器,也不选择离散图像词表项。

报告从 SigLIP-2 checkpoints 出发继续动态分辨率训练。默认使用 SO-400M 系列,小型 2B/4B 语言模型使用 SigLIP2-Large。把结果叫作未变动的冻结 SigLIP-2,会漏掉这段继续训练。

阅读顺序从左到右。点击模块,将它与计算和代码对应。代码为教学伪代码;来源链接提供论文方法或已核查的实现。

像素变成动态空间网格

8B checkpoint 使用 27 层、宽 1152 的视觉编码器,空间 patch 边长 16、时间 patch 大小 2、空间合并边长 2。图像 processor 在像素面积限制下,把两边调整成 32 的倍数。单图通过重复输入帧满足时间 patch 接口,并未增加新的观测。

pixels, grid_thw = image_processor(image)
z = patch_embed_3d(pixels)
z = z + interpolated_absolute_positions
z = vision_blocks(z, spatial_rotary_positions)

训练状态:静态实现审计;训练状态见下文。

Xtube∈RN×(2⋅16⋅16⋅3)⟶Z∈RN×1152X_{\rm tube}\in\mathbb R^{N\times(2\cdot16\cdot16\cdot3)}\longrightarrow Z\in\mathbb R^{N\times1152}

逐步讲解:像素变成动态空间网格

四个空间向量变成一个语言宽度向量

对主 merger,先归一化视觉向量,再拼接每个空间 2×2 分组,经两层 MLP 返回 LLM 宽度。已调整的 512×512 像素对应 1024 个编码器位置,合并成 256 个向量;每个向量先为 4×1152=4608 维,再投影到 8B 的 4096 维。

group = spatially_group(norm(z), side=2)
merged = fc2(gelu(fc1(group)))
inputs_embeds[image_mask] = merged

训练状态:静态实现审计;训练状态见下文。

vg=W2 GELU⁡ ⁣(W1concat⁡i∈gLN⁡(zi)+b1)+b2v_g=W_2\,\operatorname{GELU}\!\left(W_1\operatorname{concat}_{i\in g}\operatorname{LN}(z_i)+b_1\right)+b_2

逐步讲解:四个空间向量变成一个语言宽度向量

DeepStack 加特征,不追加位置

8B 视觉 block 索引 [8,16,24] 从零开始。专用 merger 把这些中间特征映射为 LLM 宽度向量;前三个语言 block 各自结束后,在视觉位置加入一组特征,文字位置不接受这次直接加法。

h = llm_block[layer](h)
if layer < len(deepstack_features):
    h[visual_mask] += deepstack_features[layer]

训练状态:静态实现审计;训练状态见下文。

HIℓ+1←HIℓ+1+Mℓ(Zkℓ),ℓ∈{0,1,2}H^{\ell+1}_{\mathcal I}\leftarrow H^{\ell+1}_{\mathcal I}+M_\ell(Z^{k_\ell}),\qquad \ell\in\{0,1,2\}

逐步讲解:DeepStack 加特征,不追加位置

查看固定版本来源

Nvisual=H′W′322N_{\rm visual}=\frac{H^\prime W^\prime}{32^2}
主路径将动态图像或视频网格转为连续的语言宽度 embeddings。
教学重绘 · 像素变成动态空间网格 每条有名称的路径从左向右阅读。不同行表示独立路径或比较方案。 · 方法来源点击图片查看全尺寸。

8B checkpoint 使用 27 层、宽 1152 的视觉编码器,空间 patch 边长 16、时间 patch 大小 2、空间合并边长 2。图像 processor 在像素面积限制下,把两边调整成 32 的倍数。单图通过重复输入帧满足时间 patch 接口,并未增加新的观测。

可学习 Conv3d 把每个 2×16×16 RGB 块映射为视觉向量。插值绝对位置嵌入与视觉二维旋转嵌入提供空间结构;语言主干另用 interleaved MRoPE。它们属于不同阶段的位置机制。

Xtube∈RN×(2⋅16⋅16⋅3)⟶Z∈RN×1152X_{\rm tube}\in\mathbb R^{N\times(2\cdot16\cdot16\cdot3)}\longrightarrow Z\in\mathbb R^{N\times1152}
pixels, grid_thw = image_processor(image)
z = patch_embed_3d(pixels)
z = z + interpolated_absolute_positions
z = vision_blocks(z, spatial_rotary_positions)
8B 使用零基视觉层 8、16、24,经独立 merger 后在前三个 LLM block 之后进行残差加法。
教学重绘 · DeepStack 加特征,不追加位置 每条有名称的路径从左向右阅读。不同行表示独立路径或比较方案。 · 方法来源点击图片查看全尺寸。

8B 视觉 block 索引 [8,16,24] 从零开始。专用 merger 把这些中间特征映射为 LLM 宽度向量;前三个语言 block 各自结束后,在视觉位置加入一组特征,文字位置不接受这次直接加法。

这是残差特征注入,不是对独立图像记忆做 cross-attention。最终合并特征已经提供初始视觉 embeddings,后续再加三组特征,不会把图像序列长度乘四。2B 改选 [5,11,17],所以层索引必须读取对应配置。

I
视觉 embeddings 所占据的位置。
M
中间视觉层对应的专用 merger。
HIℓ+1←HIℓ+1+Mℓ(Zkℓ),ℓ∈{0,1,2}H^{\ell+1}_{\mathcal I}\leftarrow H^{\ell+1}_{\mathcal I}+M_\ell(Z^{k_\ell}),\qquad \ell\in\{0,1,2\}
h = llm_block[layer](h)
if layer < len(deepstack_features):
    h[visual_mask] += deepstack_features[layer]

四个空间向量变成一个语言宽度向量

Section titled “四个空间向量变成一个语言宽度向量”

对主 merger,先归一化视觉向量,再拼接每个空间 2×2 分组,经两层 MLP 返回 LLM 宽度。已调整的 512×512 像素对应 1024 个编码器位置,合并成 256 个向量;每个向量先为 4×1152=4608 维,再投影到 8B 的 4096 维。

Processor 会安排 patch 顺序,使相邻位置正确成组。直接 reshape 任意 raster 序列可能组合错误位置。该操作是可学习特征压缩,不是平均池化,也不是最近码字选择。

vg=W2 GELU⁡ ⁣(W1concat⁡i∈gLN⁡(zi)+b1)+b2v_g=W_2\,\operatorname{GELU}\!\left(W_1\operatorname{concat}_{i\in g}\operatorname{LN}(z_i)+b_1\right)+b_2
group = spatially_group(norm(z), side=2)
merged = fc2(gelu(fc1(group)))
inputs_embeds[image_mask] = merged

从像素尺寸追踪到视觉 token

形状计算,不运行模型。图像模式复现固定版本的尺寸取整规则;Qwen 的预算在此指定为最大视觉 token 对应的像素面积,不是服务商计费值。

阶段/计算项结果
调整后高度512
调整后宽度512
时间组数1
补齐/复制帧数1
模型 patch 网格行数32
模型 patch 网格列数32
预处理空间单位 × 时间组1024
模型 patch 位置数1024
有效视觉 token256
LLM 视觉特征形状[256, 4096]
连续标量数1048576

2×16×16 patches → ViT → 2×2 concat + MLP → LLM

27 vision blocks · width 1152 → 4096

输入:视觉 embedding 写入图像位置,文字 embedding 保留。

当前型号的固定配置

有效 token 不包括 padding 槽、图片边界、换行、时间戳文字或其他文本。视频模式不执行抽帧和视频预算分配:输入边长必须是 Qwen 的 32 或 Gemma 的 48 的倍数。单图的帧复制是时空 patch 接口操作,不意味着有运动信息。

已核对的具体配置

核对日期:2026-11-03. 每行链接到固定版本。参数相同不表示权重相同;12B 的 patch 列表示模型接收的像素块。

型号模型 patch视觉层/宽空间操作LLM 宽DeepStack 零基层
Qwen3-VL-2B-Instruct16×1624 / 10242×2 concat + MLP20485, 11, 17
Qwen3-VL-8B-Instruct16×1627 / 11522×2 concat + MLP40968, 16, 24
Qwen3-VL-235B-A22B-Instruct16×1627 / 11522×2 concat + MLP40968, 16, 24

“—”表示本轮检查的路径没有 DeepStack 注入,不表示没有视觉信息。所有分支传递连续向量;本表没有把文字词表大小当作视觉码本。

报告描述先仅更新 merger 的对齐阶段,再进行全部参数的更长上下文预训练。DeepStack 消融采用内部 15B-A2B 模型、200B tokens、无后训练;平均分 74.7→76.0,DocVQA 89.5→91.1。这些不是公开 8B checkpoint 的分数。

视频还涉及抽帧、空间调整、时间分组和文字时间戳。计算器从已采样、已调整尺寸的视频帧开始。三帧输入时间大小为二的编码器时,重复最后一帧得到两个时间组;时间戳文字成本不计入该数。

这些连续特征服务于文字生成与视觉推理,已审计路径没有像素解码器或 VQ 码本。用于重建时,还需选择特征层、训练解码器,并把重建与 VQA 分开评估。

报告与当前实现分别固定为两份证据,未记录的训练细节保留未知。型号选择器展示已检查的配置差异,不声称名称相近的 checkpoints 共用相同权重。

DeepStack 会让视觉上下文长度变成三倍吗?

不会。它在早期 LLM 层已有的视觉位置上相加特征。

返回学习地图

自绘图和伪代码用于教学;原论文图片单独标注来源。论文报告、固定实现观察和解析示例分别标记;未运行研究模型。