大语言模型听起来很玄,但把它拆开,几乎每个零件都能在更早、更简单的模型里找到原型。这篇从中学就学过的「画一条直线」出发,一次只加一个新想法,走十三步,走到今天的大语言模型。

每一步只回答两个问题:上一步卡在哪,这一步加了什么。读正文只需要会看坐标图、理解加减乘除;公式和推导放在折叠区,可以先跳过。图里的数值来自可复算的教学例子或论文,模拟数据和示意权重会单独标明。

一、从拟合一条直线开始

1 线性回归:给关系配几个旋钮

假设你想根据房子的面积估价格。把手头的成交记录画在图上,横轴是面积,纵轴是价格,点大致排成一条斜线。线性回归做的事,就是找一条最贴近这些点的直线。

这条直线由两个数决定:斜率(每多一平米贵多少)和截距(起步价)。可以把它们想成两个旋钮,拧一拧,直线就跟着转、跟着平移。特征多了,比如再加上房龄、楼层,就是多几个旋钮,道理一样。

怎么算「最贴近」?对每套房子,用预测价格减去真实价格,得到图上的竖直差距;把这些差距平方后取平均,得到均方误差,也就是这里的损失。损失越小,直线对这批数据拟合得越好。

30 套模拟成交记录。蓝线是让橙色竖线平方和最小的直线,均方误差 375;随手画的灰色虚线,均方误差 1101。

这就是后面所有模型的骨架:模型是带旋钮的函数,损失是一个越小越好的分数,训练就是找到让损失最小的那组旋钮。大语言模型也是这样,只不过旋钮多到几千亿个。

公式版

预测是输入的加权和,权重 w\mathbf{w} 和 bb 就是旋钮:

y^=w⊤x+b\hat{y} = \mathbf{w}^\top \mathbf{x} + b

损失用均方误差:

L(w,b)=1n∑i=1n(y^i−yi)2L(\mathbf{w}, b) = \frac{1}{n}\sum_{i=1}^{n} \left(\hat{y}_i - y_i\right)^2

2 梯度下降:蒙着眼睛下山

线性回归可以通过解方程求出最优参数;参数较多时也仍然有直接求解的办法。但后面要遇到的多层非线性网络,通常没有这样的现成解。我们需要一种更通用的办法,一点点把损失降下来。

换个思路:把损失想成一片山地,旋钮的每种组合是地上的一个位置,海拔就是损失。我们蒙着眼睛站在山上,只能用脚感受哪个方向最陡,然后往下迈一小步,再感受,再迈一步……这就是梯度下降。「梯度」是脚下最陡的方向,「学习率」是每一步迈多大:迈得太大容易越过谷底来回晃,迈得太小又走得太慢。

同一片损失地形上,从同一个起点出发:学习率合适时几步到谷底;太小时 25 步还没走到;太大时在山谷两侧来回跳。

实际训练时数据太多,不可能每走一步都把全部数据看一遍,于是每次只抽一小批样本来估计方向,叫小批量随机梯度下降。今天训练大模型常用的 Adam 等优化器,是在这个基础上加了「惯性」,并让每个旋钮各自决定步子迈多大。

公式版

θ\theta 代表全部旋钮,η\eta 是学习率,∇θL\nabla_\theta L 是梯度:

θ←θ−η ∇θL(θ)\theta \leftarrow \theta - \eta \, \nabla_\theta L(\theta)

3 Softmax 与交叉熵:从猜数字到做选择题

很多任务要的不是一个数,而是一个选项:这封邮件是不是垃圾邮件?这张图是猫、狗还是鸟?

做法是先给每个选项打一个分(分数可正可负,没有固定范围),再用 softmax 把分数换算成加起来等于 100% 的概率。它先对分数取指数,再除以总和:分数越高,分到的概率越大。

左:模型给三个选项打的分。中:softmax 换算成的概率。右:交叉熵,正确答案的概率越低,损失涨得越快。

怎么衡量猜得好不好?看模型给正确答案的概率有多高。正确答案是猫,模型给了 66%,损失不大;要是模型很笃定地说是鸟,只给猫 1%,损失就会很大。这种衡量方式叫交叉熵。

请记住这一步:大语言模型的最后一步,就是一道选择题,从词表里几万个候选里挑出下一个词。

公式版

softmax 把分数 zkz_k 变成概率:

p(y=k∣x)=softmax⁡(z)k=ezk∑j=1Kezjp(y = k \mid \mathbf{x}) = \operatorname{softmax}(\mathbf{z})_k = \frac{e^{z_k}}{\sum_{j=1}^{K} e^{z_j}}

交叉熵就是正确答案概率的负对数:

L=−log⁡p(y=y∗∣x)L = -\log p(y = y^\ast \mid \mathbf{x})

4 多层网络:一条直线不够,就多叠几层

直线(在更高维时是平面)能表达的关系很有限。经典的反例是「异或」:两个开关状态相同时灯灭,不同时灯亮。把四种情况画在纸上,亮和灭的点交叉摆放,怎么画一条直线都分不开。

解决办法是在中间加几道「加工」:先把输入组合成一些新特征,再用新特征做判断。关键在于每道加工后面都要接一个非线性的开关,比如 ReLU:小于零就输出零,大于零就原样输出。没有这个开关,叠多少层,效果都和一层直线一样。

左:异或的四个点,亮灭交叉,一条直线分不开。右:经过两个 ReLU 特征,四个点被挪到新位置,一条直线就分开了。

中间这些层叫隐藏层,可以理解为模型自己学出来的「看问题的角度」。层数越多,能表达的关系越复杂,这就是「深度学习」里「深度」的意思。后面 Transformer 里的「前馈网络」,就是这样一个两层的小网络。

5 反向传播:把责任分摊到每个旋钮

梯度下降要求知道每个旋钮该往哪拧。网络有很多层、几亿个旋钮时,一个一个去试是不可能的。

反向传播的思路像事故复盘:先从前往后算出结果和损失,这叫正向;再从后往前追责,这叫反向。输出层先算出自己该负多少责任,再按贡献大小把责任分给上一层,一层层传回去,直到每个旋钮都知道自己该往哪拧、拧多少。

一个只有两个旋钮的小网络:正向算出损失 4,反向算出两个旋钮的梯度 8 和 4,各挪一小步后损失降到 1。

一次正向加一次反向,就能算出所有旋钮的调整方向,计算量和正向算一遍差不多。这个方法在 1986 年由 Rumelhart、Hinton 和 Williams 推广开来。今天的深度学习框架都会自动完成这一步。

二、让模型读懂文字

6 词向量:给每个词一个坐标

前面的模型吃的都是数字,可文字不是数字。最笨的办法是给每个词编个号,但编号本身没有意义:「猫」是 3 号、「狗」是 4 号,不代表它们相近。

更好的办法是给每个词一串数字,当作它在「意义空间」里的坐标,意思相近的词,坐标也靠得近。这些坐标一开始是随机的,跟着训练一起调整。2013 年的 word2vec 发现,学出来的坐标甚至能做类比:

词向量示意:意思相近的词聚在一起,「男 → 女」「普通人 → 王室」这样的关系变成了平行的方向。

另外,模型处理的单位不一定是完整的词。词表太大装不下,于是用 BPE 之类的方法把文字切成常见的片段,叫 token:可能是一个词、半个词,也可能是一个字。

7 语言模型:把写作变成「猜下一个词」

怎样让模型学会语言本身?一个看似简单的办法是:给它一段话的开头,让它猜下一个词。

这正是第 3 步的选择题,只是选项换成了整个词表。猜对了损失小,猜错了损失大,再用梯度下降慢慢调。

这个任务妙在不需要人工标注:任何一段文字都是现成的题库,每个位置都是一道题,答案就是原文里的下一个词。互联网上的海量文本,于是都成了训练数据。

一句话里的每个位置都是一道题:蓝色是已知的前文,橙色是要猜的下一个词,答案就是原文。

2003 年 Bengio 等人的神经语言模型就是这个思路:把前面几个词的坐标拼起来,送进多层网络,猜下一个词。但它只能看固定的前几个词,再远就看不到了。

公式版

一整段文字的概率,拆成每一步「猜下一个词」的概率相乘:

p(x1,x2,…,xT)=∏t=1Tp(xt∣x1,…,xt−1)p(x_1, x_2, \dots, x_T) = \prod_{t=1}^{T} p(x_t \mid x_1, \dots, x_{t-1})

训练的损失,就是每一步猜中正确词的交叉熵取平均:

L=−1T∑t=1Tlog⁡pθ(xt∣x<t)L = -\frac{1}{T} \sum_{t=1}^{T} \log p_\theta(x_t \mid x_{<t})

8 循环神经网络:边读边记笔记

句子有长有短,关键信息可能在很前面。循环神经网络(RNN)的办法是边读边记笔记:每读一个词,就把新内容和旧笔记合在一起,更新成一份新笔记,再带着它读下一个词。

理论上,笔记可以带着任意长的前文。但实际上有三个问题:

  • 记不远:笔记一遍遍被改写,很早的信息会慢慢被冲淡。1997 年提出的 LSTM 给笔记加了「阀门」,决定哪些该留、哪些该忘,缓解了这个问题,但很长的距离仍然吃力。

  • 只能排队:同一句话里,第 10 个词的状态要等第 9 个词算完,不能像矩阵运算那样把所有位置一起算。不同句子仍然可以组成一批并行处理。

  • 一页笔记装全部:不管前文多长,都要压进一份固定大小的笔记里。

训练信号每往回传一步都要乘一个系数:略小于 1,50 步后只剩约 0.5%;略大于 1,会放大到 117 倍。

9 注意力:需要什么,就回头翻原文

与其把所有内容压进一页笔记,不如换个思路:原文都留着,需要的时候直接回头翻。

比如读到「小猫追着毛线球跑,因为它很好奇」里的「它」,我们希望模型能从前文取回与指代有关的信息。下面用一组人为设定的权重演示:把较多注意力分给「小猫」,较少分给其他位置,再按这些比例汇总信息。这张图说明计算方式,不代表真实模型一定会这样分配注意力。

示意权重:每行把 100% 的注意力分给当前位置和更早的位置;右上角的 × 挡住未来。读到「它」这一行时,「它」已经是输入,用它的表示去预测后面的 token。

这就是注意力。具体做法是:每个词带着一个「我在找什么」的提问,也挂着一张「我是什么」的标签和一份「我能提供什么」的内容。提问和标签越匹配,就从这个词拿走越多内容。把匹配程度换算成权重时,用的又是第 3 步的 softmax。

这样,远处的信息不必经过一长串递归状态才能传过来,模型更容易利用长距离联系;已知输入的各个位置也能并行计算。代价是普通的全注意力要比较各位置之间的关系,序列越长,计算量按长度的平方增长。路径变短不等于模型一定能记住所有细节。Bahdanau 等人在 2014 年把注意力用到神经机器翻译;这里画的是后来用于自回归语言模型的自注意力。

公式版

提问、标签、内容分别记作 QQ、KK、VV。先算匹配程度,再用 softmax 换成权重,最后加权汇总:

Attention⁡(Q,K,V)=softmax⁡(QK⊤dk)V\operatorname{Attention}(Q, K, V) = \operatorname{softmax}\left(\frac{Q K^\top}{\sqrt{d_k}}\right) V

除以 dk\sqrt{d_k} 是为了让分数不要太大,否则 softmax 会几乎只盯着一个词,训练时调不动。

10 Transformer:用注意力搭起整个网络

2017 年的 Transformer 去掉了循环结构,改用注意力和前馈网络组成积木。原论文是编码器—解码器架构;这里沿着语言模型这条线,只看 GPT 使用的解码器式网络:每块积木先用带因果遮挡的自注意力让各位置交换信息,再用前馈网络(第 4 步的多层网络)分别加工每个位置。它没有机器翻译解码器里读取编码器输出的那一层交叉注意力。

GPT-2 small:12 个块之后,还要经过最后一次 LayerNorm,再投影到词表。
按 GPT-2 公开代码的尺寸计算,共 124,439,808 个参数。输出投影与词嵌入共享权重,不重复计数。

这里明确画的是 GPT-2 small。它沿用最初 GPT 的基本骨架,但把 LayerNorm 移到子层输入端,并在全部块之后增加一次 LayerNorm;不能说两者结构完全相同。尺寸和计算顺序可对照 GPT-2 论文 §2.3 与 公开实现。

几个配件各管一件事:

配件

管什么

多头注意力

同时从几个角度看词与词的关系,比如语法、指代

残差连接

给每块积木加一条旁路,信息和训练信号可以直接穿过,叠几十上百层也训得动

层归一化

把数值调到稳定的范围,训练更稳

位置编码

注意力本身不分先后,要额外告诉模型每个词排在第几位

因果遮挡

预测第 5 个 token 时,只能看前 4 个;答案本身和之后的位置都不能看

第 9 步的热力图和这里并不矛盾:输入位置 i 可以看自己和更早的输入,但它负责预测的是位置 i+1。训练时把输入与答案错开一格,再配上因果遮挡,就能同时算各个位置的预测,又不泄露答案。

三、从会续写到会对话

前两部分讲的是模型长什么样;这一部分讲它怎样变成能对话的助手。Andrej Karpathy 的 Deep Dive into LLMs like ChatGPT(2025)梳理了这条流水线。先抓住三个阶段,下面第 11、12 步再展开:

  1. 预训练:从大量文本学习续写,得到基础模型(Base model)。

  2. 指令微调:学习「问题—好回答」的示范,得到 SFT 模型。

  3. 偏好对齐:根据回答的比较或反馈继续调整,让回答更符合期望;第 12 步用 InstructGPT 的 RLHF 路线说明。

延伸阅读:Karpathy 视频完整白板
Karpathy 视频配套的白板笔记长图:左半部分是预训练、监督微调和强化学习,右半部分是日常用法

这张白板左侧是预训练、监督微调和强化学习,右侧是另一个视频 How I use LLMs 的使用笔记。需要核对细节时,可以点开图片放大;正文只沿左侧的训练流程往下讲。

白板把基础模型叫作 internet document simulator,也就是「互联网文档模拟器」:它擅长接着已有文字写下去,却还不一定按提问者的意图回答。第 12 步要解决的正是这个差别。

11 规模化预训练:大力出奇迹,但有规律

结构定了,剩下的问题是:多投入一份算力,能换来多少提升?2020 年 Kaplan 等人发现,模型越大、数据越多、算力越多,损失就越低,而且下降得很有规律:画在对数坐标上,几乎是一条直线。这意味着可以先拿小模型做实验,预测大模型的效果。

2022 年 Hoffmann 等人进一步研究了固定训练算力该怎样分配:参数量和训练 token 数需要一起增长。他们的 Chinchilla 用 700 亿参数配 1.4 万亿个 token,约为每个参数 20 个 token。这个比例是那组实验下的训练算力分配结论,不是所有模型都必须遵守的固定配方。

左:Kaplan 等论文的公式,参数每多 10 倍,损失乘以约 0.84。右:Chinchilla 论文表 1 的六个模型,灰线是每个参数 20 个 token。

规模还带来了新能力。2020 年的 GPT-3 有 1750 亿个参数,只要在提问里给几个例子,不用重新训练,就能完成不少新任务,这叫上下文学习。而它的训练目标,始终还是第 7 步的「猜下一个词」。

12 微调与对齐:从续写机器到助手

预训练出来的模型,就是白板上说的「互联网文档模拟器」:你问它一个问题,它可能接着编出更多问题,因为网上的文字常常就是这样排列的。要把它变成助手,还要再走两步。

InstructGPT 的三步:照示范学、训练打分模型、用强化学习拿高分,以及每一步用了多少数据(数字来自 Ouyang 等 2022)。

指令微调:请人写大量「问题—好回答」的示范,让模型照着学。用的仍然是「猜下一个词」,只是题目换成了对话。

偏好对齐:好回答很难写得完美,却比较容易比较。于是请人看两个回答,挑出更好的那个。经典做法 RLHF 先用这些比较结果训练一个「打分模型」,再用强化学习让语言模型去拿高分,同时拉着它别离原来的模型太远,免得为了刷分说怪话。2023 年提出的 DPO 更直接,省掉打分模型,直接用比较结果训练语言模型。

效果很明显:2022 年的 InstructGPT 报告,经过这套流程的 13 亿参数模型,回答比 1750 亿参数的 GPT-3 更受标注者青睐。

公式版

打分模型把「哪个更好」当成二分类,让更受欢迎的回答 ywy_w 比另一个 yly_l 得分更高:

Lr=−log⁡σ(rϕ(x,yw)−rϕ(x,yl))L_{r} = -\log \sigma\left(r_\phi(x, y_w) - r_\phi(x, y_l)\right)

RLHF 让模型拿高分,同时用 KL 散度拉住它不跑太远:

max⁡θ  Ey∼πθ(⋅∣x)[rϕ(x,y)]−β KL(πθ ∥ πref)\max_{\theta} \; \mathbb{E}_{y \sim \pi_\theta(\cdot \mid x)}\left[r_\phi(x, y)\right] - \beta \, \mathrm{KL}\left(\pi_\theta \,\|\, \pi_{\text{ref}}\right)

DPO 省掉打分模型,直接用比较结果训练:

LDPO=−log⁡σ(βlog⁡πθ(yw∣x)πref(yw∣x)−βlog⁡πθ(yl∣x)πref(yl∣x))L_{\text{DPO}} = -\log \sigma\left(\beta \log \frac{\pi_\theta(y_w \mid x)}{\pi_{\text{ref}}(y_w \mid x)} - \beta \log \frac{\pi_\theta(y_l \mid x)}{\pi_{\text{ref}}(y_l \mid x)}\right)

13 生成:一个词一个词往外蹦

实际生成时,先把已有的提示词整体送进网络,这一步常叫预填充(prefill);接着根据末尾位置的概率选出一个 token,把它接回输入,再预测下一个。这个逐步生成的阶段叫解码(decode),直到遇到结束符或达到长度限制。训练时可以并行算已知答案的损失,生成时则必须等新的答案产生;两者用的是同一个网络。

「按规则选」很有讲究:

  • 每次都选概率最高的:稳,但容易重复、乏味。

  • 调温度:温度低,分布更集中、更保守;温度高,分布更平、选择更多样,也更容易跑偏;多样并不保证更正确。

  • Top-p:按概率从高到低累加,保留达到阈值所需的最少候选,再把它们的概率重新归一后抽样。低概率不等于错误,这只是控制候选范围的一种办法。

下面三张图用同一组示意分数回答「今天天气很 ___」。先比较温度改变后的分布,再看中间那张图怎样应用 top-p:

温度 0.5:概率更集中,「好」约占 76%。
温度 1:柱长是截断前概率。top-p = 0.9 留前 5 项,灰色项被排除;真正抽样前,保留项还要重新归一。
温度 2:概率更平,「好」约占 29%,其余候选也更有机会。

生成时通常会保留各层里旧 token 的 K、V,这就是 KV 缓存。新一步只为新 token 计算新的表示,并让它查询此前保存的 K、V,省去反复计算整段前文。缓存的是中间结果,不是重新训练出来的参数;前文越长,缓存占用的内存也越多。

回头看:什么变了,什么没变

步骤

新加的设计

在大语言模型里的位置

1 线性回归

参数、损失、训练

每一层里的矩阵乘法

2 梯度下降

沿梯度的反方向更新参数

训练用的优化器

3 Softmax 与交叉熵

分数变概率,最大似然

输出层与训练损失

4 多层网络

非线性与隐藏层

每一层的前馈网络

5 反向传播

链式法则逐层求梯度

框架的自动求导

6 词向量与子词

离散符号变成稠密向量

分词器与输入的嵌入矩阵

7 语言模型

文本概率拆成逐词预测

预训练目标

8 循环神经网络

用状态记住变长的前文

已被注意力取代

9 注意力

按相关性直接取用任意位置

每一层的自注意力

10 Transformer

多头、残差、归一化、位置编码、因果掩码

整体结构

11 规模化预训练

幂律与算力分配

训练规划

12 微调与对齐

示范数据与人类偏好

从续写模型到助手

13 生成

自回归采样与 KV 缓存

推理服务

一路走下来,模型从两个旋钮长到了几千亿个旋钮,输入从几个数字变成了整个互联网的文本。但最底下的那套逻辑一直没变:写出一个带旋钮的函数,定一个衡量好坏的分数,用梯度下降把它一点点调好。大语言模型的能力究竟从何而来,至今仍有很多没被完全理解的地方;但它的每个零件为什么长成这样,现在应该都能找到来处了。

参考资料


全文评论

0

正在加载评论…