正余弦位置编码的数学原理究竟有何神秘之处?

摘要:Transformer的位置编码采用正余弦函数形式,通过不同频率的正弦波叠加实现多尺度位置表示。设计目标包括唯一性、相对位置线性可表示性和多尺度编码。频率按维度指数衰减(底数10000为经验值),偶数维用正弦、奇数维用余弦,形成对称表示。这
Transformer 位置编码(Positional Encoding) 采用的是正余弦位置编码,其形式是: \[PE_{(pos,2i)}=\sin\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right) \] \[PE_{(pos,2i+1)}=\cos\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right) \] 两个问题: 为什么是 (\(2i/d_{model}\)) 为什么底数是 10000 这不是严格“数学推导出来”的,而是 根据设计目标推导出的一个合理形式。下面我们一步一步解释这个设计逻辑。 一、出发点:为何需要位置编码 Transformer 的自注意力机制是 置换不变(permutation invariant) 的,即它无法天然感知输入序列的顺序。 例如:"I love you", "you love I" 如果不加入位置信息,模型无法区分它们在语义上的差异。 因此需要给每个位置 \(pos\) 一个向量: \[PE(pos) \in \mathbb{R}^{d_{model}} \] 并且让嵌入向量和位置编码可以直接相加: \[x_{pos} = embedding(pos) + PE(pos) \] 二、理想位置编码应满足的设计目标 论文在设计位置编码时,主要考虑了以下几点: (1)唯一性:不同位置 \(pos\) 应该得到不同向量。 (2)相对位置的可线性表示性:模型应能容易地学习到相对位置关系。理想情况下,\(PE(pos+k)\) 应该能由 \(PE(pos)\) 通过线性变换得到。正余弦函数天然满足这一性质: \[\sin(\theta + \frac{\pi}{2}) = \cos(\theta),\text{ } \cos(\theta + \frac{\pi}{2}) = -\sin(\theta) \] 更一般地,可以通过线性变换表示: \[\begin{bmatrix} \cos(\theta) \\ \sin(\theta) \end{bmatrix} = \begin{bmatrix} \cos(\phi) & -\sin(\phi) \\ \sin(\phi) & \cos(\phi) \end{bmatrix} \begin{bmatrix} \cos(\theta - \phi) \\ \sin(\theta - \phi) \end{bmatrix} \] 这一性质源自三角恒等式: \[\cos(A + B) = \cos A \cos B - \sin A \sin B \] \[\sin(A + B) = \sin A \cos B + \cos A \sin B \] 自己手推一下就知道了。 (3)多尺度表示:希望不同维度能捕捉不同粒度的位置信息——有的维度变化快(适合短距离依赖),有的变化慢(适合长距离依赖),类似于多尺度编码的思想。 三、从目标到形式:逐步构造位置编码 目标有了,现在就开始想解决办法。 第一步:使用周期函数编码位置 受三角函数线性变换性质的启发,可以考虑用正弦函数表示位置: \[PE(pos)=\sin(\omega \cdot pos) \] 或\(PE(pos)=\cos(\omega \cdot pos)\),其中,\(\omega\)是频率。 第二步:不同维度用不同频率 设词嵌入 (embedding) 维度为\(d_{\text{model}}\)。我们希望每一维都有不同频率。例如,\(\omega_0,\omega_1,\omega_2,...,\omega_{d_{model}-1}\),以编码不同尺度的信息: \[PE(pos,i)=\sin(\omega_i\cdot pos) \] 其中,\(i\) 是维度。 第三步:频率如何分布? 我们希望频率从高到低呈指数级变化,这样既能覆盖短距离细节,也能表达长距离结构。这与傅里叶特征(Fourier Features)中的做法类似。 定义波长为 \(\lambda_i=\frac{1}{\omega_i}\),希望波长从小到大 指数增长: \[\lambda_i=\lambda_{min}\cdot r^i \] 其中,\(\lambda_{min}\) 为最小波长,\(r>1\) 是增长因子。 \(i\) 的范围比较大,需要合理归一化。 第四步:引入指数衰减的频率 设最小波长为 1,最大波长为 \(L\),并令波长随维度 \(i\) 指数增长: \[\lambda_i=L^{\frac{2i}{d_{\text{model}}}} \] 则频率为: \[\omega_i=\frac{1}{\lambda_i}=\frac{1}{L^{{2i}/{d_{model}}}} \] Transformer 中取 \(L=10000\),于是: \[\omega_i=\frac{1}{10000^{{2i}/{d_{model}}}} \] 四、为什么是 2i? 为了将同一频率的正弦和余弦配对,分别用于偶数维和奇数维,形成更丰富的表示。\(2i\) 能表示偶数维度,\(2i+1\) 能表示奇数维度。设 \(i=0,1,2,...,\frac{d_{model}}{2}-1\),则: \[PE_{(pos,2i)}=\sin\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right) \] \[PE_{(pos,2i+1)}=\cos\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right) \] 这样既保证了频率的多样性,又保持了表示的对称性。 五、为什么是 10000? 这是一个 经验性选择。作用是控制 波长范围。刚刚提到,波长定义式是\(\lambda_i=L^{\frac{2i}{d_{\text{model}}}}\)。 当 \(i=0\) 时,波长 \(\lambda= 1\),周期 \(= 2\pi\) 当 \(i=\frac{d_{\text{model}}}{2}\)时,波长 \(\lambda=10000\),周期 \(= 10000\times 2\pi\) 这样可以覆盖短距离和长距离关系。如果序列长度是512、1024、4096都能表示。实际上很多模型会改成1000、100000或设为可学习参数。 六、总结 位置编码本质是 不同频率的正弦波叠加 类似傅里叶特征和信号频谱。 低维维度:频率高 → 适合捕捉短距离依赖 高维维度:频率低 → 适合捕捉长距离依赖 这种设计将绝对位置 pos 映射到一个多频率坐标系中,使得模型既能区分不同位置,也能通过线性变换轻松学习相对位置关系。最终的形式简洁而统一,成为 Transformer 成功的关键组件之一。