一句话总结:Token Embedding 本身不带位置,Positional Encoding 就是给每个位置加上独特的"门牌号",让标准 Transformer 能够利用"我爱你"和"你爱我"的顺序差别。


5.1 为什么需要位置信息?

上一章我们把文字转换成了向量。但这里有一个关键问题:相同的 token,查 Embedding 表得到的起点向量一样,向量本身并没有写着它出现在哪里。

5.1.1 一个关键问题

考虑这两个句子:

  • "我爱你"
  • "你爱我"

如果只看 Embedding,"我"在两个句子中的向量完全相同,"爱"完全相同,"你"也完全相同。

但这两个句子的意思完全不同!

问题出在哪里?这些内容向量还缺少位置信号。标准自注意力没有 RNN 那样的递归,也没有 CNN 那样的局部卷积,所以原始 Transformer 在输入端主动注入顺序。

5.1.2 位置信息的三个作用

位置编码的作用

Positional Encoding 解决了三个问题:

  1. 每个 Token 都能包含它的位置信息

    • 模型知道这是第 1 个字、第 2 个字、还是第 100 个字
  2. 模型可以看到文字之间的"距离"

    • "我"和"爱"相邻,"我"和"你"隔了一个字
    • 这种相对位置关系对理解语义很重要
  3. 模型可以学习解读一致的位置规则

    • 正弦公式可以计算任意位置,不需要为每个新位置再存一行参数
    • 它给了模型外推的可能,但不保证训练长度以外一定表现良好

5.2 最简单的方案:直接用整数

在讲 Transformer 的方案之前,让我们先看最直观的方法。

5.2.1 整数位置编码

简单整数相加

最简单的想法:直接把位置编号加到向量上。

假设输入是"LLM张老师":

Embedding 向量(每个字的语义表示):

字维度1维度2维度3维度4
L0.62-0.510.090.85
L0.62-0.510.090.85
M0.07.........
张0.43.........
老1.30.........
师0.98.........

位置向量(每个位置的编号):

位置维度1维度2维度3维度4
11111
22222
33333
44444
55555
66666

相加结果:

字维度1维度2维度3维度4
L0.62+1-0.51+10.09+10.85+1
L0.62+2-0.51+20.09+20.85+2
...............

5.2.2 整数方案的问题

这个方案并非数学上“不能用”,但直接把原始整数复制到每一维,有两个明显的局限:

  1. 尺度会不断增长:位置越靠后,加的数字越大。位置 1000 就要加 1000,容易压过原本在零附近的 Embedding 信号,让优化更困难。这不等于“梯度必然爆炸”,但是一个很差的尺度设计。

  2. 信号太单一:每一维都加同一个数,位置只沿着一个方向变化。网络并非完全无法学习这个线性信号,但它没有多尺度的距离结构,用起来不够灵活。

所以 Transformer 用了一个更聪明的方案:正弦位置编码(Sinusoidal Positional Encoding)。


5.3 Transformer 的方案:正弦位置编码

5.3.1 核心思想

Transformer 的位置编码使用 sin 和 cos 函数 来生成位置向量。

正弦余弦位置编码公式、频率和 d_model=4 的正确数值

公式是:

偶数维度:PE(pos, 2i) = sin(pos / 10000^(2i/d_model))
奇数维度:PE(pos, 2i+1) = cos(pos / 10000^(2i/d_model))

别被公式吓到!核心思想很简单:

  • 偶数维度用 sin 函数
  • 奇数维度用 cos 函数
  • 不同维度用不同频率的波

5.3.2 波形可视化

把位置沿着序列画出来,每一对维度都像一只 sin/cos 时钟:

  • 前面的维度分母小,变化快,像秒针
  • 后面的维度分母大,变化慢,像时针

把快慢不同的时钟组合起来,实用范围内的每个位置就有了可区分的"指纹"。

5.3.3 实际数值

图中下方的表格展示了具体数值:

位置维度0维度1维度2维度3
L (pos=0)0.001.000.001.00
L (pos=1)0.840.540.011.00
M (pos=2)0.91-0.420.021.00
张 (pos=3)0.14-0.990.031.00
老 (pos=4)-0.76-0.650.041.00
师 (pos=5)-0.960.280.051.00

注:位置从 0 开始编号(pos=0, 1, 2...)。pos=0 时 sin(0)=0, cos(0)=1。

注意:

  • 所有数值都在 [-1, 1] 范围内(sin/cos 的值域)
  • 在这个例子和实用上下文范围内,不同位置得到可区分的向量
  • 数值变化有规律可循

5.3.4 为什么用 sin/cos?

正弦位置编码有几个优点:

  1. 数值稳定:永远在 [-1, 1] 范围内,不会爆炸

  2. 公式可以外推:训练长度之外仍然能计算位置向量;但模型是否真能用好它,还要看训练和架构

  3. 固定偏移有线性关系:对于任意固定的 k,PE(pos+k) 可以由 PE(pos) 经过一个只与 k 有关的线性旋转得到。这是原论文选择 sin/cos 的动机之一

公式能外推,不等于模型实际长度也会自动外推。后来的 RoPE、ALiBi 等方案会更直接地把相对位置放进 Attention,但它们的长上下文能力同样取决于训练长度、缩放方法和模型配置。第 25 章再详细拆开。


5.4 Embedding + Position = Input

现在让我们看完整的过程:把 Embedding 向量和位置向量加起来。

5.4.1 向量相加

三个矩阵的关系:

Embedding Vector(蓝色):词的语义信息

L:  [0.62, -0.51, 0.09, 0.85]
L:  [0.62, -0.51, 0.09, 0.85]  # 注意:两个 L 的 embedding 相同
M:  [0.07, ..., ..., ...]
张: [0.43, ..., ..., ...]
老: [1.30, ..., ..., ...]
师: [0.98, ..., ..., ...]

Position Vector(黄色):位置信息

位置1: [0.00, 1.00, 0.00, 1.00]
位置2: [0.84, 0.54, 0.01, 1.00]
位置3: [0.91, -0.42, 0.02, 1.00]
位置4: [0.14, -0.99, 0.03, 1.00]
位置5: [-0.76, -0.65, 0.04, 1.00]
位置6: [-0.96, 0.28, 0.05, 1.00]

Input Embeddings(绿色):相加结果

L(位置1): [0.62+0.00, -0.51+1.00, 0.09+0.00, 0.85+1.00]
L(位置2): [0.62+0.84, -0.51+0.54, 0.09+0.01, 0.85+1.00]
...

关键观察:两个 L 虽然 Embedding 相同,但加上不同的位置编码后,结果不同了!

这样模型就能区分"第一个 L"和"第二个 L"了。

为了让加法看得清楚,上面用了直接 Embedding + Position。原始 Transformer 论文在相加前还会把 token embedding 乘以 sqrt(d_model):Input = sqrt(d_model) × Embedding + PE。不同现代架构的细节可能不同,但“把内容与位置合成同形状输入”这个主线不变。

5.4.2 几何直觉

向量相加可视化

让我们用 2D 简化例子来理解向量相加的几何意义。

假设:

  • Embedding 向量 L = [1, 3](蓝色箭头)
  • Position 向量 = [2, 1](红色箭头)

相加结果:

  • Input = [1+2, 3+1] = [3, 4](合成向量)
平行四边形法则

从几何上看,这就是向量加法的平行四边形法则:

  • 两个向量首尾相接
  • 结果是从原点到对角的向量

5.4.3 相对距离 vs 绝对位置

一个重要的洞察:在许多任务中,模型更关心的是"相对距离"而不是"绝对位置"。

注意:这并非绝对——不同的位置编码方案(如学习式 vs RoPE vs ALiBi)对绝对/相对位置的处理方式不同,详见第 25 章。

要注意,位置向量本身不会决定一个词的语义。它的作用是让 Attention 知道谁在谁前面、隔了多远。于是“我爱你”和“你爱我”虽然由同一组 token 组成,后面的 Attention 却能读到两种不同的排列和邻域,再把它们组合成不同的上下文表示。


5.5 训练过程中的位置编码

5.5.1 Embedding 是可学习的,Position 是固定的

一个重要的区别:

  • Embedding 向量:是模型参数,训练时会接收梯度并更新
  • Position 向量(正弦版本):由公式确定,不是可学习参数,优化器不会更新它

训练的是“如何解读位置信号”,不是改写这个固定信号本身。

有些模型(如 BERT)使用"可学习的位置编码",Position 向量也作为参数训练。但原始 Transformer 使用的是固定的正弦编码。

5.5.2 在完整架构中的位置

架构中的位置

看这张详细的架构图:

  1. 输入文字经过 Embedding(文字转数字 → 嵌入向量)
  2. 加上 Positional Encoding(位置信息编码)
  3. 得到 Input Embeddings,送入 Attention 层

对本章的“相加式正弦编码”来说,位置信号在进入第一个 Transformer Block 之前加入。RoPE 一类现代方案则在 Attention 内部旋转 Q/K,不走这条“输入向量相加”的路。


5.6 深入理解:为什么是"相加"?

你可能会问:为什么是把 Embedding 和 Position 相加?为什么不是拼接?

5.6.1 拼接 vs 相加

拼接(Concatenation):

  • 把两个向量接在一起
  • 如果两边都保留 d_model 宽度,[embedding | position] 会变成 2 × d_model
  • 优点:信息完全独立
  • 缺点:后面的层要么承受更宽的矩阵和更高计算量,要么先投影回 d_model

相加(Addition):

  • 对应维度直接相加
  • embedding + position → 相同维度的向量
  • 优点:维度不变,计算高效
  • 缺点:两种信息混合在一起

5.6.2 为什么相加可行?

关键洞察:高维空间很"宽敞"。

在 768 维或 4096 维的空间里,后面的投影矩阵可以学会如何同时解读 Embedding 和 Position 信号。它们有可能形成部分分离的方向,但“必然正交”不是加法本身的保证。

这就像在一个巨大的房间里,放两套家具。虽然在同一个房间,但各自有各自的区域,不会混乱。


5.7 本章总结

这一章我们学习了 Transformer 如何处理位置信息。

5.7.1 核心概念

概念解释
Positional Encoding给每个位置添加独特的向量表示
正弦位置编码用 sin/cos 函数生成位置向量
相加操作Embedding + Position = Input Embeddings
相对位置模型关心词之间的距离,而不只是绝对位置

5.7.2 数据变换过程

Embedding [seq_len, d_model]    # 词的语义信息
        +
Position  [seq_len, d_model]    # 位置信息(正弦编码)
        =
Input     [seq_len, d_model]    # 完整的输入表示

5.7.3 核心认知

Positional Encoding 补上了 Token Embedding 的“位置盲点”。它把顺序信号注入输入,Attention 才能结合内容、前后和距离,理解“我爱你”和“你爱我”的区别。


本章交付物

学完这一章,你应该能够:

  • 解释为什么 Transformer 需要位置编码
  • 理解正弦位置编码的基本原理(sin/cos 函数)
  • 说明 Embedding 和 Position 是如何结合的
  • 区分"可学习位置编码"和"固定正弦编码"

下一章预告

现在我们的输入已经完整了:语义信息(Embedding)+ 位置信息(Position)。

下一章,我们来学习两个重要的数学工具:LayerNorm(层归一化) 和 Softmax。它们在 Transformer 中无处不在,理解它们是理解整个架构的基础。

引用本文 / Cite
Zhang, Wayland (2026). 第 5 章:Positional Encoding - 给文字加位置. In Transformer 架构:从直觉到实现. https://waylandz.com/llm-transformer-book/%E7%AC%AC05%E7%AB%A0-Positional-Encoding-%E7%BB%99%E6%96%87%E5%AD%97%E5%8A%A0%E4%BD%8D%E7%BD%AE/
@incollection{zhang2026transformer_05_-Positional-Encoding-,
  author = {Zhang, Wayland},
  title = {第 5 章:Positional Encoding - 给文字加位置},
  booktitle = {Transformer 架构:从直觉到实现},
  year = {2026},
  url = {https://waylandz.com/llm-transformer-book/%E7%AC%AC05%E7%AB%A0-Positional-Encoding-%E7%BB%99%E6%96%87%E5%AD%97%E5%8A%A0%E4%BD%8D%E7%BD%AE/}
}