一句话总结:词嵌入(Embedding)表示"这是什么词",位置编码(Positional Encoding)表示"这个词在哪里"。Transformer 把它们直接相加而不是拼接,因为相加既能保留两种信息,又不增加维度,还让模型更容易学习。


14.1 回顾:输入处理的两个步骤

在第 4 章和第 5 章,我们分别学习了:

章节组件作用
第 4 章Embedding把 Token ID 变成向量(语义信息)
第 5 章Positional Encoding给向量添加位置信息

这一章,我们来深入理解:为什么这两个信息要通过"相加"来结合?


14.2 两种信息的本质

14.2.1 词嵌入:语义信息

回顾第 4 章的 Embedding 查找表:

Embedding查找表

每个词有一个对应的向量,这个向量包含了词的语义信息

  • "国王"和"王后"的向量接近(都是皇室)
  • "国王"和"苹果"的向量很远(没有关系)

Embedding 回答的问题是:这个词是什么意思?

14.2.2 位置编码:位置信息

回顾第 5 章的位置编码:

位置编码公式

位置编码是一组正弦/余弦函数,每个位置有唯一的编码:

  • 位置 0 有自己的向量
  • 位置 1 有不同的向量
  • ...

位置编码回答的问题是:这个词在句子的什么位置?

14.2.3 两种信息都很重要

考虑这两个句子:

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

它们包含完全相同的词,但意思完全不同。位置改变了含义

所以 Transformer 需要同时知道:

  1. 每个词是什么(Embedding)
  2. 每个词在哪里(Positional Encoding)

14.3 结合方式:相加 vs 拼接

14.3.1 两种选择

有两种直观的方式来结合 Embedding 和 Positional Encoding:

方式一:拼接(Concatenation)

输入向量 = [Embedding; Positional Encoding]
维度:d_model + d_model = 2 × d_model

方式二:相加(Addition)

输入向量 = Embedding + Positional Encoding
维度:d_model(不变)

Transformer 选择了相加。为什么?

14.3.2 相加的优势

1. 维度不增加

拼接会让维度翻倍:

  • 原本 d_model = 512
  • 拼接后变成 1024

这意味着所有后续层的参数量都要翻倍!

相加保持维度不变:

  • 原本 d_model = 512
  • 相加后还是 512

2. 信息可以共存

两个向量相加后,信息并没有丢失,而是"叠加"在一起:

embedding = [0.5, 0.3, -0.2, 0.8, ...]  # 语义
position  = [0.1, 0.0, 0.1, -0.1, ...]  # 位置
combined  = [0.6, 0.3, -0.1, 0.7, ...]  # 包含两种信息

3. 模型可以学会分离

神经网络有很强的表达能力,它可以学会:

  • 从 combined 中提取语义相关的部分
  • 从 combined 中提取位置相关的部分

14.3.3 一个直观的类比

想象你在一个派对上:

  • 你的外表(Embedding):告诉别人"你是谁"
  • 你站的位置(Positional Encoding):告诉别人"你在哪"

这两个信息是独立的,但可以同时存在。别人看到你,既知道你是谁,也知道你在哪里。


14.4 计算方式示例

14.4.1 具体计算

计算方式示例

看这张图,我们来追踪一个具体的计算:

假设

old_embedding_value = 0.9   # 某个词的 embedding 中的一个值
positional_encoding = 0.1   # 对应位置的位置编码值

输入阶段(相加):

combined = embedding + positional_encoding
         = 0.9 + 0.1
         = 1.0

训练阶段(反向传播更新 embedding):

new_embedding_value = old_embedding_value - lr * error_gradient
                    = 0.9 - 0.1 * (-0.4)
                    = 0.9 + 0.04
                    = 0.94

下一次前向传播

new_combined_value = new_embedding_value + positional_encoding
                   = 0.94 + 0.1
                   = 1.04

14.4.2 关键观察

注意这个过程中:

  1. Embedding 是可学习的:在训练过程中不断更新
  2. Positional Encoding 是固定的:不参与训练(使用正弦/余弦函数)
  3. 相加发生在每次前向传播:不是一次性的

14.5 深层逻辑:为什么这种设计有效?

14.5.1 向量空间的视角

在高维向量空间中,方向代表含义,位置代表不同的概念。

相加可以理解为:

  • Embedding 向量指向"语义方向"
  • Positional Encoding 向量提供"位置偏移"

最终的向量既有语义信息,又被"偏移"到了正确的位置。

14.5.2 正交性假设

一个重要的假设是:语义信息和位置信息在某种程度上是正交的

正交意味着:

  • 语义变化不会影响位置信息
  • 位置变化不会影响语义信息

虽然这不是严格成立的,但神经网络可以学会近似这种分离。

14.5.3 Attention 如何利用这两种信息

在 Attention 计算中:

Q = (Embedding + PE) @ Wq
K = (Embedding + PE) @ Wk

Wq 和 Wk 可以学习到:

  • 某些维度主要关注语义相似度
  • 某些维度主要关注位置关系

例如:

  • "sat" 和 "cat" 的语义相关(动词+主语)
  • 相邻位置的词可能语法相关

Attention 可以同时捕捉这两种关系。


14.6 变体:不同的位置编码方法

14.6.1 原始方法:相加固定编码

input = Embedding(token_ids) + PositionalEncoding(positions)

这是原始 Transformer(2017)使用的方法,采用正弦余弦固定编码。

注意:GPT-2 虽然也是"相加",但使用的是可学习的位置编码,而非固定的正弦编码。

14.6.2 可学习位置编码

GPT 系列实际上使用的是可学习的位置编码

# 代码示例
class LearnablePositionalEncoding(nn.Module):
    def __init__(self, max_len, d_model):
        super().__init__()
        # 位置编码也是一个可学习的 Embedding
        self.pe = nn.Embedding(max_len, d_model)

    def forward(self, x):
        positions = torch.arange(x.size(1), device=x.device)
        return x + self.pe(positions)

可学习位置编码的优势:

  • 让模型自己学习最优的位置表示
  • 不需要手动设计正弦/余弦函数

14.6.3 RoPE:旋转位置编码

更现代的方法是 RoPE(Rotary Position Embedding),它不是简单地相加,而是通过旋转来编码位置:

Q_rotated = rotate(Q, position)
K_rotated = rotate(K, position)

RoPE 的优势:

  • 相对位置信息更明确
  • 可以外推到更长的序列

LLaMA、GPT-NeoX 等现代模型都使用 RoPE。这个话题我们在第 25 章详细讨论。


14.7 实际代码:输入处理完整流程

14.7.1 PyTorch 实现

# 代码示例
class TransformerInput(nn.Module):
    def __init__(self, vocab_size, d_model, max_len, dropout=0.1):
        super().__init__()
        # 词嵌入
        self.token_embedding = nn.Embedding(vocab_size, d_model)
        # 位置编码(可学习)
        self.position_embedding = nn.Embedding(max_len, d_model)
        # Dropout
        self.dropout = nn.Dropout(dropout)
        # 缩放因子
        self.scale = d_model ** 0.5

    def forward(self, x):
        # x: [batch_size, seq_len]  token IDs

        # 1. 词嵌入
        token_emb = self.token_embedding(x)  # [batch, seq, d_model]

        # 2. 缩放(可选,有些实现会做)
        token_emb = token_emb * self.scale

        # 3. 位置编码
        positions = torch.arange(x.size(1), device=x.device)
        pos_emb = self.position_embedding(positions)  # [seq, d_model]

        # 4. 相加
        combined = token_emb + pos_emb  # [batch, seq, d_model]

        # 5. Dropout
        return self.dropout(combined)

14.7.2 维度追踪

输入 token_ids: [4, 16]           # 4个句子,每句16个token

Token Embedding:
  查表: token_embedding([4, 16])
  输出: [4, 16, 512]               # 每个token变成512维向量

Position Embedding:
  位置: [0, 1, 2, ..., 15]
  查表: position_embedding([16])
  输出: [16, 512]                  # 每个位置有512维向量
  广播: [4, 16, 512]               # 广播到batch维度

相加:
  [4, 16, 512] + [4, 16, 512] = [4, 16, 512]

输出: [4, 16, 512]                 # 包含语义+位置信息的向量

14.8 常见问题

14.8.1 相加会不会让信息混淆?

不会,因为:

  1. 向量空间是高维的(512维),有足够的"空间"容纳两种信息
  2. Attention 的 Wq、Wk、Wv 可以学会提取需要的信息
  3. 多层 Transformer 可以逐步分离和处理这些信息

14.8.2 为什么位置编码的幅度要小?

如果位置编码太大,会"淹没"词嵌入的信息:

embedding = [0.5, 0.3, -0.2]   # 语义信息
position  = [10, 20, -15]       # 位置信息(太大了!)
combined  = [10.5, 20.3, -15.2] # 主要是位置信息

所以正弦/余弦位置编码的值在 [-1, 1] 之间,和 embedding 的量级相当。

14.8.3 可学习 vs 固定位置编码哪个好?

类型优点缺点
固定(正弦/余弦)理论上可外推到任意长度不一定是最优的
可学习能学到任务特定的位置模式只能处理见过的长度

实践中,可学习位置编码在多数任务上表现更好,所以 GPT 系列都用可学习的。


14.9 本章总结

14.9.1 核心概念

信息类型来源表示什么是否可学习
词嵌入Embedding 查表词的语义
位置编码位置 Embedding/正弦函数词的位置取决于实现
输入向量两者相加语义 + 位置-

14.9.2 为什么相加而不是拼接

  1. 维度不变:不增加计算量
  2. 信息叠加:高维空间可以容纳两种信息
  3. 可分离:Attention 可以学会分别利用两种信息

14.9.3 核心认知

词嵌入和位置编码通过简单的相加结合在一起,这种设计既高效又有效。词嵌入提供"是什么"的语义信息,位置编码提供"在哪里"的位置信息。Transformer 的 Attention 机制可以从这个混合向量中提取需要的信息,实现对语言的深度理解。


本章交付物

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

  • 解释词嵌入和位置编码分别表示什么
  • 说出为什么选择相加而不是拼接
  • 理解相加后信息如何被 Attention 利用
  • 知道可学习位置编码和固定位置编码的区别

下一章预告

现在我们理解了输入是如何准备的:词嵌入 + 位置编码 → 相加 → 输入向量。

下一章,我们将把所有组件串起来,追踪数据从输入到输出的完整前向传播过程。这是理解 Transformer 如何工作的最后一块拼图!

引用本文 / Cite
Zhang, W. (2026). 第 14 章:词嵌入与位置信息的深层逻辑 - 为什么相加而不是拼接. In Transformer 架构:从直觉到实现. https://waylandz.com/llm-transformer-book/第14章-词嵌入与位置信息的深层逻辑-为什么相加而不是拼接
@incollection{zhang2026transformer_第14章_词嵌入与位置信息的深层逻辑_为什么相加而不是拼接,
  author = {Zhang, Wayland},
  title = {第 14 章:词嵌入与位置信息的深层逻辑 - 为什么相加而不是拼接},
  booktitle = {Transformer 架构:从直觉到实现},
  year = {2026},
  url = {https://waylandz.com/llm-transformer-book/第14章-词嵌入与位置信息的深层逻辑-为什么相加而不是拼接}
}