Transformer 入门:从 Seq2Seq 到自注意力机制

背景:Transformer 解决的是什么问题

Transformer 最初可以放在 Seq2Seq 问题里理解:输入一个序列,输出另一个序列。机器翻译、文本摘要、对话生成、语音识别都属于这类问题。

传统 RNN/LSTM 按时间步顺序处理序列,天然适合顺序数据,但也带来两个问题:训练不容易完全并行,长距离依赖要经过很多步传递。Transformer 的核心变化是:不再依赖循环结构逐步传信息,而是让序列中的每个位置都可以直接和其他位置建立关系。

这就是自注意力机制的价值。

Transformer 总览

自注意力:让每个 token 直接看全局

自注意力机制做的事情可以概括为:

对序列中每个 token,计算它应该关注序列里哪些位置,再把相关位置的信息加权汇聚回来。

它带来两个直接收益。

第一是并行计算。序列中每个位置的注意力分数可以矩阵化计算,不必像 RNN 那样等待前一个时间步处理完。

第二是全局视野。任意两个 token 之间可以直接计算相关性,长距离信息不必层层传递,因此更适合处理长文本中的依赖关系。

从符号到向量:嵌入层

模型不能直接理解“词”这个符号。嵌入层的作用就是把词表中的 token 转成连续高维向量,例如 512 维向量。这样,文本从离散符号变成了可以参与矩阵运算的数据。

词嵌入空间有几个重要特点:

  • 语义相近的词在向量空间中距离更近;
  • 向量可以参与距离计算、相似度计算和梯度下降训练;
  • 自注意力后续计算 Q、K、V 时,依赖的正是这些可计算的向量表示。

词嵌入空间

不过,词向量本身只表示 token 的语义,不天然携带顺序。例如“我喜欢你”和“你喜欢我”的词集合相近,但顺序不同,含义也不同。因此 Transformer 还需要位置编码。

位置编码:给无序的注意力补上顺序感

自注意力本身是位置无关的。只看一组 token 向量,模型无法知道哪个词在前、哪个词在后。位置编码的做法是为每个位置生成一个位置向量,然后把它加到对应的词向量上:

1
token 表示 = 词嵌入 + 位置编码

经典 Transformer 使用正余弦位置编码:

其中, 表示 token 在序列中的位置, 表示维度索引, 表示嵌入维度。这样每个位置都有独特编码,模型就能在没有循环结构的情况下感知顺序。

正余弦位置编码

Q、K、V:注意力公式如何理解

注意力机制可以类比为一次检索。

  • Query:我想找什么;
  • Key:我能被什么样的问题匹配;
  • Value:我真正提供的信息。

在自注意力中,Q、K、V 都来自同一个输入序列 ,只是经过三组不同的线性变换:

单头缩放点积注意力的核心公式是:

这条公式可以分成四步理解:

  1. 计算每个 token 的 Query 与所有 Key 的相似度;
  2. 除以 做缩放,避免点积过大导致 softmax 过尖锐;
  3. 用 softmax 把相似度归一化成注意力权重;
  4. 用这些权重对 Value 加权求和,得到融合上下文后的新表示。

注意力机制

单头注意力

多头注意力:多个观察角度

单头注意力只有一套 QKV 投影,相当于只用一种检索方式看整个序列。多头注意力把输入投影到多组子空间中,让不同 head 学到不同关系:

1
2
3
4
5
head_1 = Attention(Q1, K1, V1)
head_2 = Attention(Q2, K2, V2)
...
head_h = Attention(Qh, Kh, Vh)
MultiHead = Concat(head_1, ..., head_h) W_O

可以把多个 head 理解成多个观察角度。有的 head 可能更关注邻近词的语法绑定,有的 head 可能更关注长距离语义关系。最后再把这些视角拼接并线性变换,形成综合表示。

Add & Norm 与前馈网络

Transformer 层并不是只有注意力。每个子模块外面通常还会有残差连接和层归一化:

1
2
x = x + Attention(x)
x = x + FFN(x)

残差连接的意义是保留原始信息通路,让模型只需要学习“增量修正”。这对堆叠很多层时的训练稳定性很重要。

注意力层负责收集和融合全局关系,前馈网络则负责对每个位置的表示做非线性变换。一个常见前馈网络由两层线性层和激活函数组成:

1
Linear -> ReLU/GELU -> Linear

如果说多头注意力是在“收集上下文线索”,那么前馈网络就是在每个 token 位置上“消化这些线索”,提取更抽象的语义特征。

Encoder-Decoder:理解整体流程

完整 Transformer 常被描述为 Encoder-Decoder 架构。

Encoder 处理源序列,例如中文句子。它的流程是:

  1. token 进入词嵌入层;
  2. 加上位置编码;
  3. 经过多层 Encoder,每层包含多头自注意力、Add & Norm、前馈网络;
  4. 输出一组带全局上下文的语义表示。

Transformer Encoder

Decoder 负责生成目标序列,例如英文翻译。它每层通常有三块:

  1. Masked Self-Attention:只能看已经生成的 token,不能偷看未来;
  2. Cross-Attention:用 Decoder 当前状态作为 Query,去 Encoder 输出中查找信息;
  3. Feed Forward:进一步处理当前表示。

Cross-Attention 的 Q、K、V 来源不同:

也就是说,Decoder 根据“当前生成到哪里了”,去 Encoder 的源句子表示中查询下一步最需要的信息。最后经过线性层和 softmax,得到下一个 token 的概率分布。

阶段性结论

这篇笔记当前可以先记住一条主线:

1
2
3
4
5
6
7
8
Seq2Seq 问题
-> 需要建模长距离依赖
-> 自注意力让 token 两两直接建立关系
-> 词嵌入提供语义向量
-> 位置编码补上顺序信息
-> QKV 完成可学习的信息检索
-> 多头注意力提供多视角关系建模
-> Encoder 理解输入,Decoder 逐步生成输出

Transformer 的关键不是某一个公式,而是它把序列建模从“按时间步传递状态”改成了“在全局范围内直接计算依赖关系”。理解这一点后,后续再看 BERT、GPT、ViT 或多模态 Transformer,就更容易把它们放回同一套结构里。