3. 相对位置编码详解

好,咱们接着聊位置编码。上一节讲了绝对位置编码,说白了就是把每个位置打上一个固定的标签。但我在实际做Transformer模型的时候,发现一个问题——绝对位置编码在处理长序列时,有点「死板」。你想想看,模型真的需要知道「第5个词」这个绝对概念吗?其实它更关心的是「这个词离我有多远」。

这就是相对位置编码的动机所在。

3.1 为什么需要相对位置编码?

我举个例子你就明白了。假设有这么两句话:

  • 「我今天去银行存钱」
  • 「我昨天去银行取钱」

对于「存」和「取」这两个词,它们和「银行」的相对距离是一样的——都是紧挨着。但绝对位置编码会把它们标记成不同的位置(位置5和位置5?不对,其实是不同句子里的不同位置)。模型需要学习的是「银行」后面这个词的语义关系,而不是它具体在第几个位置。

我个人习惯把这个问题总结为三点:

  1. 泛化能力差:训练时见过的最大长度是512,推理时来了个600的序列,绝对位置编码直接懵了
  2. 缺乏平移不变性:同样的语义关系,换个位置就要重新学
  3. 长距离依赖捕捉困难:位置越远,绝对编码的区分度反而下降

核心洞察:注意力机制本质上是在计算「词与词之间的关系」,而这个关系主要取决于它们的相对距离,而不是绝对坐标。

3.2 Shaw等人提出的方法

说到相对位置编码,最早被广泛引用的工作是Shaw et al. 2018年的论文。我记得当时读这篇论文时,第一反应是「原来可以这样玩」。

他们的思路很直接:在计算注意力分数时,把位置信息加到Query和Key的交互中。具体来说,标准注意力公式是:

Attention(Q, K, V) = softmax(QK^T / sqrt(d)) V

Shaw的做法是,在QK^T这一步里加入一个相对位置偏置项:

e_ij = (x_i W_Q)(x_j W_K + a_{ij}^K)^T / sqrt(d)

这里a_{ij}^K是一个可学习的向量,表示位置i和位置j之间的相对距离。说白了,就是给每个可能的相对距离(比如-3, -2, -1, 0, 1, 2, 3)都分配一个专属的向量。

嗯,这里要注意一个细节:相对距离是有范围的。你不能让模型去学无限多种距离,所以通常会设置一个截断窗口k。比如k=3,那就只考虑[-3, 3]这个范围内的相对位置,超出部分统一用边界值表示。

我的经验:k的取值很关键。我在做文本生成任务时试过k=16和k=64,发现k=32左右效果最好。太小了捕捉不到长距离依赖,太大了参数量暴增而且容易过拟合。

3.3 Transformer-XL中的相对位置编码

接下来要聊的是Transformer-XL,这个工作把相对位置编码推到了一个新高度。说实话,我第一次看Transformer-XL的论文时,被它的设计惊艳到了——它解决了两个痛点:长序列建模和上下文碎片问题。

Transformer-XL的核心改进有两点:

  1. 片段级循环机制:把上一个片段的隐状态缓存下来,给当前片段用
  2. 全新的相对位置编码:彻底抛弃绝对位置,全部用相对位置表示

我们重点看第二点。Transformer-XL的注意力分数计算长这样:

A_{i,j}^{rel} = (q_i^T k_j) + (q_i^T R_{i-j}) + (u^T k_j) + (v^T R_{i-j})

别被这个公式吓到,我来拆解一下:

  • 第一项 q_i^T k_j:标准的content-based attention,只看词义不看位置
  • 第二项 q_i^T R_{i-j}:query和相对位置编码的交互,告诉模型「这个词离我多远」
  • 第三项 u^T k_j:全局的key偏置,u是可学习的向量,对所有位置都一样
  • 第四项 v^T R_{i-j}:全局的位置偏置,v也是可学习的

这里R_{i-j}用的是正弦编码,但注意——它不是绝对位置的正弦编码,而是相对距离的正弦编码。也就是说,R_3表示「距离为3」的编码,不管你是从位置5到位置2,还是从位置100到位置97,R_3都是一样的。

我曾经踩过的坑:在实现Transformer-XL时,我一开始把R_{i-j}的索引搞反了。i-j和j-i的区别很大,前者表示「j相对于i的位置」,后者相反。这个符号问题让我debug了整整两天,最后发现是索引方向错了。大家实现时一定要确认清楚。

3.4 相对位置编码的SVG结构图

下面我用一张图来总结相对位置编码的核心逻辑,方便你理解整个知识体系:

相对位置编码核心逻辑 动机 • 泛化能力差 • 缺乏平移不变性 • 长距离依赖困难 Shaw et al. 方法 • 可学习相对位置向量 • 截断窗口k • 加到QK交互中 Transformer-XL • 片段循环 • 四项注意力公式 • 正弦相对编码 关键对比 绝对位置编码 位置i → 固定向量PE(i) 不同位置相同距离 → 编码不同 外推能力弱 参数量随长度线性增长 相对位置编码 距离d → 向量R(d) 相同距离 → 相同编码 外推能力强 参数量由窗口大小决定 相对位置编码:关注「距离」而非「坐标」

3.5 实际应用中的选择建议

好了,理论讲完了,我来说点实际的。你在项目中到底该选哪种?

场景 推荐方案 理由
短文本分类(长度<128) 绝对位置编码 够用,实现简单,训练快
长文本生成(长度>512) Transformer-XL相对编码 外推性好,支持超长序列
机器翻译 Shaw相对编码 窗口适中,效果稳定
代码生成/数学推理 相对编码(窗口大一些) 需要精确捕捉符号间的相对关系

一句话总结:相对位置编码的核心思想,就是让模型关注「词与词之间的距离」,而不是「词在序列中的绝对坐标」。这个思路后来被RoPE(旋转位置编码)进一步发扬光大,下一章我们会详细聊。

我个人在实际项目中,除非是特别短的序列任务,否则都会优先考虑相对位置编码。它带来的泛化能力提升,绝对值回票价。


公众号:蓝海资料掘金营,微信deep3321