基于多头注意力机制的神经机器翻译(NMT)中的位置编码(Positional Encoding)算法详解
题目描述
在基于Transformer的神经机器翻译模型中,自注意力机制能够并行处理序列中所有词之间的关系,但它本身不具备捕捉词序(顺序信息)的能力。位置编码(Positional Encoding)就是一种为输入序列中的每个词嵌入注入位置信息的算法。你的任务是理解并掌握如何通过数学公式为词向量添加位置信息,使模型能够利用序列的顺序。
解题过程
我们将循序渐进地讲解位置编码的动机、数学定义、具体实现以及其关键特性。
第一步:理解问题与动机
- 核心问题:Transformer的自注意力机制是“置换不变”的。这意味着,如果我们把输入句子中词的顺序打乱,自注意力层对每个词计算出的新表示(在不考虑掩码的情况下)是一样的,因为它只关注词与词之间的关系,而不关心它们的绝对或相对位置。
- 解决方案需求:为了让模型理解“我 爱 你”和“你 爱 我”是不同的,我们必须向模型显式地提供词在序列中的位置信息。
- 方法:将位置信息编码为一个向量,然后与词的嵌入向量相加,作为编码器的输入。这样,输入到Transformer的每个向量就既包含了词的语义信息,也包含了其位置信息。
第二步:位置编码的数学定义
原始Transformer论文提出使用正弦和余弦函数来生成位置编码。对于一个长度为 \(L\) 的序列,其第 \(pos\) 个位置(\(pos \in [0, L-1]\))的编码向量 \(PE_{(pos)}\) 的维度为 \(d_{model}\)(与词嵌入维度相同)。这个向量的第 \(i\) 个元素(\(i\) 为维度索引, \(i \in [0, d_{model}-1]\))由以下公式定义:
\[PE_{(pos, 2i)} = \sin\left(\frac{pos}{10000^{2i / d_{model}}}\right) \]
\[ PE_{(pos, 2i+1)} = \cos\left(\frac{pos}{10000^{2i / d_{model}}}\right) \]
公式详解:
- \(pos\):词在序列中的绝对位置(从0开始计数)。
- \(i\):位置编码向量中的维度索引。注意,在公式中,\(i\) 对应的是维度分组,而不是直接索引。实际编程中,我们通常用维度索引 \(j\) 来循环。
- \(d_{model}\):模型的嵌入维度(例如512、768)。
- \(10000^{2i / d_{model}}\):这个项决定了正弦波的波长。随着维度索引 \(i\) 的增大,分母的指数 \(2i/d_{model}\) 从0增长到接近2,使得波长从 \(10000^0=1\) 到 \(10000^2=100000000\) 呈几何级数增长。这意味着不同维度捕获不同频率的位置信息。
- \(\sin\) 和 \(\cos\) 交替使用:对每个位置 \(pos\),其编码向量的偶数索引(\(2i\))使用正弦函数,奇数索引(\(2i+1\))使用余弦函数。这种设计具有一个关键优势。
第三步:关键性质与直观理解
- 唯一性:每个绝对位置都有一个唯一的位置编码向量。
- 相对位置关系的线性表达:这是正弦编码最精妙之处。对于任意固定的偏移量 \(k\),位置 \(pos + k\) 的编码可以由位置 \(pos\) 的编码线性变换得到。这是因为三角函数具有性质:
\[ \begin{aligned} \sin(\alpha + \beta) &= \sin\alpha \cos\beta + \cos\alpha \sin\beta \\ \cos(\alpha + \beta) &= \cos\alpha \cos\beta - \sin\alpha \sin\beta \end{aligned} \]
如果我们将 $\alpha$ 视为与 $pos$ 相关的项,$\beta$ 视为与 $k$ 相关的项,那么 $PE_{(pos+k)}$ 可以表示为 $PE_{(pos)}$ 的线性函数。这使得模型能够轻松地学习到相对位置信息(例如,“下一个词”、“前一个词”)。
- 有界性:正弦和余弦函数的值域是 \([-1, 1]\),这使得位置编码的值范围是可控的,不会在相加时过度扰乱词嵌入。
第四步:具体计算示例
假设模型维度 \(d_{model}=4\),我们计算位置 \(pos=0\) 和 \(pos=1\) 的编码。
首先,计算各维度的波长除数:
- 当 \(i=0\) (对应维度0和1): \(10000^{2*0/4} = 10000^0 = 1\)
- 当 \(i=1\) (对应维度2和3): \(10000^{2*1/4} = 10000^{0.5} = 100\)
对于 \(pos=0\):
- 维度0 (\(2i=0\)): \(PE(0,0) = \sin(0/1) = \sin(0) = 0\)
- 维度1 (\(2i+1=1\)): \(PE(0,1) = \cos(0/1) = \cos(0) = 1\)
- 维度2 (\(2i=2\)): \(PE(0,2) = \sin(0/100) = \sin(0) = 0\)
- 维度3 (\(2i+1=3\)): \(PE(0,3) = \cos(0/100) = \cos(0) = 1\)
- 所以,\(PE_{(0)} = [0, 1, 0, 1]\)
对于 \(pos=1\):
- 维度0: \(PE(1,0) = \sin(1/1) = \sin(1) \approx 0.8415\)
- 维度1: \(PE(1,1) = \cos(1/1) = \cos(1) \approx 0.5403\)
- 维度2: \(PE(1,2) = \sin(1/100) = \sin(0.01) \approx 0.0100\)
- 维度3: \(PE(1,3) = \cos(1/100) = \cos(0.01) \approx 0.9999\)
- 所以,\(PE_{(1)} \approx [0.8415, 0.5403, 0.0100, 0.9999]\)
最终输入:词“我”的嵌入向量(假设为 \([x_0, x_1, x_2, x_3]\))在位置0的最终输入是 \([x_0+0, x_1+1, x_2+0, x_3+1]\)。
第五步:在模型中的应用与扩展
- 应用:在Transformer的编码器和解码器底部,将计算好的位置编码矩阵(形状为
[max_seq_length, d_model])与词嵌入矩阵相加,作为第一层的输入。 - 可学习的位置编码:位置编码也可以设置为可学习的参数(一个形状为
[max_seq_length, d_model]的矩阵),在训练过程中通过梯度下降优化。BERT等模型就采用了这种方式。其优点是更灵活,但可能缺乏正弦编码的归纳偏置(如外推到更长序列的能力)。 - 相对位置编码:后续研究(如Transformer-XL、T5、DeBERTa)发现,直接建模词与词之间的相对位置关系(如“相距k个词”)比绝对位置更有效,因此发展出了各种相对位置编码方法,但其核心思想仍是解决自注意力机制的顺序感知问题。
总结:位置编码算法通过将序列顺序信息编码为与词嵌入同维度的向量,并与词嵌入相加,巧妙地解决了Transformer结构固有的“无序”问题。正弦/余弦函数形式的绝对位置编码因其能够线性表达相对位置关系而成为经典。理解其公式、性质及计算过程,是掌握Transformer架构的重要基石。