大家都可以通过写 prompt 来和大模型对话,那大模型之前的算法是怎样的,算法世界经过了哪些比较关键的发展,最后为什么是大模型这条路线走向了 AGI,作者用两篇文章共5.7万字详细探索一下。
咱们之前聊过的 Word2Vec 其实就是一个预训练模型,它通过大量的文本数据来学习每个词的向量表示。不过它有个挺明显的缺点:它只关注词和它附近词的关系,完全没考虑词的顺序。正因为没考虑顺序,每个词只能学到一个固定的向量,没法区分一词多义的情况。也就是说,如果一个词有多个意思,Word2Vec 只能学到它最常见的那个意思,其他的意思就被忽略了。
为了更好地解决这一问题,2018年提出的ELMo(Embeddings from Language Models)提出了一种基于上下文的方法,通过在大量文本数据上预先训练一个双向的LSTM模型(需要时序的场景,就有 LSTM的身影),为每个词生成上下文相关的embedding。
elmo 的参数量0.09B
图 67 ELMo
我们用一个例子直观感受下:
“我刚刚用手机完成了一笔支付,速度真快。”
“那家餐厅只接受现金支付,得带钱包去。”
在 ELMo 的上下文敏感模型中,“支付”这个词在两个句子中的含义有细微差别。在第一个句子中,“支付”指的是在线支付行为,而在第二个句子中则指的是传统的现金交易。
word2vec 和 elmo 都是词向量,那么一整句话的sentence embedding 呢。
sentence embedding 模型超级多,因为大模型幻觉问题产生的 RAG 方案中,是核心组件角色,承担着把文本转成向量的角色。我们介绍一下中文领域最好的模型 bge,其来源于北京智源人工智能研究院。
具体的模型结构参考了 transformer 的 encoder decoder 架构。
encoder 生成句子向量,以及一个简化的一层decoder 用于重建句子。解码器部分采用了极为简单的网络结构以及高比例的mask策略,使得解码任务变得极具挑战性。这种策略迫使编码器生成高质量的句子向量,以确保能够准确地重建原文本。
图68 bge 模型
训练方式如下:
图69 bge 模型训练步骤
1.
编码阶段:
首先,输入的数据会被“遮住”一部分(图中 M 阴影部分),然后模型会学习那些没被遮住的部分,生成一个句子的整体表示(sentence embedding,图中绿色部分)。
这一步的重点是让模型学会从可见的部分提取关键特征。
2.
解码阶段:
接下来,输入的数据会被“遮得更多”(图中 M 阴影部分),然后模型会结合上一步生成的句子嵌入,尝试把被遮住的部分“猜”出来。
这一步的目的是让模型学会利用上下文信息,更准确地恢复隐藏的内容。
3.
强化编码阶段:
最后,模型会利用句子嵌入和上下文信息,重新构建所有的输入内容,这一步是为了让模型更好地理解上下文,从而提高重构的文本的准确性。
通过这种“遮一部分、猜一部分”的方式,压迫模型最终生成更准确的sentence embedding,不然第二步和第三步无法依赖这个 embedding准确生成内容。
上边我们主要介绍了 embedding 表征模型,接下来我们主要介绍基于 transformer 的预训练模型系列,其模型很多。
图70 transformer 系预训练模型时间、参数量
图片来自论文《Unifying Large Language Models and Knowledge Graphs: A Roadmap》,可以发现其主要有三条发展路线,encoder-decoder 模式的 BART( 来源于 facebook) 到大模型时代的 GLM(来源智谱清源),我们本次不去介绍了。
我们主要介绍下encoder-only 的 bert 系列和 decoder-only 系列的 gpt。和大家的直观感受不同,其实 gpt 出现的比 bert 要更早。其第一个版本是 gpt1。
NLP 的问题
此时训练一个 NLP 模型和我们之前做的推荐类似,针对某个任务,首先搞一些样本,然后对模型进行有监督训练。问题出在题面上。
1.
样本怎么来,大量的高质量的标注不太容易获得。
2.
模型训练的任务是固定的,很难学到泛化能力,没法复用到做其他任务。
这样训练出来的模型被困在了一个特定的领域,离我们想要的 AGI(人工通用智能)有点远。
GPT的解法
2018 年 6 月Openai 发布第一个 GPT 版本。论文:《Improving Language Understandingby Generative Pre-Training》
其思路如下:
1.
用了4.6GB的BookCorpus数据集(该数据集主要是小说,openai 为了验证技术可行性,特意选了未出版的 7000 本书),无监督训练一个预训练模型,即generative pre-training,GPT 名字的由来。
2.
对于子任务,用有标签的小的数据集训练一个微调模型,discriminative fine-tuning。
图71 gpt 模型架构+微调方法
微调方式具体来说,可见上图右图部分。
对于每个任务,输入会被构造成一个连续的 token 序列。分类任务,会将输入文本拼接成一个序列,并在开头添加一个特殊token-start,在结尾增加 extract然后经过模型+线性层后输出结果,对于相似度的文本比较有趣,比如看 A 和 B 是否相似,那么就组成个序列分别为 AB 和 BA,其输入模型后,最终通过softmax 判断,是否相似,是个二分类问题。第四个问答其实是一个多分类问题。
这四个任务有一个共性,就是我们只需要对输入做定制化,输出做一些定制,但是中间的 transformer 模型不会去动它。
左图:GPT是一个transformer decoder-only的结构, MHA +add&norm 的 Block 其用了 12 层,参数量 0.11B,对,此时它还很小。另外输入的token 用了word2vec做了 embedding 表征。
收获
GPT1 可以认为是 openai 的一个试水版本,其主要验证了预训练+微调的方式能不能通过自回归的方式 work,这是一条全新的路子。事实仅仅证明可以,但是效果不是特别理想,落后于encoder-only 的 bert 方案,
gpt1发布4 个月后的 2018 年 10 月,Google 出品了 bert,选择了 encoder only架构, base 模型的参数量和 gpt 一致(故意设计的一致,一较高下),学习的数据除了 gpt 的BookCorpus 还学习了Wikipedia(只学了英文),数据量用了16GB,是 gpt1 的三倍多。
bert 的学习方式和 GPT1 类似,都是先预训练后微调。预训练阶段从输入句子中随机选择约 15% 的token并将其遮盖,然后让模型补齐这些隐藏内容,最终完形填空做多了,模型学会了所有词的上下文关系。
bert 设计了几个尺寸的模型,分别为 base 0.11B ,large 0.34B
图72 bert 性能
bert 论文中在几个任务上(QQP 和 MRPC 的结果报告为 F1 分数,STS-B 为Spearman相关系数,其他任务报告为准确率分数)对比了 gpt,结果是全方位领先。
收获
让更大的模型(bert-large) 学习更多的数据,可以显著提升模型的性能。
bert 发布后的 4 个月后,2019 年 2 月,openai 将 gpt 版本升级到 v2.
如果说 gpt1 证明了路可走,bert 证明了增加数据量可以有成效。那此时 gpt2 的问题变成了,怎么采集更巨量的数据,然后让模型去无监督学习。
首先 OpenAI 专门为 GPT-2 构建的一个数据集,通过从互联网上爬取高质量网页内容(特别是 Reddit 上获得超过 3 个赞的外链网页)来构建了WebText数据集,加上其他公开的数据集,一共 40GB,相比较于第一个版本数据提升了 10 倍左右。
然后 openai 和 google类似,同时设计了多个尺寸,gpt2 有四个尺寸的模型,分别命名为 small medium large 和 extra large。其中extra large的参数量已经来到了 1.5B。
图73 gpt参数
layers 我们已经很熟了就是 注意力block 的层数, dmodel 其实就是词向量的维度,我们在 word2vec 提到过的概念。在模型上,主要的改动是将 norm 后置换成了前置。这个思路其实被后来的开源大模型沿用了,比如 qwen 、llama 等
图74 llama 架构
zero-shot learning
gpt1 的思路是先预训练然后微调,在微调阶段,模型可以通过学习任务特定的输入格式(如Start、Delim、Extract 等特殊 token)来适应下游任务,利用这些特殊 token 帮助模型理解输入的结构和任务类型,模型是在微调阶段慢慢学会这些 special tokens,知道它们出现的时候要做什么任务。问题出在special tokens需要去特殊定义,多了一步数据标注的工作。
openai 的愿景更宏大,可不可以跳过这种方式微调,或者直接不微调。其提出了Zero-shot learning概念,即适应下游任务时,不修改模型参数,不需要任何额外的标注信息。
为了在 Zero-Shot 任务中让模型理解任务需求,GPT-2 引入了 prompt 的概念,嗯,就是我们现在常说的提示词。prompt 通过将任务描述直接拼接在输入文本中,引导模型生成符合任务要求的输出。
prompt 使用自然语言描述任务,例如:
效果怎么样呢,其实挺好的,依赖zero-shot,gpt2 在7 个任务上成为 sota。
图75 模型性能
但是文本摘要总结任务中表现不佳。
图76 gpt2 文本摘要性能
收获
在论文中提到,“Our speculation is that a language model with sufficient capacity will begin to learn to infer and perform the tasks demonstrated in natural language sequences in order to better predict them, regardless of their method of procurement. If a language model is able to do this it will be, in effect, performing unsupervised multitask learning.”
这其实就是我们现在常说上下文学习能力In-Context Learning的雏形。如果有了更强的 ICL ,就可以用prompt 的形式和模型进行各种对话了。
而 zero-shot 是明显区别于 bert的关键(gpt 预训练+prompt,bert 预训练+微调)因为 bert 的设计原因,适应下游具体任务是微调阶段获得的,不是通过预训练阶段,所以 bert 并没有再预训练阶段变大,甚至很多工作是想办法将预训练模型变小,获得一个又小又好的模型。
而 gpt 在持续增大的过程中发现性能也在提升,更是在后来发现了大模型的专属Scaling Law,如摩尔定律一般指导大模型的演进。
既然增大了数据量,模型学会了 zero-shot,是不是继续增加,模型还会有潜能被激发。2020年6月 openai 发布 gpt3。
图76 gpt3语料
数据集方面,Openai 主要用了一个网站爬虫数据集(Common Crawl),大约有 45TB,过滤后,只有 570GB,这大概相当于 400b tokens。在训练时,openai 会对不同质量的数据集有区别的采样,比如CommonCrawl 和 Books2 数据集在训练中被使用的次数不到一次,而其他一些数据集则使用了 2 到 3 次。这种做法实际上是用少量的过拟合风险来换取更高质量的训练数据。
模型方面其提供了更多尺寸,直接从 gpt2 的最大1.5B 增长到 175B,膨胀 100 倍。
图77 gpt3 模型参数
在 gpt3 中,模型涌现了真正的ICL,通过实验发现 few-shot 效果很好,所以gp3 的论文是《Language Models are Few-Shot Learners》。
图78 few-shot
模型表现很优秀,在很多领域都比肩或者超过了有监督微调的 SOTA 模型。
比如翻译 few-shot 有三个工作超过了 sota:
图79 gpt3模型性能
常识推理,在 PIQA 物理常识推理测评中超过 sota:
图80 gpt3 模型性能
因为表现不错,openai 部署了几个版本的 gpt3,开放了 api 实现了商业化。
收获
更大的模型+few shot无限逼近或者超过了经过微调的的 sota 模型,few-shot 的方式可以提升模型的性能。
图81 gpt3模型性能
第二个比较有收获的事情是,在实验过程中,发现最后不同参数量,算力、模型性能之间最终都会拟合到一条线上,这就是后来大家熟知的Scaling Law,openai 在 gpt3 正式发布之前几个月专门写了一篇论文介绍这个现象,《Scaling Laws for Neural Language Model》。
图82 Scaling Law
gpt3 之后,距离我们熟知的 chatgpt 还有一段路要走。
主要解决的问题是让语言模型变得更大并不一定能使其在遵循用户意图方面表现更好。例如,大型语言模型可能生成不真实、有毒或根本无助于用户的输出。换句话说,这些模型与用户并不对齐 。需要解决三个问题:
1.
helpful——有用性,帮助用户解决问题
2.
honest——诚实性,不能伪造信息或误导用户
3.
harmless——无害性,不能对人或环境造成身体、心理或社会伤害
具体怎么做呢,如果我们把 GPT3 当做一个刚毕业的学生,需要告知他社会的真相,比如可以做 A 不可以做 B。
openai 的具体做法是先 SFT,微调一个微调模型。训练一个对齐人类喜好的 RM 模型,用来后续代替真正的人类评价模型输出是否符合人类表达。最后用这个 RM 模型以 PPO 的方式训练第一步的 SFT 模型。这里产生了大模型后训练的范式,SFT+RLHF
最终效果对比,其中下图的 GPT 指的 GPT3 模型(175B),优化下用 few-shot prompt 可以带来性能提升,sft 和 PPO 的模型表现会更优秀一些,更甚者 1.5B PPO 模型,性能也明显比 175B 的 GPT3 好很多。
图83 模型性能对比
上述的 PPO-ptx 表现更好,也就是我们后来常听说的 InstrcutGPT。
收获
从 GPT3 到 chatgpt:其经过了几个版本的迭代,这里有一个有趣的现象,在 GPT3 基础上用 code 训练了代码模型,模型在学习代码的过程中,提升了自己的推理能力,然后在代码基础出上做PPO 得到了一个推理能力更强的模型,最后经过了几轮演进,才有了我们的 chatgpt。
图84 chatgpt 的演进过程
2022 年 11 月 30 日, OpenAI 首次向公众开放 ChatGPT。
有了 chatgpt,大家都可以通过大白话 prompt 和大模型进行对话了。
后来大家发现在写 prompt 的过程中,如果指定模型的处理步骤,并让模型按照步骤一步一步处理,往往能得到更好的回答,这种方式称为 COT。其实我们想一下 cot 的本质是什么,其实是把我们的推理逻辑作为上下文,让模型在产生下一个 token 的时候,每次都可以看到这个逻辑,有效利用额外的计算,带来了性能的提升。
这个思路也被接下来的模型借鉴了,模型多做一步自己会生成这个 cot,这样我们写prompt的时候就不用写cot 了,原理就是这么朴实无华。
具体来说就是把推理过程加在 label里让模型去学习。如果说以前的大模型是学习数据,这种更像学习了这个具体的推理思维,为了区别于之前的大模型一般称为推理大模型。比如 gpt o1 deepseek r1。
图85 来源a-visual-guide-to-reasoning-llms
这些模型更适合解决科学、编码、数学等领域的复杂问题。比如o1 在这几个任务上表现不错。
图86 gpt 推理模型对比
收获
openai 用强化学习算法训练 o1 ,让模型学会如何利用cot进行高效思考。过程中发现,o1 的性能随着更多强化学习(训练时计算资源)和更多思考时间(测试/推理时计算资源)的投入而持续提升,发现了test-time scaling law或者用更通俗一点叫inference-time scaling law 推理的scaling law 。
图87 test-time scaling law
我们之前介绍的 openai 发现的大模型预训练阶段通过增加算力、数据、参数的方式提升模型性能的的scaling law,一般称为pretrain-time scaling law。但是随着人类的知识用完,再增加另外两个数据也带不来模型性能的提升了,预训练的scaling law见顶。
o1 证明了如果增加推理阶段的计算量可以提升模型性能。假设公司有 1w 张 GPU,能提供的算力是固定的,现在问题是,怎么合理分配训练阶段和推理阶段的算力,让模型性能最大化。
Google 在论文《Scaling LLM Test-Time Compute Optimally can be More Effective than Scaling Model Parameters》提到了做的实验,利用一个小尺寸的模型(更少的预训练计算量)+更多的推理计算量,和一个大了其 14 倍的预训练模型(更多的预训练计算量)进行性能对比,并且让两者的总的计算量保持一致。小模型靠着提升推理计算量,表现居然比大模型还好(在更复杂的问题上不是很明显,但是不影响最终结论)。
其证明了一种趋势,即在预训练时花费更少的计算量,同时增大推理阶段的计算量。
deepseek 经过了三个大的版本迭代,24 年底发布了v3版本。关于 deepseek 的核心 MLA+MOE上一篇我们提过了,这我们不再赘述了,我用类似 Openai 怎么通过gpt3搞出 chatgpt 的过程,介绍从 deepseek v3 (最强工具人)怎么一步一步演进出的 R1。
第一步 r1 zero
在这个阶段, 跳过 SFT 直接 RL(GRPO)出来 R1 zero 模型。让模型生成答案,发现答案质量参差不齐,人工从输出中选择了一些质量高的COT 样本,这个样本的推理步骤都很长,更详细更细节。
图89 r1 zero
第二步 sft+rl
上一步产生的 COT 样本,微调 deepseek v3 版本,得到一个微调模型。然后再利用强化学习让sft 模型学会代码推理等能力,产生一个强化学习版本 v1模型,我们简称 rl v1。
图90 sft+rl
第三步 样本准备
从存量非推理微调样本中,让 deepseekv3 采样并添加 cot,最终选了 20w 这种样本,具体做法是通过样本中的QA对,让模型反推补cot。利用我们上一步得到的 rl v1 这个模型产出 60w 具有 cot 的推理类型(Reasoning)的样本,具体做法是让 rl v1 产出多个答案,用deepseekv3做选择。这里说的推理指的是任务维度的,推理任务一般是代码、数学等任务。
这一步一共得到了 80w 样本,都具有 cot,样本格式对齐了。
图91 产生 cot 样本
第四步 得到R1
利用上一步得到的样本,用deepseekv3 微调,然后强化学习,最终得到了deepseek r1。