【大模型】对齐机制(下):M-RoPE 与动态分辨率,视觉 token 如何“知道“自己在哪?|多模态大模型专栏⑤

对齐机制(下):M-RoPE 与动态分辨率,视觉 token 如何"知道"自己在哪?|多模态大模型专栏⑤

一句话讲透本篇:把图像拍平成一条序列喂给 LLM,1D 位置编码会让"上下相邻"和"左右相邻"看起来差了 3 倍距离。M-RoPE 的解法极优雅:把位置编码拆成 (时间, 行, 列) 三段,文本退化、图像获益。


写在前面

第④篇(上) 我们搞定了 Projector:视觉特征(N, d_v)被翻译成(N, d_h),塞进 LLM 文本流。但还差最后一块拼图——位置

文本 token 用 1D-RoPE 就够了,因为文本天然是一维序列。但图像 patch 是二维网格:第 0 号 patch 和第 1 号 patch 是左右相邻,第 0 号和第 3 号(下一行第一个)是上下相邻——几何上它们等距,但拍平后 1D 序号差分别是 1 和 3

这就是本篇要解决的两个问题:

  1. M-RoPE:怎么让位置编码感知 2D(甚至 3D 视频)结构?(Qwen2-VL 的核心创新)
  2. 动态分辨率:固定 336×336 输入做不好文档,怎么处理任意大小的高分辨率图?

阅读本篇后可获得:

  • ✅ 讲清 M-RoPE 的 (t, h, w) 三段设计,理解它为什么在文本上严格等于 1D-RoPE
  • ✅ 用真实数值证明"1D-RoPE 拍平图像会破坏邻接",知道 M-RoPE 怎么修复
  • ✅ 区分两种动态分辨率方案:AnyRes Tile(LLaVA-NeXT)vs Native Resolution + Bucket(Qwen2-VL)
  • ✅ 跑通一份零依赖的 4 段 demo,亲手验证上述每一条结论

一、RoPE 30 秒回顾(NLP 工程师可直接跳到第二节)

RoPE(旋转位置编码)对每一对相邻维度(q_{2k}, q_{2k+1})做旋转,角度由位置pos和频率θ_i决定:

angle i = pos ⋅ θ i , θ i = base − 2 i / d \text{angle}_i = \text{pos} \cdot \theta_i, \qquad \theta_i = \text{base}^{-2i/d}anglei=posθi,θi=base2i/d

  • pos是 token 在序列里的位置(0, 1, 2, …)
  • θ_i是第 i 个维度对的频率,i 越大频率越高(转得越快)
  • 两个 token 在第 i 对上"对齐"的好坏,取决于它们的(pos_a - pos_b)·θ_i

关键直觉:1D-RoPE 里,pos是一个标量(序列下标)。M-RoPE 唯一的改动,就是把这个标量换成三个标量,分别驱动不同子空间。仅此而已。


二、M-RoPE:(t, h, w) 三段拆分

Qwen2-VL 把d/2个维度对平均切成三段,每段用一个独立的位置标量驱动:

head_dim d 的 d/2 个旋转对

时段 T
前 1/3 对
由 temporal 驱动

行段 H
中 1/3 对
由 height 驱动

列段 W
后 1/3 对
由 width 驱动

temporal_idx
视频帧号

height_idx
patch 行号

width_idx
patch 列号

  • 文本 token:设(t, h, w) = (p, p, p)(p 是序列下标),三段用同一个数 → M-RoPE 退化为 1D-RoPE
  • 图像 token(t, h, w) = (帧, 行, 列),h/w 按 2D 网格赋值
  • 视频 token:t 随帧变化

这就是全部设计。下面用 4 段 demo 的真实数值验证它(code/02_alignment/04_mrope_numpy.py,零依赖可跑)。


三、Demo 验证:四步看懂 M-RoPE

Demo 1:1D-RoPE 的角度长什么样(基线)

d=8(4 个旋转对)的小配置上,6 个 token 的 1D-RoPE 角度:

Tokens: [BOS] The cat sat on mat pos=0 | 0.0000 0.0000 0.0000 0.0000 pos=1 | 1.0000 0.1000 0.0100 0.0010 pos=2 | 2.0000 0.2000 0.0200 0.0020 pos=3 | 3.0000 0.3000 0.0300 0.0030

读法:pos=0全零(不旋转);pos越大每对转得越快;pair0(最低频)转最慢,最后一个对转最快。这就是 RoPE 相对位置泛化的来源。记住这 4 个角度随 pos 线性增长的形态,下一步对比要用。

Demo 2:M-RoPE 在 3×3 图像网格上的角度

把图像排成 3×3 patch 网格(单帧 t=0),每个 patch 拿(t=0, h, w)

patch | pair0 (T) pair1 (H) pair2 (W) (h=0,w=0) | 0.0000 0.0000 0.0000 (h=0,w=1) | 0.0000 0.0000 0.0100 (h=0,w=2) | 0.0000 0.0000 0.0200 (h=1,w=0) | 0.0000 0.1000 0.0000 (h=1,w=1) | 0.0000 0.1000 0.0100 (h=2,w=2) | 0.0000 0.2000 0.0200

关键洞察:同一行(如(0,0)(0,1)(0,2))的 H 段角度全相同(都是 0.0000),只有 W 段在变。这意味着同一行的 patch 在 H 子空间里"看起来一样",互相 attend 时不受列差异干扰——这就是 2D 邻接被编码进去的方式。1D-RoPE 在拍平序列上做不到这点。

Demo 3:退化证明(最关键的性质)

文本 token 设(t,h,w)=(p,p,p),对比两种算法的 pair0 角度:

pos | 1D-RoPE pair0 M-RoPE pair0 | match 0 | 0.000000 0.000000 | OK 1 | 1.000000 1.000000 | OK 2 | 2.000000 2.000000 | OK 3 | 3.000000 3.000000 | OK 4 | 4.000000 4.000000 | OK All pairs match across all positions: True

全部精确匹配。这就是 M-RoPE 最巧妙的地方:它是 1D-RoPE 的严格推广(strict generalization)。文本 token 行为和之前一模一样,零回归代价;图像/视频 token 才获得额外的 2D/3D 结构。

💡 这个性质为什么重要:它意味着把一个纯文本 LLM 换成 M-RoPE,不会损失任何语言能力。Qwen2-VL 敢直接复用 Qwen2 的预训练权重,底气就在这里。

Demo 4:1D-RoPE 拍平图像为什么是错的(核心证据)

把 3×3 图像按 row-major 拍平(flat index 0…8),看四对邻居的位置差:

pair | 1D Δ | T Δ H Δ W Δ same row (horiz) | 1.0000 | 0.0000 0.0000 0.0100 same col (vert) | 3.0000 | 0.0000 0.1000 0.0000 diagonal | 2.0000 | 0.0000 0.1000 0.0100 far, diff row/col | 1.0000 | 0.0000 0.1000 0.0200

这张表是本篇的灵魂,逐行读:

邻居关系几何真相1D-RoPE 看到的距离问题
同行(左右相邻)距离 1Δ = 1.0✓ 正确
同列(上下相邻)距离 1Δ = 3.0几何等距,却被看成 3 倍远
对角线距离 √2Δ = 2.0偏差

1D-RoPE 把"上下相邻"误判成"3 倍远"——因为拍平后,下一行的同列 patch 序号差是行宽 3。这就是为什么纯文本 LLM 直接看图像效果差:位置先验是错的。

M-RoPE 怎么修复?看右边三列:

  • 同行邻居:H Δ = 0(行坐标相同)+W Δ = 0.01(列差 1)→ 正确反映"水平相邻"
  • 同列邻居:W Δ = 0(列坐标相同)+H Δ = 0.1(行差 1)→ 正确反映"垂直相邻"
  • 不再用单一标量把 2D 压扁,而是 per-axis 各自保留坐标

M-RoPE 三段

同行: HΔ=0, WΔ≠0
同列: WΔ=0, HΔ≠0

2D 邻接 per-axis 保留
✅ 文本零回归

1D-RoPE 拍平图像

同行 Δ=1
同列 Δ=3

几何等距 → 看成 3× 远
❌ 位置先验错误


四、动态分辨率:高分辨率图怎么处理?

M-RoPE 解决了"位置",但还有个前置问题:输入分辨率

固定 336×336 输入(LLaVA-1.5)会把所有图 resize 成同一个大小——文档里的小字 resize 后糊掉,OCR 必然崩。于是演化出两种动态分辨率方案。

方案 1:AnyRes Tile(LLaVA-NeXT / OneVision)

思路:把大图切成多个固定大小的 tile

原图(任意 H×W) → 选最近的长宽比(6:1, 3:1, 4:3 … 共 9 档) → 切成 K 个 336×336 的 tile → 额外加 1 个缩略图 tile(原图缩到 336×336,提供全局上下文) → 每个 tile 过 ViT 得 576 token → 总共 (K+1) × 576 个视觉 token

一张 2:1 的长文档图 → K=2 个 tile + 1 缩略图 =3 × 576 = 1728个视觉 token。

  • 优点:细节(每个 tile)+ 全局(缩略图)都有,OCR 大幅提升
  • 缺点:高分辨率图能产生 2880+ token,显存压力大;tile 间的空间关系靠缩略图隐式补

方案 2:Native Dynamic Resolution + Bucket(Qwen2-VL / InternVL2.5)

思路:不切 tile,直接让 patch 数随图像大小变化

  • 输入(H, W)→ patch 数N_v = (H/14) × (W/14),动态变化
  • 不再用固定 336,小图几十个 token、大图几千个 token

问题来了:变长序列怎么组 batch?Qwen2-VL 用bucket 分桶

Step 1: 按 patch 数划分 K 个 bucket bucket_0: [0, 256] ← 小图(图标) bucket_1: [256, 576] ← 中图(照片) bucket_2: [576, 1024] ← 大图(文档) bucket_3: [1024, 2304] ← 高分图(票据) bucket_4: [2304, +∞) ← 超高分 Step 2: 每 batch 只从一个 bucket 取样 → batch 内 patch 数接近 → padding 浪费 < 30% Step 3: 不同 bucket 按比例采样(如 1:4:4:2:1),防止只学小图

为什么不直接 pad 到全局最大?全局最大可能 2304 token,小图 pad 到 2304 浪费 90% 算力,且 pad token 干扰注意力。Bucket 把浪费控制在桶内。注意:bucket 是训练专用优化,推理单张图不需要。

两种方案对比

维度AnyRes Tile(LLaVA-NeXT)Native Resolution(Qwen2-VL)
处理方式切固定块 + 缩略图直接变 patch 数
视觉 token(K+1) × 576,离散档位连续变化,任意 N_v
跨区域空间关系缩略图隐式补M-RoPE 显式编码
batch 处理tile 数固定,易组 batch需 bucket 分桶
优雅度工程化、务实更统一、更彻底

趋势:Native Resolution + M-RoPE 是更晚、更彻底的方案,Qwen2-VL 之后逐渐成主流;AnyRes 因实现简单,仍是很多框架的默认选项。


五、5 个关键

  1. 1D-RoPE 拍平图像是错的:上下相邻和左右相邻几何等距,却被看成差 3 倍——这是纯文本 LLM 看图效果差的根因之一。
  2. M-RoPE 的改动极小:只是把 1 个位置标量换成 (t, h, w) 三个,分别驱动 head_dim 的三段子空间。
  3. M-RoPE 是 1D-RoPE 的严格推广:文本设(p,p,p)就精确退化,零回归代价——这是它能直接复用预训练 LLM 的底气。
  4. 2D 邻接靠 per-axis 保留:同行 H 坐标相同、同列 W 坐标相同,而不是压成一个标量。
  5. 动态分辨率两条路线:Tile(切块 + 缩略图,工程务实)vs Native(变 patch 数 + bucket,更彻底)。配合 M-RoPE,Native 方案更统一。

📎 本篇涉及代码

文件说明
code/02_alignment/04_mrope_numpy.pyM-RoPE vs 1D-RoPE 对比(4 段 demo,含退化证明与邻接破坏分析)

动态分辨率(AnyRes / Native + Bucket)目前以docs/02_alignment.md文档形式说明,暂无独立 demo。


小结

概念一句话
1D-RoPE 的问题拍平图像后,上下相邻 = 3× 左右相邻的距离
M-RoPE(t, h, w) 三段,文本退化、图像获益
退化性质文本 (p,p,p) → M-RoPE 严格等于 1D-RoPE
AnyRes Tile切 K 个固定 tile + 1 缩略图(LLaVA-NeXT)
Native Resolution变 patch 数 + bucket 分桶训练(Qwen2-VL)

至此,阶段 2 对齐机制全部讲完——已覆盖 Projector 设计、token layout、M-RoPE、动态分辨率,足以拆解任意现代 VLM 的架构。下一篇进入阶段 3:训练 Pipeline——多阶段训练配方、显存预算、文档 SFT 数据构造,将真正动手训练一个文档领域的 VLM。

专栏:《从 NLP 到 VLM:多模态大模型研发实战》
上一篇:④ 对齐机制(上)· Projector | 本篇:⑤ 对齐机制(下)· M-RoPE 与动态分辨率 | 下一篇:⑥ 训练 Pipeline · LoRA SFT