mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
719 字
2 分钟
Transformer 架构革命:Attention Is All You Need
2025-01-23

2017 年,Google 团队发表了一篇论文,标题简洁有力:《Attention Is All You Need》。

这篇论文提出的 Transformer 架构,彻底改变了自然语言处理领域。从此,「注意力机制」成为 AI 模型的核心组件,RNN 和 CNN 逐渐退出历史舞台。

Transformer 是大语言模型时代的基石。

本文要点#

  • 论文背景与动机
  • 自注意力机制详解
  • 多头注意力设计
  • 位置编码原理
  • Encoder-Decoder 架构
  • 可视化图解

一、论文背景#

1.1 研究动机#

flowchart TB subgraph 2017年前NLP格局 A[主流架构] A --> B[RNN 循环神经网络] A --> C[LSTM 长短期记忆网络] A --> D[CNN 卷积神经网络] B --> B1[问题:无法并行,长距离依赖困难] C --> C1[问题:训练慢,梯度问题] D --> D1[问题:局部感受野,难以捕获长距离关系] E[核心痛点] E --> E1[序列计算无法并行] E --> E2[长距离依赖建模困难] E --> E3[训练效率低] F[Transformer 的解决] F --> F1[完全基于注意力机制,无需循环] F --> F2[并行计算,训练效率大幅提升] F --> F3[任意距离的依赖都可以直接建模] end

1.2 论文信息#

论文:Attention Is All You Need
作者:Ashish Vaswani, Noam Shazeer, Niki Parmar,
Jakob Uszkoreit, Llion Jones, Aidan N. Gomez,
Łukasz Kaiser, Illia Polosukhin
机构:Google Brain, Google Research
发表:NeurIPS 2017
引用:10万+ 次(截至 2025 年)

二、自注意力机制#

2.1 核心思想#

自注意力(Self-Attention)让序列中的每个位置都能直接关注到其他所有位置。

flowchart LR subgraph 自注意力计算 A[输入 X] --> B[Query Q] A --> C[Key K] A --> D[Value V] B --> E[注意力分数] C --> E E --> F[Softmax] F --> G[加权求和] D --> G G --> H[输出] end

2.2 数学表达#

flowchart TB subgraph 自注意力公式 A["Attention(Q, K, V) = softmax(QK^T / √d_k) V"] B[其中] B --> B1["Q = XW_Q (Query,查询矩阵)"] B --> B2["K = XW_K (Key,键矩阵)"] B --> B3["V = XW_V (Value,值矩阵)"] B --> B4["d_k = Key 的维度(用于缩放,防止梯度消失)"] C[直观理解] C --> C1["Query:我在找什么?"] C --> C2["Key:你有什么特征?"] C --> C3["Value:你的内容是什么?"] C --> C4["注意力分数:Query 和 Key 的相似度"] end

2.3 计算过程详解#

import torch
import torch.nn.functional as F
def self_attention(X, W_q, W_k, W_v):
"""
自注意力计算
Args:
X: 输入序列 [batch, seq_len, d_model]
W_q, W_k, W_v: 投影矩阵
"""
# 1. 计算 Q, K, V
Q = X @ W_q # [batch, seq_len, d_k]
K = X @ W_k # [batch, seq_len, d_k]
V = X @ W_v # [batch, seq_len, d_v]
# 2. 计算注意力分数
d_k = Q.size(-1)
scores = Q @ K.transpose(-2, -1) / torch.sqrt(torch.tensor(d_k))
# scores: [batch, seq_len, seq_len]
# 3. Softmax 归一化
attention_weights = F.softmax(scores, dim=-1)
# 4. 加权求和
output = attention_weights @ V
return output, attention_weights
# 示例:理解「The animal didn't cross the street because it was too tired」
# 当处理「it」时,注意力机制会关注到「animal」

2.4 可视化:注意力权重#

flowchart TB subgraph 句子注意力示例 A["The"] --> B["animal"] B --> C["didn't"] C --> D["cross"] D --> E["the"] E --> F["street"] F --> G["because"] G --> H["it"] H --> I["was"] I --> J["too"] J --> K["tired"] end L["处理 'it' 时的注意力"] --> M["高权重 → 'animal'"] L --> N["低权重 → 'street'"] style H fill:#ff9800,color:#fff style B fill:#4caf50,color:#fff

三、多头注意力#

3.1 为什么需要多头?#

单个注意力头的问题:
• 只能学习一种「关注模式」
• 表达能力有限
多头注意力的优势:
• 不同的头关注不同的位置关系
• 就像多个人从不同角度观察
• 捕获更丰富的语义信息

3.2 架构设计#

flowchart TB A[输入 X] --> B[Head 1] A --> C[Head 2] A --> D[Head 3] A --> E["..."] A --> F[Head h] B --> G[Concat] C --> G D --> G E --> G F --> G G --> H[Linear] H --> I[输出]

3.3 数学表达#

flowchart TB subgraph 多头注意力公式 A["MultiHead(Q, K, V) = Concat(head_1, ..., head_h) W_O"] B[其中] B --> B1["head_i = Attention(QW_Qi, KW_Ki, VW_Vi)"] C[参数说明] C --> C1["h:头的数量(原论文 h=8)"] C --> C2["d_k = d_model / h(每个头的维度)"] C --> C3["W_O:输出投影矩阵"] D[原论文配置] D --> D1["d_model = 512"] D --> D2["h = 8"] D --> D3["d_k = d_v = 64"] end

3.4 代码实现#

class MultiHeadAttention(nn.Module):
"""多头注意力实现"""
def __init__(self, d_model=512, num_heads=8):
super().__init__()
self.num_heads = num_heads
self.d_k = d_model // num_heads
# Q, K, V 投影
self.W_q = nn.Linear(d_model, d_model)
self.W_k = nn.Linear(d_model, d_model)
self.W_v = nn.Linear(d_model, d_model)
# 输出投影
self.W_o = nn.Linear(d_model, d_model)
def forward(self, x, mask=None):
batch_size, seq_len, d_model = x.size()
# 1. 投影并分割成多头
Q = self.W_q(x).view(batch_size, seq_len, self.num_heads, self.d_k).transpose(1, 2)
K = self.W_k(x).view(batch_size, seq_len, self.num_heads, self.d_k).transpose(1, 2)
V = self.W_v(x).view(batch_size, seq_len, self.num_heads, self.d_k).transpose(1, 2)
# 2. 计算注意力
scores = torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(self.d_k)
if mask is not None:
scores = scores.masked_fill(mask == 0, -1e9)
attention = F.softmax(scores, dim=-1)
# 3. 加权求和
context = torch.matmul(attention, V)
# 4. 合并多头
context = context.transpose(1, 2).contiguous().view(batch_size, seq_len, d_model)
# 5. 输出投影
output = self.W_o(context)
return output

四、位置编码#

4.1 为什么需要位置编码?#

问题:
• 自注意力是置换不变的
• 打乱词序,注意力输出不变
• 无法区分「猫吃鱼」和「鱼吃猫」
解决:
• 添加位置信息
• 让模型知道每个词的位置

4.2 正弦余弦编码#

flowchart TB subgraph 位置编码公式 A["PE(pos, 2i) = sin(pos / 10000^(2i/d_model))"] A1["PE(pos, 2i+1) = cos(pos / 10000^(2i/d_model))"] B[其中] B --> B1["pos:位置索引(0, 1, 2, ...)"] B --> B2["i:维度索引(0 到 d_model/2 - 1)"] C[设计思想] C --> C1["不同频率的正弦余弦组合"] C --> C2["偶数维度用 sin,奇数维度用 cos"] C --> C3["可以学习相对位置关系"] C --> C4["可以外推到任意长度"] end

4.3 可视化#

import numpy as np
import matplotlib.pyplot as plt
def get_positional_encoding(max_len, d_model):
"""生成位置编码"""
PE = np.zeros((max_len, d_model))
for pos in range(max_len):
for i in range(0, d_model, 2):
PE[pos, i] = np.sin(pos / (10000 ** (i / d_model)))
if i + 1 < d_model:
PE[pos, i + 1] = np.cos(pos / (10000 ** (i / d_model)))
return PE
# 可视化:每个位置有独特的编码模式
# 不同频率捕获不同尺度的位置关系

五、Encoder-Decoder 架构#

5.1 整体架构#

flowchart TB subgraph Encoder E1[输入嵌入 + 位置编码] E2[多头自注意力] E3[Add & Norm] E4[前馈网络] E5[Add & Norm] E6[× N 层] E1 --> E2 --> E3 --> E4 --> E5 --> E6 end subgraph Decoder D1[输出嵌入 + 位置编码] D2[掩码多头自注意力] D3[Add & Norm] D4[编码器-解码器注意力] D5[Add & Norm] D6[前馈网络] D7[Add & Norm] D8[× N 层] D9[Linear + Softmax] D1 --> D2 --> D3 --> D4 --> D5 --> D6 --> D7 --> D8 --> D9 end E6 --> D4

5.2 Encoder 层详解#

flowchart TB subgraph Encoder层结构 A[每个 Encoder 层包含] A --> B[多头自注意力子层] B --> B1[输入来自上一层的输出] B --> B2[每个位置可以关注所有位置] A --> C[前馈神经网络子层] C --> C1[两层全连接 + ReLU] C --> C2["FFN(x) = max(0, xW_1 + b_1)W_2 + b_2"] C --> C3[中间维度通常是 d_model 的 4 倍] A --> D[残差连接 + 层归一化] D --> D1["LayerNorm(x + Sublayer(x))"] D --> D2[稳定训练,缓解梯度问题] E[原论文配置] E --> E1["N = 6 层"] E --> E2["d_model = 512"] E --> E3["d_ff = 2048"] end

5.3 Decoder 层详解#

flowchart TB subgraph Decoder层结构 A[每个 Decoder 层包含] A --> B[掩码多头自注意力子层] B --> B1[防止位置关注到后面的位置(自回归)] B --> B2[训练时的因果掩码] A --> C[编码器-解码器注意力子层] C --> C1[Query 来自 Decoder] C --> C2[Key 和 Value 来自 Encoder 输出] C --> C3[让解码器关注输入序列的相关部分] A --> D[前馈神经网络子层] D --> D1[与 Encoder 相同] E[掩码的作用] E --> E1[训练时:已知目标序列,但需要掩盖未来信息] E --> E2[推理时:逐词生成,只能看到已生成的词] end

六、Jay Alammar 可视化图解#

6.1 The Illustrated Transformer#

Jay Alammar 的可视化解读是理解 Transformer 的最佳入门材料。

核心可视化要点:
1. 整体架构图
• 左边是 Encoder(6 层堆叠)
• 右边是 Decoder(6 层堆叠)
• 箭头表示数据流动方向
2. 自注意力可视化
• 矩阵形式展示 Q、K、V 计算
• 注意力权重用颜色深浅表示
• 每个词对其他词的关注程度
3. 多头注意力可视化
• 不同的头关注不同的语义关系
• 比如有的头关注语法关系
• 有的头关注语义关系
4. 位置编码可视化
• 每个位置有独特的编码向量
• 不同频率的正弦波
• 捕获不同尺度的位置信息

6.2 注意力矩阵可视化#

flowchart TB subgraph 注意力矩阵 A["位置 0"] --> B["位置 1"] A --> C["位置 2"] A --> D["位置 3"] E["位置 1"] --> F["高权重关注"] E --> G["低权重关注"] H["颜色深浅"] --> I["表示注意力权重"] end

七、实验结果与影响#

7.1 WMT 机器翻译任务#

xychart-beta title "WMT 2014 英德翻译 BLEU 分数" x-axis ["GNMT", "ConvS2S", "Transformer (base)", "Transformer (big)"] y-axis "BLEU" 20 --> 30 bar [24.6, 25.1, 27.3, 28.4]
flowchart TB subgraph 实验结果亮点 A[性能提升] A --> A1["英德翻译:BLEU 28.4,超越之前最佳 2.0 分"] A --> A2["英法翻译:BLEU 41.8,新 SOTA"] B[训练效率] B --> B1["训练时间:从几天缩短到 12 小时"] B --> B2["并行化:所有位置同时计算"] B --> B3["硬件利用:GPU 利用率大幅提升"] C[模型规模] C --> C1["Base:65M 参数,6 层"] C --> C2["Big:213M 参数,6 层"] end

7.2 对后续研究的影响#

flowchart TB subgraph Transformer的影响 A[架构影响] A --> A1[GPT 系列:仅使用 Decoder] A --> A2[BERT 系列:仅使用 Encoder] A --> A3[T5:完整 Encoder-Decoder] A --> A4[所有现代 LLM 都基于 Transformer] B[技术影响] B --> B1[注意力机制成为标配] B --> B2[位置编码被广泛采用] B --> B3[残差连接 + LayerNorm 成为标准] B --> B4[多头注意力提升表达能力] C[产业影响] C --> C1[Google 搜索、翻译全面升级] C --> C2[ChatGPT、Claude 等产品诞生] C --> C3[开启大模型时代] end

常见问题 FAQ#

Q1:Transformer 为什么比 RNN 快?

A:RNN 必须顺序处理,每个时间步依赖前一个时间步。Transformer 使用自注意力,所有位置可以并行计算,充分利用 GPU 并行能力。

Q2:自注意力的复杂度是多少?

A:时间复杂度 O(n²d),空间复杂度 O(n²)。n 是序列长度,d 是维度。长序列是 Transformer 的主要瓶颈。

Q3:为什么用 sin/cos 位置编码?

A:1)可以外推到任意长度;2)相对位置可以通过线性变换得到;3)不需要学习,减少参数。

Q4:Encoder 和 Decoder 的区别是什么?

A:Encoder 是双向的(可以看到所有输入),Decoder 是单向的(只能看到已生成的)。GPT 只用 Decoder,BERT 只用 Encoder。

Q5:Transformer 有什么缺点?

A:1)长序列计算复杂度高;2)位置编码对超长序列效果下降;3)内存占用大。


小结#

《Attention Is All You Need》是 NLP 历史上最重要的论文之一。

核心贡献:

flowchart TB subgraph Transformer核心总结 A[自注意力] --> A1[让每个位置直接关注所有位置] B[多头注意力] --> B1[从多个角度捕获语义关系] C[位置编码] --> C1[为序列注入位置信息] D[并行计算] --> D1[训练效率大幅提升] E[影响深远] --> E1[开启大语言模型时代] end

参考资料#

支持与分享

如果这篇文章对你有帮助,欢迎支持作者或分享给更多人

Transformer 架构革命:Attention Is All You Need
https://blog.souloss.com/posts/machine-learning/llm-paper-history/transformer-architecture-revolution/
作者
Souloss
发布于
2025-01-23
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时