Transformer 模型由 Google Brain 团队在 2017 年的论文 “Attention Is All You Need” 中提出。它彻底改变了自然语言处理 (NLP) 领域,并成为了当前大语言模型 (LLM) 的基石。Transformer 模型以其强大的并行计算能力和卓越的长距离依赖建模能力,取代了传统的循环神经网络 (RNN) 和长短期记忆网络 (LSTM) 结构,成为了序列建模任务的主流架构。

核心思想:Transformer 放弃了传统的循环和卷积结构,完全依赖于注意力机制 (Attention Mechanism)来捕捉输入序列中的依赖关系。通过精心设计的自注意力 (Self-Attention) 机制,模型能够同时关注输入序列中的所有位置,从而实现高效的并行计算和对任意距离依赖的有效建模。


一、为什么需要 Transformer?

在 Transformer 出现之前,RNN 及其变体 (如 LSTM 和 GRU) 是序列建模任务的主流。然而,它们存在一些固有的局限性:

  1. 顺序依赖:RNN 必须顺序地处理序列中的每个元素,后一个元素的计算依赖于前一个元素。这导致:
    • 难以并行化:限制了训练速度,尤其是在处理长序列时。
    • 长距离依赖问题:随着序列长度增加,信息在传播过程中逐渐衰减,模型难以捕捉到相距较远元素之间的关联,即“梯度消失”或“梯度爆炸”问题。
  2. 计算效率低下:每个时间步的计算都需要等待前一个时间步的结果,导致训练和推理速度慢。

Transformer 模型通过引入自注意力机制,有效地解决了这些问题,实现了序列建模的范式转变。

二、Transformer 架构概览

Transformer 模型遵循经典的编码器-解码器 (Encoder-Decoder) 结构,但其内部实现完全基于注意力机制。

整体结构:

  • 编码器 (Encoder):由 N 个相同的编码器层堆叠而成。它负责将输入序列(例如,源语言句子)转换为一系列连续的表示。
  • 解码器 (Decoder):由 N 个相同的解码器层堆叠而成。它负责将编码器的输出和之前生成的输出序列(例如,目标语言句子)作为输入,生成下一个输出序列的元素。

三、编码器 (Encoder) 详解

每个编码器层包含两个主要的子层:

  1. 多头自注意力机制 (Multi-Head Self-Attention)
  2. 前馈神经网络 (Feed-Forward Network, FFN)

每个子层之后都跟着一个残差连接 (Residual Connection)层归一化 (Layer Normalization)

3.1 输入嵌入 (Input Embedding) 与位置编码 (Positional Encoding)

在将输入序列送入编码器之前,每个词(token)首先被转换成一个词向量 (Word Embedding)。由于 Transformer 模型不包含循环或卷积,它自身无法感知输入序列中词的顺序信息。因此,需要引入位置编码来注入词的位置信息。

位置编码公式:

我们使用不同频率的正弦和余弦函数来生成位置编码:

$$
PE_{(pos, 2i)} = \sin(pos / 10000^{2i/d_{model}}) \
PE_{(pos, 2i+1)} = \cos(pos / 10000^{2i/d_{model}})
$$

其中:

  • pos 是词在序列中的位置 (0 到 max_sequence_length - 1)。
  • i 是位置编码向量的维度索引 (0 到 d_model/2 - 1)。
  • d_model 是词向量的维度。

最终的输入是词嵌入和位置编码的简单求和。

3.2 多头自注意力机制 (Multi-Head Self-Attention)

这是 Transformer 的核心,允许模型在处理序列的某个词时,同时关注序列中的其他词,并计算它们之间的关联性。

a. 自注意力 (Self-Attention)

对于输入序列中的每个词,自注意力机制会计算三个向量:查询 (Query, Q)键 (Key, K)值 (Value, V)。它们通过将词嵌入向量与三个不同的权重矩阵 $W^Q, W^K, W^V$ 相乘得到。

一旦有了 Q、K、V 向量,我们就可以计算自注意力的输出了:

  1. 计算注意力分数:将查询向量 $Q$ 与所有键向量 $K$ 进行点积,得到注意力分数。点积衡量了查询与每个键之间的相似度。
  2. 缩放 (Scaling):为了防止点积结果过大导致 softmax 函数进入梯度饱和区,将注意力分数除以 $\sqrt{d_k}$ (键向量的维度)。
  3. Softmax:对缩放后的分数应用 Softmax 函数,将其转换为概率分布,表示每个词对当前词的关注程度。
  4. 加权求和:将 Softmax 结果(注意力权重)与所有值向量 $V$ 相乘并求和,得到当前词的自注意力输出。

Scaled Dot-Product Attention 公式:

$$
Attention(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V
$$

其中:

  • $Q$ 是查询矩阵 (queries, 维度 $n \times d_k$)。
  • $K$ 是键矩阵 (keys, 维度 $m \times d_k$)。
  • $V$ 是值矩阵 (values, 维度 $m \times d_v$)。
  • $n$ 是输出序列长度, $m$ 是输入序列长度。在自注意力中,$n=m$。
  • $d_k$ 是键向量的维度。

b. 多头注意力 (Multi-Head Attention)

多头注意力是自注意力机制的扩展。它将 Q、K、V 投影到 $h$ 个不同的子空间中($h$ 为头的数量),然后独立地并行执行 $h$ 次自注意力计算。每个头都可以学习到不同的关注模式。最后,将所有头的输出拼接起来,再通过一个线性投影得到最终输出。

多头注意力使得模型能够:

  • 在不同的表示子空间中捕捉到不同类型的依赖关系。
  • 提高模型捕捉复杂模式的能力。

3.3 Add & Norm (残差连接与层归一化)

每个子层(多头自注意力或前馈网络)的输出都会与该子层的输入进行残差连接,然后进行层归一化。

  • 残差连接:$x + \text{Sublayer}(x)$。有助于解决深度网络中的梯度消失问题,使信息能够更容易地在网络中传播。
  • 层归一化 (Layer Normalization):对每个样本的特征维度进行归一化,稳定了深层网络的训练过程。

3.4 前馈神经网络 (Feed-Forward Network, FFN)

FFN 是一个简单的两层全连接网络,通常包含一个 ReLU 激活函数:

$FFN(x) = \max(0, xW_1 + b_1)W_2 + b_2$

它对每个位置独立地进行相同的转换。

四、解码器 (Decoder) 详解

每个解码器层包含三个主要子层:

  1. 遮盖多头自注意力机制 (Masked Multi-Head Self-Attention)
  2. 多头编码器-解码器注意力机制 (Multi-Head Encoder-Decoder Attention)
  3. 前馈神经网络 (Feed-Forward Network, FFN)

同样,每个子层之后也跟着一个残差连接和层归一化。

4.1 遮盖多头自注意力 (Masked Multi-Head Self-Attention)

与编码器中的自注意力类似,但它在 Softmax 之前引入了一个“遮盖”机制。
遮盖 (Masking):确保解码器在预测当前位置的输出时,只能关注当前位置及之前的词,而不能“看到”未来的词。这模拟了序列生成的顺序性。

4.2 多头编码器-解码器注意力 (Multi-Head Encoder-Decoder Attention)

这个注意力层用于连接编码器和解码器。

  • 查询 (Q) 向量来自前一个解码器层的输出。
  • 键 (K)值 (V) 向量来自编码器层的输出。

这使得解码器在生成输出时,能够关注输入序列中的相关部分。

4.3 最终输出层

解码器的输出经过一个线性层 (Linear Layer) 和一个 Softmax 层,转换为词汇表上每个词的概率分布,从而预测下一个词。

五、Transformer 的训练

Transformer 通常通过最大化下一个词的对数似然进行训练,即一个标准的序列到序列任务的交叉熵损失函数。优化器常采用 Adam,并结合自定义的学习率调度策略。

六、Transformer 的优缺点与应用

6.1 优点

  1. 并行计算能力:自注意力机制允许模型同时处理序列中的所有词,极大地提高了训练效率。
  2. 有效捕捉长距离依赖:通过注意力机制,模型可以轻松地连接相距很远的词,克服了 RNN 的长距离依赖问题。
  3. 更少的归纳偏置 (Inductive Bias):相较于 CNN 和 RNN,Transformer 对数据结构的假设更少,理论上可以学习更广泛的模式。
  4. 模型可解释性:注意力权重可以部分揭示模型在决策时关注了哪些输入部分。

6.2 缺点

  1. 计算复杂度:自注意力机制的计算复杂度是序列长度 $L$ 的平方 ($O(L^2)$),对于非常长的序列,计算成本非常高。
  2. 位置编码依赖:Transformer 本身不具备处理顺序的能力,必须依赖于位置编码。
  3. 内存消耗:Q、K、V 矩阵以及注意力矩阵的存储需要大量内存,尤其是在处理长序列时。

6.3 典型应用

Transformer 模型及其变体已成为各种 AI 任务的核心:

  • 自然语言处理 (NLP)
    • 机器翻译 (Machine Translation)
    • 文本摘要 (Text Summarization)
    • 问答系统 (Question Answering)
    • 情感分析 (Sentiment Analysis)
    • 预训练语言模型 (如 BERT, GPT 系列, T5)
  • 计算机视觉 (CV)
    • 图像分类 (Vision Transformer, ViT)
    • 目标检测 (DETR)
    • 图像生成
  • 语音识别 (Speech Recognition)
  • 多模态任务 (结合文本和图像等)

七、核心组件 Go 语言代码示例 (概念性)

由于 Go 语言在深度学习模型构建方面不如 Python (TensorFlow/PyTorch) 常用,以下提供一个概念性的 Go 语言实现,着重展示 Scaled Dot-Product Attention 的核心计算逻辑。实际的矩阵运算在 Go 中通常会依赖专门的线性代数库。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package transformer

import (
"fmt"
"math"
"gonum.org/v1/gonum/mat" // 假设使用gonum/mat进行矩阵操作
)

// ScaledDotProductAttention 实现缩放点积注意力
// Q: Query 矩阵
// K: Key 矩阵
// V: Value 矩阵
// mask: 可选的注意力掩码 (例如,用于解码器自注意力)
// 返回注意力机制的输出矩阵
func ScaledDotProductAttention(Q, K, V *mat.Dense, mask *mat.Dense) (*mat.Dense, error) {
// 1. QK^T
// 获取 Q 的行数和 K 的列数,K^T 的行数是 K 的列数
rQ, cQ := Q.Dims()
rK, cK := K.Dims()

// 确保 Q 的列数等于 K 的列数 (d_k)
if cQ != cK {
return nil, fmt.Errorf("query and key dimensions mismatch: cQ=%d, cK=%d", cQ, cK)
}

// K 转置
Kt := mat.NewDense(cK, rK, nil)
Kt.CloneFrom(K.T()) // K.T() 返回的是 View,需要CloneFrom

scores := mat.NewDense(rQ, rK, nil) // rQ x rK (m x m for self-attention)
scores.Mul(Q, Kt) // QK^T

// 2. 缩放 (Scaling)
dk := float64(cQ) // d_k 是 Q 的列数 (或 K 的列数)
scaleFactor := math.Sqrt(dk)
scores.Scale(1/scaleFactor, scores)

// 3. 应用掩码 (如果存在)
if mask != nil {
rMask, cMask := mask.Dims()
if rMask != rQ || cMask != rK {
return nil, fmt.Errorf("mask dimensions mismatch: expected %dx%d, got %dx%d", rQ, rK, rMask, cMask)
}
// 遍历 scores 矩阵,将 mask 为 0 的位置替换为负无穷
scores.Apply(func(r, c int, v float64) float64 {
if mask.At(r, c) == 0 { // 假设 mask 为 0 表示该位置被遮盖
return math.Inf(-1) // 负无穷
}
return v
}, scores)
}

// 4. Softmax
// 需要对每一行独立进行 Softmax
rScores, cScores := scores.Dims()
attentionWeights := mat.NewDense(rScores, cScores, nil)

for r := 0; r < rScores; r++ {
row := mat.Row(nil, r, scores)
// 计算行的指数和
sumExp := 0.0
for _, val := range row {
sumExp += math.Exp(val)
}
// 计算 softmax 值
for c := 0; c < cScores; c++ {
attentionWeights.Set(r, c, math.Exp(row[c])/sumExp)
}
}

// 5. 与 Value 矩阵相乘
rV, cV := V.Dims()
if cScores != rV { // attentionWeights 的列数必须等于 V 的行数
return nil, fmt.Errorf("attention weights column count %d mismatches Value matrix row count %d", cScores, rV)
}

output := mat.NewDense(rQ, cV, nil) // 输出维度 rQ x cV
output.Mul(attentionWeights, V)

return output, nil
}

/*
// 示例用法:
func main() {
// 假设 d_model = 4, sequence_length = 3
// Q, K, V 都是 (sequence_length, d_k) 矩阵
// 在自注意力中,d_k 通常等于 d_model / num_heads

qData := []float64{
1.0, 0.0, 1.0, 0.0,
0.0, 1.0, 0.0, 1.0,
1.0, 1.0, 0.0, 0.0,
}
kData := []float64{
1.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 1.0,
1.0, 0.0, 1.0, 0.0,
}
vData := []float64{
2.0, 0.0, 2.0, 0.0,
0.0, 3.0, 0.0, 3.0,
4.0, 4.0, 0.0, 0.0,
}

Q := mat.NewDense(3, 4, qData)
K := mat.NewDense(3, 4, kData)
V := mat.NewDense(3, 4, vData)

fmt.Println("Q:\n", mat.Formatted(Q))
fmt.Println("K:\n", mat.Formatted(K))
fmt.Println("V:\n", mat.Formatted(V))

// 模拟一个掩码 (例如,下三角矩阵用于 masked self-attention)
maskData := []float64{
1, 0, 0,
1, 1, 0,
1, 1, 1,
}
mask := mat.NewDense(3, 3, maskData)
fmt.Println("Mask:\n", mat.Formatted(mask))


output, err := ScaledDotProductAttention(Q, K, V, mask)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("Attention Output:\n", mat.Formatted(output))
}
*/

八、总结

Transformer 模型以其完全基于注意力机制的创新设计,彻底改变了深度学习在序列建模领域的应用。它通过并行计算能力和对长距离依赖的有效捕捉,超越了传统 RNN 模型的局限性,成为 NLP、CV 等众多领域的核心模型。从机器翻译到大语言模型,Transformer 及其变体持续推动着人工智能技术的发展。理解其编码器-解码器架构、多头自注意力机制和位置编码是理解现代 AI 模型工作原理的关键。