mirror of
https://github.com/skindhu/Build-A-Large-Language-Model-CN.git
synced 2026-07-29 15:20:24 +08:00
update with img path
This commit is contained in:
@@ -32,7 +32,9 @@
|
||||
|
||||
在之前的章节中,我们实现了数据采样、注意力机制,并编写了 LLM 的架构。本章的核心是实现训练函数并对 LLM 进行预训练,详见图 5.1。
|
||||
|
||||
<img src="../Image/chapter5/figure5.1.png" width="75%" />
|
||||
<div style="text-align: center;">
|
||||
<img src="Image/chapter5/figure5.1.png" width="75%" />
|
||||
</div>
|
||||
|
||||
如图5.1所示,我们将继续学习基本的模型评估技术,以衡量生成文本的质量,这对于在训练过程中优化 LLM 是非常必要的。此外,我们将讨论如何加载预训练权重,以便为接下来的微调提供坚实的基础。
|
||||
|
||||
@@ -48,7 +50,9 @@
|
||||
|
||||
本章开篇,我们将基于上一章的代码设置 LLM 进行文本生成,并讨论如何对生成文本质量进行评估的基本方法。而本章剩余部分的内容请参考图5.2。
|
||||
|
||||
<img src="../Image/chapter5/figure5.2.png" width="75%" />
|
||||
<div style="text-align: center;">
|
||||
<img src="Image/chapter5/figure5.2.png" width="75%" />
|
||||
</div>
|
||||
|
||||
如图 5.2 所示,接下来的小节我们首先简要回顾上一章末尾的文本生成过程,然后深入探讨文本评估及训练和验证损失的计算方法。
|
||||
|
||||
@@ -84,7 +88,9 @@ model.eval()
|
||||
|
||||
我们通过前一章节中介绍的 generate_text_simple 函数来使用 GPTmodel 实例,同时引入了两个实用函数:text_to_token_ids 和token_ids_to_text。这些函数简化了文本与 token 表示之间的转换,本章中我们将多次使用这种技术。图 5.3 可以帮助我们更清楚地理解这一过程。
|
||||
|
||||
<img src="../Image/chapter5/figure5.3.png" width="75%" />
|
||||
<div style="text-align: center;">
|
||||
<img src="Image/chapter5/figure5.3.png" width="75%" />
|
||||
</div>
|
||||
|
||||
图 5.3 展示了使用 GPT 模型生成文本的三个主要步骤。首先,分词器将输入文本转换为一系列 token ID(在第 2 章中已有讨论)。然后,模型接收这些 token ID 并生成对应的 logits(即词汇表中每个 token 的概率分布,具体见第 4 章)。最后,将 logits 转换回 token ID,分词器将其解码为可读的文本,完成从文本输入到文本输出的循环。
|
||||
|
||||
@@ -135,7 +141,9 @@ Output text:
|
||||
|
||||
图 5.4 展示了从输入文本到 LLM 生成文本的整体流程,该流程通过五个步骤实现。
|
||||
|
||||
<img src="../Image/chapter5/figure5.4.png" width="75%" />
|
||||
<div style="text-align: center;">
|
||||
<img src="Image/chapter5/figure5.4.png" width="75%" />
|
||||
</div>
|
||||
|
||||
图 5.4 展示了第 4 章中`generate_text_simple`函数内部的本生成过程。在后续章节中计算生成文本的质量损失之前,我们需要先执行这些初始步骤。
|
||||
|
||||
@@ -208,13 +216,17 @@ Outputs batch 1: Armed heNetflix
|
||||
|
||||
可以看到,模型生成的文本与目标文本不同,因为它尚未经过训练。接下来,我们将通过‘损失’来数值化评估模型生成文本的质量(详见图 5.5)。这不仅有助于衡量生成文本的质量,还为实现训练函数提供了基础,训练函数主要通过更新模型权重来改善生成文本的质量。
|
||||
|
||||
<img src="../Image/chapter5/figure5.5.png" width="75%" />
|
||||
<div style="text-align: center;">
|
||||
<img src="Image/chapter5/figure5.5.png" width="75%" />
|
||||
</div>
|
||||
|
||||
文本评估过程的一部分(如图 5.5 所示)是衡量生成的 token 与正确预测目标之间的差距。本章后面实现的训练函数将利用这些信息来调整模型权重,使生成的文本更接近(或理想情况下完全匹配)目标文本。
|
||||
|
||||
换句话说,模型训练的目标是提高正确目标 token ID 所在位置的 softmax 概率,如图 5.6 所示。接下来的部分中,我们还会将该 softmax 概率作为评价指标,用于对模型生成的输出进行数值化评估:正确位置上的概率越高,模型效果越好。
|
||||
|
||||
<img src="../Image/chapter5/figure5.6.png" width="75%" />
|
||||
<div style="text-align: center;">
|
||||
<img src="Image/chapter5/figure5.6.png" width="75%" />
|
||||
</div>
|
||||
|
||||
请注意,图 5.6 使用了一个包含 7 个 token 的简化词汇表,以便所有内容可以在一张图中展示。这意味着 softmax 的初始随机值会在 1/7 左右(约 0.14)。
|
||||
|
||||
@@ -251,7 +263,9 @@ Text 2: tensor([1.0337e-05, 5.6776e-05, 4.7559e-06])
|
||||
|
||||
在本节剩余内容中,我们将针对`target_probas_1`和`target_probas_2`的概率得分计算损失。图 5.7 展示了主要步骤。
|
||||
|
||||
<img src="../Image/chapter5/figure5.7.png" width="75%" />
|
||||
<div style="text-align: center;">
|
||||
<img src="Image/chapter5/figure5.7.png" width="75%" />
|
||||
</div>
|
||||
|
||||
由于我们已经完成了图 5.7 中列出的步骤 1-3,得到了 `target_probas_1` 和 `target_probas_2`,现在进行第 4 步,对这些概率得分取对数:
|
||||
|
||||
@@ -407,7 +421,9 @@ tensor(10.7940)
|
||||
|
||||
在本节中,我们首先准备训练和验证数据集,以用于后续 LLM 的训练。接着,我们计算训练集和验证集的交叉熵(如图 5.8 所示),这是模型训练过程中的重要组成部分。
|
||||
|
||||
<img src="../Image/chapter5/figure5.8.png" width="75%" />
|
||||
<div style="text-align: center;">
|
||||
<img src="Image/chapter5/figure5.8.png" width="75%" />
|
||||
</div>
|
||||
|
||||
为了计算训练集和验证集上的损失(如图 5.8 所示),我们使用了一个非常小的文本数据集,即伊迪丝·华顿的短篇小说《判决》,我们在第 2 章中已对此文本进行过处理。选择公共领域的文本可以避免任何关于使用权的担忧。此外,我们选择小数据集的原因在于,它允许代码示例在普通笔记本电脑上运行,即使没有高端 GPU 也能在几分钟内完成,这对于教学尤为有利。
|
||||
|
||||
@@ -447,7 +463,9 @@ Tokens: 5145
|
||||
|
||||
接下来,我们将数据集划分为训练集和验证集,并使用第二章的数据加载器为 LLM 训练准备需输入的批量数据。图 5.9 展示了该过程。
|
||||
|
||||
<img src="../Image/chapter5/figure5.9.png" width="75%" />
|
||||
<div style="text-align: center;">
|
||||
<img src="Image/chapter5/figure5.9.png" width="75%" />
|
||||
</div>
|
||||
|
||||
出于可视化的需要,图 5.9 将最大长度设置为 6。然而,在实际数据加载器中,我们会将最大长度设置为 LLM 支持的 256 个 token 的上下文长度,使得模型在训练时可以看到更长的文本。
|
||||
|
||||
@@ -600,7 +618,9 @@ Validation loss: 10.98110580444336
|
||||
|
||||
现在我们已经有了评估生成文本质量的方法,接下来我们将训练 LLM 以减少损失,从而提升文本生成的效果,如图 5.10 所示。
|
||||
|
||||
<img src="../Image/chapter5/figure5.10.png" width="75%" />
|
||||
<div style="text-align: center;">
|
||||
<img src="Image/chapter5/figure5.10.png" width="75%" />
|
||||
</div>
|
||||
|
||||
如图 5.10 所示,下一节将重点讲解 LLM 的预训练过程。在模型训练完成后,将应用不同的文本生成策略,并保存和加载预训练模型的权重。
|
||||
|
||||
@@ -610,7 +630,9 @@ Validation loss: 10.98110580444336
|
||||
|
||||
在本节中,我们将实现 LLM(基于GPTModel)的预训练代码。我们重点采用一种简单的训练循环方式来保证代码简洁易读(如图 5.11 所示)。不过,有兴趣的读者可以在附录 D 中了解更多高级技术,包括学习率预热、余弦退火和梯度裁剪等,以进一步完善训练循环。
|
||||
|
||||
<img src="../Image/chapter5/figure5.11.png" width="75%" />
|
||||
<div style="text-align: center;">
|
||||
<img src="Image/chapter5/figure5.11.png" width="75%" />
|
||||
</div>
|
||||
|
||||
图 5.11 中的流程图展示了一个典型的 PyTorch 神经网络训练流程,我们用它来训练大语言模型(LLM)。流程概述了 8 个步骤,从迭代各个 epoch 开始,处理批次数据、重置和计算梯度、更新权重,最后进行监控步骤如打印损失和生成文本样本。如果你对使用 PyTorch 如何训练深度神经网络不太熟悉,可以参考附录 A 中的 A.5 至 A.8 节。
|
||||
|
||||
@@ -771,7 +793,9 @@ plot_losses(epochs_tensor, tokens_seen, train_losses, val_losses)
|
||||
|
||||
生成的训练损失和验证损失图表如图 5.12 所示。
|
||||
|
||||
<img src="../Image/chapter5/figure5.12.png" width="75%" />
|
||||
<div style="text-align: center;">
|
||||
<img src="Image/chapter5/figure5.12.png" width="75%" />
|
||||
</div>
|
||||
|
||||
如图 5.12 所示,训练损失和验证损失在第一个 epoch 开始时都有所改善。然而,从第二个 epoch 之后,损失开始出现分歧。验证损失远高于训练损失,这表明模型在训练数据上出现了过拟合。我们可以通过搜索生成的文本片段(例如“The Verdict”文件中的片段:“quite insensible to the irony”)来确认模型逐词记住了训练数据。
|
||||
|
||||
@@ -800,7 +824,9 @@ plot_losses(epochs_tensor, tokens_seen, train_losses, val_losses)
|
||||
|
||||
在接下来的部分(如图 5.13 所示),我们将探讨 LLM 使用的采样方法,这些方法可以减轻记忆效应,从而生成更具新意的文本。
|
||||
|
||||
<img src="../Image/chapter5/figure5.13.png" width="75%" />
|
||||
<div style="text-align: center;">
|
||||
<img src="Image/chapter5/figure5.13.png" width="75%" />
|
||||
</div>
|
||||
|
||||
如图 5.13 所示,下一节将介绍适用于 LLM 的文本生成策略,以减少训练数据的记忆倾向,提升 LLM 生成文本的原创性。之后我们还会讨论权重的加载与保存,以及从 OpenAI 的 GPT 模型加载预训练权重。
|
||||
|
||||
@@ -948,7 +974,9 @@ plt.show()
|
||||
|
||||
图 5.14 展示了生成的图表:
|
||||
|
||||
<img src="../Image/chapter5/figure5.14.png" width="75%" />
|
||||
<div style="text-align: center;">
|
||||
<img src="Image/chapter5/figure5.14.png" width="75%" />
|
||||
</div>
|
||||
|
||||
当 temperature 取 1 时,logits 在传递给 softmax 函数之前会除以 1,计算概率得分。这意味着,temperature 为 1 时相当于不进行任何缩放。在这种情况下,模型将根据原始的 softmax 概率,通过 PyTorch 中的`multinomial`函数来选择 token。
|
||||
|
||||
@@ -985,7 +1013,9 @@ plt.show()
|
||||
|
||||
在 top-k 采样中,我们可以将采样限制在最有可能的前 k 个 token 内,并通过将其他 token 的概率设为零,将它们排除在选择之外,如图 5.15 所示。
|
||||
|
||||
<img src="../Image/chapter5/figure5.15.png" width="75%" />
|
||||
<div style="text-align: center;">
|
||||
<img src="Image/chapter5/figure5.15.png" width="75%" />
|
||||
</div>
|
||||
|
||||
如图 5.15 所示,将所有未选中的 logits 替换为负无穷(-inf),这样在计算 Softmax 时,非 top-k 的 token 的概率为 0,剩下的概率之和为 1。(细心的读者可能记得,我们在第 3 章的因果注意力模块中使用过这种掩码技巧。)
|
||||
|
||||
@@ -1129,7 +1159,9 @@ Every effort moves you stand to work on surprise, a one of us had gone with rand
|
||||
|
||||
如图 5.16 的章节概览所示,本节将介绍如何保存和加载预训练模型。然后,在接下来的部分中,我们将从 OpenAI 加载一个更强大的预训练 GPT 模型到我们的 GPTModel 实例中。
|
||||
|
||||
<img src="../Image/chapter5/figure5.16.png" width="75%" />
|
||||
<div style="text-align: center;">
|
||||
<img src="Image/chapter5/figure5.16.png" width="75%" />
|
||||
</div>
|
||||
|
||||
幸运的是,保存 PyTorch 模型相对简单。推荐的做法是保存模型的 `state_dict`(状态字典),这是一个字典,用于将模型的每一层映射到其对应的参数上,可以通过 `torch.save` 函数来实现,代码如下所示:
|
||||
|
||||
@@ -1272,7 +1304,9 @@ Token embedding weight tensor dimensions: (50257, 768)
|
||||
|
||||
我们通过 `download_and_load_gpt2(model_size="124M", ...)` 加载了最小的 GPT-2 模型权重。此外,OpenAI 还提供了更大规模模型的权重,包括 "355M"、"774M" 和 "1558M" 等。尽管模型规模不同,但其整体架构是相同的,如图 5.17 所示。
|
||||
|
||||
<img src="../Image/chapter5/figure5.17.png" width="75%" />
|
||||
<div style="text-align: center;">
|
||||
<img src="Image/chapter5/figure5.17.png" width="75%" />
|
||||
</div>
|
||||
|
||||
如图 5.17 所示,不同大小的 GPT-2 模型在总体架构上保持一致,但注意力头和 Transformer 模块等组件的重复次数以及嵌入维度大小有所不同。本章的剩余代码也会兼容这些更大的模型。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user