从零到一理解大语言模型的构建


从零到一理解大语言模型的构建

写给被上班磨平棱角,数学功力尽失的你。尽量用人话和加减乘除的方式,来理解大模型的整体构建。


写在前面:这篇文章要回答什么

如果你用过 ChatGPT、Claude 或者任何大语言模型(LLM),你大概会有这些疑问:

  1. 它到底是怎么”理解”我说的话的?
  2. 它是怎么”生成”看起来像人写的文字的?
  3. 它真的”懂”吗?还是在某种意义上的”高级自动补全”?
  4. 为什么它有时候会一本正经地胡说八道(幻觉)?
  5. 为什么 GPT-4 比 GPT-3 强那么多?到底强在哪?

这篇文章会从最基本的问题出发,一步步拆解大语言模型背后的数学和工程设计。我会尽量做到:

  • 每个数学概念先说人话,再给公式
  • 每个公式配一个就算数学底子很差的人也能理解的小例子
  • 每个设计决策先说要解决什么问题,再说怎么解决的

全文结构如下:

1
2
3
4
5
6
7
8
9
第一章:LLM 要解决的核心问题(语言建模)
第二章:如何用数学描述语言(概率论基础)
第三章:如何让计算机"理解"文字(词向量与嵌入)
第四章:Attention 机制——LLM 的核心发明
第五章:Transformer 架构——把所有东西组装起来
第六章:训练——如何让模型从"白痴"变"天才"
第七章:从 GPT 到 Claude——现代 LLM 的演进
第八章:为什么它会"幻觉"?局限性的数学解释
第九章:总结——一张图看懂全貌

第一章:LLM 要解决的核心问题

1.1 一句话说清楚

大语言模型的本质任务:给定前面的文字,预测下一个最可能出现的字(token)。

就这么简单。不管是写诗、写代码、回答哲学问题,模型做的事情从头到尾都是一件事:预测下一个字

举个例子。当你输入:

1
"今天天气真"

模型在做的事情是:

1
2
3
4
5
"今" → 可能的下一个字:天(0.3)、年(0.2)、日(0.1)...
"今天" → 可能的下一个字:天(0.4)、是(0.2)、我(0.1)...
"今天天" → 可能的下一个字:气(0.8)、啊(0.05)...
"今天天气" → 可能的下一个字:真(0.3)、不(0.2)、很(0.15)...
"今天天气真" → 可能的下一个字:好(0.5)、热(0.2)、冷(0.1)...

它选了”好”(概率最高),然后把”好”加到后面,继续预测下一个字。如此循环,直到它觉得该停了。

你的整个对话体验——能聊天、能写作、能推理——都是从这个简单的”下一个字预测”任务中涌现出来的。

1.2 为什么”预测下一个字”这么强大?

你可能会想:就猜下一个字?这能有多厉害?

想象一下,如果你真的能完美地预测任何文本的下一个字,你需要具备什么能力?

  • 要预测”中国的首都是___”,你需要知识
  • 要预测”如果 x + 3 = 7,那么 x = ___”,你需要推理
  • 要预测”他伤心地走开了,因为___”,你需要情感理解
  • 要预测 Python 代码的下一行,你需要编程能力

换句话说,要完美地预测下一个字,你需要理解整个人类语言和知识体系

当然,当前的 LLM 远没有”完美”,但它们已经做得足够好,好到让人觉得它们”像是懂了”。

1.3 所以,技术问题变成了

1
2
3
4
5
6
输入:一段文字(叫做 "上下文" 或 "context")
输出:下一个字的概率分布

要解决的问题:如何设计一个数学模型,
使得它看了海量文本之后,
能够非常准确地预测下一个字?

接下来的所有章节,都是在回答这个问题。


第二章:如何用数学描述语言

2.1 概率:一切的基础

先回忆一下概率最基本的概念。

概率就是一件事发生的可能性,用 0 到 1 的数字表示。

  • 抛硬币正面朝上:概率 = 0.5(50%)
  • 明天太阳升起:概率 ≈ 1.0(几乎肯定)
  • 你明天中彩票:概率 ≈ 0.000001(几乎不可能)

我们用 P(事件) 表示一个事件的概率。比如:

1
2
P(硬币正面) = 0.5
P(明天下雨) = 0.3

2.2 条件概率:在已知某些信息时的概率

条件概率是:在已经知道一些事情的前提下,另一件事发生的概率。

记作 P(A | B),读作”在 B 发生的条件下,A 发生的概率”。

日常例子:

1
2
3
P(带伞 | 天气预报说下雨) = 0.9    # 知道要下雨,你带伞的概率很高
P(带伞 | 天气预报说晴天) = 0.1 # 知道是晴天,你带伞的概率很低
P(带伞) = 0.4 # 不看天气预报,随便猜你带伞的概率

看到没?有了额外信息(条件),预测就更准了。这正是 LLM 在做的事——它用前面的文字作为”条件”来预测下一个字。

2.3 语言模型 = 条件概率

现在我们可以用数学来描述”预测下一个字”了:

1
P(下一个字 | 前面所有的字)

用具体的例子:

1
2
3
4
5
P("好" | "今天天气真") = 0.5
P("热" | "今天天气真") = 0.2
P("冷" | "今天天气真") = 0.1
P("差" | "今天天气真") = 0.05
...(所有可能的字加起来 = 1.0)

一个语言模型就是一个能算出这个条件概率的函数。

用数学符号写得更正式一点:

1
2
3
4
5
6
7
给定一个词序列 w₁, w₂, ..., wₙ
语言模型要计算: P(wₙ₊₁ | w₁, w₂, ..., wₙ)

其中:
- w₁, w₂, ..., wₙ 是你已经输入的文字
- wₙ₊₁ 是要预测的下一个字
- P 是概率

翻译成人话:给定你已经说的 n 个字,第 n+1 个字是什么的概率。

2.4 生成文本 = 反复采样

知道了每个字的概率,如何生成一段完整的文本?

反复从概率分布中”抽签”(术语叫”采样”):

1
2
3
4
5
6
7
8
9
10
11
12
13
第1步:输入 "今天"
模型计算 → P("天" | "今天") = 0.4, P("是" | "今天") = 0.2, ...
抽签结果 → "天"

第2步:输入 "今天天"
模型计算 → P("气" | "今天天") = 0.8, ...
抽签结果 → "气"

第3步:输入 "今天天气"
模型计算 → P("真" | "今天天气") = 0.3, P("不" | "今天天气") = 0.2, ...
抽签结果 → "真"

...如此反复,直到生成一个"结束"标记

这就是为什么 LLM 每次回答可能不一样——因为”抽签”有随机性。概率最高的字更容易被选中,但不是每次都选概率最高的。

温度(Temperature)参数就是控制这个”随机性”的旋钮:

  • 温度 = 0:永远选概率最高的字(确定性最强,但可能很无聊)
  • 温度 = 1:完全按概率抽签(正常随机性)
  • 温度 = 2:更随机(可能产生有创意但也可能胡说的结果)

2.5 关键问题:如何计算这个概率?

到目前为止,我们把问题定义清楚了:LLM 就是要算出 P(下一个字 | 前面的字)

但怎么算呢?

最原始的方法:数频次。翻遍所有书籍,统计”今天天气真”后面跟”好”的次数占多少比例。

这有两个致命问题:

  1. 数据稀疏:大部分句子组合从来没出现过。你在任何书里都找不到你刚刚打的那句话
  2. 存储爆炸:中文常用字 3000+,长度为 20 的序列有 3000²⁰ 种可能——比宇宙中的原子还多

所以我们需要一种可泛化的方法——不是死记硬背每种组合,而是学会语言的规律

这就是神经网络登场的地方。


第三章:如何让计算机”理解”文字

3.1 第一个问题:计算机不认字

计算机只认数字。它不知道”猫”是什么,不知道”狗”和”猫”比”汽车”更相似。

所以第一步是:把文字变成数字

3.2 最笨的方法:独热编码(One-Hot Encoding)

假设我们的词库只有 5 个字:[猫, 狗, 鱼, 车, 树]

我们可以这样编码:

1
2
3
4
5
猫 = [1, 0, 0, 0, 0]
狗 = [0, 1, 0, 0, 0]
鱼 = [0, 0, 1, 0, 0]
车 = [0, 0, 0, 1, 0]
树 = [0, 0, 0, 0, 1]

每个字用一个向量(一串数字)表示,其中只有一个位置是 1,其余全是 0。

问题:在这种表示下,”猫”和”狗”的距离 = “猫”和”车”的距离。计算机完全不知道猫和狗都是动物,而车不是。

而且,如果词库有 10 万个词,每个词就需要一个 10 万维的向量——太浪费了。

3.3 聪明的方法:词嵌入(Word Embedding)

核心思想:用一个短短的、稠密的向量来表示每个字,并且让意思相近的字的向量也相近。

比如,我们用 3 个数字(3 维向量)来表示每个字:

1
2
3
4
5
猫 = [0.9, 0.1, 0.3]    ← 动物、小型、毛茸茸
狗 = [0.8, 0.3, 0.4] ← 动物、中型、毛茸茸(和"猫"很近!)
鱼 = [0.7, 0.0, -0.2] ← 动物、但和猫狗不太一样
车 = [-0.5, 0.8, 0.1] ← 完全不同的类别
树 = [0.1, 0.6, -0.3] ← 也完全不同

虽然这些数字不是人为赋予含义的(模型自己学出来的),但训练后向量之间的关系会反映语义关系。

著名的例子

1
"国王" - "男人" + "女人" ≈ "女王"

真的!在训练好的词向量空间里,这种算术关系真的成立。这说明模型某种程度上学到了语义关系

3.4 向量距离 = 语义相似度

怎么衡量两个向量”有多近”?用余弦相似度——听着吓人,其实很简单:

两个向量的夹角越小,它们越相似。

1
2
3
相似度的直觉:
猫 · 狗:方向很接近 → 相似度 0.95(很相似)
猫 · 车:方向很不同 → 相似度 0.1(不相似)

计算方式(以二维为例,实际类似):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
向量 A = [3, 4]
向量 B = [4, 3]

cos(A, B) = (3×4 + 4×3) / (√(3²+4²) × √(4²+3²))
= (12 + 12) / (5 × 5)
= 24 / 25
= 0.96 ← 非常相似!

向量 C = [-3, 4]

cos(A, C) = (3×(-3) + 4×4) / (5 × 5)
= (-9 + 16) / 25
= 7 / 25
= 0.28 ← 不太相似

3.5 Token:不是字,也不是词

最后一个细节:LLM 处理的不是”字”也不是”词”,而是 Token

Token 是一种介于字和词之间的切分单位。比如:

1
2
3
4
5
"I love playing basketball"
切分为 token: ["I", " love", " play", "ing", " basket", "ball"]

"今天天气真好"
切分为 token: ["今天", "天气", "真", "好"]

为什么用 Token 而不是字或词?

  • 比”字”更高效(减少序列长度)
  • 比”词”更灵活(能处理从没见过的新词——拆成子词组合)
  • 词库大小可控(通常 32K-100K 个 token)

在实际的 LLM 中,每个 token 被映射为一个高维向量(如 4096 维)。这个映射就是”嵌入层”(Embedding Layer),是模型要学习的第一个参数。

3.6 小结

1
2
3
4
5
6
7
8
9
10
文字世界                     数字世界
───────── ─────────
"今天天气真好" Token化 ["今天", "天气", "真", "好"]

嵌入(Embedding)

每个 token 变成一个向量
"今天" → [0.2, -0.5, 0.8, ..., 0.1] (4096个数字)
"天气" → [0.1, 0.3, -0.2, ..., 0.7] (4096个数字)
...

现在计算机有了一串数字可以处理了。下一步:怎么从这些数字中算出”下一个 token 的概率”?


第四章:Attention 机制——LLM 的核心发明

4.1 为什么需要 Attention?

把每个 token 变成向量之后,我们面临一个关键问题:

同一个词在不同上下文中意思完全不同。

1
2
例子1:"苹果发布了新手机"  →  "苹果" = 科技公司
例子2:"我吃了一个苹果" → "苹果" = 水果

如果”苹果”的向量是固定的,它怎么能同时表示公司和水果?

答案是:让每个词的向量根据周围的词动态调整

“苹果”看到周围有”发布””手机”时,它的向量自动偏向”科技公司”的含义;看到”吃””一个”时,自动偏向”水果”的含义。

这种”看看周围的词,然后调整自己的含义”的机制,就叫 Attention(注意力)。

4.2 Attention 的直觉

想象你在读一句话:

1
"那只猫坐在垫子上,因为它觉得很舒服"

当你读到”它”的时候,你的大脑会自动回头看前面的内容,找到”它”指的是”猫”。你不会平均地看每个词,而是重点关注与当前相关的词

这就是 Attention 做的事情:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
处理 "它" 时的 Attention 分数:
"那" → 0.01 (不重要)
"只" → 0.01 (不重要)
"猫" → 0.50 (最重要!"它"指的就是"猫")
"坐在" → 0.05 (有点关系)
"垫子" → 0.10 (有点关系)
"上" → 0.01 (不重要)
"因为" → 0.02 (不重要)
"它" → 0.20 (自己看自己)
"觉得" → 0.05
"很" → 0.02
"舒服" → 0.03
──────────────
合计 1.00 (所有分数加起来等于1)

然后,”它”的新向量 = 按这些分数加权混合所有词的向量:

1
新的"它" = 0.50 × "猫"的向量 + 0.20 × "它"的向量 + 0.10 × "垫子"的向量 + ...

这样,”它”的向量就自动融合了”猫”的语义信息。模型知道了”它 = 猫”。

4.3 Attention 的计算过程(用简单例子)

Attention 的核心是三个角色:Query(查询)、Key(键)、Value(值)

用一个生活中的比喻:

1
2
3
4
5
6
7
8
9
10
你去图书馆找书:
- Query(你的需求):你想找"关于猫的行为学"的书
- Key(书的标签): 每本书都有一个主题标签
- Value(书的内容):每本书的实际内容

过程:
1. 你拿着你的 Query,和每本书的 Key 比对
2. 算出每本书和你需求的"匹配度"(Attention 分数)
3. 匹配度高的书多看点,匹配度低的少看点
4. 把所有书的内容按匹配度加权混合,就是你的收获

对应到数学计算,假设我们有一个超级简化的例子——只有3个 token,每个向量只有 2 维:

1
2
3
4
三个 token 的向量:
"我" = [1, 0]
"爱" = [0, 1]
"猫" = [1, 1]

Step 1:每个 token 生成自己的 Q、K、V

通过三个不同的变换(乘以不同的矩阵),每个 token 产生三个角色的向量。这里用超简化版:

1
2
3
4
5
6
7
8
Query 矩阵 Wq = [[1, 0], [0, 1]]  (简化为恒等变换)
Key 矩阵 Wk = [[1, 0], [0, 1]]
Value 矩阵 Wv = [[1, 0], [0, 1]]

每个 token 的 Q、K、V(简化后和原向量一样):
"我": Q=[1,0], K=[1,0], V=[1,0]
"爱": Q=[0,1], K=[0,1], V=[0,1]
"猫": Q=[1,1], K=[1,1], V=[1,1]

Step 2:计算 Attention 分数(Q 和 K 的点积)

点积就是对应位相乘再求和。直觉上,两个向量方向越接近,点积越大

1
2
3
4
5
以 "猫" 的 Query 为例,和所有 Key 计算点积:

"猫"Q · "我"K = [1,1] · [1,0] = 1×1 + 1×0 = 1
"猫"Q · "爱"K = [1,1] · [0,1] = 1×0 + 1×1 = 1
"猫"Q · "猫"K = [1,1] · [1,1] = 1×1 + 1×1 = 2 ← 最高!自己和自己最匹配

Step 3:归一化(Softmax)——让分数变成概率

我们需要把分数转化成概率(加起来等于1)。用 Softmax 函数:

1
2
3
4
5
6
7
8
9
10
11
12
Softmax 的直觉:把任意数字变成概率分布。大的数字变得更大,小的变得更小。

原始分数: [1, 1, 2]

Softmax计算过程:
e^1 ≈ 2.72
e^1 ≈ 2.72
e^2 ≈ 7.39
总和 = 2.72 + 2.72 + 7.39 = 12.83

概率 = [2.72/12.83, 2.72/12.83, 7.39/12.83]
= [0.21, 0.21, 0.58]

所以”猫”对三个 token 的 Attention 权重是 [0.21, 0.21, 0.58]——最关注自己。

Step 4:加权求和 Value

1
2
3
4
"猫"的新向量 = 0.21 × "我"V + 0.21 × "爱"V + 0.58 × "猫"V
= 0.21 × [1,0] + 0.21 × [0,1] + 0.58 × [1,1]
= [0.21, 0] + [0, 0.21] + [0.58, 0.58]
= [0.79, 0.79]

“猫”的新向量 [0.79, 0.79] 融合了上下文信息。

4.4 完整的 Attention 公式

上面的过程用一个公式就能概括:

$$
\text{Attention}(Q, K, V) = \text{Softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V
$$

别被这个公式吓到,它就是我们刚才做的四步:

公式部分 对应步骤 人话
$QK^T$ Step 2 Q 和 K 的点积(算匹配度)
$\div \sqrt{d_k}$ 缩放 除以向量维度的平方根(防止数字太大导致 Softmax 极端化)
$\text{Softmax}(…)$ Step 3 把分数变成概率
$… \times V$ Step 4 按概率加权混合 Value

其中 $d_k$ 是向量的维度。如果维度是 64,那 $\sqrt{64} = 8$。这个缩放因子是为了防止点积值太大——想象两个 4096 维的向量做点积,不缩放的话数字会非常大,Softmax 之后几乎变成 one-hot(一个接近1,其他接近0),模型就没法学到”同时关注多个位置”了。

4.5 Multi-Head Attention:从多个角度看

一个 Attention 只能捕捉一种关系。但语言中有很多种关系:

1
2
3
4
5
6
"小明在学校把作业交给了老师"

语法关系: "交给" 关注 → "小明"(主语)和 "老师"(间接宾语)
位置关系: "学校" 关注 → "在"(介词标记)
语义关系: "作业" 关注 → "交给"(动作)和 "老师"(接收者)
指代关系: 如果后面有"他",需要关注 → "小明"

所以 LLM 用多个 Attention Head 并行工作,每个 Head 学习不同类型的关系:

1
2
3
4
5
6
7
Head 1:可能学会了"主谓关系"
Head 2:可能学会了"修饰关系"
Head 3:可能学会了"指代关系"
...
Head 32:可能学会了某种我们人类都说不清的关系

最后把所有 Head 的结果拼起来 → 综合信息

实际的 LLM 通常有 32-128 个 Head。

4.6 因果掩码:不能偷看未来

最后一个关键设计:在生成文本时,模型只能看到前面的 token,不能偷看后面的。

1
2
3
4
5
处理 "今天天气" 时:
"今" 只能看到: [今]
"天" 只能看到: [今, 天]
"天" 只能看到: [今, 天, 天]
"气" 只能看到: [今, 天, 天, 气]

这通过**掩码矩阵(Mask)**实现——在计算 Attention 分数时,把”未来位置”的分数设为负无穷,Softmax 之后就变成 0。

1
2
3
4
5
6
7
8
Attention 分数矩阵(4×4):
今 天 天 气
今 [ 1.0 -∞ -∞ -∞ ] ← "今"只看自己
天 [ 0.3 1.0 -∞ -∞ ] ← "天"看前两个
天 [ 0.1 0.5 1.0 -∞ ] ← 第二个"天"看前三个
气 [ 0.1 0.2 0.5 1.0] ← "气"看所有

经过 Softmax 后,-∞ 变成 0,就实现了"不偷看未来"。

第五章:Transformer 架构——把所有东西组装起来

5.1 Transformer 是什么

Transformer 是 2017 年 Google 在论文《Attention Is All You Need》中提出的架构。它把 Attention 和一些其他组件组装在一起,形成了一个完整的模型。

几乎所有现代 LLM(GPT-4、Claude、Llama、Gemini)都是基于 Transformer 架构的。 区别只在于具体参数和训练方法。

5.2 一个 Transformer 层(Block)长什么样

一个 Transformer 层由两个子模块组成,非常简单:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
┌─────────────────────────────────────────┐
│ Transformer Block │
│ │
│ 输入 x (token向量序列) │
│ │ │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ 1. 多头注意力层 │ ← 让每个 token │
│ │ (Multi-Head │ 看到其他 token│
│ │ Attention) │ 并更新自己 │
│ └─────────────────────┘ │
│ │ │
│ ▼ (加上残差连接 + 层归一化) │
│ │
│ ┌─────────────────────┐ │
│ │ 2. 前馈神经网络 │ ← 对每个 token │
│ │ (Feed-Forward │ 独立做非线性 │
│ │ Network, FFN) │ 变换 │
│ └─────────────────────┘ │
│ │ │
│ ▼ (加上残差连接 + 层归一化) │
│ │
│ 输出 (更新后的 token 向量序列) │
└─────────────────────────────────────────┘

Attention 负责”交流”——让 token 之间交换信息。
FFN 负责”思考”——对每个 token 独立做进一步处理。

5.3 残差连接:不要忘了自己是谁

残差连接(Residual Connection)是一个非常简单但极其重要的设计:

1
输出 = 子模块(输入) + 输入

就是把子模块的输出和原始输入相加

为什么这很重要? 想象你让一个人阅读一段文字然后总结——如果他只记住总结忘了原文,那信息就丢了。残差连接相当于说”你可以在原文基础上添加新的理解,但别把原文丢了”。

在训练深层网络时(几十层甚至上百层),没有残差连接的话梯度会消失(后面会解释),模型根本训不动。

5.4 层归一化:保持数字稳定

LayerNorm(层归一化)确保每一层的输出数值不会太大或太小。

直觉:想象你在叠积木,每叠一层积木都会有点歪。如果不修正,叠到第 96 层就完全倒了。LayerNorm 就是每叠一层就校正一下。

计算方式很简单——对向量中的所有数字算平均值和标准差,然后标准化:

1
2
3
4
5
6
原始向量: [10, 20, 30]
平均值 μ = (10+20+30)/3 = 20
标准差 σ = √((10-20)²+(20-20)²+(30-20)²)/3) = √(200/3) ≈ 8.16

标准化后: [(10-20)/8.16, (20-20)/8.16, (30-20)/8.16]
= [-1.22, 0, 1.22]

这样不管原始数字多大多小,标准化后都在一个可控的范围内。

5.5 前馈网络(FFN):模型的”记忆存储器”

FFN 是 Transformer 中参数最多的部分(通常占总参数量的 2/3),结构却超级简单:

1
FFN(x) = 激活函数(x × W₁ + b₁) × W₂ + b₂

翻译成人话:

  1. 把输入向量 x 乘以一个大矩阵 W₁(通常从 4096 维扩展到 16384 维)
  2. 过一个激活函数(引入非线性,后面解释)
  3. 再乘以另一个大矩阵 W₂(从 16384 维压回 4096 维)

FFN 的作用是什么? 研究表明,FFN 本质上是一个知识存储器

当你问”法国的首都是哪里”,模型知道答案是”巴黎”——这个知识就存储在某些 FFN 层的参数中。不同的神经元存储不同的知识片段。

5.6 激活函数:引入非线性

如果所有操作都是线性的(乘以矩阵、加偏置),那无论叠多少层,效果都等价于一层。

激活函数打破了这个限制,引入了”非线性”——让模型能学到复杂的模式。

现代 LLM 常用的激活函数是 GELU(高斯误差线性单元),但理解其前身 ReLU 就够了:

1
2
3
4
5
6
7
8
ReLU(x) = max(0, x)

意思是:正数不变,负数变成0。

ReLU(3) = 3
ReLU(-5) = 0
ReLU(0.1) = 0.1
ReLU(-100) = 0

就这么简单——但它赋予了模型表达任意复杂函数的能力。

5.7 把所有层堆叠起来

一个完整的 LLM 就是把很多个 Transformer Block 堆叠起来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
输入 tokens: "今天天气"

┌── Embedding Layer ──┐ 把 token 变成向量
│ "今天" → [0.2, ...]│
│ "天气" → [0.1, ...]│
└─────────────────────┘

┌── Transformer Block 1 ──┐ 浅层:学习基础语法
└──────────────────────────┘

┌── Transformer Block 2 ──┐
└──────────────────────────┘

...(重复 N 次)...

┌── Transformer Block N ──┐ 深层:学习复杂推理
└──────────────────────────┘

┌── 输出层 (Linear + Softmax) ──┐
│ 把最后一个 token 的向量 │
│ 映射到词库大小的概率分布 │
│ P("好")=0.5, P("热")=0.2, ... │
└─────────────────────────────────┘

层数的意义

  • 浅层(第 1-10 层):学习基础的语法模式、词性、短语结构
  • 中层(第 10-60 层):学习语义关系、知识检索、简单推理
  • 深层(第 60-96 层):学习复杂推理、抽象概念、长距离依赖

GPT-3 有 96 层,GPT-4 的具体架构未公开但估计超过 100 层。Claude 3.5 Sonnet 的具体层数也未公开。

5.8 模型大小 = 参数量

你经常听到”7B 模型”、”70B 模型”、”175B 模型”——这里的 B 是 Billion(十亿),指的是模型的参数总量

参数来自哪里?

1
2
3
4
5
6
7
8
9
10
一个 Transformer Block 的参数:
- Attention 的 Q/K/V 矩阵:4096 × 4096 × 3 = 50M 参数
- Attention 输出矩阵: 4096 × 4096 = 17M 参数
- FFN 的两个矩阵: 4096 × 16384 × 2 = 134M 参数
- 各种偏置和归一化: 约 1M 参数
────────────────────────
一个 Block ≈ 200M 参数

96 个 Block = 96 × 200M = 19.2B 参数
加上 Embedding 层等 ≈ 总计约 175B 参数 (这就是 GPT-3!)

参数越多,模型的”容量”越大——能记住更多知识、能处理更复杂的推理。但也需要更多数据来训练,更多计算资源来运行。


第六章:训练——如何让模型从”白痴”变”天才”

6.1 训练前的模型是什么样的

一个未训练的模型,所有参数都是随机数。它的输出完全是胡言乱语——给它”今天天气”,它预测下一个字的概率就像掷骰子一样随机。

1
2
3
4
5
未训练的模型:
P("好" | "今天天气真") = 0.003 ← 随机的,不比其他字概率高
P("桌" | "今天天气真") = 0.004 ← 甚至比"好"还高
P("?" | "今天天气真") = 0.002
...

训练的目标是:调整参数,让模型对正确答案的预测概率越来越高

6.2 损失函数:衡量模型有多”差”

**损失函数(Loss Function)**是一个数字,告诉模型”你的预测离正确答案有多远”。

LLM 使用的损失函数叫 交叉熵损失(Cross-Entropy Loss)

1
Loss = -log(P(正确的字))

这个公式说的是:正确答案的概率越高,Loss 越低。

用例子感受一下:

1
2
3
4
5
6
7
8
9
10
假设正确的下一个字是 "好"

情况1:模型预测 P("好") = 0.9(很自信,而且对了)
Loss = -log(0.9) = 0.046 ← 很小,模型做得好!

情况2:模型预测 P("好") = 0.1(不太确定)
Loss = -log(0.1) = 1.0 ← 比较大,模型需要改进

情况3:模型预测 P("好") = 0.001(几乎不考虑正确答案)
Loss = -log(0.001) = 3.0 ← 很大!模型太差了

为什么用 -log 而不是直接用 1 - P?
因为 -log 有一个好的性质:当概率接近 0 时,Loss 趋向无穷大——这会给模型一个强烈的信号说”你大错特错了”。而 1 - P 在这种情况下最多也就是 1,信号不够强。

6.3 梯度下降:如何调整参数

知道了”有多差”(Loss),下一步是”怎么变好”。

**梯度下降(Gradient Descent)**是核心方法。用爬山的比喻:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
你蒙着眼睛站在山上,想走到山谷(Loss 最低的地方)。
你看不见路,但你能感觉脚下的坡度(梯度)。

策略:
1. 感受当前脚下的坡度方向(计算梯度)
2. 朝着下坡的方向走一小步(更新参数)
3. 重复 1-2,直到到达山谷

数学表达:
新参数 = 旧参数 - 学习率 × 梯度

其中:
- 梯度 = Loss 对参数的导数(坡度的方向和陡度)
- 学习率 = 每一步走多远(通常很小,如 0.0001)

梯度就是”导数”在多维情况下的推广。对于一个参数:

1
2
3
4
5
6
7
导数的直觉:
如果我把这个参数稍微增大一点点,Loss 会增大还是减小?

如果 Loss 增大 → 导数为正 → 这个参数应该减小
如果 Loss 减小 → 导数为负 → 这个参数应该增大

按照 "新 = 旧 - 学习率 × 梯度" 更新,就能让 Loss 变小

6.4 反向传播:如何计算梯度

模型有 1750 亿个参数,怎么算每个参数的梯度?

反向传播(Backpropagation)利用的是数学中的链式法则

链式法则的直觉:

1
2
3
4
5
6
如果你知道:
- 改变 A 会怎样影响 B(A对B的导数)
- 改变 B 会怎样影响 C(B对C的导数)

那么你就知道:
- 改变 A 会怎样影响 C = (A对B的导数) × (B对C的导数)

一个简单的例子:

1
2
3
4
5
6
7
8
9
10
11
假设 y = 2x + 1,z = y²

问:x 变化会怎样影响 z?

dy/dx = 2 (x 增加1,y 增加2)
dz/dy = 2y (y 增加1,z 增加 2y)

所以 dz/dx = dy/dx × dz/dy = 2 × 2y = 4y

如果 x=1,则 y=3,dz/dx = 4×3 = 12
验证:x从1变到1.001,y从3变到3.002,z从9变到9.012 ✓

在神经网络中

1
2
3
4
5
6
7
8
9
Loss 受到最后一层参数的影响,
最后一层受到倒数第二层的影响,
......
第 2 层受到第 1 层的影响,
第 1 层受到输入和第 1 层参数的影响。

反向传播从 Loss 开始,一层一层往回算,
用链式法则把每一层的影响串起来,
最终得到 Loss 对每个参数的梯度。

这就是为什么叫”反向”传播——计算方向是从输出到输入。

6.5 训练数据:互联网就是教科书

LLM 是怎么训练的?简单说就是:喂给它海量的文本,让它不停地预测下一个 token,不停地调整参数。

训练数据来源(以 GPT-3 为例):

1
2
3
4
5
6
- 互联网网页(Common Crawl):60%
- 高质量书籍(Books1, Books2):16%
- Wikipedia:3%
- 其他(代码、论文等):21%

总计约 3000 亿 token

训练过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
for 每一批训练数据 (batch):
1. 取一段文本,比如 "我爱吃苹果和香蕉"

2. 模型尝试预测每个位置的下一个 token:
P("爱" | "我") → 和正确答案"爱"比较 → 算 Loss
P("吃" | "我爱") → 和正确答案"吃"比较 → 算 Loss
P("苹果" | "我爱吃") → 和正确答案"苹果"比较 → 算 Loss
P("和" | "我爱吃苹果") → 和正确答案"和"比较 → 算 Loss
...

3. 把所有位置的 Loss 加起来

4. 反向传播,算出所有参数的梯度

5. 用梯度下降更新参数

6. 回到 1,处理下一批数据

重复几十万次甚至几百万次迭代...

6.6 预训练 → 微调 → RLHF:三段式训练

现代 LLM 的训练分三个阶段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
┌──────────────────────────────────────────────────────────┐
│ 阶段 1: 预训练 (Pre-training) │
│ 目标: 学习语言的基本规律和世界知识 │
│ 数据: 海量互联网文本(万亿 token) │
│ 方法: 预测下一个 token(自监督学习) │
│ 结果: 模型会"补全"文本,但不会"对话" │
│ 算力: 数千张 GPU 跑数月,成本数百万美元 │
│ │
│ 类比: 让一个小孩读遍了图书馆的所有书 │
│ → 他知识渊博,但你问他问题他可能不会好好回答 │
├──────────────────────────────────────────────────────────┤
│ 阶段 2: 监督微调 (SFT - Supervised Fine-Tuning) │
│ 目标: 教模型以"助手"的方式回答问题 │
│ 数据: 人工标注的"问题-高质量回答"对(几万到几十万条) │
│ 方法: 继续用同样的 Loss 训练,但数据是对话格式 │
│ 结果: 模型学会了"对话"的格式和礼节 │
│ │
│ 类比: 给小孩请了一个家教,教他"别人问什么,应该怎么回答" │
├──────────────────────────────────────────────────────────┤
│ 阶段 3: RLHF (基于人类反馈的强化学习) │
│ 目标: 让模型的回答更符合人类偏好(有帮助、无害、诚实) │
│ 数据: 人类标注的"回答A好还是回答B好"的偏好数据 │
│ 方法: 先训练一个"奖励模型"学习人类偏好, │
│ 再用强化学习让 LLM 最大化奖励 │
│ 结果: 模型回答更像"人话",更有帮助,更安全 │
│ │
│ 类比: 给小孩一个辅导员,告诉他"这样回答好,那样不好" │
│ 小孩慢慢学会了什么样的回答最讨人喜欢 │
└──────────────────────────────────────────────────────────┘

6.7 RLHF 的数学原理(简化版)

RLHF 的核心思路:

1
2
3
4
5
6
7
8
9
10
11
第1步:训练奖励模型(Reward Model)
- 给同一个问题生成两个回答 A 和 B
- 让人类标注员选"哪个更好"
- 训练一个模型来预测"人类更喜欢哪个"
- 这个模型就是"奖励模型"——给任何回答打个分

第2步:用奖励模型来训练 LLM
- LLM 生成一个回答
- 奖励模型给这个回答打分
- 如果分数高 → 调整参数让模型以后更容易生成类似的回答
- 如果分数低 → 调整参数让模型以后避免类似的回答

这里用到的强化学习算法叫 PPO(Proximal Policy Optimization),核心公式是:

$$
L^{CLIP} = \min(r_t \cdot A_t, \text{clip}(r_t, 1-\epsilon, 1+\epsilon) \cdot A_t)
$$

看不懂没关系!翻译成人话就是:

“根据奖励调整模型,但每次调整幅度不要太大(clip),防止模型走偏。”

这个 clip 很重要——没有它,模型可能会找到一种”讨好奖励模型但实际上回答很烂”的捷径(叫 reward hacking)。


第七章:从 GPT 到 Claude——现代 LLM 的演进

7.1 规模定律(Scaling Law)

2020 年,OpenAI 发现了一个惊人的规律:

模型的能力和三个因素成幂律关系:

$$
L \propto \frac{1}{N^{0.076}} + \frac{1}{D^{0.095}} + \frac{1}{C^{0.050}}
$$

其中 L 是 Loss(越低越好),N 是参数量,D 是数据量,C 是计算量。

人话翻译:更大的模型 + 更多的数据 + 更多的算力 = 更好的模型

而且这个关系是平滑的、可预测的——你可以在小模型上做实验,然后预测大模型的性能。

这就是为什么 AI 公司都在疯狂扩大模型规模。

7.2 涌现能力(Emergent Abilities)

更有意思的是,当模型规模超过某个阈值后,会突然”涌现”出小模型完全不具备的能力:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
模型大小 vs 能力(示意):

能力 ╱
│ ╱
│ ╱╱╱╱
│ ╱╱╱
│ ────────╱ ← 突然跳跃!(涌现)
│ ──────
│ ──────
│ ──
└──────────────────────────────→ 参数量
1B 10B 50B 175B 540B

小模型(<10B):能补全文字,但不会做算术
中模型(~50B):突然会做简单算术了
大模型(>100B):突然会做思维链推理了
超大模型(>500B):突然能理解笑话和隐喻了

这就像水温从 99°C 到 100°C 的那一度——量变引起了质变。

7.3 思维链推理(Chain of Thought)

传统做法:

1
2
问:一个商店有 23 个苹果,卖掉了 17 个,又进了 6 个,还剩多少?
模型直接回答:12 ✓ (有时对有时错)

思维链做法:

1
2
3
4
5
6
7
问:一个商店有 23 个苹果,卖掉了 17 个,又进了 6 个,还剩多少?
模型回答:
让我一步步想:
1. 开始有 23 个苹果
2. 卖掉 17 个:23 - 17 = 6
3. 又进了 6 个:6 + 6 = 12
所以还剩 12 个苹果。✓ (几乎总是对的)

为什么分步骤就更准确? 因为每一步只需要做简单计算,错误率低。而直接一步到位需要”跳跃式推理”,错误率高。

Claude 的”Extended Thinking”功能就是让模型在回答前先进行长时间的内部推理。

7.4 上下文窗口:能记住多少

LLM 能处理的最大文本长度叫上下文窗口(Context Window)

1
2
3
4
GPT-3 (2020):    4K tokens ≈ 3000 字
GPT-3.5 (2023): 16K tokens ≈ 12000 字
GPT-4 (2023): 128K tokens ≈ 96000 字
Claude 3.5 (2025):200K tokens ≈ 150000 字(一本中篇小说)

为什么有上限? 因为 Attention 的计算量和内存随序列长度平方增长

1
2
3
序列长度 n = 1000 → Attention 矩阵大小 = 1000 × 1000 = 1,000,000
序列长度 n = 10000 → Attention 矩阵大小 = 10000 × 10000 = 100,000,000
序列长度 n = 200000 → Attention 矩阵大小 = 200000 × 200000 = 40,000,000,000

长度增加 10 倍,计算量增加 100 倍。这就是为什么超长上下文很昂贵。

各种优化技术(如 Flash Attention、稀疏 Attention、KV Cache)都在试图降低这个 O(n²) 的成本。


第八章:为什么它会”幻觉”?局限性的数学解释

8.1 幻觉的本质

幻觉(Hallucination)= 模型一本正经地输出了错误的信息。

比如:

1
2
问:爱因斯坦是哪年获得诺贝尔化学奖的?
模型:爱因斯坦于 1921 年获得诺贝尔化学奖。 ← 错!是物理学奖!

模型为什么会这样?因为从概率角度看:

1
2
3
4
P("化学" | "爱因斯坦...诺贝尔...奖") 和 P("物理" | "爱因斯坦...诺贝尔...奖")

这两个概率可能差距不大(比如 0.4 vs 0.5),
模型有时候就会选到错误的那个。

8.2 为什么幻觉不可避免

从数学角度看,幻觉至少有三个来源:

来源1:训练数据中存在矛盾信息

1
2
3
4
5
6
互联网上关于某个事实可能有正确和错误两个版本:
文档A:"维生素C可以治感冒" (错误但广泛流传)
文档B:"维生素C不能治愈感冒" (正确但数量少)

模型学到的是加权平均:
P("可以治感冒" | "维生素C") 偏高,因为训练数据中这种说法更多。

来源2:模型本质上是在做”模式插值”

模型见过”爱因斯坦+诺贝尔+奖”,也见过”化学+奖”和”物理+奖”。当它需要填空时,它在做这些模式的插值。如果训练数据中”诺贝尔化学奖”这个词组出现的频率很高,模型可能就会倾向于输出它。

来源3:自回归生成的错误累积

模型一次只生成一个 token。如果第 N 个 token 选错了,后面所有 token 都是在错误基础上继续的:

1
2
3
4
"法国的首都是里" → 模型已经选了"里"
→ 现在 P("昂" | "法国的首都是里") 很高
→ 于是输出 "里昂" ← 错!应该是巴黎
→ 但回不去了...

8.3 温度和采样策略如何影响幻觉

1
2
3
4
5
6
7
8
9
10
11
12
温度低(如 0.1):
→ 几乎总是选概率最高的 token
→ 更"安全",但更"无聊"
→ 如果最高概率的就是错的,则幻觉是确定性的

温度高(如 1.5):
→ 随机性更大
→ 可能选到概率不那么高但实际上正确的 token
→ 也可能选到更离谱的错误 token
→ 幻觉是随机性的

实际上取一个适中的温度(0.7-1.0)通常效果最好。

8.4 模型并不”知道”自己知不知道

这是最根本的问题:模型对自己的不确定性没有可靠的自我感知。

一个理想的系统应该是:

1
2
知道的事情 → 自信地回答
不知道的事情 → 说"我不确定"

但 LLM 的训练目标是”总是预测下一个 token”——它的训练中没有”拒绝回答”这个选项。即使模型对某个事实的内部概率分布非常扁平(每个选项概率差不多),它也必须输出一个 token,而且输出的方式看起来和它很自信时没什么区别

RLHF 可以一定程度上缓解这个问题(教模型说”我不确定”),但不能从根本上解决。


第九章:总结——一张图看懂全貌

9.1 完整的 LLM 工作流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
┌─────────── 训练阶段 ──────────────┐
│ │
│ 1. 海量文本数据(万亿 token) │
│ ↓ │
│ 2. 分词(Tokenization) │
│ ↓ │
│ 3. 预测下一个 token │
│ → 计算 Loss(交叉熵) │
│ → 反向传播算梯度 │
│ → 梯度下降更新参数 │
│ → 重复几百万次 │
│ ↓ │
│ 4. 监督微调(对话格式) │
│ ↓ │
│ 5. RLHF(学习人类偏好) │
│ ↓ │
│ 训练完成!参数固化 │
└────────────────────────────────────┘

┌─────────── 推理阶段 ──────────────┐
│ │
│ 用户输入: "解释一下量子力学" │
│ ↓ │
│ 1. Token化: ["解释", "一下", ...] │
│ ↓ │
│ 2. 嵌入: 每个 token → 向量 │
│ ↓ │
│ 3. 经过 N 层 Transformer: │
│ 每层 = Attention + FFN │
│ Attention: token 之间交换信息 │
│ FFN: 从知识库中检索/推理 │
│ ↓ │
│ 4. 最后一层输出 → 概率分布 │
│ P("量")=0.3, P("这")=0.2, ... │
│ ↓ │
│ 5. 采样:选一个 token │
│ ↓ │
│ 6. 回到步骤 2,继续生成下一个 token │
│ ↓ │
│ 7. 直到生成"结束"标记 │
│ ↓ │
│ 输出: "量子力学是物理学的一个分支..." │
└────────────────────────────────────┘

9.2 核心数学概念速查表

概念 人话解释 在 LLM 中的作用
概率 一件事发生的可能性 (0~1) 预测每个 token 出现的可能性
条件概率 知道一些信息后的概率 P(下一个字 | 前面的字)
向量 一串有序的数字 表示 token 的含义
矩阵乘法 一种线性变换 变换向量(Q/K/V 生成、FFN 等)
点积 对应位相乘再求和 衡量两个向量的相似度
Softmax 把数字变成概率分布 Attention 权重归一化、最终概率输出
交叉熵 衡量预测分布和真实分布的差距 训练的损失函数
梯度 函数在某点的变化方向和速度 告诉模型参数该怎么调
链式法则 复合函数求导的规则 反向传播的数学基础
梯度下降 沿着下坡方向走 优化参数的方法

9.3 为什么 LLM 这么强?

回到最初的问题:为什么”预测下一个字”就能产生这么强大的能力?

答案是三个因素的结合

1
2
3
4
5
6
7
8
9
10
11
12
1. Transformer 架构的表达能力
→ Attention 让模型能关注任意距离的上下文
→ FFN 提供了巨大的参数空间来存储知识
→ 多层堆叠允许逐步抽象和推理

2. 海量训练数据
→ 互联网上的文本蕴含了人类大量的知识和推理模式
→ 要准确预测下一个字,模型被迫学会了这些知识和模式

3. 规模效应
→ 更大的模型 + 更多的数据 → 更好的预测
→ 超过某个规模后,涌现出推理、知识检索、创造性等能力

9.4 最后的思考

LLM 本质上是一个极其庞大的条件概率模型。它不”理解”语言(至少不像人类那样理解),但它通过学习海量文本中的统计规律,达到了在行为层面看起来像理解了的效果。

这是否等于”真正的理解”?这是一个哲学问题,目前没有共识。

但从工程角度看,它已经足够有用了——写代码、回答问题、翻译、创作、推理——这些能力都是从那个简单的目标”预测下一个 token”中涌现出来的。

这大概是人工智能历史上最美丽的意外之一。


附录 A:关键术语对照表

英文 中文 简单解释
LLM 大语言模型 能理解和生成文本的大型AI模型
Token 词元 文本的最小处理单位(介于字和词之间)
Embedding 嵌入 把 token 变成向量的过程
Attention 注意力 让模型关注重要的上下文
Transformer 当前所有 LLM 的底层架构
Parameters 参数 模型中可学习的数字,决定模型行为
Loss 损失 衡量模型预测有多差的数字
Gradient 梯度 告诉参数该怎么调的方向指标
Backpropagation 反向传播 从输出到输入计算梯度的方法
Fine-tuning 微调 在特定数据上继续训练
RLHF 基于人类反馈的强化学习 用人类偏好来优化模型
Inference 推理 模型生成回答的过程
Hallucination 幻觉 模型自信地说出错误信息
Context Window 上下文窗口 模型能处理的最大文本长度
Scaling Law 规模定律 更大=更强 的数学关系
Temperature 温度 控制生成随机性的参数

附录 B:推荐继续学习的资源

如果你看完这篇文章觉得意犹未尽,推荐以下资源(按难度递增):

1
2
3
4
5
6
7
8
9
10
11
12
13
入门级:
📺 3Blue1Brown "Neural Networks" 系列(B站有搬运)
📺 Andrej Karpathy "Let's build GPT from scratch"
📖 《这就是ChatGPT》 Stephen Wolfram 著(薄而精彩)

进阶级:
📄 "Attention Is All You Need"(Transformer 原始论文,必读)
📄 "Language Models are Few-Shot Learners"(GPT-3 论文)
📺 Stanford CS224N(NLP 经典课程)

实践级:
💻 Andrej Karpathy 的 nanoGPT(从零实现一个小 GPT)
💻 Hugging Face Transformers 库(动手跑模型)

写完这篇文章,我最大的感受是:LLM 的数学原理其实并不复杂——概率、线性代数、微积分的基础知识就够了。真正令人惊叹的是,这些简单的数学组件组合在一起,加上足够大的规模,就涌现出了接近人类水平的语言能力。这或许是近代数学最优美的应用之一。


文章作者: RickDamon
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 RickDamon !
 上一篇
基于Google最新Agents论文的学习文档 基于Google最新Agents论文的学习文档
导语原链接:Google AI Agents Technical Guide 这份白皮书是 Google 对AI Agent 从概念到生产部署的完整技术路线图,涵盖了: ✅ AI Agent 的定义和分类 ✅ Agent 开发框架(ADK
下一篇 
Golang1.22非兼容性更新踩坑记录 Golang1.22非兼容性更新踩坑记录
导语坑的内容主要是golang在1.22版本中更新了循环中的临时变量,每次循环为单独的地址,而在旧版本中,所有循环中的临时变量,指向的是同一块内存。说的更详细点:在 Go 1.22 之前的版本中,for _, p := range arr
2024-10-18
  目录