Attention Is All You Need

提出 Transformer 架构,以纯注意力机制替代 RNN/CNN,重写了序列建模的工程范式与研究方向。

年份与会议

2017 · NeurIPS

作者

Ashish Vaswani、Noam Shazeer、Niki Parmar、Jakob Uszkoreit

主题

Transformer

阅读时长

约 3 分钟

收录时间

2017/06/12

标签

原文链接

https://arxiv.org/abs/1706.03762

这篇论文解决了什么问题

在 Transformer 出现之前,主流序列模型主要是 RNN、LSTM 以及少量卷积式 seq2seq。它们都能做机器翻译,但存在两个很现实的工程问题:

  1. 序列必须按时间步推进,训练难以充分并行,GPU 利用率不高。
  2. 长距离依赖需要跨很多步传播,信息容易衰减,优化难度大。

《Attention Is All You Need》最重要的贡献,不只是“提出了一种新模型”,而是提出了一个新的判断标准:对于序列建模,是否真的必须依赖递归结构?作者给出的答案是否定的。他们用纯注意力机制搭建了完整的 encoder-decoder 架构,在翻译任务上取得了更好结果,同时显著缩短训练时间。

从今天回头看,这篇论文的真正历史地位在于,它把“并行友好、可扩展、易于堆叠”的设计思路变成了后续大模型时代的默认前提。

方法总览:Transformer 的骨架

Transformer 仍然保留了经典的 seq2seq 任务分解方式:

  1. Encoder 负责把输入序列编码成上下文表示。
  2. Decoder 负责基于已生成内容和 encoder 表示,逐步预测下一个 token。

与传统 seq2seq 的区别在于,Transformer 的每一层都不再依赖循环单元,而是由以下模块组成:

  • Multi-Head Self-Attention
  • Encoder-Decoder Attention
  • Position-wise Feed Forward Network
  • Residual Connection + LayerNorm

Encoder 的每一层包括“自注意力 + 前馈网络”;Decoder 的每一层包括“带 mask 的自注意力 + encoder-decoder attention + 前馈网络”。这种结构简单、规则、易堆叠,非常适合做深层网络和大规模训练。

如果把这篇论文最关键的结构压成一张图,可以得到下面这条主线:

Transformer 编码器解码器结构图 输入 token 经过 embedding 和位置编码进入编码器堆栈;解码端经过 masked self-attention、encoder-decoder attention 和前馈网络后,通过线性层与 softmax 输出下一个 token。 Transformer 的最小骨架
  <g>
    <rect x="42" y="92" width="168" height="66" rx="18" fill="#e8f1ff" stroke="#98b7e1" />
    <text x="126" y="122" text-anchor="middle" font-size="19" font-weight="700">输入 Token</text>
    <text x="126" y="145" text-anchor="middle" font-size="13" fill="#4b5563">Embedding + 位置编码</text>
  </g>

  <g>
    <rect x="260" y="72" width="220" height="208" rx="22" fill="#f6f9ff" stroke="#d7e2f1" />
    <text x="370" y="102" text-anchor="middle" font-size="21" font-weight="700">Encoder Stack</text>
    <rect x="292" y="122" width="156" height="44" rx="14" fill="#eef6e8" stroke="#a8c48e" />
    <text x="370" y="149" text-anchor="middle" font-size="17" font-weight="700">Multi-Head Self-Attention</text>
    <rect x="292" y="182" width="156" height="44" rx="14" fill="#fff4dc" stroke="#e2c36f" />
    <text x="370" y="209" text-anchor="middle" font-size="17" font-weight="700">Feed Forward</text>
    <rect x="292" y="242" width="156" height="24" rx="10" fill="#f4ebff" stroke="#c7afe8" />
    <text x="370" y="258" text-anchor="middle" font-size="12" fill="#4b5563">Residual + LayerNorm + 堆叠 N 层</text>
  </g>

  <g>
    <rect x="542" y="72" width="220" height="208" rx="22" fill="#fbfaf5" stroke="#e6ddc4" />
    <text x="652" y="102" text-anchor="middle" font-size="21" font-weight="700">Decoder Stack</text>
    <rect x="574" y="118" width="156" height="40" rx="14" fill="#fce7ef" stroke="#e2a8bd" />
    <text x="652" y="143" text-anchor="middle" font-size="16" font-weight="700">Masked Self-Attention</text>
    <rect x="574" y="172" width="156" height="40" rx="14" fill="#e0f2e5" stroke="#8bc09b" />
    <text x="652" y="197" text-anchor="middle" font-size="16" font-weight="700">Encoder-Decoder Attention</text>
    <rect x="574" y="226" width="156" height="40" rx="14" fill="#fff4dc" stroke="#e2c36f" />
    <text x="652" y="251" text-anchor="middle" font-size="16" font-weight="700">Feed Forward</text>
  </g>

  <g>
    <rect x="804" y="92" width="134" height="66" rx="18" fill="#dff4f0" stroke="#8dc7bd" />
    <text x="871" y="120" text-anchor="middle" font-size="18" font-weight="700">输出分布</text>
    <text x="871" y="143" text-anchor="middle" font-size="13" fill="#4b5563">Linear + Softmax</text>
  </g>

  <g>
    <rect x="42" y="222" width="168" height="58" rx="18" fill="#fef3c7" stroke="#e2c36f" />
    <text x="126" y="255" text-anchor="middle" font-size="18" font-weight="700">已生成 Token</text>
  </g>

  <line x1="210" y1="125" x2="260" y2="125" stroke="#5b6b7f" stroke-width="3" marker-end="url(#transformer-arrow)" />
  <line x1="480" y1="125" x2="542" y2="125" stroke="#5b6b7f" stroke-width="3" marker-end="url(#transformer-arrow)" />
  <line x1="762" y1="125" x2="804" y2="125" stroke="#5b6b7f" stroke-width="3" marker-end="url(#transformer-arrow)" />
  <line x1="210" y1="251" x2="542" y2="251" stroke="#5b6b7f" stroke-width="3" marker-end="url(#transformer-arrow)" />
  <line x1="480" y1="206" x2="574" y2="206" stroke="#5b6b7f" stroke-width="3" marker-end="url(#transformer-arrow)" />
  <text x="528" y="196" font-size="13" fill="#4b5563">encoder 输出作为 memory</text>
</g>
Transformer 最关键的变化,不是保留了 seq2seq,而是把其中的循环单元替换成了统一、可并行堆叠的注意力模块。

核心机制一:Scaled Dot-Product Attention

论文最核心的计算模块可以写成:

Attention(Q, K, V) = softmax(QK^T / sqrt(d_k))V

可以把它理解成一个三步过程:

  1. 用 query 和所有 key 做匹配,得到“我要关注谁”的分数。
  2. 用 softmax 把分数归一化为权重分布。
  3. 用这些权重对 value 做加权求和,形成新的表示。

这里的关键设计有两个:

  • 使用点积来衡量 query 与 key 的相似度,计算效率高,适合矩阵并行。
  • 除以 sqrt(d_k) 做缩放,避免维度增大时点积值过大,导致 softmax 过早饱和,训练不稳定。

这一步看似只是一个公式,但它把“序列中任意两个位置的信息交互”变成了一个统一、可并行的矩阵运算。后面几乎所有大模型优化,都是围绕这个内核展开的。

核心机制二:Multi-Head Attention

如果只用一个注意力头,模型只能在同一个表示子空间里完成匹配。论文引入多头注意力,是为了让模型在不同子空间中同时学习不同关系,例如:

  • 某些头关注主谓对应关系。
  • 某些头关注长距离指代。
  • 某些头关注局部搭配或短语边界。

具体做法是:先把输入分别线性投影为多组 Q/K/V,每组独立做注意力,再把多个头的输出拼接起来,并通过一次线性层融合。这样既保留了并行计算优势,也提升了表示能力。

从后续研究看,多头机制虽然并不保证每个头都“有意义”,但它确实为模型提供了更强的关系建模弹性。很多解释性工作、剪枝工作、长上下文研究,也都是沿着“头的分工”展开的。

核心机制三:位置编码

纯注意力机制没有天然的顺序感。如果不给模型额外的位置信号,“猫咬狗”和“狗咬猫”对它来说只是同一组 token 的排列变化。

为了解决这个问题,论文引入了位置编码。原文采用的是固定的正弦/余弦位置编码,其优点是:

  • 不需要额外学习参数。
  • 不同频率的正余弦可以为不同位置提供可区分的模式。
  • 相对位置信息可以通过线性组合间接表达。

今天我们已经有了 RoPE、ALiBi、相对位置编码等改进方案,但“位置是序列建模中必须显式处理的信号”这一点,就是由这篇论文明确推到台前的。配合站内的 Transformer 注意力机制入门RoPE Visualizer,会更容易把抽象公式变成直觉。

训练细节:为什么它不只是一个好想法

这篇论文很值得学习的一点,是作者没有停留在概念层面,而是把训练工程也设计得非常完整。几个关键点包括:

  • 使用残差连接和 LayerNorm,保证深层训练稳定。
  • 使用 position-wise FFN,在每个位置上独立做非线性变换,提升表达能力。
  • 在 decoder 自注意力里加入 causal mask,保证生成时只能看见当前位置之前的 token。
  • 使用学习率 warmup、Adam 优化器和 label smoothing,让训练曲线更稳。
  • 通过子词分词把词表规模和未登录词问题控制在可管理范围内。

这些设计后来几乎都变成了大模型训练的基础模板。即便今天具体实现细节已经演化,例如 pre-norm、更大的 batch、更复杂的 tokenizer,但总体工程逻辑仍然延续自这里。

实验结果说明了什么

论文主要在机器翻译任务上验证 Transformer,结论可以概括为三点:

  1. 在 WMT 英德、英法翻译任务上,Transformer 达到了当时非常有竞争力的结果。
  2. 由于没有循环结构,训练并行度显著提高,单位时间内能处理更多 token。
  3. 当序列长度适中时,纯注意力结构在效果和训练效率上都优于过去的主流方案。

这里最值得读者关注的,其实不是某个具体 BLEU 分数,而是“效果更好 + 训练更快”这个组合。很多架构论文只能在准确率上略胜一筹,却要付出更复杂的工程代价;Transformer 恰恰相反,它把研究价值和工程价值统一了起来。

为什么说它开启了现代大模型时代

这篇论文之后,整个领域出现了非常清晰的演化链条:

  • BERT 继承 Transformer encoder,走向双向表征学习。
  • GPT 系列强化 decoder-only 路线,走向大规模自回归预训练。
  • T5、PaLM、LLaMA、Mixtral 等模型继续沿用 Transformer 作为基本积木。
  • ViT 把 Transformer 扩展到视觉,多模态模型又进一步把它扩展到图像、语音与视频。

换句话说,这篇论文不是“某个方向中的一篇代表作”,而是后来大量路线的共同祖先。它定义了现代大模型最重要的接口形式:token、attention、层堆叠、可扩展训练。

局限与后续影响

当然,Transformer 也不是终点。原始论文中的设计很快暴露出一些边界:

  • 注意力计算和显存占用随序列长度二次增长,长上下文成本高。
  • 固定位置编码在长度外推上存在局限。
  • 原始架构主要在翻译场景验证,还没有今天这样大规模预训练的设定。
  • 多头注意力并不天然高效,后续出现了 FlashAttention、MQA、GQA、稀疏注意力等大量系统优化。

也正因为这些局限足够明确,后续研究者才能围绕它持续改进。很多“后 Transformer”工作,本质上都在回答一个问题:如何保留 Transformer 的表达能力和工程友好性,同时缓解它在长序列、推理成本和对齐阶段的压力。

读这篇论文时最该抓住什么

如果你第一次读原文,不要试图一次记住所有矩阵维度和公式推导,先抓住下面四件事:

  1. 为什么去掉 RNN 后,训练可以更并行。
  2. 为什么注意力能让任意位置直接交互。
  3. 为什么需要多头和位置编码。
  4. 为什么一个结构规则、模块统一的架构,会天然适合规模化。

理解了这四点,你再去看后续的 BERT、GPT、FlashAttention、RoPE、长上下文优化时,就会知道它们分别是在 Transformer 的哪一个组件上继续演化。

延伸阅读

相关内容

沿着相近主题继续阅读,加深对方法边界与实践场景的理解。