Positional Encoding in Transformer

8 min read 1,979 words 0
Positional Encoding in Transformer

由于Transformer的自注意力机制具有置换不变形(Permutation Invariance)。也就是说即使输入词序列即使被打乱,自注意力的计算结果也完全一致。我们没有recurrence 和 convolution

因而我们需要引入位置信息。

图1. token embedding矩阵行代表着16个token,列代表着60个特征值。图2. sinusoidal encoding沿着词向量维度的轴,不同token之间的变换频率越来越高。图3. 是位置编码后的输出。

Sinusoidal PE

在 Vaswani et al. (2017) 中,作者使用了 Sinusoidal Positional ecoding:

PE(pos,2i)=sin⁡(pos100002i/d),PE(pos,2i+1)=cos⁡(pos100002i/d)PE_{(pos, 2i)} = \sin\left(\frac{pos}{10000^{2i/d}}\right), \quad PE_{(pos, 2i+1)} = \cos\left(\frac{pos}{10000^{2i/d}}\right)

sin and cos

let’s review sin and cos function!

sin 和 cos 的值永远在 [-1, 1]

sin(100x) 频率高,晃动极快和 sin(0.01x) 频率低,晃动极慢

在平面直角坐标系上,如果横坐标是 cos⁡(θ)\cos(\theta),纵坐标是 sin⁡(θ)\sin(\theta),随着 θ\theta 变大,这个点 (cos⁡θ,sin⁡θ)( \cos\theta, \sin\theta ) 会在圆周上匀速画圈。 sin⁡\sin 和 cos⁡\cos 就像钟表上的指针:x和y的值作为pointer vector,可以表示出在圆周上的点的位置。

想象用二进制计数:

  • 第 0 位:0, 1, 0, 1, 0, 1… (变化最快,高频)
  • 第 1 位:0, 0, 1, 1, 0, 0… (变慢了一半)
  • 第 2 位:0, 0, 0, 0, 1, 1… (更慢)

又像是一个钟表:

  • 秒针 转得飞快(高频)
  • 分针 转得中等
  • 时针 转得最慢(低频)

现在问你:下午 3 点 15 分 42 秒 是一个独一无二的时间吗?是的,我们当然可以把这三个指针的朝向组合起来,精准且唯一地表示一天中的任何时刻。

PE(pos,2i)=sin⁡(pos⋅ωi),PE(pos,2i+1)=cos⁡(pos⋅ωi)PE_{(pos, 2i)} = \sin(pos \cdot \omega_i), \quad PE_{(pos, 2i+1)} = \cos(pos \cdot \omega_i)

ωi=1100002i/d\omega_i = \frac{1}{10000^{2i/d}}

  • pos 就是单词的在句子里的位置索引(0, 1, 2, 3…)。
  • d 词向量的维度
  • i 当前处于哪一组维度,i∈[0,d2−1]i \in [0, \frac{d}{2}-1]

整个的p向量为:

pt⃗=[sin⁡(ω1t)cos⁡(ω1t)sin⁡(ω2t)cos⁡(ω2t)⋮sin⁡(ωd/2t)cos⁡(ωd/2t)]d×1\vec{p_t} = \begin{bmatrix} \sin(\omega_1 t) \\ \cos(\omega_1 t) \\ \sin(\omega_2 t) \\ \cos(\omega_2 t) \\ \vdots \\ \sin(\omega_{d/2} t) \\ \cos(\omega_{d/2} t) \end{bmatrix}_{d \times 1}

随着维度 ii 的增大,100002i/d10000^{2i/d}呈几何倍地增大,ww 角频率随之呈几何倍地减小。

在低维度中,i→0i \to 0, 波长 λ≈2π\lambda \approx 2\pi(约 6.28 个位置就完成一个周期),频率极高,可以捕捉小尺度的局部顺序

在高维度中,i→d/2i \to d/2, 波长 λ≈2π×10000≈62831\lambda \approx 2\pi \times 10000 \approx 62831,频率极低,可以捕捉全局的长跨度的相对位置

why?

We chose this function because we hypothesized it would allow the model to easily learn to attend by relative positions, since for any fixed offset kk, PE(pos+k)PE(pos+k) can be represented as a linear function of PE(pos)PE(pos).

论文选择正余弦配对,最关键的数学性质在于利用三角恒等式捕获相对距离:对于固定的偏移量 kk,PEpos+kPE_{pos+k} 可以由 PEposPE_{pos} 经过一个固定的线性变换矩阵得到。

现在我们只挑出向量里的某一小对相邻的维度(偶数维用 sin ⁡ sin ,奇数维用 cos ⁡ cos )。

假设这一对维度的频率系数是 ω\omega(也就是公式里的 1100002i/d\frac{1}{10000^{2i/d}}):

  • 在位置 pospos 处,这个二维向量是: vpos=[sin⁡(ω⋅pos)cos⁡(ω⋅pos)]v_{pos} = \begin{bmatrix} \sin(\omega \cdot pos) \\ \cos(\omega \cdot pos) \end{bmatrix}

现在,单词往后挪了 kk 个身位,到了位置 pos+kpos + k。这个位置的向量是: vpos+k=[sin⁡(ω(pos+k))cos⁡(ω(pos+k))]v_{pos+k} = \begin{bmatrix} \sin(\omega (pos + k)) \\ \cos(\omega (pos + k)) \end{bmatrix}

如果把它改写成线性代数的矩阵乘法:

[sin⁡(ω(pos+k))cos⁡(ω(pos+k))]=[cos⁡(ωk)sin⁡(ωk)−sin⁡(ωk)cos⁡(ωk)][sin⁡(ω⋅pos)cos⁡(ω⋅pos)]\begin{bmatrix} \sin(\omega(pos + k)) \\ \cos(\omega(pos + k)) \end{bmatrix}=\begin{bmatrix} \cos(\omega k) & \sin(\omega k) \\ -\sin(\omega k) & \cos(\omega k) \end{bmatrix} \begin{bmatrix} \sin(\omega \cdot pos) \\ \cos(\omega \cdot pos) \end{bmatrix}

也就是说:

vpos+k=Mk⋅vposv_{pos+k} = M_k \cdot v_{pos}

这意味着:

这里的震撼之处在哪里?

你看中间那个 2×22 \times 2 的变换矩阵 MkM_k: Mk=[cos⁡(ωk)sin⁡(ωk)−sin⁡(ωk)cos⁡(ωk)]M_k = \begin{bmatrix} \cos(\omega k) & \sin(\omega k) \\ -\sin(\omega k) & \cos(\omega k) \end{bmatrix}

这个矩阵里,只有相对距离 kk,完全没有绝对位置 pospos 的影子!

  • 无论你的词是在句首(pos=1pos=1 挪到 pos=3pos=3),还是在句尾(pos=98pos=98 挪到 pos=100pos=100);
  • 只要两者的相对距离都是 k=2k=2;
  • 连接它们两个位置编码的,永远是同一个固定的线性变换矩阵 MkM_k!

神经网络最擅长做什么?就是学矩阵乘法(线性变换)! 因为从 pospos 到 pos+kpos+k 的映射就是一个现成的纯线性矩阵,模型只需要调整自己的注意力权重参数(WQ,WKW_Q, W_K),就能非常自然、轻松地捕捉到“相对相隔 kk 个词”这种空间关系。


3. 几何直觉:这其实就是一个「旋转」

学过线性代数的同学可能一眼就看出来了: 那个矩阵 MkM_k,正是大名鼎鼎的 2D 旋转矩阵!

我们把位置编码画在一个圆上:

  • 在位置 pospos 时,指针指在角度为 θ1=ω⋅pos\theta_1 = \omega \cdot pos 的方向。
  • 往后走 kk 步,相当于把指针旋转了 Δθ=ωk\Delta\theta = \omega k 的角度。

钟表比喻再次出现: “往前走 3 个小时”是什么操作?

  • 如果现在是 2 点,往前拨 90 度,到了 5 点。
  • 如果现在是 8 点,往前拨 90 度,到了 11 点。

“距离相隔 3 个小时”这个相对概念,对应在表盘上,永远都只是“顺时针转动 90 度”这一个恒定的旋转动作。 这就是为什么 sin⁡\sin 和 cos⁡\cos 必须成对出现——因为只有一对 (sin⁡,cos⁡)(\sin, \cos) 才能组成一个可以在平面内自由旋转的二维向量。


4. 在注意力机制(Attention)中的终极体现:点乘

Transformer 算注意力分数,核心是用词向量算点乘(内积):Q⋅KTQ \cdot K^T。

如果模型计算位置 pos1pos_1 和位置 pos2pos_2 之间的编码相似度(内积): 内积=sin⁡(ω⋅pos1)sin⁡(ω⋅pos2)+cos⁡(ω⋅pos1)cos⁡(ω⋅pos2)\text{内积} = \sin(\omega \cdot pos_1)\sin(\omega \cdot pos_2) + \cos(\omega \cdot pos_1)\cos(\omega \cdot pos_2)

利用高中余弦差角公式:cos⁡(A−B)=cos⁡Acos⁡B+sin⁡Asin⁡B\cos(A - B) = \cos A \cos B + \sin A \sin B 上面这个内积直接等于: 内积=cos⁡(ω(pos1−pos2))\text{内积} = \cos\big(\omega (pos_1 - pos_2)\big)

你看!绝对位置 pos1pos_1 和 pos2pos_2 彻底消失了! 算出来的相似度只取决于它们的差值 Δpos=pos1−pos2\Delta pos = pos_1 - pos_2(相对距离)。


补充:你知道这个思想现在有多火吗?

这个“旋转矩阵表达相对位置”的绝妙思路,后来被苏剑林(Jianlin Su)等人进一步发扬光大,直接做成了现在所有主流大模型(LLaMA 2/3、Mistral、DeepSeek、Qwen 等)标配的:

👉 RoPE(旋转位置编码,Rotary Position Embedding)

RoPE 的本质,就是不再把 (sin⁡,cos⁡)(\sin, \cos) 当作向量直接加到词向量上,而是把你的词向量直接乘上上面推导出的那个旋转矩阵 MkM_k!

所以,你今天弄懂了成对的 sin⁡/cos⁡\sin/\cos 为什么是一个旋转矩阵,不仅彻底攻克了初代 Transformer 的位置编码,还顺便把当下最前沿的大模型位置编码底层数学原理给搞懂了。

在标准Transformer的设计中,必须保证d_model为偶数。

原因一是因为sin/cos编码需要两两成对。偶数堆为d/2,奇数堆也为d/2

二是任意偶奇相邻通道 (2i,2i+1)(2i, 2i+1) 构成一个 2D 平面旋转群 SO(2)SO(2)。

再者,Multi-Head Attention也无法使用奇数的d_model

other why

我们自然而然会想到一个问题,为什么不用1,2,3,4…作为位置信息?

这其实要引出另一个问题:我们的架构需要什么样的位置信息?

我们需要的是「以固定步长计数的绝对位置」,但最终目的是为了让模型能够推导出「相对位置关系」。

因为我们希望我们的编码方式是有界的,不能冲垮神经网络的数值范围。就算归一化到0~1,我们发现10个词的第5个词(0.5)和100个词的第50个词(0.5),意义完全不一样。

See also