概率与统计 入门
读懂任何 LLM 训练论文之前所需的最少概率与统计。5 个短小主题,涵盖「概率到底是什么」、 概率分布及其「加起来等于 1」的约束、条件概率、期望 / 均值 / 方差,以及在每个语言模型背后 默默运行的对数概率。除高中代数外,不假定任何先验数学。
概率(Probability)
一个 0 到 1 之间的数,表示我们对某件事发生有多确信。
抛一枚均匀硬币。在它落地之前,你说不出是正面还是反面 —— 但你能说出一件有用的事: 两个结果感觉上「一样可能」。概率 就是把这种感觉钉成一个数。正面对应 0.5,反面也是 0.5。形式化写法是 P(正面) = 0.5 —— 读作「正面的概率是二分之一」。
这个数永远落在闭区间 [0, 1]。两端是人人都知道的两种极端情况, 只是换了套正式的外衣:
P(事件) = 0—— 事件不可能发生。硬币立在边上还长出翅膀飞走。P(事件) = 1—— 事件一定发生。明天太阳照常升起(差不多)。P(事件) = 0.5—— 不偏不倚,就像一次抛硬币。P(事件) = 0.99—— 几乎必然,但还差那么一点。P(事件) = 0.001—— 不太可能,但并非不可能。
这个数有两种等价的读法,平时都用得上:
- 作为长期频率。把硬币抛一百万次,大约有五十万次落到正面。 概率就是次数比例最终收敛到的那个数。
- 作为信念强度。就算只抛一次,在抛之前你也愿意 50/50 下注。 概率就是你对某个结果押注的强度。
为什么用一个数就够?因为一旦有了它,很多后续问题就靠几步算术就能答出来:P(非正面) = 1 − P(正面) = 0.5;两次独立抛掷都是正面, 概率是 0.5 × 0.5 = 0.25;两次中至少一次是正面, 概率是 1 − 0.25 = 0.75。整套「可能会发生什么」的演算, 归根结底就是对 [0, 1] 之间的几个数做加减乘。
概率并不只属于硬币和骰子。一切「不确定」的事都有一个概率,只是没人写下来而已:
- 天气。「明天 70% 概率下雨」=
P(下雨) = 0.7。 - 垃圾邮件过滤。每封邮件都被打一个分数;超过阈值就进垃圾箱。
- 医学检测。阳性不等于得病 —— 它只是把概率向上挪一截。
- 体育比分。「热门 1.4 赔率」≈ 庄家给出的隐含概率
0.71左右。 - LLM。「The quick brown」之后下一个 token 是 cat 的概率,模型会算出来。
值得先记住的几个记号。P(A) 表示事件 A 的概率。P(A 且 B) —— 也写作 P(A ∩ B) 或 P(A, B) —— 表示两者都发生的概率。P(A 或 B) —— 也写作 P(A ∪ B) —— 表示至少一个发生的概率。 而 P(非 A),写作 P(¬A) 或 P(Aᶜ), 按定义等于 1 − P(A)。
在 Transformer 里:每个 LLM 的最后一层, 都会为「下一个可能 token」各输出一个 [0, 1] 之间的数 —— 词表里每个词片段一个,加起来是几万个。生成下一个 token 时,模型就按这些数挑一个。 你最喜欢的聊天机器人写下的每一个字,都起源于这一段区间里的一个概率值。 后面四节会讲这些数字如何组合、求和、做条件、最终从数据里学出来。
概率分布(Probability Distribution)
把每个结果的概率列在一起 —— 而且加起来必须等于 1。
一枚硬币给出两个概率:P(正面) = 0.5、P(反面) = 0.5。 一颗六面骰子给出六个,每面 1/6 ≈ 0.167。一个 10 万词表的语言模型给出 10 万个。 把所有可能结果的概率打包在一起,得到的就是 概率分布 —— 还是「每个结果一个数」,只是一次看全。
每个概率分布都遵循两条规则,值得直接背下来:
- 每个数都在
[0, 1]里 —— 每一项都是合法的概率。 - 所有数加起来正好等于 1 —— 必须有件事发生。
「加起来等于 1」这条规则才是真正的核心。乍看像是教条,直到想起它为什么成立: 如果列举出所有可能发生的结果,那么以概率 1(也就是「一定」)其中之一会发生。 你以后会做的概率运算 —— 把分数归一成概率、把概率拆成几种子情况、计算边缘概率 —— 十有八九都是为了让数字加起来变成 1。
一个简单的分布:明天的天气有四种互斥结果:
P(晴) = 0.55 P(多云) = 0.25 P(雨) = 0.15 P(雪) = 0.05 ───────────────── 总和 = 1.00 ✓
四个数,每个都在 [0, 1],加起来等于 1。这就是一个分布。你可以读出任何单一结果的概率, 也可以把结果打包:P(降水) = P(雨) + P(雪) = 0.20。 打包就是相加 —— 因为这四个结果互斥(此模型里同一天不会又下雨又下雪), 它们把所有可能性划分得干干净净。
到处都会碰到两种分布形态,规则都是上面那两条,只是「记账方式」不同:
- 离散分布。结果是有限(或可数)多个。一枚硬币、一颗骰子、词表里的一个 token、 一个分类标签。分布就是一串数字,「求和」就是普通的求和。
- 连续分布。结果取自一段连续区间 —— 身高(厘米)、温度、时间。 这时不再是一串数,而是一条密度曲线
p(x); 概率藏在曲线下的面积里;「加起来等于 1」变成「总面积等于 1」。 直觉一样,只是换成了微积分的记号。
最有名的连续分布是 正态分布(高斯分布)—— 你在每张分数图上都见过的那条钟形曲线。 它只需要两个数就能描述:峰在哪里(μ,均值)和钟有多宽(σ,标准差)。 成人身高、测量误差、神经网络初始化权重时加的噪声,差不多都服从正态分布。
离散这一侧,LLM 里的主力是 类别分布(categorical distribution) —— 正是上面那张天气表的结构,只是宽得多。语言模型每挑一个下一个 token, 都是在整张词表上的类别分布里采样。
分布是怎么得到的?主要有两种方式,都很熟悉:
- 从计数得到。把骰子掷 6000 次,其中 1003 次是 4 点, 那么经验估计就是
P(4) ≈ 1003/6000 ≈ 0.167。 所有计数除以总次数,得到的概率天然加起来等于 1。 - 从分数经 softmax 得到。一个公式 ——
softmax(zᵢ) = exp(zᵢ) / Σⱼ exp(zⱼ)—— 把任意一串实数变成一个合法的概率分布。这一步值得仔细拆开看,因为每个 LLM 都用它。
softmax 在做什么。输入是一串实数分数 (z₁, z₂, …, z_n) —— 正、负、任意,无所谓。输出是同样长度的一串数,每一项都落在 [0, 1], 加起来正好等于 1。一个合法的概率分布,永远成立。
为什么需要它。神经网络最后一层不过是一组加权和 —— 输出可以是 −5.2、17.8,什么都行。要把这些分数当概率来用, 必须(a)让每一项非负,(b)让它们加起来等于 1。 你可能会想用一个更简单的办法:把所有分数平移到非负,再除以总和。 但平移会丢信息 —— −2 和 −10 平移后都变成「小正数」, 哪怕原本它们在「信心强度」上差了很多。而且一旦所有分数恰好相互抵消, 除以总和就变成除以 0。Softmax 用「先取指数」一招把这两个问题都绕开。
三步配方。给定 logits (z₁, z₂, …, z_n):
- 每一项取指数:
exp(zᵢ)。任何实数的指数都是正的。 - 求和:
S = Σⱼ exp(zⱼ)。 - 每一项除以总和:
softmax(zᵢ) = exp(zᵢ) / S。
具体例子。在提示词「The quick brown」之后, LLM 给三个候选续写打分:
fox dog hen
logit 4.50 3.20 0.80
exp 90.02 24.53 2.23
──────────────────────────────────────
sum = 116.78
softmax 0.77 0.21 0.02 ✓ 合计 = 1.00看看指数干了什么。fox 和 dog 在 logit 上只差了 1.3, 但经过 softmax 之后,fox 比 dog 大约 3.7 倍更可能。dog 和 hen 在 logit 上差 2.4, 但在概率上差 10 倍。指数会把差距放大: logit 上一点点优势,经过 softmax 就变成概率上明显的差距。 这就是它的设计意图 —— 把一组模糊的「相对排名」,变成一个清晰可采样的概率地形。
在 Transformer 里:LLM 最后一层,会为词表中的每个 token 输出一个实数分数 —— 叫 logit。Softmax 一行代码就把这整个 logit 向量(几万个数)变成词表上的一个 类别分布。这就是模型用来采样下一个 token 的分布。 你读到的每一次聊天回复,都是从几千个这样的分布里,各抽一个 token 拼起来的。
条件概率(Conditional Probability)
在 B 已经发生的前提下,A 的概率。
在地球上随便挑一个成年人,他拥有智能手机的概率大约是 P(智能手机) ≈ 0.7。 现在把镜头拉近:挑一个住在东京的成年人,这个概率可能跳到 0.95。 同一个问题,起始范围不同 —— 答案就变了。第二个数就是 条件概率, 写作 P(智能手机 | 住在东京),读作「在他住东京的条件下, 他有智能手机的概率」。
那根竖线 | 就是这套记号的全部诀窍,读作「在……条件下」: 竖线右边的事是你已知必然成立的;竖线左边的事是你在那个前提下要问的。P(A | B) 就是「已知 B 的情况下,A 的概率」。
定义的机械形式只有一行:
P(A | B) = P(A 且 B) / P(B)
看着抽象,图像却很具体。在条件 B 下,你只关心 B 成立的那一片; 在这一片里,有多少比例同时也满足 A?这个比例就是 P(A | B)。 分母 P(B) 把这一片重新「拉回」一个总和为 1 的合法分布; 分子 P(A 且 B) 是两者的重叠部分。
具体例子。假设每 1000 个成年人里:
· 有手机,住东京 = 19 ← A 且 B · 有手机,不住东京 = 681 · 没手机,住东京 = 1 · 没手机,不住东京 = 299 ──────────────────────────── 合计 = 1000 P(有手机) = 700 / 1000 = 0.70 P(住东京) = 20 / 1000 = 0.02 ← P(B) P(有手机 且 住东京) = 19 / 1000 = 0.019 ← P(A 且 B) P(有手机 | 住东京) = 0.019 / 0.02 = 0.95
注意发生了什么。P(有手机) 在全体里是 0.7;一旦只看 20 个东京居民这一片, 他们里有 19 个有手机,条件概率就跳到 0.95。条件化本质是一次放大镜操作: 把 B 不成立的行扔掉,再把剩下的部分重新归一化。
如果条件化「不改变答案」,即 P(A | B) = P(A), 就说 A 和 B 独立。知道 B 发生了,对 A 一点信息都没有。 两次抛硬币是独立的:第一次正面还是反面,第二次都还是 50/50。否则就是依赖的: 知道 B 会改变你对 A 的信念。现实世界里几乎所有有意思的事件对都是依赖的 —— 条件概率之所以是机器学习的核心杠杆,原因就在这里。
把定义稍微挪一挪,就得到 ML 论文里随处可见的 链式法则:
P(A 且 B) = P(A | B) · P(B) = P(B | A) · P(A)
计算「A 且 B」的联合概率有两种走法,挑哪个方向更顺手就用哪个。 把两边右手项画上等号,再两边同除以 P(B), 就得到 贝叶斯定理:P(A | B) = P(B | A) · P(A) / P(B) —— 这个公式让你把条件方向翻转过来。医学检测、垃圾邮件过滤、整个贝叶斯推断的领域, 都是这一步重新整理的延伸。
一个经典陷阱:P(A | B) 和 P(B | A) 不是同一个数。P(下雨 | 人行道湿) 很高 —— 人行道湿大多是下雨造成的;P(人行道湿 | 下雨) 也很高(甚至可以是 1)。 再看 P(患病 | 阳性) 和 P(阳性 | 患病):即使灵敏度 99% (P(阳性 | 患病) = 0.99),只要这个病很罕见,大多数阳性其实是假阳性。 同样几个数,条件方向反过来,结论可能天差地别。贝叶斯定理就是把两者重新串起来的那道桥。
在 Transformer 里:LLM 输出的每一个概率,本质都是条件概率。 让它续写「法国的首都是」时,模型在计算 P(下一个 token | 前面所有 token) —— 请仔细看那根竖线:整段 prompt 在竖线右边,要预测的在竖线左边。 训练 LLM 就是用海量文本去估计这个庞大的条件分布:语料里每一段文本, 模型都被问「在你已经看到的内容下,接下来是什么?」生成,就是同一招正向跑一遍, 一次一个条件概率。一篇聊天回复就是一连串条件概率,由上面的链式法则把它们拼起来。
期望、均值与方差
两个数把一整个分布压缩成「它落在哪里」和「它有多分散」。
一个分布可能有几十、几千、甚至无穷多项 —— 多到没法一眼看清。 所以我们把它压缩成几个摘要数字。绕不开的两个是 均值(分布平均落在哪里) 和 方差(它在均值附近散得多开)。
假设你转一个转盘,可能赢 4 种不同金额,概率列在下面:
奖金 $0 $10 $50 $1000 P 0.70 0.20 0.09 0.01
转一次「平均」会赢多少?当然单次拿不到这个数 —— 单次只会出 4 个奖金里的一个。 但如果转 100 万次,把每次奖金平均一下,长期平均值就会收敛到 期望(也叫 期望值 或就叫 均值),记作 E[X]。 公式是「结果乘以概率,再求和」:
E[X] = Σ xᵢ · P(xᵢ)
对这个转盘:
E[X] = 0·0.70 + 10·0.20 + 50·0.09 + 1000·0.01
= 0 + 2 + 4.5 + 10
= 16.5平均每转一次能赢 $16.50 —— 虽然没有任何一次会正好赢到这个数。 均值是一个加权平均:每个结果被它发生的频率加权。 极少出现的结果(比如 $1000 大奖)只贡献它那一小份; 常见结果(比如 $0)把整个均值往低处压。
一个概念,三种说法。均值、平均数、期望 三个词经常混用,但区分一下还是有好处:
- 一串数的均值 —— 算术平均。全部加起来,除以个数。
mean([2, 4, 9]) = 5。 - 分布的期望 —— 如果你不停从该分布里采样,算术平均最终会收敛到的值。 同一个想法,从概率视角看。
- 样本均值 —— 基于你实际抽到的样本,对底层期望的经验估计。 样本越多,它越逼近真实期望。
均值告诉你分布落在哪里,却没告诉你它有多散。 想象两种收益分布,均值都是 0:一个是「每天稳赚 0」的存折, 另一个是「+100 / −100 各 50%」的轮盘。均值一样,体感却天差地别。 所以我们需要第二个数来度量「分散」。
这个数就是 方差,记作 Var(X)。 思路:看每个结果偏离均值多远,把这些偏差平方 (一来变正,二来让大偏差权重更大),然后取这些平方偏差的期望:
Var(X) = E[(X − μ)²]
这里 μ(希腊字母 mu)只是 E[X] 的简写 —— 统计学里习惯用 μ 表示均值。对我们这个转盘(μ = 16.5):
Var(X) = (0 − 16.5)²·0.70
+ (10 − 16.5)²·0.20
+ (50 − 16.5)²·0.09
+ (1000 − 16.5)²·0.01
= 190.575 + 8.45 + 101.0025 + 9672.7225
≈ 9972.75方差很大,被那个罕见的 $1000 奖项主宰着。 方差有个不太顺手的地方:它的单位是平方(这里是「美元的平方」), 所以通常我们改报它的平方根 —— 标准差 σ = √Var(X)。 对这个转盘,σ ≈ $99.86。它和均值同单位, 所以你能说「典型奖金落在 $16.50 ± $99.86」,这种比较才有意义。
三个到处都用得上的实用事实:
- 期望的线性。
E[X + Y] = E[X] + E[Y],永远成立。 就算 X 和 Y 互相纠缠也没关系 —— 不需要独立性。 这是初等概率里最出乎意料的强大恒等式。 - 方差与常数。
Var(aX) = a² · Var(X)—— 方差按平方缩放。 每个奖金翻倍,方差会变成原来的 4 倍。 - 独立和的方差。当 X 和 Y 独立时,
Var(X + Y) = Var(X) + Var(Y)—— 方差相加。 这就是「平均多个独立测量能压低噪声」的原理:Var(n 个的平均) = σ² / n, 所以σ以1/√n的速度收缩。
在 Transformer 里:训练每个 LLM 用的 损失函数 —— 交叉熵 —— 本质上就是一个期望:把每个 token 的损失,在整个训练语料上平均, 梯度下降去最小化这个平均值。方差则出现两次:LayerNorm 把每个 token 向量 重新调整成「均值 0、方差 1」,以保持激活值稳定; 梯度下降在每个 mini-batch 上看到的梯度噪声本身就有方差 —— 所以批量越大,训练曲线越平滑(平均更多样本,噪声以 √n 速度被压低)。 现代 ML 的三个核心套路 —— 最小化平均损失、归一化激活、批量化梯度 —— 全是均值与方差的具体应用。
对数概率(Log Probability)
概率小到可怕,而且要连乘;它们的对数是不大不小的数,而且只要相加。
实际工程里,概率有个问题:它们小得非常快。一段特定句子出现在野外的概率大约是10⁻³⁰;一段 100 词的段落?10⁻³⁰⁰。 这些数小到无法存进 64 位浮点数 —— double 类型能表示的最小正数大约是 10⁻³⁰⁸, 再小就直接四舍五入到 0 了。把一堆概率连乘下去,很快就跌出这道悬崖。
解药是取 对数。一个数的对数,回答的是「e(约 2.718)的多少次方等于它?」 例如 log(0.5) ≈ −0.693、log(0.01) ≈ −4.605、log(10⁻³⁰⁰) ≈ −690.78。极小的正概率, 变成不大不小的负数,既好存又好算。
对数有三条性质,刚好让它和概率天造地设。三条都源自同一条规则 log(a · b) = log(a) + log(b):
- 乘法变加法。N 个独立事件的联合概率是
p₁ · p₂ · … · pN—— 这个连乘会下溢。 取对数后,变成log p₁ + log p₂ + … + log pN—— 无论你加多少项都不会爆。 - 大小顺序保持不变。对数单调递增 ——
p > q当且仅当log p > log q。所以只要你做的是比较或排序 (哪个 token 最可能?哪个分类得分最高?),比较 log 给出完全相同的答案。 原本想最大化的东西,可以直接最大化它的 log。 - 数值范围被压平。概率分布在
[0, 1],但有意思的事情大多挤在 0 附近 ——0.001和0.0001视觉上很像,可发生频率却差 10 倍。 取 log 后,它们成了−6.91和−9.21,差异一目了然。 基于梯度的优化器看到的「损失地形」干净得多。
约定:ML 里默认是 自然对数(以 e 为底),写作 log 或 ln。有些教材用以 2 为底(单位是 bit)或以 10 为底,但定性行为完全一样 —— 换底只是给所有对数乘上一个常数。
一个具体例子。用一个简陋的语言模型,把句子「the cat sat」的概率, 按第 3 节的链式法则拆开来算:
P("the cat sat")
= P(the) · P(cat | the) · P(sat | the cat)
= 0.04 · 0.001 · 0.0002
= 0.000000008 ← 才三个 token 就够呛;100 个 token 没救。
log P("the cat sat")
= log(0.04) + log(0.001) + log(0.0002)
= −3.22 + −6.91 + −8.52
= −18.65 ← 三个数相加,稳稳的,不会下溢。同样的信息,两种尺度。乘法在浮点寄存器里直接归零;加法是个体感舒服的 −18.65。 100 个 token 的序列,连乘根本走不到终点,而加法只是越加越负到几百而已。 每个 LLM 的打分流程、每次困惑度计算、每个束搜索排序器,都在 log 空间里跑,原因就在这。
读 ML 论文时立刻会撞上的两个相关量:
- 负对数似然(NLL)。就是
−log P。我们翻个符号, 让「更可能」对应更小的数 —— 优化器都喜欢这样(它们都做最小化)。 最大化似然和最小化 NLL 是同一件事。 - 交叉熵损失。每个 LLM 的训练目标:
L = −Σ log P(正确 token | 之前的 tokens),在语料上求平均。 就是「在每个位置上,把正确答案的概率取负对数,然后求和」。 换个名字的 NLL,但你在论文里看到的总是「cross-entropy」这个词。
还有一个常见招式:log-sum-exp。在 log 空间里把几个概率相加(比如把若干条推理路径的 log-prob 合并成一个总概率),要小心,因为 log(p + q) ≠ log p + log q。技巧是 log(Σ exp(log pᵢ)),每个框架都把这件事封装成数值稳定的 logsumexp。第 2 节的 softmax,就是它的一个应用。
在 Transformer 里:模型输出的是 logits,真正喂进损失函数的是log_softmax(logits) —— 也就是对数概率。 训练循环计算 cross_entropy = −mean(log P(正确 token)),然后反向传播。 推理时,束搜索和采样按「累积对数概率」给候选续写排序 —— 每延伸一个 token 就把这个 token 的 log-prob 加上去。 本文里我们写作 P(x) 的每一个概率,在真实训练 / 推理代码里, 几乎都是以 log P(x) 的形态存储和操作的。 数学上是同一件事,只是浮点寄存器能活下来。