本文是对 Andrej Karpathy 的在 2023 年 3 月份的 Microsoft Build 演讲的整理。
演讲 Beamer 可见于:https://karpathy.ai/stateofgpt.pdf
演讲介绍了 GPT 的训练过程,发展地步,当前的 LLM 生态以及未来展望,在一年后的今天也没有过时,完全可以与当下的实际发展对比阅读、分析。
Overview#
pretraining 部分占据了绝大部分训练时间,后面的三个阶段都是 fine-tuning 阶段。
Data collection#
Training data mixture used in Meta's LLaMA model
Composition of the mixture:
- CommonCrawl: 普通的网络爬虫
- C4:Common Crawl 的一个巨大而干净的版本。
- 其它高质量数据集如图所示
这些知识混合在一起,然后根据给定的比例进行采样,构成了 GPT 神经网络的训练集。
Pre-training#
实际训练前,需要进行预处理步骤如下。
tokenization#
基本上是把互联网上爬取的原始文本转译为整数序列(sequence of integers)的无损转换过程。
可以使用像byte-pair encoding(BPE)的方法,迭代合并小文本块并将它们分组为token
Transformer 神经网络的超参数表格
-
Vocabulary Size(词汇表大小):
- 词汇表大小指的是模型能够识别和生成的唯一词汇(包括单词、字符或子词单元)的总数。这个数字定义了模型输入和输出的可能性范围。
- 类比Bigram中,我们指定的是输出预测的字母,因此是 “字符表”,大小为 27
-
Context Length(上下文长度):
- 上下文长度指的是模型在处理文本时能够考虑的最大单元数(通常是词或者 token)的数量。这个长度定义了模型在生成文本或理解文本时能够回顾的信息量。
- NPLM模型中,上下文长度就被设为 3,也就是通过前 3 个 token 预测下一个。
- 如今 GPT4 等模型可以接受十万多的输入。
-
参数量(Parameters)
- 参数量指的是构成模型的参数的总数,这些参数在训练过程中学习并调整,以最小化预测误差。参数可以是权重(weights)和偏置(biases),它们在神经网络中用于处理输入数据,进行变换,并最终生成输出。模型的参数量是衡量模型大小和复杂度的一个直接指标。
- NPLM中的这段代码中就统计了模型的参数量,并尝试了通过增加隐藏层神经元数等方式来加大参数量改善拟合。
g = torch.Generator().manual_seed(2147483647)
C = torch.randn((27,2), generator=g)
W1 = torch.randn((6,100), generator=g)
b1 = torch.randn(100, generator=g)
W2 = torch.randn((100,27), generator=g)
b2 = torch.randn(27, generator=g)
parameters = [C, W1, b1, W2, b2]
sum(p.nelement() for p in parameters)
- Training Tokens Total(训练的 token 总量):
- 训练的 token 总量指的是在训练过程中模型处理的 token(可以是单词、字符或子词单元)的总数。这个数字反映了模型训练过程中 “看到” 和学习的数据量。
- 类比姓名数据集中,一共有 30k 数据,那可以理解为 (1B 是,即十亿)。
可以看到,LLaMA 的训练量十分之大,用更长的训练时间取得了比 GPT-3 更好的效果,因此不能只根据模型的参数量来判断性能。
最开始的时候,模型的权重是随机的,因此采样结果是完全随机的。随着训练时间增常,从模型中获取的样本就会越来越连贯而一致。从图中最后可以看出,这个 GPT 模型已经学到了单词、空格和标点符号等方面的知识。
Training curve#
随着训练进度推移,关注的重点是损失函数的变化,低损失意味着这个 Transformer 模型对序列中正确的下一个整数给予了更高的概率。
GPT 学习到了强大的general representations,也可以非常高效的地去微调,适用于任意下游任务。
以情感分类任务为例子,我之前正好参与过相关研究,当时是调用了百度的某个情感分析 API 来对我们收集到的数据进行积极、消极判断等处理,得到监督学习中可以使用的数据,然后再用其它 NLP 模型进行训练。但 GPT 出现后,完全可以先忽略情感分类去做 LLM 的预训练,用少量的数据高效微调针对这一任务的 Transformer 模型。
这是因为 Transformer 模型在语言建模任务中被强制执行了大量的multitask,它被迫要了解文本的结构和其中所有不同的概念来预测下一个 token。这是 GPT-1 阶段。
在 GPT-2 阶段,人们注意到使用prompt(提示词)实际上比微调更好、更有效。
Base model ≠ Assistant#
基础模型并非我们平时使用的 ChatGPT,我们使用的是 GPT 模型的 api 如 Davinci、3.5 Turbo,它们是助手。而真正的基础模型并不是assistant,只是想补全文件:
你你可以通过创建特定的few-shot prompt来讲基础模型变为助手,让它看看起来像是有一个中间的交互文档,然后将你的查询放在末尾,基础模型就会自我调整为一个能帮忙的助手回答问题。但这不太可靠并且效果欠佳,所以创建实际的 GPT 助手走了一条不同的的路。
Supervised Finetuning#
这个阶段收集小而高质量的数据集,用众包的形式,人工收集 prompt 和理想回应的数据。继续对这些数据进行语言建模,算法不变,只是更换了数据集。训练得到一个 SFT (Supervised Fine-Tuning) 模型,这是可部署的真正助手,有一定效果。
示意图,众包工人撰写的回应被要求友好、真实和无害,并遵循着指示文件。
RLHF pipeline#
acronym of reinforcement learning from human feedback
Reward Modeling#
这个阶段,我们将收集到的数据转为Comparisons的形式,用相同的 prompt,来要求助手完成任务,让训练好的 SFT 模型创建多个版本的回答,再让人们去评估哪个版本更好(这个很费时费力)
然后对这些版本进行分类,做法是在最后添加一个特殊的reward token,然后基本上只监督这个 (绿色) token 上用 Transformer。Transformer 会预测完成某个 prompt 的回答对应的奖励,根据人工标注的真实奖励标签转化为损失函数,然后训练我们的模型,让它产生和人工众包的评估事实一致的对奖励的预测。
建立好奖励模型后,它本身作为助手还不是很有用,但是对接下来的强化学习阶段十分有用。
Reinforcement Learning#
根据奖励模型,我们可以为任何给定 prompt 的 completion 完成质量打分。这个阶段将针对奖励模型来进行强化学习。
现在的训练目标是 (黄色的) completion。使用 SFT 模型对不同 prompt 创建一些 completion,然后再次添加奖励 token,根据已经固定的奖励模型指示的奖励来权衡语言建模目标。
图中可以看出,高绝对值的 reward 会增加未来 token 采样的权重。
在大量 prompt 和 batches 上迭代,获得了能创建在奖励模型中取得高分的 completion 的策略。
得到了一个可部署的 RLHF 模型。
Why RLHF?#
表现更好,人类更喜欢它们生成的回答。
一种解释可能:判断比较和生成的难度是不对等的,比如相比于创作一个优秀的俳句 (一种日本的古典短诗),判断几个俳句中哪个写的更好显然更简单。这可以潜在地利用人类的判断力,创建更好的模型。
但也因此,相较于 Basemodel,RLHF 后的模型失去了一些熵。也就是说模型输出的变换很小,而 basemodel 具有很高的熵,并产生多种可能的输出。因此在类似 “生成更多 Pokemon 名字” 的任务中,basemodel 也许更擅长。
Apply LLM Assistant#
Chain of thought#
aka COT
当人类写作的时候,我们内心有一个独立的过程 —— 总是在审视我们所写的内容,并判断写的是否 good enough,我们可能删掉一部分或者重新写,然后对结果满意。
而在 GPT 的视角,这只是一系列 token,它会查看每个 token 并在每个 token 上花费等量的计算,完全不会有上述的内心独白。也就是说,Transformers 模型就相当于 token 模拟器,它们不知道自己善于或不擅长什么,只是拟合下一个 token。模型不会对任何内容做反馈、合理性检查或是纠错。
GPT 通过存储大量领域的基于事实的知识,用几十亿个参数存储,拥有很强的工作记忆力。因此,在上下文长度范围内的任何内容都可以通过 Transformer 内部的自注意力机制立即获得,无损地记住这些内容。相当于是有限的完美记忆。
Prompting 只是弥补人脑和 “LLM 脑” 之间的认知差异的一种方式。因此实践中,如果你在做需要推理能力的任务,你不能指望 Transformer 能对每个 token 都做太多推理,所以你必须将推理分散到更多 token 中。
让 LLM 模拟这种推理
或者是多次采样,然后投票选出答案
或者是我们生活中常用的:告诉 LLM 它的回答有错误,它会认识到错误。但如果你没有提示他,他就根本不会自主反馈。
Tree of Thoughts#
通过同时考虑多个潜在的可行计划,并利用价值反馈机制进行决策,扩展了现有的规划方法。此外,该方法还引入了自我反思机制,使语言模型能够评估自身生成的候选项的可行性。
这是通过 python 粘合代码 (Glue Code) 和单个 prompt 共同实现,其中还包括树搜索等。
AlphaGo 就是模拟人类的决策,用蒙特卡洛树搜索等评估所有可能性,然后保留那些好的选择。
可以类比为针对文字的 AlphaGo。
人们开始探索更通用的技术,而不是单一的 prompt,更像是通过将很多 prompt 粘合在一起。
Chains / Agents#
- ReAct:将对 prompt 的回答结构化为一系列 thought, action, observation, ... 的组合,用思考过程回答问题,这过程中模型也可以使用外部工具。
- AutoGPT:允许 LLM 保持任务列表并递归拆分完成任务的项目,表现一般但可以带来一些启发。
Condition on good performance#
Prompt Engineering#
LLM 其实有 “不想成功完成任务” 的 “心理怪癖”,它只是想模拟训练集的数据,但你想完成任务,因此你要做出要求。
如:对于一个数学问题,训练数据中可能有一个学生给出了错误答案,而一个数学专家给出了完美的答案,Transformers 无法区分哪个答案质量高。所以你必须要求它才能得到更好的表现。
听上去可能很荒唐,这能让 Transformers 现在不必将概率密度寄托在低质量的解决方案上
但也不要让它有 “400 的 IQ”,这可能会得到科幻作品般的回答。
Tools / Plugins#
LLM 默认情况下不知道自己不擅长什么。
因此甚至可以在 prompt 中告诉它 “你不擅长计算”,计算的部分用这个 token 组合(如通过调用计算器 api 得到的)
Retrieval-Augmented LLMs#
搜索引擎是Retrieval only(只有检索能力) 的代表,也就是前 LLM 时代的主流。
而 LLM 则是Memory only,在两个极端的之间存在很大的Retrieval augment(检索增强) 空间。
以 LlamaIndex 为例,它可以连接不同类型的数据,对这些数据建立索引并对 LLM 开放。
原理是将所给的文档分成块 (chunks),然后嵌入它们得到表示数据的嵌入向量 (embedding vectors),把它存储在向量存储库中。提问时,会对向量存储发出某种查询,获取可能与所提出的任务相关的块,然后塞入 prompt 中再生成回答。实践中效果很好。
可以类比,就算是一个记忆力出色的学生,但期末考试前还是会希望能去教材中找到具体原文。
Constraint prompting#
这基本上是一些强制 LLMs 输出特定模板的技术
下面例子中,我们强制要求 LLM 输出 JSON 格式,然后可以对放入模板中这些空白处的内容强制实施额外限制。
Microsoft 的 “guidance” 项目
Finetuning#
模型微调意味着改变模型的权重,一些技术让这件事变得比以前更容易了。如 LoRA 可以确保你可以用低精度的推理(而不是梯度下降)只训练模型中小而稀疏的部分(只有部分允许更改),做到有效微调,效果很好的同时降低了成本。
Suggestions#
建议分为针对两个目标如下,也算是回顾了。
目标 1 得到最佳表现:
- 使用 GPT-4。
- 设计详细任务上下文、相关信息和指令的提示(prompt)。
- 若无法通过电邮回复,询问任务承包人将会怎样做。
- 为提示(prompt)添加任何相关的上下文或信息。
- 尝试使用之前幻灯片中提到的提示工程技术(prompt engineering techniques)。
- 使用少数示例(few-shot examples)进行实验,确保这些示例 1)与测试案例相关,2)多样性(如果适当)。
- 使用工具 / 插件来卸载对于大型语言模型(LLMs)难以处理的任务(如计算、代码执行等)。
- 质量时间优化流程 /“链(chains)”。
- 如果你对已经最大化了提示效用有信心,考虑收集 SFT 数据和 RLHF 微调(fine-tuning)。
目标 2 优化成本:
- 一旦实现了最高性能,尝试节省成本的措施(例如使用更短的提示,GPT-3.5 等)。