你给视觉模型一张 224×224 的图片。模型先把图切成 14×14 个小块,每个小块映射成一个向量,然后按从左到右、从上到下的顺序排成一整条 token 序列。从这一刻起,一个本来有宽有高的画面,被压成了一个只有「先后」的句子。

句子是一维的,图像是二维的。第 10 个 patch 的右边是第 11 个 patch,但它的下方是第 24 个 patch。一维位置编码能告诉模型「10 在 11 前面」,却告诉不了它「10 在 24 的上方」。文档理解更吃亏:OCR 按阅读顺序吐出一行文字,可 PDF 里的表格、多栏、印章根本不会沿着一条直线排。二维位置编码要解决的,正是这个问题——让 Transformer 记住 token 在空间中的真实坐标,而不只是它在队列里的序号。
一维位置编码原本在解决什么问题
自注意力机制有个天生缺陷:它的计算基于 token 两两之间的相似度,完全不理会顺序。「我打你」和「你打我」在没有位置信息的 Transformer 眼里,几乎是同一串词。原始 Transformer 论文的方案是用一组正弦波给每个位置算一个固定向量:
PE(pos, 2i) = sin(pos / 10000^(2i/d))
PE(pos, 2i+1) = cos(pos / 10000^(2i/d))
不同维度使用不同频率,相当于给位置 0、1、2… 各发了一个「频率指纹」。token 的向量里叠加这个指纹后,attention 才能在计算时区分先后。这个机制来自 Attention Is All You Need。
但注意,这个指纹只沿着一条轴展开,也就是序列轴。对文本来说,序列顺序几乎等于全部上下文;可一旦图像被压成序列,这个一维指纹反而会误导模型——它把「垂直相邻」也理解成了「距离很远」。
LayoutLM 的直白答案:把坐标当作索引去查表
我第一次看到 LayoutLM 的做法时愣了一下:它也太直白了。OCR 已经给出每个词在页面上的包围盒,也就是 (x0, y0, x1, y1),那直接把这些坐标当输入不就行了?
LayoutLM 论文的处理方式是:坐标归一化到 0~1000,然后为 x0、y0、x1、y1 分别建一个可学习的位置嵌入表,查出来的向量相加,得到一个「布局嵌入」,再叠加到文本 embedding 上。
x0, y0, x1, y1 = normalize_bbox(page_bbox)
layout_emb = emb_x0(x0) + emb_y0(y0) + emb_x1(x1) + emb_y1(y1)
final_emb = word_emb + seq_pos_emb + segment_emb + layout_emb
为什么这样有效?因为文档理解真正需要的不是像素级精度,而是结构邻近——同一个表格行的词,就算在阅读顺序上隔了很远,它们在二维平面上的坐标仍然相邻。这会直接改变注意力的分布:模型终于知道「该和谁放一起看」。
但这个方案有一个明显代价:坐标是离散 ID。你只是把 2D 连续空间切成了固定大小的格子,模型没见过的坐标(比如比训练集更大的页面)天然没有对应向量。换分辨率、换长宽比时,坐标要重新归一化或截断。
图像任务常用的二维正弦:把 XY 也变成波形
如果不想被离散表限制,就用连续函数。二维正弦位置编码是常见做法,它的思路简单到令人怀疑:对 x 坐标算一组一维正弦编码,对 y 坐标再算一组,然后拼起来。
pe = concat(sinusoidal_1d(x), sinusoidal_1d(y))
好处是任何实数坐标都能算,patch 数量从 196 变成 1024 也无需重新训练位置表,天然支持外推。DETR 等很多检测模型就用这种编码把归一化的框坐标喂给 Transformer。
但它也有坑:拼接之后,模型并不天然知道前一半维度是 x、后一半是 y;它需要从数据里猜出这两个轴的关系。正弦编码给的是「坐标的数值指纹」,不是「轴的几何语义」。所以你会发现,很多实现最后还是得叠加可学习参数,让模型自己调。
RoPE 扩展到二维:M-RoPE 把位置变成旋转角度
近两年大模型更常用旋转位置编码 RoPE。它不把位置加在 embedding 上,而是把 embedding 切成两两一组的二维子空间,按位置角度做旋转。这样设计有个好性质:两个 token 的点积结果只依赖它们的相对位置 m-n,而不是各自的绝对位置。
M-RoPE 是 Qwen2-VL 引入的多模态扩展,思路是:把整个 embedding 维度按比例切成多段,每一段对应一个坐标轴。于是每个 token 的位置可以同时携带多个轴的信息:
- 文本 token:位置就是它在序列里的全局序号,高度、宽度固定为 0;
- 图像 patch:位置包含 patch 在网格里的行和列;
- 视频 token:还能再加一条时间轴。
这样做最大的价值,是让同一套 Transformer 可以同时处理文字和图像的交错序列。文字仍然是纯 1D 顺序,图像则保留 2D 结构,两者在维度分组上互不打架。这也是新一代多模态大模型普遍放弃「简单 1D 位置表」的重要原因。
二维位置编码方案对比
| 方案 | 典型代表 | 本质 | 优点 | 边界 |
|---|---|---|---|---|
| 二维绝对查表 | LayoutLM | 坐标离散化后查可学习向量 | 简单,文档结构任务效果好 | 外推差,分辨率变化要重归一化 |
| 二维正弦 | DETR 等 | x、y 分别用 sin/cos 编码再拼接 | 任意分辨率可编码 | 轴语义需模型自己学 |
| 二维相对偏置 | LayoutLMv2、Swin | attention 分数中加上与 2D 相对距离相关的可学习偏置 | 直接表达「相邻」关系 | 计算对数增长,需有 bbox 或网格 |
| M-RoPE | Qwen2-VL | 维度分组,各轴独立旋转 | 1D/2D/3D 统一,多模态共用 | 轴多时每轴维度少,频率需调试 |
我踩过的坑:绝对位置表不会自动泛化
我最早以为位置编码只是给 token 加个编号,细节无所谓。后来在一项多模态任务里,我把训练时的 224×224 图像在测试时换成了 448×448,模型 loss 直接飞了。查了半天才发现,位置采用一维可学习表:14×14 的网格在测试时变成 28×28,新增的 588 个位置 ID 从未进入过训练。那一刻我才真正明白:位置编码的选择本质上是在为模型定义「空间坐标系的泛化方式」。离散表记住的是位置格子,连续函数记住的是坐标规则。
几个容易被问倒的问题
为什么不直接把图像按扫描线摊平,当 1D 序列处理?扫描线能保留局部水平关系,但断掉垂直关系。多栏 PDF 尤其明显:左栏最后一行和右栏第一行在扫描顺序上可能紧挨着,在语义上其实隔了整个版面。
二维位置编码只用于文档理解吗?只要输入有二维结构就值得考虑:图像 token、分子图、页面布局、强化学习里的网格状态。区别只是坐标怎么定义。
所以别问「哪种二维位置编码最好」,要问「我的任务空间结构是否固定」。固定版式文档,LayoutLM 式查表很稳;任意分辨率的图像和混合输入,连续正弦和 M-RoPE 更接近正确方向。位置编码本质上是一套坐标系统。选错了,模型只能靠猜;选对了,空间结构才真正成为模型的一部分。
原创文章,作者:guanweilu,如若转载,请注明出处:https://guanweilu.cn/article/1012.html