深入理解 Transformer:从自注意力到现代大模型的基石
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+Whhht−1+b)
这种设计虽然符合人类阅读的直觉(从左到右逐字理解),却带来了三个难以克服的结构性问题:
| 问题 | 具体表现 | 根本原因 |
|---|---|---|
| 无法并行 | 训练速度极慢,难以利用 GPU | 计算 hth_tht 必须等待 ht−1h_{t-1}ht−1 |
| 长程依赖 | 相隔较远的词难以关联 | 梯度在时间上反向传播时指数衰减/爆炸 |
| 信息瓶颈 | 长序列信息被压缩进固定大小的隐藏状态 | 最后一个状态必须"记住"整句话 |
尽管 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=1∑Tαt,ihi,αt,i=softmax(score(st−1,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}}X∈Rn×dmodel(nnn 为序列长度,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,WV∈Rdmodel×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
逐步拆解这个公式:
- 计算得分:S=QK⊤∈Rn×nS = Q K^\top \in \mathbb{R}^{n \times n}S=QK⊤∈Rn×n,其中 Sij=qi⋅kjS_{ij} = \mathbf{q}_i \cdot \mathbf{k}_jSij=qi⋅kj,即第 iii 个 Query 与第 jjj 个 Key 的点积相似度。
- 缩放:除以 dk\sqrt{d_k}dk,防止维度 dkd_kdk 过大时点积数值过大。
- 归一化:对每一行做 softmax,得到注意力权重矩阵 A∈Rn×nA \in \mathbb{R}^{n \times n}A∈Rn×n,每行之和为 1。
- 加权求和:AV∈Rn×dvA V \in \mathbb{R}^{n \times d_v}AV∈Rn×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}q 和 k\mathbf{k}k 的每个分量独立且服从标准正态分布(均值为 0、方差为 1),则它们的点积 q⋅k\mathbf{q}\cdot\mathbf{k}q⋅k 的方差为 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=64,WO∈Rhdv×dmodelW^O \in \mathbb{R}^{h d_v \times d_{model}}WO∈Rhdv×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}_jqi⋅kj 不涉及位置下标)。
但语言是有严格顺序的:“狗咬人” 和 “人咬狗” 含义截然不同。因此必须显式地把位置信息注入输入。
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/2−1)
- dmodeld_{model}dmodel:模型维度
最终把位置编码与词嵌入相加:
X=Embedding(tokens)+PE X = \text{Embedding}(\text{tokens}) + PE X=Embedding(tokens)+PE
为什么用正弦/余弦? 它有几个优雅的性质:
- 相对位置可表达:存在线性变换可以表示任意偏移 kkk 后的位置编码(PEpos+kPE_{pos+k}PEpos+k 可由 PEposPE_{pos}PEpos 线性表示),这让模型更容易学到相对位置关系。
- 多频率:不同维度的波长从 2π2\pi2π 到 10000⋅2π10000 \cdot 2\pi10000⋅2π 不等,形成类似"二进制码"的多尺度表示。
- 可外推:可以处理训练中未见过的更长序列(虽然实际效果有限)。
后续的 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}}W1∈Rdmodel×dff,W2∈Rdff×dmodelW_2 \in \mathbb{R}^{d_{ff} \times d_{model}}W2∈Rdff×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 t1∼t 的词,防止"偷看未来"。
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=dmodel−0.5⋅min(step_num−0.5,step_num⋅warmup_steps−1.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/LSTM | CNN | Transformer |
|---|---|---|---|
| 并行化 | 差(顺序) | 好(局部并行) | 优(全局并行) |
| 长程依赖 | 差(梯度衰减) | 需堆叠多层 | 优(O(1)O(1)O(1) 路径) |
| 任意两位置路径 | O(n)O(n)O(n) | O(logn)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 的并行性差、长程依赖弱、信息瓶颈三大难题。回顾其设计,几个思想尤为关键:
- Query-Key-Value 抽象,把"关注什么"与"内容是什么"解耦;
- 缩放点积,用 dk\sqrt{d_k}dk 保持梯度稳定;
- 多头机制,让模型并行捕捉多种关系;
- 位置编码,弥补注意力的顺序盲区;
- 残差 + LayerNorm,让深层堆叠得以训练。
从 2017 年的一篇论文,到今天支撑起千亿参数的大模型,Transformer 证明了:一个简单而优雅的架构,加上足够的数据和算力,能够产生远超预期的能力。
参考文献
- Vaswani, A., et al. Attention Is All You Need. NeurIPS 2017.
- Bahdanau, D., Cho, K., & Bengio, Y. Neural Machine Translation by Jointly Learning to Align and Translate. ICLR 2015.
- Devlin, J., et al. BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding. NAACL 2019.
- Radford, A., et al. Improving Language Understanding by Generative Pre-Training. 2018.
- Dosovitskiy, A., et al. An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale. ICLR 2021.
更多推荐




所有评论(0)