原文:
towardsdatascience.com/large-language-models-gpt-1-generative-pre-trained-transformer-7b895f296d3b
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/4b7ef9b2a91903c00d06e0ad0f732afd.png
简介
2017 年是机器学习历史上的一个重要年份。谷歌大脑团队的研究人员引入了Transformer,它迅速超越了大多数现有的深度学习方法。著名的注意力机制成为了从 Transformer 派生出来的未来模型的关键组件。关于 Transformer 架构的惊人事实是其巨大的灵活性:它可以高效地用于各种机器学习任务类型,包括 NLP、图像和视频处理问题。
原始的 Transformer 可以分解为两部分,称为编码器和解码器。正如其名所示,编码器的目标是将以数字向量形式编码输入序列,这是一种机器能理解的低级格式。另一方面,解码器接收编码后的序列,通过应用语言建模任务,生成一个新的序列。
编码器和解码器可以单独用于特定任务。从原始 Transformer 中提取其部分的两个最著名的模型被称为**BERT(来自 Transformer 的双向编码器表示)和GPT**(生成预训练 Transformer),由解码器块组成。
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/61a9268b9e08f9ffcf0717a3a825d636.png
Transformer 架构
在这篇文章中,我们将讨论 GPT 并了解它是如何工作的。从高层次的角度来看,有必要了解 GPT 架构由一系列 Transformer 块组成,如上图所示,除了它没有输入编码器的事实之外。
大型语言模型:BERT – 来自 Transformer 的双向编码器表示
框架
对于大多数 LLM(大型语言模型)而言,GPT 的框架由两个阶段组成:预训练和微调。让我们研究它们是如何组织的。
1. 预训练
损失函数
如论文所述,“我们使用标准的语言建模目标来最大化以下似然率”:
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/b4986b7b41a481306ff8b2b6f3489024.png
预训练损失函数。
在这个公式中,在每一步,模型输出所有可能的标记作为下一个标记i的概率分布,对于由最后k个上下文标记组成的序列。然后,计算真实标记的概率的对数,并将其用作损失函数中几个值之一。
参数 k 被称为上下文窗口大小。
提到的损失函数也被称为对数似然。
编码器模型(例如 BERT)根据来自两边的上下文预测标记,而解码器模型(例如 GPT)仅使用前面的上下文,否则它们将无法学习生成文本。
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/92983e0be4e31ffef93a6cefd300b795.png
GPT 预训练期间的图
损失函数背后的直觉
由于对数似然的表达式可能不容易理解,本节将详细解释它是如何工作的。
如其名所示,GPT 是一个生成模型,这意味着其最终目标是推理期间生成一个新的序列。为了实现这一点,在训练期间,输入序列被嵌入并分割成大小相等的几个子字符串k。之后,对于每个子字符串,模型被要求通过为所有词汇标记构建的输出概率分布(使用最终的 softmax 层)来预测下一个标记。在这个分布中的每个标记都被映射到这个标记确实是子序列中下一个真实标记的概率。
为了使事情更清晰,让我们看看下面的例子,其中我们给出了以下字符串:
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/75d5d719caeb1b3d0fb32d968dd7b22e.png
我们将这个字符串分割成长度为k = 3的子字符串。对于这些子字符串中的每一个,模型都会为语言建模任务输出一个概率分布。预测的分布如下表所示:
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/b2202198a21991633522ff955ff1e7cf.png
在每个分布中,取与序列中真实标记对应的概率(黄色高亮显示)并用于损失计算。最终的损失等于真实标记概率的对数之和。
GPT 试图最大化其损失,因此更高的损失值对应于更好的算法性能。
从上面的分布示例中可以看出,对应于真实标记的高预测概率会为损失函数添加更大的值,这表明算法性能更好。
损失函数背后的微妙之处
我们已经理解了 GPT 预训练损失函数背后的直觉。然而,对数似然的表达式最初是从另一个公式推导出来的,可能更容易解释!
让我们假设模型执行相同的语言建模任务。然而,这次,损失函数将最大化所有预测概率的乘积。这是一个合理的选择,因为所有不同子序列的输出预测概率都是独立的。
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/856c68aefa4203643cd99d73a981a693.png
之前示例中概率的乘积作为损失值
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/1325e51b05a501a6b5ab8ebb9282e5f1.png
计算损失值
由于概率被定义为范围 [0, 1],这个损失函数也将在这个范围内取值。最高值 1 表示模型以 100% 的信心预测了所有修正的标记,因此它可以完全恢复整个序列。因此,
概率乘积作为语言建模任务的损失函数,最大化了正确恢复整个序列(-s)的概率。
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/c0e53d7911a94da2e92f51a349810ac8.png
语言建模中概率乘积的通用公式
如果这个损失函数如此简单,看起来有如此好的解释,为什么它没有被用于 GPT 和其他大型语言模型(LLM)?问题出在计算限制上:
在公式中,一组概率被相乘。它们所代表的值通常非常低,接近于 0,尤其是在预训练步骤的开始阶段,算法还没有学到任何东西,因此为它的标记分配随机概率。
在现实生活中,模型是在批量而不是单个示例上训练的。这意味着损失表达式中概率的总数可以非常高。
因此,许多很小的值被相乘。不幸的是,计算机机器的浮点运算并不足以精确地计算这样的表达式。这就是为什么损失函数通过在整体乘积后插入对数而略有变换。这样做的原因是两个有用的对数性质:
- 对数是单调的。这意味着更高的损失仍然对应着更好的性能,而更低的损失对应着更差的表现。因此,最大化L或log(L)不需要修改算法。
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/f8dde03235fe662e7bd0f13d13952ed7.png
自然对数图
- 乘积的对数等于其因子的对数之和,即 log(ab) = log(a) + log(b)。这个规则可以用来将概率乘积分解为对数之和:
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/6e0601a918ac0bf16f03c719210500cc.png
我们可以注意到,仅仅通过引入对数变换,我们就得到了 GPT 中原始损失函数所使用的相同公式!鉴于上述观察,我们可以得出一个重要的事实:
GPT 中的对数似然损失函数最大化了正确预测输入序列中所有标记的概率的对数。
文本生成
一旦 GPT 预训练完成,它就可以用于文本生成。GPT 是一个自回归模型,这意味着它使用先前预测的标记作为预测下一个标记的输入。
在每次迭代中,GPT 取一个初始序列并预测其下一个最可能的标记。之后,将序列和预测的标记连接起来,作为输入再次预测下一个标记,等等。这个过程一直持续到预测到[结束]标记或达到最大输入大小。
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/37d3b98f157266078c1f50188e65cd0e.png
GPT 对句子进行自回归补全
2. 微调
预训练后,GPT 可以捕捉输入序列的语言知识。然而,为了使其在下游任务上表现更好,它需要在*[监督问题]*上进行微调。
对于微调,GPT 接受一个标记的数据集,其中每个示例包含一个输入序列x和一个相应的标签y,需要预测。每个示例都通过模型传递,模型在最后一层输出它们的隐藏表示h。然后,这些向量被传递到一个添加的具有可学习参数W的线性层,然后通过 softmax 层。
用于微调的损失函数与预训练阶段提到的非常相似,但这次它评估的是观察目标值y的概率,而不是预测下一个标记。最终,对批处理中的几个示例进行评估,然后计算对数似然。
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/c7944678c1f60f148d9e5ffdb62a3a29.png
下游任务的损失函数
此外,论文的作者们发现,在微调损失函数中包含用于预训练的辅助目标也是有用的。据他们所说,它:
提高模型的一般化;
加速收敛。
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/eb6212b86af47db7c385230d20a0b915.png
GPT 微调过程中的图示。图片由作者采用。
最后,微调损失函数采用以下形式(α是一个权重):
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/496e9324cee0acc3fc9d244c9d5a0a15.png
微调损失函数
下游任务上的输入格式
在 NLP 中存在许多微调模型的方法。其中一些需要更改模型的架构。这种方法的明显缺点是,它使得使用迁移学习变得更加困难。此外,这种技术还需要对模型进行大量的定制,这在实际中完全不实用。
另一方面,GPT 采用遍历式方法:对于不同的下游任务,GPT 不需要对其架构进行更改,只需更改输入格式。原始论文展示了 GPT 在各个下游问题中接受的输入格式的可视化示例。让我们分别来看一下。
分类
这是最简单的下游任务。输入序列被包裹在*[start]和[end]*标记(这些是可训练的)中,然后传递给 GPT。
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/382db82bf4fe25f38e6cb137b2f9cf70.png
微调的分类流程。图片由作者采用。
文本蕴涵
文本蕴涵或自然语言推理(NLI)是确定第一个句子(前提)是否逻辑上跟随第二个句子(假设)的问题。为此任务建模,前提和假设通过分隔符标记($)连接。
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/c48ff674e1518c3faf04469e0b82f399.png
微调的文本蕴涵流程。图片由作者采用。
语义相似度
相似性任务的目标是理解一对句子在语义上有多接近。通常,比较的句子对没有顺序。考虑到这一点,作者提出将句子对以两种可能的顺序连接起来,并将结果序列输入到 GPT 中。然后,将两个隐藏输出 Transformer 层逐元素相加,并传递到最终的线性层。
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/28b6611f9a23e2bc5a247c2c038e4f37.png
微调的语义相似度流程。图片由作者采用。
问题回答 & 多项选择题回答
多项选择题回答是基于提供的上下文信息正确选择一个或多个答案的任务。
对于 GPT,每个可能的答案都与上下文和问题连接起来。然后,将所有连接的字符串独立地传递到 Transformer 中,其线性层的输出被聚合,并基于最终的答案概率分布选择预测。
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/cfc7e036c803f9ebf3dc3aedd66b9fa5.png
微调的多项选择题流程。图片由作者采用。
设置
GPT 在包含 7k 本书的 BookCorpus 数据集上进行预训练。这个数据集被特意选择,因为它主要由长文本段组成,这使得模型能够更好地捕捉长距离上的语言信息。说到架构和训练细节,模型有以下参数:
Transformer 块数量:12
嵌入大小:768
注意力头数量:12
FFN 隐藏状态大小:3072
优化器:Adam(学习率设置为 2.5e-4)
激活函数:GELU
使用词汇量为 40k 的字节对编码
总参数数量:120M
最后,GPT 在 100 个 epoch 的 64 个批次的连续 512 个 token 序列上进行预训练。
用于微调的大多数超参数与预训练期间使用的相同。然而,对于微调,学习率降低到 6.25e-5,批处理大小设置为 32。在大多数情况下,3 个微调周期就足以使模型产生强大的性能。
字节对编码有助于处理未知标记:它迭代地在子词级别构建词汇表,这意味着任何未知标记都可以被分割成学习到的子词表示的组合。
结论
结合 Transformer 块的力量和优雅的架构设计,GPT 已成为机器学习中最基础的模型之一。它在顶级基准测试中建立了 12 项中的 9 项新的最先进结果,并成为其未来庞大的继任者(如 GPT-2、GPT-3、GPT-4、ChatGPT 等)的关键基础。
资源
- 通过生成预训练改进语言理解
所有图像均为作者创作,除非另有说明