1. 引言:序列建模的范式革命

1.1 为什么需要 Transformer?

在 Transformer 出现之前,处理序列数据(文本、语音、时间序列)的主流方案是**循环神经网络(RNN)**及其变体 LSTM、GRU。它们通过一个隐藏状态 hth_tht 在时间维度上"接力"传递信息:

ht=f(Wxhxt+Whhht−1+b) h_t = f(W_{xh} x_t + W_{hh} h_{t-1} + b) ht=f(Wxhxt+Whhht1+b)

这种设计虽然符合人类阅读的直觉(从左到右逐字理解),却带来了三个难以克服的结构性问题:

问题具体表现根本原因
无法并行训练速度极慢,难以利用 GPU计算 hth_tht 必须等待 ht−1h_{t-1}ht1
长程依赖相隔较远的词难以关联梯度在时间上反向传播时指数衰减/爆炸
信息瓶颈长序列信息被压缩进固定大小的隐藏状态最后一个状态必须"记住"整句话

尽管 LSTM 用门控机制(gate)缓解了梯度消失,把信息保存在细胞状态(cell state)中,但本质上仍是顺序计算,无法根治并行性和长程依赖问题。

核心矛盾:我们既希望模型能捕捉任意两个位置之间的依赖关系,又希望计算能够高度并行。

1.2 Attention 的前奏

在 Transformer 之前,注意力机制(Attention) 已经作为 RNN 的"外挂"出现。以 Bahdanau Attention 为例,解码器在生成每个词时,动态地对编码器的所有隐藏状态加权求和,从而"聚焦"到最相关的输入部分:

ct=∑i=1Tαt,ihi,αt,i=softmax(score(st−1,hi)) c_t = \sum_{i=1}^{T} \alpha_{t,i} h_i, \qquad \alpha_{t,i} = \text{softmax}\left(\text{score}(s_{t-1}, h_i)\right) ct=i=1Tαt,ihi,αt,i=softmax(score(st1,hi))

注意力的巨大成功启发了一个大胆的想法:

如果注意力机制本身已经足够强大,为什么还要保留 RNN 这个"骨架"呢?

1.3 Transformer 的诞生

2017 年,Google 团队在论文 “Attention Is All You Need” 中给出了答案——彻底抛弃循环和卷积,只用注意力机制构建整个序列模型,这就是 Transformer

它的核心思想可以概括为一句话:

让序列中的每一个位置,直接与所有其他位置建立加权联系,并让这些联系在所有位置、所有层上并行计算。

这一设计带来的结果是革命性的:

  • 训练并行:所有位置同时计算,GPU 利用率大幅提升
  • 长程依赖:任意两个位置的距离是常数 O(1)O(1)O(1),不再随序列长度衰减
  • 可扩展性:计算和参数量可以随数据规模线性扩展,直接催生了 GPT、BERT、LLaMA 等大语言模型

2. 整体架构:编码器-解码器

Transformer 延续了经典的 Encoder-Decoder(编码器-解码器) 框架:

                    ┌─────────────────────────────────────────────┐
                    │                  Transformer                 │
                    │                                              │
  输入序列           │   ┌─────────────┐        ┌─────────────┐     │   输出序列
 "I love AI"  ─────►│   │   Encoder   │───────►│   Decoder   │────►│ "我 爱 人工智能"
  (Token 序列)       │   │   × N 层     │        │   × N 层     │     │   (概率分布)
                    │   └─────────────┘        └─────────────┘     │
                    └─────────────────────────────────────────────┘
  • 编码器(Encoder):读取整个输入序列,将其编码为一组上下文相关的向量表示(contextual representation)。
  • 解码器(Decoder):根据编码器的输出,结合已生成的词,自回归地(autoregressive) 逐词生成输出。

编码器和解码器都由 NNN相同的层(layer) 堆叠而成(论文中 N=6N = 6N=6)。每一层内部包含若干子层(sublayer)

编码器层的组成:

        ┌──────────────────────────┐
        │    Multi-Head Attention   │  ← 自注意力:关注输入内部
        └──────────────────────────┘
                    ↓ (+ 残差 & LayerNorm)
        ┌──────────────────────────┐
        │   Feed-Forward Network    │  ← 逐位置的全连接
        └──────────────────────────┘
                    ↓ (+ 残差 & LayerNorm)

解码器层的组成:

        ┌──────────────────────────┐
        │ Masked Multi-Head Attention│ ← 自注意力:只看到已生成的部分
        └──────────────────────────┘
                    ↓ (+ 残差 & LayerNorm)
        ┌──────────────────────────┐
        │  Cross Multi-Head Attention│ ← 交叉注意力:关注编码器输出
        └──────────────────────────┘
                    ↓ (+ 残差 & LayerNorm)
        ┌──────────────────────────┐
        │   Feed-Forward Network    │
        └──────────────────────────┘
                    ↓ (+ 残差 & LayerNorm)

关键区别:解码器比编码器多了一个 交叉注意力(Cross-Attention) 子层——它的 Key 和 Value 来自编码器输出,Query 来自解码器自身,从而实现"输出对齐输入"。

3. 自注意力:Transformer 的灵魂

3.1 直观理解

考虑句子:

“The animal didn’t cross the street because it was too tired.”

这里的代词 “it” 到底指代 “animal” 还是 “street”?人类能轻松判断,但传统 RNN 很难跨越这么长的距离建立联系。

自注意力(Self-Attention) 的做法是:对于序列中的每一个词,计算它与所有词(包括自己)的相关度,然后按相关度对所有词的信息做加权求和,得到该词的新表示。

 The  animal  didn't  cross  the  street  because  it  was  too  tired
  ↑      ↑                                         ↑
  │      └───────────── 高权重 ───────────────────┘
  │                         ("it" 主要关注 "animal")
  │
  └── 每个词都会与包括自己在内的所有词计算相关度

经过自注意力后,“it” 的新向量会"吸收"了 “animal” 的信息,从而在语义上更明确地指向"动物"。

3.2 Query / Key / Value 抽象

自注意力机制借用了信息检索中的概念,把每个输入向量投影成三个角色:

  • Query(查询)q\mathbf{q}q:我在"寻找"什么?(当前词的需求)
  • Key(键)k\mathbf{k}k:我"提供"什么?(被检索词的标识)
  • Value(值)v\mathbf{v}v:我实际携带的内容是什么?(被检索词的信息)

对输入矩阵 X∈Rn×dmodelX \in \mathbb{R}^{n \times d_{model}}XRn×dmodelnnn 为序列长度,dmodeld_{model}dmodel 为向量维度),通过三个可学习矩阵进行线性投影:

Q=XWQ,K=XWK,V=XWV Q = X W^Q, \quad K = X W^K, \quad V = X W^V Q=XWQ,K=XWK,V=XWV

其中 WQ,WK,WV∈Rdmodel×dkW^Q, W^K, W^V \in \mathbb{R}^{d_{model} \times d_k}WQ,WK,WVRdmodel×dk(通常 dk=dvd_k = d_vdk=dv)。

一句话理解:注意力就是"用 Query 去匹配所有 Key,得到相关性权重,再用这些权重对 Value 加权求和"。

3.3 缩放点积注意力

Transformer 使用的是缩放点积注意力(Scaled Dot-Product Attention)

Attention(Q,K,V)=softmax(QK⊤dk)V \text{Attention}(Q, K, V) = \text{softmax}\left(\frac{Q K^\top}{\sqrt{d_k}}\right) V Attention(Q,K,V)=softmax(dkQK)V

逐步拆解这个公式:

  1. 计算得分S=QK⊤∈Rn×nS = Q K^\top \in \mathbb{R}^{n \times n}S=QKRn×n,其中 Sij=qi⋅kjS_{ij} = \mathbf{q}_i \cdot \mathbf{k}_jSij=qikj,即第 iii 个 Query 与第 jjj 个 Key 的点积相似度。
  2. 缩放:除以 dk\sqrt{d_k}dk,防止维度 dkd_kdk 过大时点积数值过大。
  3. 归一化:对每一行做 softmax,得到注意力权重矩阵 A∈Rn×nA \in \mathbb{R}^{n \times n}ARn×n,每行之和为 1。
  4. 加权求和AV∈Rn×dvA V \in \mathbb{R}^{n \times d_v}AVRn×dv,得到输出。

其中 softmax 定义为:

softmax(z)i=ezi∑j=1nezj \text{softmax}(z)_i = \frac{e^{z_i}}{\sum_{j=1}^{n} e^{z_j}} softmax(z)i=j=1nezjezi

为什么除以 dk\sqrt{d_k}dk

假设 q\mathbf{q}qk\mathbf{k}k 的每个分量独立且服从标准正态分布(均值为 0、方差为 1),则它们的点积 q⋅k\mathbf{q}\cdot\mathbf{k}qk 的方差为 dkd_kdk。当 dkd_kdk 很大时,点积的绝对值会很大,softmax 的输入进入饱和区,梯度趋近于 0,导致训练困难。除以 dk\sqrt{d_k}dk 可以把方差拉回 1,让梯度保持稳定。

3.4 计算流程示意

以句子 ["I", "love", "AI"]n=3n=3n=3)为例:

         Q = X W^Q          K = X W^K          V = X W^V
       ┌──────────┐       ┌──────────┐       ┌──────────┐
  "I"  │  q₁      │       │  k₁      │       │  v₁      │
 "love"│  q₂      │       │  k₂      │       │  v₂      │
  "AI" │  q₃      │       │  k₃      │       │  v₃      │
       └──────────┘       └──────────┘       └──────────┘

     S = Q Kᵀ / √d_k          A = softmax(S)         O = A V
   ┌─────────────────┐      ┌─────────────────┐     ┌──────────┐
   │ q₁·k₁  q₁·k₂  q₁·k₃│   │ a₁₁  a₁₂  a₁₃ │     │  o₁      │
   │ q₂·k₁  q₂·k₂  q₂·k₃│ → │ a₂₁  a₂₂  a₂₃ │  →  │  o₂      │
   │ q₃·k₁  q₃·k₂  q₃·k₃│   │ a₃₁  a₃₂  a₃₃ │     │  o₃      │
   └─────────────────┘      └─────────────────┘     └──────────┘
       (每行 softmax 归一化)      (注意力权重)         (加权求和输出)

可以看到,整个计算完全基于矩阵乘法,所有位置一次性并行算出,这是 Transformer 高效性的根源。

4. 多头注意力

4.1 为什么需要多头?

单个注意力头只能学到一种"关注模式"。但语言中往往存在多种并行的关系

  • 一句话可能同时存在指代关系(it → animal)、修饰关系(形容词 → 名词)、句法结构(主语 → 谓语)等。

多头注意力(Multi-Head Attention) 的做法是:把 Q,K,VQ, K, VQ,K,V 投影到 hhh不同的低维子空间(论文中 h=8h=8h=8),在每个子空间里独立计算注意力,最后把结果拼接起来再投影回原维度:

MultiHead(Q,K,V)=Concat(head1,…,headh) WO \text{MultiHead}(Q, K, V) = \text{Concat}(\text{head}_1, \dots, \text{head}_h) \, W^O MultiHead(Q,K,V)=Concat(head1,,headh)WO

headi=Attention(QWiQ, KWiK, VWiV) \text{head}_i = \text{Attention}(Q W_i^Q, \, K W_i^K, \, V W_i^V) headi=Attention(QWiQ,KWiK,VWiV)

其中投影矩阵满足 dk=dv=dmodel/h=64d_k = d_v = d_{model}/h = 64dk=dv=dmodel/h=64WO∈Rhdv×dmodelW^O \in \mathbb{R}^{h d_v \times d_{model}}WORhdv×dmodel

        ┌────────────────────────────────────────────────┐
        │                  Multi-Head Attention          │
        │                                                 │
   X ───┤  ┌── head 1 ──┐                                 │
        │  │ Q₁ K₁ V₁   │ → Attention₁                    │
        │  └────────────┘                                 │
        │  ┌── head 2 ──┐                                 │
        │  │ Q₂ K₂ V₂   │ → Attention₂                    │──► Concat ──► W^O ──► O
        │  └────────────┘                                 │
        │       ...                                        │
        │  ┌── head h ──┐                                 │
        │  │ Qₕ Kₕ Vₕ   │ → Attentionₕ                    │
        │  └────────────┘                                 │
        └────────────────────────────────────────────────┘

直觉:可以把每个头理解为"从不同角度观察同一句话"——有的头关注近距离语法,有的头关注远距离指代,有的头关注语义相关性。多个头组合起来,模型就能同时捕捉丰富的关系。

5. 位置编码

5.1 注意力是"位置无关"的

自注意力对每个位置的处理是对称的:如果把输入 ["I", "love", "AI"] 打乱成 ["AI", "love", "I"],注意力机制本身完全无法感知这种顺序差异(因为点积 qi⋅kj\mathbf{q}_i \cdot \mathbf{k}_jqikj 不涉及位置下标)。

但语言是有严格顺序的:“狗咬人” 和 “人咬狗” 含义截然不同。因此必须显式地把位置信息注入输入

5.2 正弦位置编码

论文采用正弦/余弦函数生成位置编码,不引入额外可学习参数:

PE(pos,2i)=sin⁡(pos100002i/dmodel) PE_{(pos, 2i)} = \sin\left(\frac{pos}{10000^{2i/d_{model}}}\right) PE(pos,2i)=sin(100002i/dmodelpos)

PE(pos,2i+1)=cos⁡(pos100002i/dmodel) PE_{(pos, 2i+1)} = \cos\left(\frac{pos}{10000^{2i/d_{model}}}\right) PE(pos,2i+1)=cos(100002i/dmodelpos)

其中:

  • pospospos:词在序列中的位置(0,1,2,…0, 1, 2, \dots0,1,2,
  • iii:维度的下标(0,1,…,dmodel/2−10, 1, \dots, d_{model}/2 - 10,1,,dmodel/21
  • dmodeld_{model}dmodel:模型维度

最终把位置编码与词嵌入相加:

X=Embedding(tokens)+PE X = \text{Embedding}(\text{tokens}) + PE X=Embedding(tokens)+PE

为什么用正弦/余弦? 它有几个优雅的性质:

  1. 相对位置可表达:存在线性变换可以表示任意偏移 kkk 后的位置编码(PEpos+kPE_{pos+k}PEpos+k 可由 PEposPE_{pos}PEpos 线性表示),这让模型更容易学到相对位置关系。
  2. 多频率:不同维度的波长从 2π2\pi2π10000⋅2π10000 \cdot 2\pi100002π 不等,形成类似"二进制码"的多尺度表示。
  3. 可外推:可以处理训练中未见过的更长序列(虽然实际效果有限)。

后续的 GPT、BERT 等模型更多采用可学习的位置嵌入(learned positional embedding),而现代大模型又发展出 RoPE(旋转位置编码)、ALiBi 等更强大的方案,这是位置编码研究的一条重要脉络。

6. 位置前馈网络

每个注意力子层后面都跟着一个逐位置的前馈网络(Position-wise Feed-Forward Network)

FFN(x)=max⁡(0, xW1+b1) W2+b2 \text{FFN}(x) = \max(0, \, x W_1 + b_1) \, W_2 + b_2 FFN(x)=max(0,xW1+b1)W2+b2

其中内层维度 dff=2048d_{ff} = 2048dff=2048(是 dmodel=512d_{model}=512dmodel=512 的 4 倍),W1∈Rdmodel×dffW_1 \in \mathbb{R}^{d_{model} \times d_{ff}}W1Rdmodel×dffW2∈Rdff×dmodelW_2 \in \mathbb{R}^{d_{ff} \times d_{model}}W2Rdff×dmodel

为什么叫"逐位置"? 它对序列中的每个位置独立地施加同一个两层的全连接变换,不跨位置交互——跨位置的信息交互已经由注意力层完成了。

分工:注意力负责"位置之间"的信息混合(mixing),FFN 负责"单个位置内部"的非线性变换(映射)。两者交替堆叠,构成了 Transformer 的基本节律。现代的 GPT 系列通常把 ReLU 换成 GELU,但结构本质不变。

7. 残差连接与层归一化

7.1 残差连接

每个子层的输出都加了残差连接(Residual Connection)

output=LayerNorm(x+Sublayer(x)) \text{output} = \text{LayerNorm}\big(x + \text{Sublayer}(x)\big) output=LayerNorm(x+Sublayer(x))

残差连接让梯度可以"抄近道"直接回传,是训练深层网络的关键。没有它,NNN 层堆叠的 Transformer 很难训练。

7.2 层归一化

层归一化(Layer Normalization)单个样本的隐藏维度做归一化(与批归一化在 batch 维度上操作不同),更适合变长序列和小的 batch:

LayerNorm(x)=γ⊙x−μσ+β \text{LayerNorm}(x) = \gamma \odot \frac{x - \mu}{\sigma} + \beta LayerNorm(x)=γσxμ+β

其中 μ,σ\mu, \sigmaμ,σxxx 在特征维度上的均值和标准差,γ,β\gamma, \betaγ,β 是可学习的缩放与平移参数。

论文最初采用 Post-LN(残差之后归一化);后来实践发现 Pre-LN(先归一化再进子层)训练更稳定,成为 GPT 等模型的主流选择。这是一个"细节决定成败"的经典案例。

8. 训练细节

论文中还有一些对最终效果至关重要的训练技巧:

8.1 掩码

  • Padding Mask:对填充的 <pad> 位置,在 softmax 前把注意力得分置为 −∞-\infty,使其权重为 0。
  • Look-ahead Mask:解码器的自注意力用上三角掩码,保证生成第 ttt 个词时只能看到 1∼t1 \sim t1t 的词,防止"偷看未来"。

Attention(Q,K,V)=softmax(QK⊤dk+M)V,Mij={0允许−∞屏蔽 \text{Attention}(Q,K,V) = \text{softmax}\left(\frac{QK^\top}{\sqrt{d_k}} + M\right)V, \qquad M_{ij} = \begin{cases} 0 & \text{允许} \\ -\infty & \text{屏蔽} \end{cases} Attention(Q,K,V)=softmax(dkQK+M)V,Mij={0允许屏蔽

8.2 标签平滑

使用 标签平滑(Label Smoothing),把 one-hot 目标从 1/0 软化,防止模型过度自信、提高泛化能力(论文用 ϵls=0.1\epsilon_{ls} = 0.1ϵls=0.1)。

8.3 优化器与学习率预热

使用 Adam 优化器,配合自定义的学习率预热(warmup) 策略:

lr=dmodel−0.5⋅min⁡(step_num−0.5,  step_num⋅warmup_steps−1.5) lr = d_{model}^{-0.5} \cdot \min\left(\text{step\_num}^{-0.5}, \; \text{step\_num} \cdot \text{warmup\_steps}^{-1.5}\right) lr=dmodel0.5min(step_num0.5,step_numwarmup_steps1.5)

学习率先线性上升(前 4000 步),再按步数的平方根缓慢衰减,保证训练初期稳定。

9. PyTorch 实现

下面给出一个精简但完整可运行的 Transformer 核心实现,覆盖自注意力、多头注意力、位置编码和编码器层。

9.1 缩放点积注意力

import math
import torch
import torch.nn as nn
import torch.nn.functional as F


def scaled_dot_product_attention(q, k, v, mask=None):
    """
    q, k, v: (batch, heads, seq_len, d_k)
    mask:    (batch, 1, seq_len, seq_len) 或可广播的形状
    """
    d_k = q.size(-1)
    # (batch, heads, q_len, k_len)
    scores = torch.matmul(q, k.transpose(-2, -1)) / math.sqrt(d_k)

    if mask is not None:
        scores = scores.masked_fill(mask == 0, float("-inf"))

    attn = F.softmax(scores, dim=-1)          # 注意力权重
    out = torch.matmul(attn, v)               # (batch, heads, q_len, d_k)
    return out, attn

9.2 多头注意力

class MultiHeadAttention(nn.Module):
    def __init__(self, d_model, num_heads):
        super().__init__()
        assert d_model % num_heads == 0
        self.d_k = d_model // num_heads
        self.num_heads = num_heads

        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 split_heads(self, x):
        # (batch, seq_len, d_model) -> (batch, heads, seq_len, d_k)
        batch, seq_len, _ = x.size()
        return x.view(batch, seq_len, self.num_heads, self.d_k).transpose(1, 2)

    def forward(self, q, k, v, mask=None):
        q = self.split_heads(self.W_q(q))
        k = self.split_heads(self.W_k(k))
        v = self.split_heads(self.W_v(v))

        out, _ = scaled_dot_product_attention(q, k, v, mask)

        # 拼接多头并投影回 d_model
        batch, _, seq_len, _ = out.size()
        out = out.transpose(1, 2).contiguous().view(batch, seq_len, -1)
        return self.W_o(out)

9.3 正弦位置编码

class PositionalEncoding(nn.Module):
    def __init__(self, d_model, max_len=5000):
        super().__init__()
        pe = torch.zeros(max_len, d_model)
        position = torch.arange(0, max_len).unsqueeze(1).float()
        # 1 / 10000^(2i/d_model)
        div_term = torch.exp(
            torch.arange(0, d_model, 2).float()
            * (-math.log(10000.0) / d_model)
        )
        pe[:, 0::2] = torch.sin(position * div_term)  # 偶数维
        pe[:, 1::2] = torch.cos(position * div_term)  # 奇数维
        self.register_buffer("pe", pe.unsqueeze(0))    # (1, max_len, d_model)

    def forward(self, x):
        return x + self.pe[:, : x.size(1)]

9.4 编码器层

class EncoderLayer(nn.Module):
    def __init__(self, d_model, num_heads, d_ff, dropout=0.1):
        super().__init__()
        self.self_attn = MultiHeadAttention(d_model, num_heads)
        self.ffn = nn.Sequential(
            nn.Linear(d_model, d_ff),
            nn.ReLU(),
            nn.Linear(d_ff, d_model),
        )
        self.norm1 = nn.LayerNorm(d_model)
        self.norm2 = nn.LayerNorm(d_model)
        self.dropout = nn.Dropout(dropout)

    def forward(self, x, mask=None):
        # 子层 1:多头自注意力 + 残差 + LayerNorm
        attn_out = self.self_attn(x, x, x, mask)
        x = self.norm1(x + self.dropout(attn_out))
        # 子层 2:前馈网络 + 残差 + LayerNorm
        ffn_out = self.ffn(x)
        x = self.norm2(x + self.dropout(ffn_out))
        return x

完整可训练模型的工程代码可参考 torch.nn.Transformer(PyTorch 内置)或 HuggingFace Transformers 库。上述代码重在展示核心计算逻辑,便于理解每个组件的作用。

10. 为什么 Transformer 如此强大?

10.1 与其他架构的对比

维度RNN/LSTMCNNTransformer
并行化差(顺序)好(局部并行)优(全局并行)
长程依赖差(梯度衰减)需堆叠多层优(O(1)O(1)O(1) 路径)
任意两位置路径O(n)O(n)O(n)O(log⁡n)O(\log n)O(logn)O(1)O(1)O(1)
归纳偏置强(顺序)强(局部性)弱(更通用)

10.2 归纳偏置的取舍

Transformer 几乎没有内置的"先验假设"(不像 CNN 假设局部性、RNN 假设顺序性),这既是缺点(需要海量数据才能学好)也是优点(足够灵活,能适应各种模态和任务)。

这也解释了为什么 Transformer 是**"规模化(scaling)"的完美载体**:它不依赖手工设计的结构先验,因此当数据量和算力持续增长时,性能能够持续提升——这正是大语言模型时代的技术底座。

11. 后续发展与深远影响

Transformer 的影响力远超机器翻译,几乎重塑了整个深度学习领域:

  • BERT(2018):只用编码器,通过掩码语言模型(MLM) 做预训练,开创了"预训练 + 微调"范式。
  • GPT(2018 → 至今):只用解码器,通过自回归语言建模做预训练,并验证了规模化定律(scaling law),演进出 ChatGPT 等产品。
  • ViT(2020):把图像切成 patch,当作 token 输入 Transformer,让 CV 也进入 Transformer 时代。
  • 多模态与生成:CLIP、Stable Diffusion、Sora 等模型都以 Transformer 为骨干,统一了文本、图像、视频等模态。
  • 架构演进:FlashAttention、稀疏注意力、Mamba(状态空间模型)等,则是在 Transformer 基础上的效率优化与探索。

12. 总结

Transformer 用自注意力这一个核心机制,同时解决了 RNN 的并行性差、长程依赖弱、信息瓶颈三大难题。回顾其设计,几个思想尤为关键:

  1. Query-Key-Value 抽象,把"关注什么"与"内容是什么"解耦;
  2. 缩放点积,用 dk\sqrt{d_k}dk 保持梯度稳定;
  3. 多头机制,让模型并行捕捉多种关系;
  4. 位置编码,弥补注意力的顺序盲区;
  5. 残差 + LayerNorm,让深层堆叠得以训练。

从 2017 年的一篇论文,到今天支撑起千亿参数的大模型,Transformer 证明了:一个简单而优雅的架构,加上足够的数据和算力,能够产生远超预期的能力。

参考文献

  1. Vaswani, A., et al. Attention Is All You Need. NeurIPS 2017.
  2. Bahdanau, D., Cho, K., & Bengio, Y. Neural Machine Translation by Jointly Learning to Align and Translate. ICLR 2015.
  3. Devlin, J., et al. BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding. NAACL 2019.
  4. Radford, A., et al. Improving Language Understanding by Generative Pre-Training. 2018.
  5. Dosovitskiy, A., et al. An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale. ICLR 2021.

更多推荐