第6章 模型训练
上一章中,我们讨论了大语言模型(例如,Transformer)的模型结构。
在本章中,我们将讨论如何训练大语言模型。
本章分成目标函数和优化算法两部分。
6.1 目标函数
我们研究三类语言模型的目标函数:
- 只包含解码器(Decoder-only)的模型(例如,GPT-3):计算单向上下文嵌入(contextual embeddings),一次生成一个token
- 只包含编码器(Encoder-only)的模型(例如,BERT):计算双向上下文嵌入
- 编码器解码器(Encoder-decoder)模型(例如,T5):编码输入,解码输出
我们可以使用任何模型将token序列映射到上下文嵌入中(例如,LSTM、Transformers):
ϕ:VL→Rd×L.
[the,mouse,ate,the,cheese]⇒ϕ[(0.11),(10),(11),(−0.11),(−10)].
6.1.1 Decoder-only 模型
回想一下,自回归语言模型定义了一个条件分布:
p(xi∣x1:i−1).
我们将其定义如下:
- 将 x1:i−1 映射到上下文嵌入ϕ(x1:i−1)。
- 应用嵌入矩阵 E∈RV×d 来获得每个token的得分 Eϕ(x1:i−1)i−1 。
- 对其进行指数化和归一化,得到预测 xi的 分布。
简洁地:
p(xi+1∣x1:i)=softmax(Eϕ(x1:i)i).
6.1.1.1 最大似然
设 θ 是大语言模型的所有参数。设 D 是由一组序列组成的训练数据。
然后,我们可以遵循最大似然原理,定义以下负对数似然目标函数:
O(θ)=x∈D∑−logpθ(x)=x∈D∑i=1∑L−logpθ(xi∣x1:i−1).
并且,有很多的方法可以有效地优化这一目标函数。
6.1.2 Encoder-only 模型
6.1.2.1 单向到双向
使用上述最大似然可以训练得到Decoder-only模型,它会产生(单向)上下文嵌入。但如果我们不需要生成,我们可以提供更强的双向上下文嵌入。
6.1.2.2 BERT
我们首先介绍BERT的目标函数,它包含以下两个部分:
- 掩码语言模型(Masked language modeling)
- 下一句预测(Next sentence prediction)
以自然语言推理(预测隐含、矛盾或中性)任务中的序列为例:
x1:L=[[CLS],all,animals,breathe,[SEP],cats,breathe].
其中有两个特殊的token:
- [CLS] :包含用于驱动分类任务的嵌入
- [SEP] :用于告诉模型第一个序列(例如,前提)与第二个序列(例如,假设)的位置。
根据上一章的公式,BERT模型定义为:
BERT(x1:L)=[Transformer](/glossary/transformer)Block24(EmbedTokenWithPosition(x1:L)+SentenceEmbedding(x1:L))∈Rd×L,
其中, SentenceEmbedding(x1:L) 根据序列返回以下两个矢量之一
- 对于 [SEP] 左边的,返回 eA∈Rd
- 对于 [SEP] 右边的,返回 eB∈Rd

BERT-large有 nheads=16 个注意头,并且 dmodel=1024 ,总共355M个参数。
6.1.2.2.1 掩码语言模型
掩码语言模型的基本思想是通过加噪然后预测来进行训练:
[the,[MASK],ate,[MASK],cheese]⇒[the,mouse,ate,the,cheese].
更普遍地说,我们可以将其视为类似于去噪自动编码器,其中我们映射有噪声/不完整版本 x~1:L ,并尝试重建原始 x1:L 。
x~1:L⇒x1:L.
建模:我们首先定义模型分布。给定输入 x~1:L 及其上下文嵌入,模型独立地预测每个token:
p(xi∣x~1:L)=softmax(Eϕ(x~1:L)i).
掩码: 我们定义了一个(随机)噪声函数 A(x~1:L∣x1:L) :
以下是 A 的定义:
- 假设 I⊂{1,…,L} 代表所有位置中随机的15%。
- 对于每个 i∈I :
- 以0.8的概率, x~i←[MASK]
- 以0.1的概率, x~i←xi
- 以0.1的概率, x~i←random word from V
减少分布偏移: 如果我们总是使用 [MASK] 来替换 I 中选定的token,则:
- 在训练期间,输入到BERT的都是带 [MASK] 的序列。
- 而在测试时,我们会输入没有 [MASK] 的句子,这将导致分布发生变化。一种启发式的解决方法是在20%的时间内(此处指训练的时间)用真实单词替换。
6.1.2.2.2 下一句预测
回想一下,BERT是在拼接好的成对句子上训练的。下一句预测的目标是预测第二句是否跟随第一句。
[[CLS],the,mouse,ate,the,cheese,[SEP],it,was,full]⇒1.
[[CLS],the,mouse,ate,the,cheese,[SEP],hello,world]⇒0.
然后使用 [CLS] 的嵌入来做二分类。
6.1.2.2.3 数据集
D 是按如下方式构造的一组样本 (x1:L,c) :
- 令 A 是语料库中的一个句子。
- 以0.5的概率, B 是下一句话。
- 以0.5的概率, B 是语料库中的一个随机句子。
- 令 x1:L=[[CLS],A,[SEP],B]
- 令 c 表示 B 是否是下一句。
6.1.2.2.4 训练目标
BERT的训练目标是:
稍后我们将讨论训练,这里简要总结一下BERT:
- BERT(以及ELMo和ULMFiT)表明,一个统一的体系结构(Transformer)可以用于多个分类任务。
- BERT真正将NLP社区转变为预培训+微调的范式。
- BERT显示了深度双向上下文嵌入的重要性,尽管通过模型大小和微调策略可能会弥补这一点(p-tuning)。
6.1.2.3 RoBERTa
RoBERTa对BERT进行了以下改进:
- 删除了下一句预测这一目标函数(发现它没有帮助)。
- 使用更多数据训练(16GB文本 ⇒ 160GB文本 )。
- 训练时间更长。
- RoBERTa在各种基准上显著提高了BERT的准确性(例如,在SQuAD上由81.8到89.4)。
6.1.3 Encoder-decoder 模型
任务示例(表格生成文本):
[name,:,Clowns,|,eatType,:,coffee,shop]Rightarrow[Clowns,is,a,coffee,shop].
回想一下编码器-解码器模型(例如,BART、T5):
- 首先像BERT一样对输入进行双向编码。
- 然后像GPT-2一样对输出进行自回归解码。
6.1.3.1 BART (Bidirectional Auto-Regressive Transformers)
BART (Lewis et al. 2019)是基于Transformer的编码器-解码器模型。
- 使用与RoBERTa相同的编码器架构(12层,隐藏维度1024)。
- 使用与RoBERTa相同的数据进行训练(160GB文本)。
BART使用了以下变换 A(x~1:L∣x1:L) :

基于BERT的实验,最终模型进行以下了变换:
最后,通过微调,BART在分类和生成任务上都展示了强大的效果。
6.1.3.2 T5 (Text-to-Text Transfer Transformer)
T5 (Raffel et al., 2020)是另一种基于Transformer的编码器-解码器模型。
预训练任务:
给定一段文本,在随机位置将其分割为输入和输出:
[the,mouse]⇒[ate,the,cheese].
论文尝试了许多不同的无监督目标:

并发现“i.i.d. noise, replace spans”效果最好(尽管许多目标相似)。
论文还将所有经典的NLP任务放在一个统一的框架中,称为“Text-to-Text”任务:

以分类任务任务为例,不同模型的差异如下:
- BERT使用 [CLS] 的嵌入来预测。
- T5、GPT-2、GPT-3等(生成模型)将分类任务转换成自然语言生成。
注意:
- 论文对整个pipline的许多方面(数据集、模型大小、训练目标等)进行了深入研究。
- 基于这些见解,他们训练了一个11B的模型。
6.2 优化算法
现在,我们将注意力转向如何优化目标函数。
为了简单起见,让我们以自回归语言模型为例:
O(θ)=x∈D∑−logpθ(x).
6.2.1 随机梯度下降(SGD)
最简单的优化算法是用小批量进行随机梯度下降,该算法的步骤如下:
- 初始化参数 θ0
- 重复以下步骤:
- 采样小批量 Bt⊂D
- 根据梯度更新参数:
θt←θt−1−η∣Bt∣1x∈Bt∑∇θ(−logpθ(x)).
优化的关键点包括:
- 我们希望参数 θ 可以快速收敛
- 我们希望优化在数值上是稳定的
- 我们希望内存高效(尤其是对于大模型)
这些点往往相互矛盾(例如,通过低精度训练,可以实现快速收敛、减少内存占用,但是会导致训练不稳定)
因此,我们可以从几个层次来进行优化:
- 针对经典优化:二阶方法、约束优化等。
- 针对机器学习:随机方法、隐式正则化+早停法
- 针对深度学习:初始化、归一化(更改模型架构)
- 针对大语言模型:由于稳定性问题,学习率和一些直觉(例如,二阶方法)仍然有用,但要使大语言模型有效训练,还需要克服许多其他独特的挑战。不幸的是,其中大部分内容都是特别的,人们对此了解甚少。
6.2.2 Adam (adaptive moment estimation)
Adam算法拥有以下两个创新:
- 引入动量(继续朝同一方向移动)。
- 参数 θ0 的每个维度都有一个自适应(不同)的步长(受二阶方法启发)。
它的步骤如下:
- 初始化参数 θ0
- 初始化动量 m0,v0←0
- 重复以下步骤:
- 采样小批量 Bt⊂D
- 按照如下步骤更新参数:
gt←∣Bt∣1∑x∈Bt∇θ(−logpθ(x)).
mt←β1mt−1+(1−β1)gt
vt←β2vt−1+(1−β2)gt2
m^t←mt/(1−β1t)
v^t←vt/(1−β2t)
θt←θt−1−ηm^t/(v^t+ϵ).
存储占用分析:
Adam将存储从2倍的模型参数( θt,gt )增加到了4倍( θt,gt,mt,vt )。
6.2.3 AdaFactor
AdaFactor是一种为减少存储占用的优化算法。它有如下特点:
- 它不储存 mt,vt 这样的 O(m×n) 矩阵,而是存储行和列的和 O(m+n) 并重构矩阵
- 去除动量
- 它被用来训练T5
- AdaFactor可能使训练变得困难(见Twitter thread和blog post)
6.2.4 混合精度训练
混合精度训练是另一种减少存储的方法
- 通常来说,默认的精度是:FP32(32位浮点)
- 其他可选精度:FP16(16位浮点),但问题是任何小于 2−24 的值都会变为0。
- 解决方案:将主权重存储在FP32中,并在FP16中执行其他所有操作。
- 损失缩放:按比例放大损失,以避免梯度数值太小。
- 结果:存储减少了一半。

6.2.5 学习率
- 通常情况下,学习率会随着时间的推移而衰减。
- 对于Transformer模型,我们实际上需要通过预热(warmup)提高学习率。
- Huang et al., 2020表明,一个潜在的原因是防止层归一化的梯度消失,导致使用Adam优化器训练时不稳定。
6.2.6 初始化
- 给定矩阵 W∈Rm×n ,标准初始化(即,xavier初始化)为 Wij∼N(0,1/n) 。
- GPT-2和GPT-3通过额外的 1/N 缩放权重,其中 N 是残差层的数量。
- T5将注意力矩阵增加一个 1/d (代码)。
以GPT-3为例,使用的参数如下:
- Adam参数: β1=0.9,β2=0.95,ϵ=10−8
- 批量小:320万个token(约1500个序列)
- 使用梯度剪裁( gt←gt/min(1,∥g∥2) )
- 线性学习率预热(前3.75亿个token)
- 余弦学习率衰减到10%
- 逐渐增加批大小
- 权重衰减设为0.1
延伸阅读
- 混合精度训练
- Fixing Weight Decay Regularization in Adam. I. Loshchilov, F. Hutter. 2017. 介绍了AdamW
- ELECTRA: Pre-training Text Encoders as Discriminators Rather Than Generators. Kevin Clark, Minh-Thang Luong, Quoc V. Le, Christopher D. Manning. ICLR 2020.
- DeBERTa: Decoding-enhanced BERT with Disentangled Attention. Pengcheng He, Xiaodong Liu, Jianfeng Gao, Weizhu Chen. ICLR 2020.