Datawhale组队打卡day7
写在前面
今天一直很忙……所以没什么时间了。本章讨论重点为如何训练模型。
真讨厌一些人啊,根本不相信然后对我说我要你帮我算一下,我说的过程中就使劲怼我说不对,虽然这点在图里面也显现了,乐。
不说了,来看!学习这一篇的
本章分成目标函数和优化算法两部分。
8.1 目标函数
将无监督学习到的知识引入有监督的任务:
比如word2vec出来之后,将预训练好的词向量加入到有监督任务中作为特征,往往带来效果提升;
再比如我们的电商推荐业务中,通过全站用户行为数据训练的图模型特征,加入到信息流推荐模型后同样带来效果提升。
我们研究三类语言模型的目标函数:
- 只包含解码器(Decoder-only)的模型(例如,GPT-3):计算单向上下文嵌入(contextual embeddings),一次生成一个token
这里token可以是汉字、单词、子词(subword)等,输出一个概率,表示这个token串是正常人类句子(或片段)的概率。
完整的Transformer模型包括encoder和decoder,而GPT只使用了decoder部分,且因为少了encoder,所以和原始的Transformer
decoder相比,不再需要encoder-decoder attention层。
decoder-only只有前向注意力,最适合训练标准的语言模型。
- 只包含编码器(Encoder-only)的模型(例如,BERT):计算双向上下文嵌入
BERT输入为句对,学习目标有两个:
Masked LM(随机遮盖句子中若干token让模型恢复)
Next Sentence Prediction(让模型判断句对是否前后相邻关系);
- 编码器解码器(Encoder-decoder)模型(例如,T5):编码输入,解码输出
我们可以使用任何模型将token序列映射到上下文嵌入中(例如,LSTM、Transformers):
T5借鉴了BERT的Masked LM(或者称作denoising目标),只不过输入输出都是text的形式
Encoder-decoder 简称ED 是原始Transformer的架构。
BERT和T5通过这种完形填空式的学习目标加强模型在语义理解上的能力,但这个训练目标和文本生成并不直接对应。如果非要按照标准语言模型目标的训练方式,即将一个文本段从头到尾依次基于上文预测下一个token,则对于Encoder-Decoder和Encoder-only架构很别扭且无法并行。
T5的对比实验部分给出了另一种替代方案:采样一段文本,然后选择一个随机点将其拆分为前缀和目标部分,前缀作为输入,目标作为输出。只不过为了防止信息泄露,Encoder-only架构要换成论文中的Prefix LM架构.
2L层的Encoder-Decoder架构和L层的Decoder-only架构的推理时间差不多,但前者参数多了一倍;同样参数规模的Decoder-only和Prefix LM对比,前者只有前向过程,推理应该能更快一些。因此假设2L层Encoder-Decoder、L层Decoder-only、L层Prefix LM三者模型效果差不多,则对比下来,Decoder-only是存储和计算上效率最高的。当然这只是假设,按照T5论文的结论,2L层Encoder-Decoder效果才是最好的,不过T5参数量才110亿,当参数规模达到GPT-3级别的千亿规模,不知道结果如何。
GPT为什么从始至终选择Decoder-only架构?
在调研过程中,发现知乎上有相关讨论[5]:“为什么现在的LLM都是Decoder only的架构?相比encoder-decoder架构,只使用decoder有什么好处吗?”
在苏剑林的最高赞回答中提到双向注意力会带来低秩问题,想通过理论视角给出答案。
Low-Rank Bottleneck in Multi-head Attention Models:理论分析表明了标准Multi-head Attention的一个固有缺陷:当head size小于输入序列长度时,会带来所谓低秩瓶颈,降低模型表达能力。
设定Transformer的输入为
n
n
n个token序列,每个token用
d
d
d维向量表示,则可以用以下矩阵统一表达输入序列。
ϕ
:
V
L
→
R
d
×
L
.
\phi : V^L \to \mathbb{R}^{d \times L}.
ϕ:VL→Rd×L.
[
the
,
mouse
,
ate
,
the
,
cheese
]
⇒
ϕ
[
(
1
0.1
)
,
(
0
1
)
,
(
1
1
)
,
(
1
−
0.1
)
,
(
0
−
1
)
]
.
\left[\text{the}, \text{mouse}, \text{ate}, \text{the}, \text{cheese}\right] \stackrel{\phi}{\Rightarrow} \left[\binom{1}{0.1}, \binom{0}{1}, \binom{1}{1}, \binom{1}{-0.1}, \binom{0}{-1} \right].
[the,mouse,ate,the,cheese]⇒ϕ[(0.11),(10),(11),(−0.11),(−10)].
8.1.1 Decoder-only 模型
回想一下,自回归语言模型定义了一个条件分布:
p
(
x
i
∣
x
1
:
i
−
1
)
.
p(x_i \mid x_{1:i-1}).
p(xi∣x1:i−1).
我们将其定义如下:
- 将 x 1 : i − 1 x_{1:i-1} x1:i−1映射到上下文嵌入 ϕ ( x 1 : i − 1 ) \phi(x_{1:i-1}) ϕ(x1:i−1)。
- 应用嵌入矩阵 E ∈ R V × d E \in \R^{V \times d} E∈RV×d来获得每个token的得分 E ϕ ( x 1 : i − 1 ) i − 1 E \phi(x_{1:i-1})_{i-1} Eϕ(x1:i−1)i−1。
- 对其进行指数化和归一化,得到预测 x i x_i xi的分布。
简洁地:
p
(
x
i
+
1
∣
x
1
:
i
)
=
s
o
f
t
m
a
x
(
E
ϕ
(
x
1
:
i
)
i
)
.
p(x_{i+1} \mid x_{1:i}) = softmax(E \phi(x_{1:i})_i).
p(xi+1∣x1:i)=softmax(Eϕ(x1:i)i).
8.1.1.1 最大似然
设
θ
\theta
θ是大语言模型的所有参数。设
D
D
D是由一组序列组成的训练数据。
然后,我们可以遵循最大似然原理,定义以下负对数似然目标函数:
O
(
θ
)
=
∑
x
∈
D
−
log
p
θ
(
x
)
=
∑
x
∈
D
∑
i
=
1
L
−
log
p
θ
(
x
i
∣
x
1
:
i
−
1
)
.
O(\theta) = \sum_{x \in D} - \log p_\theta(x) = \sum_{x \in D} \sum_{i=1}^L -\log p_\theta(x_i \mid x_{1:i-1}).
O(θ)=x∈D∑−logpθ(x)=x∈D∑i=1∑L−logpθ(xi∣x1:i−1).
并且,有很多的方法可以有效地优化这一目标函数。
8.1.2 Encoder-only 模型
8.1.2.1 单向到双向
使用上述最大似然可以训练得到Decoder-only模型,它会产生(单向)上下文嵌入。但如果我们不需要生成,我们可以提供更强的双向上下文嵌入。
8.1.2.2 BERT
BERT强调了不再像以往一样采用传统的单向语言模型 或者把两个单向语言模型进行浅层拼接的方法进行预训练 ,而是采用新的masked language model(MLM),以致能生成深度的双向语言表征 。
采用MLM对双向的Transformers进行预训练,以生成深层的双向语言表征。
预训练后,只需要添加一个额外的输出层进行fine-tune,就可以在各种各样的下游任务中取得state-of-the-art的表现。在这过程中并不需要对BERT进行任务特定的结构修改。
我们首先介绍BERT的目标函数,它包含以下两个部分:
- 掩码语言模型(Masked language modeling)
利用MLM进行预训练并且采用深层的双向Transformer组件来构建整个模型,因此最终生成能融合左右上下文信息的深层双向语言表征。
(单向的Transformer一般被称为Transformer decoder,其每一个token(符号)只会attend到目前往左的token。而双向的Transformer则被称为Transformer encoder,其每一个token会attend到所有的token。)
- 下一句预测(Next sentence prediction)
BERT的输入为每一个token对应的表征(图中的粉红色块就是token,黄色块就是token对应的表征),并且单词字典是采用WordPiece算法来进行构建的。为了完成具体的分类任务,除了单词的token之外,作者还在输入的每一个序列开头都插入特定的分类token([CLS]),该分类token对应的最后一个Transformer层输出被用来起到聚集整个序列表征信息的作用。
那么如何令模型有能力去分辨哪个范围是属于句子A,哪个范围是属于句子B呢?BERT采用了两种方法去解决:
1)在序列tokens中把分割token([SEP])插入到每个句子后,以分开不同的句子tokens。
2)为每一个token表征都添加一个可学习的分割embedding来指示其属于句子A还是句子B。
以自然语言推理(预测隐含、矛盾或中性)任务中的序列为例:
x 1 : L = [ [CLS] , all , animals , breathe , [SEP] , cats , breathe ] . x_{1:L} = [\text{[CLS]}, \text{all}, \text{animals}, \text{breathe}, \text{[SEP]}, \text{cats}, \text{breathe}]. x1:L=[[CLS],all,animals,breathe,[SEP],cats,breathe].
因此,BERT的输入为每一个token对应的表征,实际上该表征是由三部分组成的,分别是对应的token,分割和位置 embeddings
根据上一章的公式,BERT模型定义为:
BERT
(
x
1
:
L
)
=
TransformerBlock
24
(
EmbedTokenWithPosition
(
x
1
:
L
)
+
SentenceEmbedding
(
x
1
:
L
)
)
∈
R
d
×
L
,
\text{BERT}(x_{1:L}) = \text{TransformerBlock}^{24}(\text{EmbedTokenWithPosition}(x_{1:L}) + \text{SentenceEmbedding}(x_{1:L})) \in \mathbb{R}^{d \times L},
BERT(x1:L)=TransformerBlock24(EmbedTokenWithPosition(x1:L)+SentenceEmbedding(x1:L))∈Rd×L,
其中, SentenceEmbedding ( x 1 : L ) \text{SentenceEmbedding}(x_{1:L}) SentenceEmbedding(x1:L)根据序列返回以下两个矢量之一
- 对于 [SEP] \text{[SEP]} [SEP]左边的,返回 e A ∈ R d e_A \in \mathbb{R}^d eA∈Rd
- 对于 [SEP] \text{[SEP]} [SEP]右边的,返回 e B ∈ R d e_B \in \mathbb{R}^d eB∈Rd
BERT-large有 n heads = 16 n_\text{heads} = 16 nheads=16个注意头,并且 d model = 1024 d_\text{model} = 1024 dmodel=1024,总共355M个参数。
8.1.2.2.1 掩码语言模型
掩码语言模型的基本思想是通过加噪然后预测来进行训练:
MLM是BERT能够不受单向语言模型所限制的原因。简单来说就是以15%的概率用mask token ([MASK])随机地对每一个训练序列中的token进行替换,然后预测出[MASK]位置原有的单词。然而,由于[MASK]并不会出现在下游任务的微调(fine-tuning)阶段,因此预训练阶段和微调阶段之间产生了不匹配(这里很好解释,就是预训练的目标会令产生的语言表征对[MASK]敏感,但是却对其他token不敏感)。
为了解决这个问题,bert采用了策略:
首先在每一个训练序列中以15%的概率随机地选中某个token位置用于预测,假如是第i个token被选中,则会被替换成以下三个token之一
1)80%的时候是[MASK]。如,my dog is hairy——>my dog is [MASK]
2)10%的时候是随机的其他token。如,my dog is hairy——>my dog is apple
3)10%的时候是原来的token(保持不变,作为2)所对应的负类)。如,my dog is hairy——>my dog is hairy
再用该位置对应的最后一个Transformer的输出去预测出原来的token(输入到全连接,然后用softmax输出每个token的概率,最后用交叉熵计算loss)
[ the , [MASK] , ate , [MASK] , cheese ] ⇒ [ the , mouse , ate , the , cheese ] . [\text{the}, \text{[MASK]}, \text{ate}, \text{[MASK]}, \text{cheese}] \Rightarrow [\text{the}, \text{mouse}, \text{ate}, \text{the}, \text{cheese}]. [the,[MASK],ate,[MASK],cheese]⇒[the,mouse,ate,the,cheese].
更普遍地说,我们可以将其视为类似于去噪自动编码器,其中我们映射有噪声/不完整版本 x ~ 1 : L \tilde x_{1:L} x~1:L,并尝试重建原始 x 1 : L x_{1:L} x1:L。
x ~ 1 : L ⇒ x 1 : L . \tilde x_{1:L} \Rightarrow x_{1:L}. x~1:L⇒x1:L.
建模:我们首先定义模型分布。给定输入
x
~
1
:
L
\tilde x_{1:L}
x~1:L及其上下文嵌入,模型独立地预测每个token:
p
(
x
i
∣
x
~
1
:
L
)
=
softmax
(
E
ϕ
(
x
~
1
:
L
)
i
)
.
p(x_i \mid \tilde x_{1:L}) = \text{softmax}(E \phi(\tilde x_{1:L})_i).
p(xi∣x~1:L)=softmax(Eϕ(x~1:L)i).
**掩码:**我们定义了一个(随机)噪声函数
A
(
x
~
1
:
L
∣
x
1
:
L
)
A(\tilde x_{1:L} \mid x_{1:L})
A(x~1:L∣x1:L):
x
1
:
L
⏟
original
⇒
A
x
~
1
:
L
⏟
noised
.
\underbrace{x_{1:L}}_\text{original} \stackrel{A}{\Rightarrow} \underbrace{\tilde x_{1:L}}_\text{noised}.
original
x1:L⇒Anoised
x~1:L.
以下是 A A A的定义:
- 假设 I ⊂ { 1 , … , L } I \subset \{1, \dots, L\} I⊂{1,…,L}代表所有位置中随机的15%。
- 对于每个
i
∈
I
i \in I
i∈I:
- 以0.8的概率, x ~ i ← [MASK] \tilde x_i \leftarrow \text{[MASK]} x~i←[MASK]
- 以0.1的概率, x ~ i ← x i \tilde x_i \leftarrow x_i x~i←xi
- 以0.1的概率, x ~ i ← random word from V \tilde x_i \leftarrow \text{random word from } \mathcal{V} x~i←random word from V
减少分布偏移: 如果我们总是使用 [MASK] \text{[MASK]} [MASK]来替换 I I I中选定的token,则:
- 在训练期间,输入到BERT的都是带 [MASK] \text{[MASK]} [MASK]的序列。
- 而在测试时,我们会输入没有 [MASK] \text{[MASK]} [MASK]的句子,这将导致分布发生变化。一种启发式的解决方法是在20%的时间内用真实单词替换。
虽然NLP领域没有像ImageNet这样质量高的人工标注数据,但是可以利用大规模文本数据的自监督性质来构建预训练任务。因此BERT构建了两个预训练任务,分别是Masked Language Model和Next Sentence Prediction。
MLM任务倾向于抽取token层次的表征,因此不能直接获取句子层次的表征。为了使模型能够有能力理解句子间的关系,BERT使用了NSP任务来预训练,简单来说就是预测两个句子是否连在一起。
具体的做法是:对于每一个训练样例,我们在语料库中挑选出句子A和句子B来组成,50%的时候句子B就是句子A的下一句(标注为IsNext),剩下50%的时候句子B是语料库中的随机句子(标注为NotNext)。
8.1.2.2.2 下一句预测(Next Sentence Prediction)
BERT是在拼接好的成对句子上训练的。下一句预测的目标是预测第二句是否跟随第一句。
[
[CLS]
,
the
,
mouse
,
ate
,
the
,
cheese
,
[SEP]
,
it
,
was
,
full
]
⇒
1.
[\text{[CLS]}, \text{the}, \text{mouse}, \text{ate}, \text{the}, \text{cheese}, \text{[SEP]}, \text{it}, \text{was}, \text{full}] \Rightarrow 1.
[[CLS],the,mouse,ate,the,cheese,[SEP],it,was,full]⇒1.
[
[CLS]
,
the
,
mouse
,
ate
,
the
,
cheese
,
[SEP]
,
hello
,
world
]
⇒
0.
[\text{[CLS]}, \text{the}, \text{mouse}, \text{ate}, \text{the}, \text{cheese}, \text{[SEP]}, \text{hello}, \text{world}] \Rightarrow 0.
[[CLS],the,mouse,ate,the,cheese,[SEP],hello,world]⇒0.
接下来把训练样例输入到BERT模型中,用[CLS]对应的C信息去进行二分类的预测。
8.1.2.2.3 数据集
D \mathcal{D} D是按如下方式构造的一组样本 ( x 1 : L , c ) (x_{1:L}, c) (x1:L,c):
- 令 A A A是语料库中的一个句子。
- 以0.5的概率, B B B是下一句话。
- 以0.5的概率, B B B是语料库中的一个随机句子。
- 令 x 1 : L = [ [CLS] , A , [SEP] , B ] x_{1:L} = [\text{[CLS]}, A, \text{[SEP]}, B] x1:L=[[CLS],A,[SEP],B]
- 令 c c c表示 B B B是否是下一句。
8.1.2.2.4 训练目标
BERT的训练目标是:
把每一个训练样例输入到BERT中可以相应获得两个任务对应的loss,再把这两个loss加在一起就是整体的预训练loss。
(也就是两个任务同时进行训练)
O
(
θ
)
=
∑
(
x
1
:
L
,
c
)
∈
D
E
I
,
x
~
1
:
L
∼
A
(
⋅
∣
x
1
:
L
,
I
)
[
∑
i
∈
I
−
log
p
θ
(
x
~
i
∣
x
1
:
L
)
]
⏟
masked language modeling
+
−
log
p
(
c
∣
ϕ
(
x
1
:
L
)
1
)
⏟
next sentence prediction
.
\mathcal{O}(\theta) = \sum_{(x_{1:L},c) \in \mathcal{D}} \underbrace{\mathbb{E}_{I, \tilde x_{1:L} \sim A(\cdot \mid x_{1:L}, I)}[\sum_{i \in I} -\log p_\theta(\tilde x_i \mid x_{1:L})]}_\text{masked language modeling} + \underbrace{-\log p(c \mid \phi(x_{1:L})_1)}_\text{next sentence prediction}.
O(θ)=(x1:L,c)∈D∑masked language modeling
EI,x~1:L∼A(⋅∣x1:L,I)[i∈I∑−logpθ(x~i∣x1:L)]+next sentence prediction
−logp(c∣ϕ(x1:L)1).
稍后我们将讨论训练,这里简要总结一下BERT:
- BERT(以及ELMo和ULMFiT)表明,一个统一的体系结构(Transformer)可以用于多个分类任务。
- BERT真正将NLP社区转变为预训练+微调的范式。
- BERT显示了深度双向上下文嵌入的重要性,尽管通过模型大小和微调策略可能会弥补这一点(p-tuning)。
8.1.2.3 RoBERTa
RoBERTa对BERT进行了以下改进:
- 删除了下一句预测这一目标函数(发现它没有帮助)。
- 使用更多数据训练(16GB文本 ⇒ \Rightarrow ⇒ 160GB文本)。
- 训练时间更长。
- RoBERTa在各种基准上显著提高了BERT的准确性(例如,在SQuAD上由81.8到89.4)。
8.1.3 Encoder-decoder 模型
Encoder-Decoder 通常称作 编码器-解码器,是深度学习中常见的模型框架,很多常见的应用都是利用编码-解码框架设计的,如:
无监督算法的 auto-encoding 就是利用编码-解码结构设计的。 image caption 的应用也是利用 CNN-RNN
的编码-解码框架。 神经网络机器翻译 NMT 模型,就是 LSTM-LSTM 的编码-解码框架。 Encoder-Decoder
并不是一个具体的模型,而是一个通用的框架。Encoder 和 Decoder 部分可以是任意文字,语音,图像,视频数据,模型可以是
CNN,RNN,LSTM,GRU,Attention 等等。所以,基于 Encoder-Decoder,我们可以设计出各种各样的模型。
Encoder-Decoder 有一个比较显著的特征就是它是一个 End-to-End 的学习算法,以机器翻译为力,可以将法语翻译成英语。这样的模型也可以叫做 Seq2Seq。
Seq2Seq 强调目的,不特指具体方法,满足输入序列,输出序列的目的,都可以统称为 Seq2Seq 模型。Seq2Seq 使用的具体方法基本都是属于 Encoder-Decoder 模型的范畴。
在训练数据集中,我们可以在每个句子后附特殊字符 ”“ (end of sequence) 以表示序列终止,每个句子前用到了特殊字符 “” (begin of seqence) 表示序列开始。Encoder 在最终时间步的隐状态作为输入句子表征和编码信息。Decoder 在各个时间步中使用输入句子的编码信息和上一个时间步的输出以及隐藏状态作为输入。
任务示例(表格生成文本):
[ name , : , Clowns , | , eatType , : , coffee , shop ] → [ Clowns , is , a , coffee , shop ] . [\text{name}, \text{:}, \text{Clowns}, \text{|}, \text{eatType}, \text{:}, \text{coffee}, \text{shop}] \to [\text{Clowns}, \text{is}, \text{a}, \text{coffee}, \text{shop}]. [name,:,Clowns,|,eatType,:,coffee,shop]→[Clowns,is,a,coffee,shop].
回想一下编码器-解码器模型(例如,BART、T5):
- 首先像BERT一样对输入进行双向编码。
- 然后像GPT-2一样对输出进行自回归解码。
8.1.3.1 BART (Bidirectional Auto-Regressive Transformers)
BART (Lewis et al. 2019)是基于Transformer的编码器-解码器模型。
- 使用与RoBERTa相同的编码器架构(12层,隐藏维度1024)。
- 使用与RoBERTa相同的数据进行训练(160GB文本)。
BART使用了以下变换 A ( x ~ 1 : L ∣ x 1 : L ) A(\tilde x_{1:L} \mid x_{1:L}) A(x~1:L∣x1:L):
基于BERT的实验,最终模型进行以下了变换:
- 掩码文档中30%的token
- 将所有子句打乱
最后,通过微调,BART在分类和生成任务上都展示了强大的效果。
8.1.3.2 T5 (Text-to-Text Transfer Transformer)
T5 (Raffel et al., 2020)是另一种基于Transformer的编码器-解码器模型。
预训练任务:
给定一段文本,在随机位置将其分割为输入和输出:
[
the
,
mouse
]
⇒
[
ate
,
the
,
cheese
]
.
[\text{the}, \text{mouse}] \Rightarrow [\text{ate}, \text{the}, \text{cheese}].
[the,mouse]⇒[ate,the,cheese].
论文尝试了许多不同的无监督目标:
并发现“i.i.d. noise, replace spans”效果最好(尽管许多目标相似)。
论文还将所有经典的NLP任务放在一个统一的框架中,称为“Text-to-Text”任务:
以分类任务任务为例,不同模型的差异如下:
- BERT使用 [CLS] \text{[CLS]} [CLS]的嵌入来预测。
- T5、GPT-2、GPT-3等(生成模型)将分类任务转换成自然语言生成。
注意:
- 论文对整个pipline的许多方面(数据集、模型大小、训练目标等)进行了深入研究。
- 基于这些见解,他们训练了一个11B的模型。
4.2 优化算法
现在,我们将注意力转向如何优化目标函数。
为了简单起见,让我们以自回归语言模型为例:
O
(
θ
)
=
∑
x
∈
D
−
log
p
θ
(
x
)
.
O(\theta) = \sum_{x \in D} -\log p_\theta(x).
O(θ)=x∈D∑−logpθ(x).
4.2.1 随机梯度下降(SGD)
最简单的优化算法是用小批量进行随机梯度下降,该算法的步骤如下:
- 初始化参数 θ 0 \theta_0 θ0
- 重复以下步骤:
- 采样小批量 B t ⊂ D B_t \subset D Bt⊂D
- 根据梯度更新参数:
θ t ← θ t − 1 − η 1 ∣ B t ∣ ∑ x ∈ B t ∇ θ ( − log p θ ( x ) ) . \theta_t \leftarrow \theta_{t-1} - \eta \frac{1}{|B_t|} \sum_{x \in B_t} \nabla_\theta (-\log p_\theta(x)). θt←θt−1−η∣Bt∣1x∈Bt∑∇θ(−logpθ(x)).
优化的关键点包括:
- 我们希望参数 θ \theta θ可以快速收敛
- 我们希望优化在数值上是稳定的
- 我们希望内存高效(尤其是对于大模型)
这些点往往相互矛盾(例如,通过低精度训练,可以实现快速收敛、减少内存占用,但是会导致训练不稳定)
因此,我们可以从几个层次来进行优化:
- 针对经典优化:二阶方法、约束优化等。
- 针对机器学习:随机方法、隐式正则化+早停法
- 针对深度学习:初始化、归一化(更改模型架构)
- 针对大语言模型:由于稳定性问题,学习率和一些直觉(例如,二阶方法)仍然有用,但要使大语言模型有效训练,还需要克服许多其他独特的挑战。不幸的是,其中大部分内容都是特别的,人们对此了解甚少。
4.2.2 Adam (adaptive moment estimation)
Adam算法拥有以下两个创新:
- 引入动量(继续朝同一方向移动)。
- 参数 θ 0 \theta_0 θ0的每个维度都有一个自适应(不同)的步长(受二阶方法启发)。
它的步骤如下:
- 初始化参数 θ 0 \theta_0 θ0
- 初始化动量 m 0 , v 0 ← 0 m_0, v_0 \leftarrow 0 m0,v0←0
- 重复以下步骤:
- 采样小批量 B t ⊂ D B_t \subset D Bt⊂D
- 按照如下步骤更新参数:
-
计算梯度
g t ← 1 ∣ B t ∣ ∑ x ∈ B t ∇ θ ( − log p θ ( x ) ) . g_t \leftarrow \frac{1}{|B_t|} \sum_{x \in B_t} \nabla_\theta (-\log p_\theta(x)). gt←∣Bt∣1x∈Bt∑∇θ(−logpθ(x)). -
更新一阶、二阶动量
m t ← β 1 m t − 1 + ( 1 − β 1 ) g t v t ← β 2 v t − 1 + ( 1 − β 2 ) g t 2 m_t \leftarrow \beta_1 m_{t-1} + (1 - \beta_1) g_t \\ v_t \leftarrow \beta_2 v_{t-1} + (1 - \beta_2) g_t^2 mt←β1mt−1+(1−β1)gtvt←β2vt−1+(1−β2)gt2 -
对偏差进行修正
m ^ t ← m t / ( 1 − β 1 t ) v ^ t ← v t / ( 1 − β 2 t ) \hat m_t \leftarrow m_t / (1 - \beta_1^t) \\ \hat v_t \leftarrow v_t / (1 - \beta_2^t) m^t←mt/(1−β1t)v^t←vt/(1−β2t) -
更新参数
θ t ← θ t − 1 − η m ^ t / ( v ^ t + ϵ ) . \theta_t \leftarrow \theta_{t-1} - \eta \, \hat m_t / (\sqrt{\hat v_t} + \epsilon). θt←θt−1−ηm^t/(v^t+ϵ).
-
存储占用分析:
Adam将存储从2倍的模型参数( θ t , g t \theta_t,g_t θt,gt)增加到了4倍( θ t , g t , m t , v t \theta_t,g_t,m_t,v_t θt,gt,mt,vt)。
4.2.3 AdaFactor
AdaFactor是一种为减少存储占用的优化算法。它有如下特点:
- 它不储存 m t , v t m_t,v_t mt,vt这样的 O ( m × n ) O(m \times n) O(m×n)矩阵,而是存储行和列的和 O ( m + n ) O(m + n) O(m+n)并重构矩阵
- 去除动量
- 它被用来训练T5
- AdaFactor可能使训练变得困难(见Twitter thread和blog post)
4.2.4 混合精度训练
混合精度训练是另一种减少存储的方法
- 通常来说,默认的精度是:FP32(32位浮点)
- 其他可选精度:FP16(16位浮点),但问题是任何小于 2 − 24 2^{-24} 2−24的值都会变为0。
- 解决方案:将主权重存储在FP32中,并在FP16中执行其他所有操作。
- 损失缩放:按比例放大损失,以避免梯度数值太小。
- 结果:存储减少了一半。
4.2.5 学习率
- 通常情况下,学习率会随着时间的推移而衰减。
- 对于Transformer模型,我们实际上需要通过预热(warmup)提高学习率。
- Huang et al., 2020表明,一个潜在的原因是防止层归一化的梯度消失,导致使用Adam优化器训练时不稳定。
4.2.6 初始化
- 给定矩阵 W ∈ R m × n W \in \mathbb{R}^{m \times n} W∈Rm×n,标准初始化(即,xavier初始化)为 W i j ∼ N ( 0 , 1 / n ) W_{ij} \sim N(0, 1/n) Wij∼N(0,1/n)。
- GPT-2和GPT-3通过额外的 1 / N 1/\sqrt{N} 1/N缩放权重,其中 N N N是残差层的数量。
- T5将注意力矩阵增加一个 1 / d ( 1/\sqrt{d}( 1/d(代码)。
以GPT-3为例,使用的参数如下:
- Adam参数: β 1 = 0.9 , β 2 = 0.95 , ϵ = 1 0 − 8 \beta_1 = 0.9, \beta_2 = 0.95, \epsilon = 10^{-8} β1=0.9,β2=0.95,ϵ=10−8
- 批量小:320万个token(约1500个序列)
- 使用梯度剪裁( g t ← g t / min ( 1 , ∥ g ∥ 2 ) g_t \leftarrow g_t / \min(1, \|g\|_2) 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.