Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

概率与随机变量

同样是打印 20 页,今天用了 79 秒,明天用了 83 秒。页数没有变,设备的预热、传输和进纸却可能有细小差别。

上一章帮助我们找到让损失下降的方向。这一章换个问题:面对这些波动,怎样表达“可能发生什么”,又怎样在获得新信息后修正判断?

概率让我们不用在“必然发生”和“绝不会发生”之间二选一。它也能帮我们识别一种常见误解:一个看起来很准的报警器,发出警报后,事情未必就有九成把握。

1. 先把事件说清楚

把“一次任务发生卡纸故障”记作事件 JJ。如果用概率模型描述它发生的可能性,可以写 P(J)=0.01P(J)=0.01。

概率介于 0 和 1 之间。0.01 也就是 1%。在反复进行、条件相似的任务中,我们可以用发生次数除以总次数,得到一个观测到的频率,用来估计这个概率。

概率是模型中的量,频率来自有限次观测。某天 100 次任务没有卡纸,不会自动把原来的 1% 变成“从此不会故障”;可能只是这一天恰巧没有遇到。

如果 JJ 表示故障,那么 ¬J\neg J 表示不故障,它的概率为:

P(¬J)=1−P(J)=0.99 P(\neg J)=1-P(J)=0.99

这一章的报警率和等待时间分布都由我们设定,供手算和模拟使用,并非真实设备的测量结果。实际估计时,首先要明确记录来自哪些设备、哪些任务、什么时间段。

2. 知道了报警,再问故障概率

给打印机装一个报警器。把“报警”记作事件 AA,假设它有这样的表现:

  • 真正发生故障时,90% 的任务会报警。
  • 没有故障时,仍有 5% 的任务会误报。

第一句话写作 P(A∣J)=0.9P(A\mid J)=0.9。竖线读作“在……条件下”,这个式子就是“已知故障时,报警的概率”。

它和 P(J∣A)P(J\mid A) 不是同一个问题。后者问的是:现在已经报警,真的故障的概率有多大?

把比例先换成数量

假设故障率为 1%。用一张 10000 次任务的教学表,把这些比例摆在一起:

情况报警不报警合计
故障9010100
未故障49594059900
合计585941510000

100 次故障里有 90 次报警;9900 次正常任务里,5% 也就是 495 次误报。于是,585 次报警中只有 90 次属于真正故障:

P(J∣A)=90585≈0.1538 P(J\mid A)=\frac{90}{585}\approx0.1538

答案是 15.38%,不是 90%。

图 1:故障本来就少,正常任务中的小比例误报,数量上也可能超过真正故障的报警。图中数量是设定概率的教学展开。

这不是说报警器毫无作用。报警前的故障概率只有 1%,报警后上升到了约 15.38%,信息已经改变了判断。接下来是否停机检查,还取决于漏掉故障和多检查一次各有什么代价。

再把数量写成公式

条件概率可以从交集定义:

P(J∣A)=P(J∩A)P(A) P(J\mid A)=\frac{P(J\cap A)}{P(A)}

J∩AJ\cap A 表示“故障且报警”,条件事件的概率 P(A)P(A) 必须大于 0。

把分子改写为 P(A∣J)P(J)P(A\mid J)P(J),就得到贝叶斯公式:

P(J∣A)=P(A∣J)P(J)P(A) P(J\mid A)=\frac{P(A\mid J)P(J)}{P(A)}

分母中的报警有两条来源:

P(A)=P(A∣J)P(J)+P(A∣¬J)P(¬J) \begin{aligned} P(A) &=P(A\mid J)P(J)\\ &\quad+P(A\mid\neg J)P(\neg J) \end{aligned}

原来的 P(J)P(J) 叫先验概率,得到报警信息后的 P(J∣A)P(J\mid A) 叫后验概率。这些名称描述的是获得这条信息之前和之后的判断,不表示先验只能凭空猜测;它也可能来自既有数据。

如果设备老化,故障率变成 10%,而两种条件报警率保持不变,后验就会变成:

0.9×0.10.9×0.1+0.05×0.9=23 \frac{0.9\times0.1} {0.9\times0.1+0.05\times0.9} =\frac23

约 66.67%。同一个报警器,面对不同的基础发生率,报警后的含义也会变化。

3. 独立,不等于互不相容

假如知道事件 BB 发生,并不改变事件 AA 的概率,我们说这两个事件独立。相应地:

P(A∩B)=P(A)P(B) P(A\cap B)=P(A)P(B)

例如,若两次任务的故障独立、故障概率都为 1%,那么两次都故障的概率为 0.012=0.00010.01^2=0.0001。

这里的“独立”是一个假设,需要根据场景判断。如果同一卷纸受潮,导致相邻任务都容易卡纸,两次故障就可能相关。不能因为记录在两行,就认为它们独立。

互不相容则是另一回事:两个事件不可能同时发生。一次抛硬币的“正面”和“反面”互不相容,但不独立——知道出现正面,反面的概率就变成了 0。

独立性很重要。后面把许多样本的概率相乘、估计均值的不确定性,都需要留意是否作了这样的假设。

4. 随机变量:给可能的结果配上数字

“这一次额外等多久”可以用一个数字来描述。假设额外等待时间 TT 只有三种可能:

等待时间 ttP(T=t)P(T=t)
0 秒0.5
10 秒0.3
30 秒0.2

TT 是一个随机变量:它把一次不确定的结果对应到一个数值。表中列出的取值与概率,组成它的概率分布。这些取值互不相容,并且已经覆盖所有可能,所以概率加起来是 1。

这里用大写 TT 指尚未确定的随机变量,小写 tt 指一个具体取值。这样的记号能提醒我们,“等待时间这个量”和“某次等了 10 秒”不是同一层意思。

平均会等多久

如果大量重复这样的任务,长期平均等待时间会接近各取值按概率加权的和:

E[T]=0×0.5+10×0.3+30×0.2=9 \mathbb E[T] =0\times0.5+10\times0.3+30\times0.2 =9

E[T]\mathbb E[T] 叫期望。它不是“最常发生的值”:本例最常发生的是 0 秒,也从来不会恰好等 9 秒,但平均仍可以是 9 秒。

一般的离散变量有取值 t1,…,tkt_1,\ldots,t_k 和概率 p1,…,pkp_1,\ldots,p_k,则:

E[T]=∑j=1kpjtj \mathbb E[T]=\sum_{j=1}^{k}p_jt_j

只知道平均,还不够

另一个系统每次都固定等 9 秒,与本例的期望相同,体验却很不一样。我们还需要描述结果围绕期望波动得多大。

把偏离期望的距离平方,再按概率平均,得到方差:

Var⁡(T)=E[(T−E[T])2] \operatorname{Var}(T)= \mathbb E[(T-\mathbb E[T])^2]

代入本例:

Var⁡(T)=0.5(0−9)2+0.3(10−9)2+0.2(30−9)2=129 \begin{aligned} \operatorname{Var}(T) &=0.5(0-9)^2+0.3(10-9)^2\\ &\quad+0.2(30-9)^2\\ &=129 \end{aligned}

单位是秒²。再开平方,得到标准差 129≈11.36\sqrt{129}\approx11.36 秒,单位就回到了秒。

期望描述平均位置,标准差描述波动大小。标准差不是每次偏差的上限,也不意味着每个结果都位于“期望加减一个标准差”之间。要判断某个范围内的概率,还需要知道分布的形状。

5. 认识几种经常出现的分布

不必把所有公式都背下来,先记住它们适合描述什么。

分布描述的问题一个例子
伯努利分布一次试验只有 0、1 两种结果一次任务是否故障
二项分布固定次数的独立伯努利试验中,1 出现多少次10 次独立任务中故障的次数
类别分布从有限个类别中选出一个选择 0、10、30 秒中的一种等待
均匀分布某个区间内,等长小区间有相同概率在 0 到 1 之间均匀抽取一个数
正态分布用钟形密度描述连续波动作为近似模型的测量误差

伯努利变量 ZZ 中,P(Z=1)=pP(Z=1)=p,P(Z=0)=1−pP(Z=0)=1-p,所以 E[Z]=p\mathbb E[Z]=p。如果做 nn 次独立、成功概率相同的试验,把结果相加,就得到二项变量 KK。

恰好有 kk 次成功的概率是:

P(K=k)=(nk)pk(1−p)n−k P(K=k)=\binom nk p^k(1-p)^{n-k}

(nk)\binom nk 是高中组合数,表示从 nn 个位置中挑出 kk 个成功位置的方法数。乘上它,是因为不同的成功排列都会贡献概率。二项变量的期望为 npnp,方差为 np(1−p)np(1-p)。

连续变量要看面积

对于均匀分布在 0 到 1 之间的变量,落在 0.2 到 0.5 之间的概率是区间长度 0.3。某一个精确实数点的概率则是 0;实际测量往往保留有限小数,对应的是一个小区间。

连续分布通常用概率密度画出来。区间下的面积才是落入该区间的概率,曲线某一点的高度不是概率。密度可以超过 1,只要整体面积仍为 1 就不矛盾。

正态分布常写作 T∼N(μ,σ2)T\sim\mathcal N(\mu,\sigma^2),意思是它服从均值为 μ\mu、方差为 σ2\sigma^2 的正态分布。σ>0\sigma>0 是标准差。它的密度公式是:

p(t)=12πσexp⁡ ⁣(−(t−μ)22σ2) p(t)=\frac{1}{\sqrt{2\pi}\sigma} \exp\!\left(-\frac{(t-\mu)^2}{2\sigma^2}\right)

exp⁡(z)\exp(z) 就是 eze^z,其中 e≈2.71828e\approx2.71828。现在不必推导这个式子,只需认出:μ\mu 决定曲线的中心,σ\sigma 决定展开的宽度。第五章还会用它解释平方误差从哪里来。

图 2:图中均值为 0、标准差为 1。着色面积约为 68.3%,这条比例来自正态分布,不能直接套到所有分布上。

正态分布是常用模型,不是“只要有噪声,就一定正态”。等待时间可能偏向一侧,错误记录可能有极端值,是否适合这种近似仍要检查。

6. 让电脑替我们重复试验

当某个计算很复杂时,可以从设定的分布反复采样,用样本平均等量近似我们关心的结果。这类方法通常称为蒙特卡洛方法。

下面从等待时间分布抽 10000 次,比较采样频率与设定概率:

图 3:电脑不是发现了新的等待规律,而是在我们给定的分布下做模拟。

脚本只使用 Python 标准库,Python 3.9 或更高版本即可运行:

python3 src/examples/probability.py

也可以下载脚本,执行 python3 probability.py。

"""第 3 章:教学设定的报警系统与离散等待时间分布。"""

from math import sqrt
from random import Random


WAIT_TIMES = [0, 10, 30]
PROBABILITIES = [0.5, 0.3, 0.2]


def posterior(prior=0.01, sensitivity=0.9, false_alarm=0.05):
    alarm = prior * sensitivity + (1 - prior) * false_alarm
    if alarm == 0:
        raise ValueError("报警事件概率为 0,不能以它为条件")
    return prior * sensitivity / alarm


def moments(values, probabilities):
    mean = sum(x * p for x, p in zip(values, probabilities))
    variance = sum(p * (x - mean) ** 2 for x, p in zip(values, probabilities))
    return mean, variance


def sample_waits(count, seed=2026):
    return Random(seed).choices(WAIT_TIMES, weights=PROBABILITIES, k=count)


def main():
    print(f"故障率 1% 时,报警后的故障概率:{posterior():.2%}")
    print(f"故障率 10% 时,报警后的故障概率:{posterior(0.1):.2%}")
    mean, variance = moments(WAIT_TIMES, PROBABILITIES)
    print(f"等待时间期望:{mean:.2f} 秒")
    print(f"方差:{variance:.2f} 秒²,标准差:{sqrt(variance):.2f} 秒")
    # 各样本量使用同一长序列的前缀,便于观察样本均值。
    samples = sample_waits(10000)
    for count in [10, 100, 10000]:
        print(f"{count} 次采样的平均等待:{sum(samples[:count]) / count:.3f} 秒")
    counts = [samples.count(value) for value in WAIT_TIMES]
    print("10000 次采样的各类频数:", counts)


if __name__ == "__main__":
    main()

本次运行得到:

故障率 1% 时,报警后的故障概率:15.38%
故障率 10% 时,报警后的故障概率:66.67%
等待时间期望:9.00 秒
方差:129.00 秒²,标准差:11.36 秒
10 次采样的平均等待:9.000 秒
100 次采样的平均等待:9.900 秒
10000 次采样的平均等待:8.720 秒
10000 次采样的各类频数: [5122, 2957, 1921]

Random(2026) 创建了固定种子的伪随机生成器,方便在相同环境中重复实验。种子不是“确保结果正确”的开关;换个种子,模拟结果会变化,设定的理论期望仍然是 9 秒。

这个输出还藏着一个好提醒:前 10 次的均值恰好等于 9,前 100 次反而偏离了。样本增多并不保证每一步都更接近期望。对于这里独立同分布、期望存在的采样,样本均值具有大数定律描述的长期趋近性质;一条有限轨迹仍会摇摆。

“独立同分布”简称 IID:各次抽样来自同一个分布,并且相互独立。真实日志里的任务顺序常有相关性,因此不能把模拟中的结论不加检查地照搬过去。

7. 自测与小实验

  1. 为什么 P(A∣J)=0.9P(A\mid J)=0.9 不能直接读成“报警后有 90% 的概率故障”?
  2. 保持故障率 1%、故障时报警率 90%,把正常时误报率降到 1%,报警后真的故障的概率是多少?
  3. 两次故障概率均为 0.1 且相互独立,两次都故障的概率是多少?如果不独立,还能直接相乘吗?
  4. 本章等待时间的期望为什么是 9 秒,而不是最常见的 0 秒?每次固定等 9 秒的系统,方差是多少?
  5. 独立重复 10 次、每次成功概率为 0.2,成功次数的期望与方差分别是多少?
  6. 连续密度曲线在某点的高度为 2,是否违反“概率不能超过 1”?
  7. 修改随机种子,多跑几次。100 次采样的均值是否每次都比 10 次更接近 9?10000 次是否必然恰好等于 9?
展开参考答案
  1. 条件反过来了。故障时是否报警,与报警中有多少来自故障,是两个不同的问题,还需要基础故障率和误报率。
  2. 0.009/(0.009+0.0099)≈47.62%0.009/(0.009+0.0099)\approx47.62\%。
  3. 为 0.12=0.010.1^2=0.01。不独立时,要用 P(J1)P(J2∣J1)P(J_1)P(J_2\mid J_1) 等方式计算,不能直接使用边缘概率的乘积。
  4. 期望按所有可能值的概率加权,30 秒的少数长等待也会贡献平均值。每次固定为 9 秒时没有波动,方差是 0。
  5. 期望为 10×0.2=210\times0.2=2,方差为 10×0.2×0.8=1.610\times0.2\times0.8=1.6。
  6. 不违反。密度是高度,概率对应面积。
  7. 都不保证。更多独立样本通常能降低估计的波动,但一次实现并不必然单调改善,也不必恰好等于理论值。

进阶选做:对每个样本量重复 100 次采样,画出 100 个样本均值的分布。你会比只盯着一条轨迹,更清楚地看到“样本量增加通常更稳”是什么意思。

下一章统计与实验中的不确定性会沿着这个问题继续走:从有限样本算出的平均值,到底有多可靠?不同实验的结果相差一点,能说明新方法更好吗?

希望系统补充概率基础,可以从 Harvard 的 Statistics 110课程入口寻找教材和视频。先挑条件概率、随机变量和期望的部分阅读即可。