Skip to main content
  1. Posts/

从标量整数到相对几何:Sinusoidal Positional Encoding 到底在设计什么?

·7074 words·15 mins
Note: This article is available in Chinese only. 本文暂无英文版本。 View original

上一篇走到了一个结论:去掉 recurrence 之后,Self-Attention 必须重新获得 positional information。position 可以加进 token 的 representation,两者相加不要求后续计算无损还原,只要下游能利用其中的信息就行。

到这里逻辑上说得通。但我接着去看原始 Transformer 的 Positional Encoding 公式时又卡住了——一个 sequence 的位置不就是 0, 1, 2, 3 这样的整数吗?为什么要搞 sin、cos、10000 的某个幂次?而且还用了很多组不同频率的 sin 和 cos?

这个公式看起来像从天上掉下来的。于是我决定把它拆开,搞清楚每一块到底在做什么。

位置本来就是一个整数
#

先退一步。Transformer 需要"发现" token 在 sequence 里的位置吗?

不需要。position 一直都在:

1position = 0, 1, 2, 3, ...

sequence 有多长、每个 token 排第几,这些在输入的时候就完全确定了。Transformer 不需要做任何推断。

真正的任务是另一件事:怎么把一个 integer position 转换成 neural network 可以使用的 vector representation?

token 那一侧早就有了:token id 查 embedding table,得到一个 \(d_{\text{model}}\) 维的向量。position 这一侧要做类似的事——把一个 integer 变成同样维度的向量,然后和 token embedding 相加。

token embedding 和 positional encoding 两路相加

所以 Positional Encoding 不是在发现 position,而是在编码一个已知的 position。它和 token embedding 一样,本质上是 representation design:给一个离散输入选一种向量化的方式。

原始公式
#

Attention Is All You Need 给出的 Sinusoidal 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) $$

其中 \(pos\) 是位置,\(i\) 是维度索引。

第一遍看到这个公式的时候我确实没有什么直觉。10000 这个常数是什么?\(2i / d_{\text{model}}\) 作为指数是什么意思?但如果把公式拆一下,它的结构其实不复杂。

每一对相邻维度 \((2i, 2i+1)\) 对应一个频率 \(\omega_i = 1 / 10000^{2i/d_{\text{model}}}\)。写成更紧凑的形式:

$$ PE_{\omega}(p) = [\sin(\omega p),\; \cos(\omega p)] $$

完整的 PE 就是把很多组不同频率的 \([\sin, \cos]\) 拼在一起:

$$ PE(p) = [\sin(\omega_0 p), \cos(\omega_0 p), \sin(\omega_1 p), \cos(\omega_1 p), \ldots] $$

\(\omega_0\) 最大(高频),\(\omega_{d/2-1}\) 最小(低频),构成一个从 1 到 \(1/10000\) 的等比数列。

这么拆开看,公式层面的复杂感消失了一大半:拿掉 10000 的指数,原始公式就是"很多组不同频率的 sin/cos"。

这是 Taylor expansion 吗
#

看到很多 sin 和 cos,我第一个想到的是 Taylor expansion。两者是不是类似的东西?

不是。Taylor expansion 用的是 polynomial basis——\(1, x, x^2, x^3, \ldots\)——在某个点附近做局部逼近。这里用的是 frequency basis——多个不同频率的 sin/cos——把一个 scalar position 展开成多个 frequency 下的特征。

思路更接近 Fourier 的方向:用不同频率的周期函数来表示信号。但也不要把它当成 Fourier series——Fourier series 是对一个已知函数做分解,这里是在设计一种 representation,把一个 integer 映射成 high-dimensional features。

我后来理解的方式是:

1scalar position → 多个 frequency 探针 → 高维 representation

每个 frequency 是一个"探针",用来从不同的尺度观察同一个 position。

完全可以提前算好
#

写到这里我停下来想了一个问题:position 是固定的,公式也是固定的,那 PE 不是每次都一样吗?

确实如此。只要 \(pos\) 和 \(d_{\text{model}}\) 确定,\(PE(pos)\) 就完全确定。它不依赖 token、不依赖 batch、不依赖 training step,也不依赖任何 model parameter。

所以对于模型支持的最大长度 \(L\),完全可以预先生成一个 \([L, d_{\text{model}}]\) 的矩阵,训练和推理时直接 slice:

1x = token_embedding + pe[:seq_len]

在 PyTorch 里通常用 register_buffer("pe", pe) 而不是 nn.Parameter——它需要跟着模型保存和移动到 GPU,但不需要梯度更新。

位置变大了,但 vector 没变大
#

然后我注意到一件事。sin 和 cos 的值域是 \([-1, 1]\),所以 PE 的每一个维度都满足:

$$ -1 \le PE(pos, k) \le 1 $$

这意味着 position 是 10 还是 10000,PE vector 的每一维都在同一个范围里。position 变大不会让 vector 的 magnitude 变大。

位置变大时,magnitude 不变,phase pattern 变化

这让我意识到一件之前没有想清楚的事:Sinusoidal PE 把 position 信息从 magnitude 编码转成了 phase 编码。 position = 10000 和 position = 10 的差异体现在各个维度的 phase pattern 不同,而不是某个 vector 比另一个"更大"。

这对后面和 token embedding 做加法是一个很自然的性质——不会因为 position 数字大就压过 content embedding 的信号。

和 embedding 相加的 scale
#

不过话说回来,PE 每维有界不等于和 embedding 的 scale 就天然匹配。representation 相加时,数值尺度确实需要考虑。

原始 Transformer 里有一个容易忽略的细节:token embedding 在进入模型前会乘以 \(\sqrt{d_{\text{model}}}\)。也就是说概念上:

$$ x = \sqrt{d_{\text{model}}} \cdot \text{Embedding}(token) + PE(pos) $$

我不想过度解读这个 scaling 的单一因果(paper 里只简单提了一句),但至少可以看出:原始 Transformer 显式考虑了 token embedding 与 PE 的相对数值尺度。

content + position 能工作这件事拆开看,有三个层面:

  1. shape / representation compatibility——两者都是 \(d_{\text{model}}\) 维向量;
  2. network 可以学习如何解释混合后的 representation——上一篇讨论过;
  3. 数值 scale 不能完全失衡——PE 有界在 \([-1,1]\) 是一个有利性质,但不能因此简单声称"它天然和 embedding 完美同尺度"。

随便给个 unique vector 不行吗
#

到这里自然会产生一个疑问:如果目的只是打破 Self-Attention 的置换不变性,让模型知道每个 token 的位置不同,为什么不直接给每个位置分配一个互不相同的唯一向量?比如随机生成一组固定的 \(d_{\text{model}}\) 维向量:

1position 0 → fixed random vector A
2position 1 → fixed random vector B
3position 2 → fixed random vector C
4...

答案是不行。

这里有一个关键区分:

  • position identity:你是谁?你是第几个?
  • position geometry:你和其他位置的相对关系是什么?距离多远?谁在谁前面?

随便给一组固定的 unique vector,确实能解决 identity——每个 token 的位置不同,置换不变性被打破了。但这些向量之间没有任何空间几何结构。在高维空间里,任意两个随机向量几乎都是相互正交的,内积接近于 0。这意味着在模型的感知里,position 1 和 position 2 的关系,跟 position 1 和 position 1000 的关系完全没有区别。模型既看不出前后顺序,也度量不出相对距离。

那为什么 BERT、GPT-2 这类模型使用的 Learned Positional Embedding 看起来也是查表(每个 position 对应一个向量),却完全能工作呢?

因为 Learned PE 绝对不是“随便给的固定唯一向量”。它的向量是可学习参数。在海量数据的预训练过程中,反向传播的梯度在强迫模型把位置之间的几何拓扑——例如相邻位置的平滑性、相对距离的衰减——硬生生“学”进了这块 embedding 表里。训练收敛后可视化这些 learned embeddings,会发现相近位置的向量相似度天然更高。

但这要付出代价:

  1. 依赖数据拟合:模型必须消耗额外的参数量和训练步数去“发现”本来就已知的位置关系;
  2. 无法外推(extrapolation):预设表长是多少就只能支持多长,遇到没见过的更长位置,完全无法计算对应的向量。

这就澄清了 Sinusoidal PE 的根本追求:Positional representation 的核心价值不只在于唯一标识位置(Identity),更在于提供规则、确定且有利于表示相对距离的几何结构(Geometry)。

它不想把位置几何的先验完全丢给训练去硬学,而是希望直接在表示空间里内建这种结构。

sinusoidal PE 的设计就是在追这后面一半。

一对 sin/cos 就是单位圆上的一个点
#

现在来看 sinusoidal PE 到底给了什么结构。

对于一个固定的频率 \(\omega\),PE 给出一个二维向量:

$$ PE_{\omega}(p) = [\sin(\omega p),\; \cos(\omega p)] $$

这两个分量满足:

$$ \sin^2(\omega p) + \cos^2(\omega p) = 1 $$

也就是说 \([\sin(\omega p), \cos(\omega p)]\) 始终在单位圆上。

position 映射到 phase,再映射到单位圆上的一个点

position 从 0 开始递增,对应的 phase \(\theta = \omega p\) 线性增长,这个二维点就沿着单位圆旋转。每个 position 对应圆上的一个 phase。

我以前看到"sin/cos encoding"的时候,只是把它当成两个数值。意识到它们在几何上构成单位圆上的一个点,是后面理解 rotation 和 relative position 的基础。

在圆上旋转
#

如果 position 从 \(p\) 变成 \(p + \Delta\),phase 就从 \(\omega p\) 变成 \(\omega p + \omega\Delta\)。

利用三角函数加法公式:

$$ \sin(\omega p + \omega\Delta) = \sin(\omega p)\cos(\omega\Delta) + \cos(\omega p)\sin(\omega\Delta) $$$$ \cos(\omega p + \omega\Delta) = \cos(\omega p)\cos(\omega\Delta) - \sin(\omega p)\sin(\omega\Delta) $$

写成矩阵形式:

$$ PE_{\omega}(p + \Delta) = \begin{bmatrix} \cos(\omega\Delta) & \sin(\omega\Delta) \\ -\sin(\omega\Delta) & \cos(\omega\Delta) \end{bmatrix} PE_{\omega}(p) $$

右边那个矩阵就是一个二维旋转矩阵 \(R_{\omega\Delta}\)。

这里最关键的一点是:这个旋转矩阵只依赖 \(\Delta\),不依赖当前位置 \(p\)。

也就是说,“往后 3 个位置"这件事,不管起点是 10 还是 100,在这个二维 sin/cos 空间里对应的都是同样大小的旋转:

position 10→13 和 100→103 对应相同的旋转角

relative displacement 在 representation space 中具有一致的几何意义。position 10 和 position 13 之间的关系,与 position 100 和 position 103 之间的关系,在同一个 frequency 下是同一种 rotation。

dot product 与相对位置
#

这个 rotation 结构还带来另一个性质。计算同一频率下两个位置的 dot product:

$$ PE_{\omega}(p) \cdot PE_{\omega}(q) = \sin(\omega p)\sin(\omega q) + \cos(\omega p)\cos(\omega q) $$

利用三角恒等式:

$$ = \cos(\omega(p - q)) $$

原来各自的 absolute position \(p\) 和 \(q\),在 dot product 之后只剩下相对位移 \(p - q\)。

所以 position 10 与 11、position 100 与 101、position 1000 与 1001——在同一 frequency 下,它们的 dot product 完全相同,因为 \(p - q\) 都是 1。

sinusoidal PE 的 geometry 让 relative relation 可以被 dot product 这样的线性操作自然提取出来。它不是显式存储了 \(p - q\),而是构造出来的几何结构让这种 relation 可以被规则地利用。

但这里必须加一个重要的限定。

真实 Transformer 的 attention score 不是直接计算 \(PE(i) \cdot PE(j)\)。实际路径是:

$$ h_i = e_i + PE(i) $$$$ q_i = h_i W_Q, \quad k_j = h_j W_K $$$$ \text{score} = q_i k_j^T $$

PE 会经过 learned projection,并且和 semantic content 混在一起。所以不能把真实 attention score 简化成"就是 relative-position cosine”——sinusoidal PE 提供的是一种有利于表达 relative structure 的 positional geometry,不是 attention 的全部。

一个圆有无限多个点
#

走到这里我产生了一个困惑,后来发现这个困惑恰好暴露了我对 multi-frequency 设计的误解。

我的问题是:一个圆不是有无限多个点吗?角度是连续的,并不是只有 360 个位置。那为什么一个圆不能表示所有 position?为什么还需要很多个圆?

这个质疑本身是成立的。只使用一个频率 \(\omega\),\([\sin(\omega p), \cos(\omega p)]\) 在数学上确实可以为大量 integer position 提供不同的表示——只要 \(\omega / 2\pi\) 是无理数,integer position 在单位圆上就永远不会精确重合。

所以 multiple frequencies 不是因为一个圆"装不下"更多位置。不是 capacity 问题。

这个认识对我来说是一个转折点,因为我之前隐约以为"多个圆是为了容纳更多位置"。不是的。

多个频率 = 多尺度位置表示
#

那为什么还需要多个频率?

假设只有一个频率 \(\omega\)。position 每增加 1,在圆上旋转 \(\omega\)。

单一频率的 trade-off:高频 vs 低频

如果 \(\omega\) 很大(高频),\(p \to p+1\) 的旋转角度大,局部的 position change 非常明显——local resolution 好。但 position 变化 100 的时候,圆上会绕很多次,从单一 frequency 看,长距离 relation 会出现周期性的模糊。

如果 \(\omega\) 很小(低频),\(p \to p+1\) 只在圆上移动一点点,对 local difference 不够敏感。但在较长 range 内 phase 变化平缓,更适合提供 coarse / long-range 的位置结构。

一个频率只能提供一个观察 position relationship 的尺度。这才是多个频率存在的真正原因。

完整 PE 把很多不同转速的圆拼在一起:

同一个 position 在多个频率下分别有 phase,拼接成完整 PE

同一个 position 同时在所有 frequency 下都有自己的 phase。最终的 PE 就是这些不同 positional scale 下 observation 的拼接。

用一个比喻来说:想象很多只不同转速的钟。position = 100 的时候,快钟已经转了很多圈,慢钟才转了一小段。完整 PE 记录的是这个 position 在所有钟上的状态。

多个圆不是为了"位置不够放",而是为了"一个频率看 position 的尺度太单一"。

每个 position 同时拥有所有 frequency component——不是每个 frequency 负责某些 position,而是所有 frequency 共同描述同一个 position。

和 FPN 的类比
#

这个 multi-scale 的思路让我想到 CV 里的 FPN(Feature Pyramid Network):

FPN 和 Sinusoidal PE 共享 multi-scale representation 的设计思路

FPN 通过不同分辨率的 feature map 同时提供 local detail 和 larger-scale structure。Sinusoidal PE 通过不同频率的 sin/cos 同时提供 fine local positional change 和 coarse long-range positional structure。

两者背后有一个相似的设计思路:不押注单一尺度,同时向下游提供多尺度 representation。

但我想把边界说清楚:这只是 design pattern 层面的类比。FPN 的 multi-scale 来自 spatial resolution 和 receptive field,sinusoidal PE 的 multi-scale 来自 frequency 和 phase。一个是空间的,一个是频率的。机制完全不同,在这里类比的只是"multi-scale representation"这个想法。

PE 固定,用法不固定
#

到目前为止,sinusoidal PE 的所有性质——有界、rotation、multi-scale——都是公式本身的数学性质,和训练没有关系。

于是我遇到了下一个问题:PE 完全固定,那 Transformer 到底怎么知道什么时候该更关注 high frequency,什么时候更关注 low frequency?

答案是把 fixed 和 learned 分开看。

token 和 position 相加之后,进入 learned projection:

$$ q_i = (e_i + p_i) W_Q = e_i W_Q + p_i W_Q $$

\(p_i\) 是固定的。但 \(W_Q\) 是 learned 的。同理 \(W_K\)、\(W_V\)、FFN 的参数都是 learned 的。

固定 PE 经过 learned projection 进入 Multi-Head Attention

所以可以这样理解:

1Sinusoidal PE = 固定的 frequency basis / features
2Transformer weights = 学习如何 project、mix、使用这些 features

这和 Fourier basis 的直觉有点类似:basis 可以固定,但 how to combine the basis 可以学习。当然不是说 Transformer 在显式做 Fourier series——只是"固定 basis + learned combination"这个模式在这里成立。

另外,我一开始想当然地觉得"不同 token 会选择不同的 frequency",但仔细一想不完全对。\(W_Q\) 等 projection 是跨 token 共享的——所有 token 用同一组 projection weights。

更准确的说法是:不同 attention head、不同 semantic context、不同 token pair 之间的 interaction,可以对不同 positional patterns 表现出不同的 sensitivity。frequency usage 是通过 learned projection、semantic interaction、attention 和 multi-head 隐式实现的,不是每个 token 自己独立选择 frequency。

content 和 position 在 attention 里怎么交互
#

把之前学过的 Q/K/V 接回来,看看 content 和 position 在 attention 里到底是什么关系。

令 \(A = W_Q W_K^T\),attention score 可以展开:

$$ (e_i + p_i)\, A\, (e_j + p_j)^T = e_i A e_j^T + e_i A p_j^T + p_i A e_j^T + p_i A p_j^T $$

四项分别对应:

attention score 展开为 content 和 position 的四项交互
  • content ↔ content:两个 token 的语义相似性;
  • content ↔ position:某种 content 对某个位置的敏感度;
  • position ↔ content:某个位置对某种 content 的偏好;
  • position ↔ position:纯位置之间的关系。

这四项都经过同一个 learned \(A\)。positional information 不是单独放在旁边被模型查阅的——从 \(e + PE\) 那一刻开始,position 和 semantic content 就共同参与了 learned interaction。

模型最终学到的不只是"这里是 position 7",而是可以形成"某种 semantic pattern 在某种 positional relationship 下是否重要"这样的交互。

再加上 Multi-Head Attention——每个 head 有自己独立的 \(W_Q^{(h)}, W_K^{(h)}, W_V^{(h)}\)——不同 head 可以学习不同的 semantic + positional interaction pattern。一个 head 可能更关注 local relation,另一个可能更容易利用 long-range structure。这不是说每个 head 严格对应一个 frequency band——真实的分工远比这复杂——但 multi-head 确实给了模型同时学习多种 interaction pattern 的自由度。

Learned PE 和 Sinusoidal PE
#

写到这里自然要问:既然 learned positional embedding 也能给每个位置一个向量,而且效果和 sinusoidal PE 接近(原始 Transformer paper 里的实验结论),那两者的区别到底在哪?

1Learned PE:position → embedding table → learned vector
2Sinusoidal PE:position → deterministic sin/cos → fixed structured vector

Learned PE 把更多 positional structure 交给训练过程自己发现。Sinusoidal PE 预先提供了 smooth、structured、multi-frequency 的 positional geometry。

一个经常被提到的 sinusoidal PE 优势是:它可以在数学上为训练时没见过的 position 生成 PE vector——只要代入公式就行。但我觉得需要加一个限定:能生成 PE(position) 不等于整个模型已经学会对未见长度正常泛化。 PE 只是 Transformer 的输入之一,后面的所有 learned weights 都是在训练分布上拟合的。

所以 sinusoidal PE 的真正特点不在于"可以 extrapolate",而在于它从一开始就提供了一种有结构的 positional representation:bounded、smooth、rotation-equivariant、multi-scale。Learned PE 当然也可能在训练中发现类似的结构,但那是训练的结果而不是设计的保证。

小结
#

这篇从"标量整数如何变成向量"走到了"为什么需要构造相对几何与多尺度结构"。回头看,整条线索可以压缩成几句话:

  • PE 不是在发现 position,是在把已知的 integer position 编码成 vector representation。
  • 随便给个固定随机向量只能解决 identity(区分位置),无法提供 geometry(相对距离与顺序);Sinusoidal PE 的根本追求是提供内建的相对位置几何。
  • 一对 \([\sin(\omega p), \cos(\omega p)]\) 构成单位圆上的一个 phase,position 增加对应 rotation。
  • 相同的 relative displacement 在同一 frequency 下对应相同大小的 rotation,这让 sinusoidal PE 的 geometry 天然有利于表达 relative structure。
  • 多个 frequency 不是为了增加 position capacity——一个圆已经有无限多个点。多个 frequency 是为了提供多尺度 positional features:高频看 local,低频看 long-range。
  • PE 有界在 \([-1,1]\),position 信息在 phase 而不在 magnitude。
  • fixed PE 不等于 fixed usage——Transformer 通过 learned projection、attention interaction 和 multi-head 来学习如何使用这些固定的 frequency basis。

Sinusoidal PE 建立的这套思路——position 对应 phase,relative displacement 对应 rotation——后来在 RoPE(Rotary Position Embedding)中被更直接地使用:RoPE 把 position-dependent rotation 直接作用在 Q 和 K 上,而不是加在 embedding 里。但那是下一篇的事了。

参考资料
#

Related

从 RNN 到 Self-Attention:信息为什么一定要沿着 State 一步步传递?

上一篇《从 RNN / LSTM / GRU 到早期 Attention》结尾我留了一句话:早期的 attention 并不是为了取代 RNN 而出现的,它只是夹在 encoder–decoder 中间解决 fixed-context bottleneck;但“根据当前需求去读取一组 representation”这种机制,并不一定要依附在 RNN 上。这篇接着讲那个“另一个故事”。