Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

7.7 预训练 Transformer LLM

正如第 1 章所讨论的,在 预训练(pretraining)中,我们把一个大型文本语料库词元化,作为训练材料;通常是在大规模网络抓取数据的基础上补充其他高质量数据。随后,在每个词元 t 处要求模型预测下一词元,并通过误差反向传播和梯度下降,训练模型的各项参数(嵌入矩阵、前馈矩阵、注意力矩阵以及其他权重矩阵)。我们把这样的模型称为 自监督模型(self-supervised model),因为不必为数据添加任何专门的标准标签;词语的自然序列本身就是监督信号!我们只需训练模型,使其在预测训练序列中真实下一词时的误差最小。

需要最小化并向网络后向传播的损失函数,是我们已经在第 4 章和第 6 章两次见过的交叉熵损失函数。回想一下,交叉熵损失衡量预测概率分布与正确分布之间的差异。这里的概率分布定义在词元词表上,因此损失为:

LCE(y^t,yt)=wVyt[w]logy^t[w](7.53)L _ {C E} (\hat {\mathbf {y}} _ {t}, \mathbf {y} _ {t}) = - \sum_ {w \in V} \mathbf {y} _ {t} [ w ] \log \hat {\mathbf {y}} _ {t} [ w ]\tag{7.53}

对于语言建模,我们因为知道下一词,所以可以获得正确分布 yt\mathbf { y }_t。该分布表示为词表上的一个独热向量:真实下一词所对应的元素为 1,其他所有元素均为 0。因此,语言建模的交叉熵损失取决于模型为正确下一词元分配的概率(式 7.53 第一项会把所有其他词元乘以零)。

因此,在不失一般性的情况下,可以说时间 tt 上式 7.53 的交叉熵损失可简化为模型赋予训练序列中下一词的负对数概率,即 logp(wt+1)- \log p ( w _ { t + 1 } )。更正式地,用 y^\hat { \mathbf { y } } 表示语言模型估计的词元概率向量:

LCE(y^t,yt)=logy^t[wt+1](7.54)L _ {C E} (\hat {\mathbf {y}} _ {t}, \mathbf {y} _ {t}) = - \log \hat {\mathbf {y}} _ {t} [ w _ {t + 1} ]\tag{7.54}

于是,在输入的每个词位置 tt,模型接收正确的词元序列 w1:tw _ { 1 : t } 作为输入,并利用它计算所有可能下一词元上的概率分布,从而得到模型对下一词元 wt+1w _ { t + 1 } 的损失。随后移到下一个词时,我们会忽略模型刚才预测出的下一词,转而使用正确的词元序列 w1:t+1w _ { 1 : t + 1 },让模型估计词元 wt+2w _ { t + 2 } 的概率。这种始终向模型提供正确历史序列来预测下一词,而不是把模型在前一时间步的最佳猜测反馈给模型的做法,称为 教师强制(teacher forcing)。

图 7.22 展示了总体训练方法。在每一步中,给定前面的所有词元,最后一个 Transformer 层会输出整个词表上的分布 y^\hat{\mathbf{y}}。训练期间,模型赋给正确词的概率用于计算序列中每一项的交叉熵损失。每个批次的损失,是整个负对数概率序列上的平均交叉熵损失;更正式地表示为:

LCE( batch of length T )=1Tt=1Tlogy^t[wt+1](7.55)L _ {C E} (\text { batch of length T }) = \frac {1}{T} \sum_ {t = 1} ^ {T} - \log \hat {\mathbf {y}} _ {t} [ w _ {t + 1} ]\tag{7.55}

随后,通过梯度下降(图 4.5)调整网络中的权重,以最小化该批次上的平均交叉熵损失;所需梯度则通过计算图上的误差反向传播计算。训练会调整网络中的全部权重,其中也包括保存各词嵌入的嵌入矩阵 EE。因此,最终学到的嵌入会尽可能有利于预测后续词语。

图 7.22 预训练 LLM。在每个词元位置,模型向上传递 y^\hat{\mathbf{y}},即它对所有可能下一词的概率估计。模型赋予正确词元的概率估计取负对数后用作损失,该损失通过模型反向传播,以训练包括嵌入在内的全部权重。一个批次中所有词元的损失会取平均。

Transformer 的一个优势是可以并行训练,因此在数万亿词元上进行预训练成为可能。之所以能够并行,是因为我们预先知道期望输出 (wt+1)\left( w _ { t + 1 } \right),而因果掩码会阻止每个位置关注自己的目标,使得每个词元的输出都能单独计算。这意味着,上下文窗口中的所有 N 个位置都可以一次性与各自真实的下一词元比较并评分,从而只需一次网络前向传递就能得到 N 个训练样本。

大型模型通常会用文本填满整个上下文窗口(包含数十万词元)来训练。如果文档短于窗口长度,就会把多个文档装入同一窗口,并在文档之间插入特殊的文本结束词元。梯度下降所用的批次大小通常相当大(最大的 GPT-3 模型使用 320 万词元的批次大小)。

7.7.1 评估大语言模型:困惑度

正如第 3 章最初介绍的,评估语言模型的一种方法是衡量它预测未见文本的能力。更好的语言模型更善于预测后续词语,因此测试集中的每个词出现时,它都会对此较少“惊讶”(也就是为该词赋予更高概率)。所以,我们可以将文本中每个词元的条件概率相乘来计算文本概率,并将其用作评价指标:

likelihood(w1:T)=i=1TP(wiw<i)(7.56)\operatorname{likelihood} \left(w _ {1: T}\right) = \prod_ {i = 1} ^ {T} P \left(w _ {i} \mid w _ {< i}\right)\tag{7.56}

不过,测试集的概率取决于其长度,而且长度越长,概率就越小。(T 越大,需要相乘的概率越多;由于每个概率都小于 1,乘积会越来越小。)因此,我们需要一种以每个词元为单位、按长度归一化的指标,以便比较不同长度的文本。

第 3 章已经介绍过这样一种按长度归一化的指标:困惑度(perplexity)。回想一下,模型在一个未见测试集上的困惑度,是模型赋予该测试集的概率之倒数,并按测试集的词元长度进行归一化。对于包含 T 个词元 w1:Tw _ { 1 : T } 的测试集,困惑度为:

 Perplexity (w1:T)=P(w1:T)1T=(t=1TP(wtw<t)1)1T(7.57)\begin{array}{l l} \text { Perplexity } (w _ {1: T}) & = P (w _ {1: T}) ^ {- \frac {1}{T}} \\ & = \left(\prod_ {t = 1} ^ {T} P (w _ {t} | w _ {< t}) ^ {- 1}\right) ^ {\frac {1}{T}} \end{array}\tag{7.57}

不过,式 7.57 中的困惑度看起来应该很熟悉:它与上一节用于训练的平均交叉熵损失函数(式 7.55)几乎相同。下面重写该方程,只稍微改变记号,用 PP 替代 y^t\hat { \mathbf { y } }_t

LCE( batch of length T )=1Tt=1TlogP(wtw<t)(7.58)L _ {C E} (\text { batch of length T }) = \frac {1}{T} \sum_ {t = 1} ^ {T} - \log P (w _ {t} | w _ {< t})\tag{7.58}

事实上,一段文本的困惑度就是该文本平均交叉熵损失的指数。证明这一点留作读者练习。(请注意,由于这里的 log\log 指自然对数,平均交叉熵损失的单位是 nat,也就是使用 ln\ln 而非 log2\log_2 时的熵单位。)

由于式 7.57 中存在倒数(而且困惑度等价于一种损失),词序列的概率越高,困惑度就越低。因此,模型在数据上的困惑度越低,模型就越好。最小化困惑度,等价于根据语言模型最大化测试集概率。

这里需要注意一点:困惑度依赖于文本中的词元数量 n,因此对词元化算法的差异非常敏感。这意味着,如果两个语言模型使用差异很大的分词器,就很难精确比较它们产生的困惑度。正因如此,困惑度最适合用于比较使用相同分词器的语言模型。

困惑度衡量的是一种准确率,即预测词语的准确程度。第 1 章还介绍了 MMLU 等数据集,用于衡量问答任务的准确率。后续章节将介绍更多用于衡量 LLM 在其他任务上准确率的任务专用评估方法:第 13 章讨论机器翻译,第 11 章讨论信息检索,第 16 章讨论语音识别。