浅谈大语言模型

By author:

| 5 minutes read


去年就一直想写一篇关于大模型的文章,一直没能够很好的整理,想写的比较多,比如从GPT开始,如何演进到ChatGPT,transformer的构造、模型的架构、模型训练、数据处理、强化学习等, 感觉写起来也会比较零乱,一直就拖着没有展开。 最近Andrey Karpathy的Deep Dive into LLMs like ChatGPT的视频,视频总共3个半小时,从tokenizer、模型结构到unsupervised pre-training、SFT以及RL都有涉及,对于大语言模型讲的比较透彻和清晰的了。

本质 — 读书百遍,其义自现

诚然,从GPT到ChatGPT里面有很多技术的演进,共同作用使得LM的能力得到大幅的提升。 回归大模型的本质,无论是训练还是推理,其本质都是一个基于概率分布的采样过程,比如目前常用的预测下一个元素,让模型能够输出下一个元素的分布概率$P(x_i|…, x_{i-1})$。

我们来看对于语言的建模。假设我们一个语言的符号集合为 $\mathcal{L}=\{l_i\}_{i=1}^L$,这个语言的最大长度为K, 符号集合的元素总个数为L。 那么在这个符号集合里面,可以构建的序列总和为$\frac{(L^{K+1} - 1)}{L-1} + 1$。 如果我们合理的给每一个序列分配概率(比如使用Trie),我们将得到这个语言的一个概率分布。这个时候,我们就可以根据概率模型来生成这个语言下的序列了。

大语言模型使用的符号集合称之为token, 自然语言(英文、中文等)经过tokenize之后,就可以转换成为token的序列。 假设有一个token的概率符合人们的使用需求,那么大模型训练的目的就是无限的逼近这个分布,从而能够使用这个分布来持续生成。 Transformer的出现,就提供了强有力的序列建模工具。

用途 — 刻意练习

如果只建模语言,我们最多就获得一个概率复读机。有意思的是,给定一个语言集合,我们可以有多种方式来定义其概率分布。 我们可以规定一些规则,使得我们想要其生成的序列概率高,不需要的序列,概率低。 比如符合语言使用习惯、语法的概率高,语句不通顺的概率低。 更近一步,既然是语言表达,问题与答案都是语言,我们让这个概率分布使得问题与其对应的回答匹配的描述概率高,不匹配的概率低。符合这样概率分布的语言模型就可以用于给定问题来生成答案。

在问答的场景里面,如果query的序列由$\mathcal{Q}=\{q_j\}$表示, answer的序列由$\mathcal{A} = \{a_i\}$, 整体的生成概率则表达为,

$$ P(\mathcal{A} | \mathcal{Q}) = \prod_{i=1} P(a_i|\mathcal{Q},…, a_{i-1}) $$

$P(\mathcal{A} | \mathcal{Q})$表示在给定$\mathcal{Q}$的情况下,生成answer $\mathcal{A}$的概率。 为了加强大模型的问答能力,于是就有了SFT(Supervised Fine-Tuning)。通过问答/对话的序列来训练模型,使得模型能够更好的解决问答序列的生成。

我们使用大模型的时候,不同的提问方式得到的答案不一样,本质是因为不同的问题($\mathcal{Q_1}$or$\mathcal{Q}_2$)生成答案($\mathcal{A}$)的概率是不一样的, 即使有时候我们觉得$\mathcal{Q_1}、\mathcal{Q_2}$只是同一个问题的不同表达。 $$ P(\mathcal{A}|\mathcal{Q_1}) \neq P(\mathcal{A} | \mathcal{Q_2}) $$

大模型刚出来的时候,需要精心准备提示词(虽然现在仍然存在一些“magic sequence”能够“开启或者关闭”模型的一些能力),从而获得更好的输出,其本质是通过一定的condition, 改变模型的生成概率, 即

$$ P(\mathcal{A}|\mathcal{Q}) < P(\mathcal{A} | Q, \mathcal{T}) $$

一个直观的想法是,既然当前大模型的概率分布使得我们还不得不使用一些prompt来引导,为什么不直接训练大模型,使得最大概率的输出我们想要的结果呢? 在之前的训练中,我们得到的是对于语言的概率分布,它只是反映了在大量的语料中的统计规律,用其生成并不一定能满足人们的使用需求。 我们希望通过进一步训练,能够让大模型输出符合人们的偏好。RLHF被引入进来 — 让模型生成多个结果,然后根据人类的偏好来引导概率偏向。

RLHF过程中,需要引入人类专家来对模型生成的多种答案进行选择/评估。 还有一些任务,我们知道答案,但是编写解答过程比较耗时,或者过程并不唯一,我们也不希望把模型限制在某一种单一解法上面,比如一些逻辑推理的任务/解题。 我们可以让模型自己找出适合的生成路径。比如,如果我们发现 $P(\mathcal{A}|\mathcal{Q}) < P(\mathcal{A} | Q, \mathcal{T})$,并且 $P(\mathcal{A}|\mathcal{Q}) < P(\mathcal{T}|\mathcal{Q})$, $\mathcal{T}$就是一个比较好的引导步骤。我们可以让模型在回答$\mathcal{A}$之前生成一些步骤$\mathcal{T}$,从而能够更好的解决问题。

直观上,如果一个问题越复杂,需要的步骤就越多。如果我们让模型直接回答答案,而跳过步骤,这个对于训练&生成都是会更困难一些。 通过CoT,不同的prompt来引导,一定程度可以引导大模型进入解题模式。

最近ChatGPT发布的一个最新的推理模型 o3-mini,推理过程会随机出现中文。 一种可能的解释是,大部分的习题、推演都是中文的数据,那么回到中文,或许是让模型更容易产生正确答案的。

因为训练大模型的数据有来自多个领域,大模型就像一个拥有多种超能力的人(比如美剧Heroes里面的Sylar)。

同样,DeepSeek在训练推理模型时候发现,引入CoT会导致language mixing。 类比拥有多种超能力的人,在处理复杂任务的时候,就交替的使用不同的能力。 当我们使用RL来训练模型,并且让模型来figure out怎样的生成路径会更有利于回答。 如果我们只关心结果,那么过程中的language mixing就没啥问题,只是可读性不好罢了。