📘 第6章 统计机器学习(概率分布和建模)
📄 一句话概括

概率分布就是把「不确定」写成函数:横轴是可能的结果,纵轴是它有多大概率。 一旦写成这个形状,剩下的问题就只剩一个:参数该取多少? 答案通常是极大似然:挑一个让「已经发生的事」最不意外的参数。抛一百次硬币出了六十三次正面, 那个参数就是 0.63。

📝 本节和前面几节的关系

第 5 章处理的全是「确定的数」:给一组点,求一条线;给一张图,找一条路。 这一章开始处理「不确定」:数据本身带着抖,答案也只能给一个范围。 这一节是整章的底座。6.2 的贝叶斯要在这个分布上加一个先验,6.3 的 MCMC 要在这个分布上抽样, 6.4 的 HMM 用这些分布当零件。先把「一个分布长什么样」这件事讲透,后面三节才有东西可加。

一、分布是什么:一张「结果对应概率」的表

抛十次硬币,正面次数可能是 0 到 10 里的任何一个。 「每个结果有多大概率」把这件事写出来,就是一个分布。 离散的和连续的要分开说。离散的结果可以一个个数出来(几次、几个、哪一类), 概率直接落在每个结果上; 连续的结果数不完(长度、时间、重量), 问「恰好等于 3.0000」的概率是 0,只能问「落在某个区间里」。

叫法 用在 回答什么
概率质量(PMF) 离散 正好等于 k 的概率
概率密度(PDF) 连续 落在某段区间里的概率(要对密度积分)
这个区别不是学术洁癖。下面会看到:把「密度」当成「概率」直接读,
会得出「密度大于 1 就是错」这种误会——密度可以大于 1,只要它积起来是 1。

二、三个最常用的分布,各自回答什么问题

分布有成百上千个,但日常九成的场合只用三个。分不清该用哪个,往往是因为没问清「我在数什么」。

分布 在数什么 两个参数 典型例子
二项 固定次里成功几次 次数 n、成功概率 p 十次射击中几次
泊松 一段时间里来几个 平均发生率 λ 一小时来几通电话
正态 一个连续量的取值 中心 μ、宽度 σ 测量误差、身高
头两行最容易混。二项有上限(最多 n 次),泊松没有上限——一小时来几通电话,
理论上可以是 100 通。Demo 里二项在 k=10 之后就没有了,泊松到 k=10 还有 0.0002 的概率。
正态那一行要单独说一句。它的三个口诀「68.3%、95.4%、99.7%」(一个、两个、
三个标准差)在 Demo 里是数值积分算出来的,不是查表抄的。
这两个数之所以能背,是因为它们跟具体问题无关——只要真是正态,换成米、换成秒都一样。

三、从数据里把参数挖出来:极大似然

分布的形状定了,就只剩参数。抛 100 次硬币出了 63 次正面,那个「正面概率 p」该取多少? 极大似然的想法很朴素: 挑一个 p,让「出现这组结果」的概率最大。出现这组结果的概率是 p 的 63 次方乘 (1−p) 的 37 次方, 扫一遍就知道峰在哪儿。

p 对数似然 说明
0.10 −148.96 太低,出不了这么多正面
0.46 −71.72 上坡中
0.63 −65.92 峰顶
0.73 −68.27 已经翻过去了
0.91 −95.04 太低,几乎不该出反面
峰正好在 0.63,也就是「正面次数除以总次数」。求导也能得到同一个答案:对数似然对 p 求导、
令其为零,解出来就是 63/100。
这不是巧合,是极大似然最常见的一个结论——
对这类「成/不成」的问题,最合理的估计就是样本里的比例。
为什么要取对数?因为概率是连乘的,连乘几十项就会下溢成 0;
取了对数变成连加,数值上稳得多,而且峰的位置一模一样(对数是单调的)。
所以实际代码里几乎从不直接算似然,都算对数似然。

四、为什么方差要除以 n−1

这件事在教科书里常被当成一个公式记住, 其实它是一次可以量出来的偏差。从一个方差为 4 的分布里抽 1000 个数,两种算法各算一遍, 重复 2000 次:

算法 两千次平均 相对真值
除以 n 3.9945 偏小
除以 n−1 3.9985 基本不偏
真值 4.0000 —
别盯着单列看,看两列之差:0.0040,正好等于「真值除以 n」。这个数不是估出来的,
是算出来的——配对相减之后,抽样的随机误差互相抵消了,剩下的就是这一份系统偏差。
为什么会有这个偏差?因为算方差之前,先用这批数据算出了均值。
而均值总会往数据中心靠,于是每个数到中心的距离都被压短了一点点。除以 n−1 就是在补这一下。
样本越小,补得越多:n=10 时差 10%,
n=1000 时只差 0.1%——这也是为什么大样本时这两个公式几乎没区别。

五、为什么正态分布到处都是

从一个根本不像正态的分布里抽样——指数分布(等车时间),大量小值、右边一条长尾巴。 每次抽 n 个求平均,重复 5000 次,看这个平均值有多宽:

每次抽几个 实测波动 理论 1/√n 比值
1 1.0041 1.0000 1.004
5 0.4528 0.4472 1.013
30 0.1801 0.1826 0.987
100 0.0989 0.1000 0.989
400 0.0503 0.0500 1.007
五行的比值都在 1 附近,说明「波动按 1/√n 缩小」是硬规律,跟原始分布无关。
更关键的是形状:抽 30 个求平均之后,这个平均值的分布已经很像正态了,哪怕原始数据是指数分布。
这就是中心极限定理。
它顺手解释了「误差为什么几乎总是正态的」。一个测量误差往往是很多小因素叠加的结果(手抖、温度、
读数、换算),叠加就是求和,求和就是平均,于是不管每个小因素长什么样,合起来都趋近正态。
1/√n 这个比例还有一个很实际的推论:想让精度翻倍,样本要翻四倍。
这是所有「多测几次取平均」的办法背后真正的那笔账——它比大多数人的直觉贵得多。

六、选分布就是选形状

最后一个问题:手里这批数据,到底该套哪个分布?答案不是「选更高级的」,而是「选形状对得上的」。 Demo 拿两组参数一样多的模型去套同一批右偏数据:

模型 参数个数 对数似然
正态 2 −1523.10
对数正态 2 −1293.82
参数一样多,对数似然差 229.28。差 1 就是 e 倍,
差 229 就是 e 的 229 次方倍——这个倍数大到没意义,只说明一件事:方向对了,差得很远。
对数正态赢在形状:它的对数才是正态,所以天生右偏、拖长尾,跟指数型的数据是一路的。
正态则是对称的,用对称的去套右偏的,两头都要吃亏:左边被拉出去,右边压不住。
顺便记一个陷阱:参数多的模型似然一定更高,这跟它准不准没关系。所以比较模型时要么固定参数个数,
要么用 AIC 这类带罚项的指标。Demo 里特意让两边都只有两个参数,就是为了绕开这个坑。

七、动手 Demo:三种分布,和「从数据里把参数挖出来」

前三段是「看形状」,后三段是「估参数」。三种分布的密度函数都手写了, 没有调任何库——二项要用组合数,泊松要用阶乘,正态的那个 √(2π) 也得自己写。 最值得自己重跑一遍的是第四段那个方差。它把「除以 n 偏小」从一个公式变成了一列能看的数, 而且差多少也能算准。

def binom_pmf(k, n, p):                 # 二项:n 次里正好 k 次
    return comb(n, k) * p ** k * (1 - p) ** (n - k)

def pois_pmf(k, lam):                   # 泊松:一段时间里正好 k 个
    return np.exp(-lam) * lam ** k / factorial(k)

def norm_pdf(x, mu, sd):                # 正态:连续,问区间概率
    return np.exp(-0.5 * ((x - mu) / sd) ** 2) / (sd * np.sqrt(2 * np.pi))

# 极大似然:扫一遍 p,挑让「已经发生的事」最不意外的那个
g = np.linspace(0.01, 0.99, 99)
ll = 63 * np.log(g) + 37 * np.log(1 - g)   # 100 次里 63 次正面
p_hat = g[ll.argmax()]                     # 0.63

# 方差的两个分母:配对相减,抽样误差会抵消,只剩系统偏差
for _ in range(2000):
    x = rg.normal(5.0, 2.0, 1000)
    v = ((x - x.mean()) ** 2).mean()
    e_n.append(v)                  # 除以 n,系统性偏小
    e_n1.append(v * 1000 / 999)    # 除以 n−1

# 中心极限定理:不管原始分布什么样,平均值都按 1/√n 收窄
for n in (1, 5, 30, 100, 400):
    s = rg.exponential(1.0, (5000, n)).mean(1)
    print(n, s.std(), 1 / np.sqrt(n))

实跑输出:

--------------------------------------------------------------------
三种分布,和「从数据里把参数挖出来」
--------------------------------------------------------------------
==============================================================

[1] 分布是用来回答「多大概率」的

  二项分布 B(10, 0.3):抛十次硬币(正面概率 0.3),正好 k 次正面的概率。

    k= 0  0.0282  ####
    k= 1  0.1211  ##################
    k= 2  0.2335  ###################################
    k= 3  0.2668  ########################################
    k= 4  0.2001  ##############################
    k= 5  0.1029  ###############
    k= 6  0.0368  ######
    k= 7  0.0090  #
    k= 8  0.0014  
    k= 9  0.0001  
    k=10  0.0000  

  泊松分布 P(2.5):一段时间里平均来 2.5 个事件,正好来 k 个的概率。

    k= 0  0.0821  #############
    k= 1  0.2052  ################################
    k= 2  0.2565  ########################################
    k= 3  0.2138  #################################
    k= 4  0.1336  #####################
    k= 5  0.0668  ##########
    k= 6  0.0278  ####
    k= 7  0.0099  ##
    k= 8  0.0031  
    k= 9  0.0009  
    k=10  0.0002  

  两种形状都是「中间高、两头低」,但**二项有上限(最多十次),泊松没有**。
  这个差别不是细节:**二项数的是「几次里成功几次」,泊松数的是「一段时间里来几个」。**

  正态分布 N(0, 1) 是连续的那一类,问的是「落在某个区间里的概率」。
  三个区间实测一遍(数值积分,不查表):

    区间            实算概率      常说的数
    --------------------------------------------------
    ±1 个标准差     0.6827        68.3%
    ±2 个标准差     0.9545        95.4%
    ±3 个标准差     0.9973        99.7%

  **这三个数之所以能背,是因为它们跟具体问题无关**——只要真是正态,换什么单位都成立。

[2] 一百次抛硬币,正面概率到底是多少

  真实情况:抛 100 次,63 次正面。**问题是:那个「正面概率 p」该取多少?**
  极大似然的做法是:**找一个 p,使得「出现这组结果」的概率最大。**

  出现这组结果的概率是 p 的 63 次方乘 (1−p) 的 37 次方。扫一遍看:

    p       对数似然      形状
    ----------------------------------------------------
    0.01    -290.498      
    0.10    -148.961      ··················
    0.19    -112.423      ······················
    0.28    -92.351       ·························
    0.37    -79.733       ··························
    0.46    -71.720       ···························
    0.55    -67.209       ····························
    0.64    -65.917       ····························
    0.73    -68.272       ····························
    0.82    -75.950       ···························
    0.91    -95.036       ························

  最高点在 p = 0.63。**为什么正好是 0.63?**它本来就是「正面次数除以总次数」。
  求导也能得到同一个答案:对数似然对 p 求导、令其为零,解出 p = 63/100。
  **这就是极大似然估计:挑一个让「已经发生的事」最不意外的参数。**

[3] 方差的那个分母:n 还是 n−1

  真值:从 N(5, 2) 里抽样,总体方差是 4。抽 1000 个,两种算法各算一遍,
  重复 2000 次,看它们平均下来偏不偏:

    算法              两千次平均      真值      偏差
    ----------------------------------------------------------
    除以 n            3.9945          4.0000    -0.0055
    除以 n−1          3.9985          4.0000    -0.0015

  **两列之差 0.0040,正好等于「真值除以 n」,也就是 4/1000 = 0.004。**
  配对相减之后,抽样的随机误差被抵消掉了,剩下的就是这一份系统偏差。
  原因很朴素:**算方差之前先用这批数据算出了均值,**
  **而均值会往数据中心靠,于是每个数到中心的距离都被压短了一点点。**
  除以 n−1 就是在补这一下。**样本越小,补得越多**——n=10 时差 10%,n=1000 时差 0.1%。

[4] 拿泊松去套一批真的计数数据

  模拟 800 天,每天来的事件数服从泊松(每天平均 2.5 个)。
  然后只拿这批数去估参数、算理论频数,看套不套得上:

    从数据估出来的 λ = 2.5000(真值 2.5)

    来了几个  实际天数    理论天数    差
    ----------------------------------------------
    0         66          65.7        +0.3
    1         169         164.2       +4.8
    2         190         205.2       -15.2
    3         171         171.0       -0.0
    4         120         106.9       +13.1
    5         57          53.4        +3.6
    6         19          22.3        -3.3
    7         6           8.0         -2.0
    8         1           2.5         -1.5

  每一档都对得上,差值最大也就十几——**这就是「这个模型能描述这批数据」的样子。**
  **注意这里做的是两件事:先估参数,再看形状。**估参数只看一个数(均值),看形状要看一整列。

[5] 为什么正态分布到处都是

  从一个根本不像正态的分布里抽样:指数分布(等车时间),大量小值、长尾巴。
  每次抽 n 个求平均,重复 5000 次,看**平均值**的分布有多宽:

    每次抽几个 n    平均值实际波动    理论 1/√n     比值
    ----------------------------------------------------------
    1               1.0041            1.0000        1.004
    5               0.4528            0.4472        1.013
    30              0.1801            0.1826        0.987
    100             0.0989            0.1000        0.989
    400             0.0503            0.0500        1.007

  单抽一个(n=1)实测波动 1.0041,抽 400 个求平均只剩 0.0503——**基本按 1/√n 缩小。**
  更关键的是形状:**抽 30 个求平均之后,这个平均值的分布已经很正态了,**
  **哪怕原始数据是指数分布。**
  这就是中心极限定理。**它解释了为什么「误差」几乎总是正态的**:
  一个测量误差往往是很多小因素叠加的结果,**叠加就是求和,求和就是平均。**

[6] 模型好不好,用什么尺子量

  两个模型套同一批数据,比较它们的对数似然。
  但有个陷阱:**参数多的模型似然一定更高,这跟它准不准没关系。**

    这批数据是指数分布右移一位:大量小值挤在左边,右边拖一条长尾。

    用正态拟合:μ = 3.938,σ = 3.064,对数似然 -1523.10,参数 2 个
    用对数正态拟合:对数似然 -1293.82,参数还是 2 个

  **参数一样多,对数似然差 229.28。**差 1 就是 e 倍,差 229 就是 e 的 229 次方倍——
  这个倍数大到没意义,只说明一件事:方向对了,差得很远。
  对数正态赢了,因为**它的形状本来就是对的方向**:右偏、长尾。
  **这就是选分布的全部道理:不是选「更高级的」,是选「形状对得上的」。**

第一段的柱状图有个细节要看:二项到 k=10 就是最后一格,泊松到 k=10 还没完。 这就是「有上限」和「没上限」的差别。 实际建模时选错了这一点,后果很直接:用泊松去拟合「十次射击中几次」这种有天花板的数据, 会算出「命中 11 次」的概率大于 0。 第三段那张对数似然的曲线,最该记的是它的宽度。峰在 0.63, 但 0.55 和 0.73 只差几个单位—— 这说明「63 次正面」对 p 的约束并不紧。换成 630 次正面(同样的比例),这条曲线会窄得多。 样本量决定的是这条曲线的陡峭程度,不是峰的位置。 第四段那两列如果分开看,都会觉得「差不多」。3.9945 和 3.9985,差 0.004,看着像噪声。 但配对相减之后 0.0040 稳稳地待在同一个数上——这正是「系统偏差」和「随机误差」的区别: 随机的会抵消,系统的不会。这个判据在别处也用得上: 重复实验一百次,偏差还在,那就不是运气问题。 第六段的结论比数字重要。两台模型参数一样多、数据一样,对数似然差 229, 这不是「一个稍微好一点」,是「一个根本不对」。所以真实工作里的顺序永远是: 先看形状(画图),再估参数,最后才比指标。反过来做, 很容易在一堆都不合适的模型里挑出一个「最好的」。

30 秒实验

  1. 把第三段的 63 改成 630、总次数改成 1000,重跑。 峰还在 0.63,但曲线陡得多——同样比例、十倍样本,对 p 的约束紧了一大截。 这就是「样本量买的是精度」。
  2. 把第五段的 exponential 换成 rg.random(n)(均匀分布,0 到 1),重跑。 1/√n 那一列还是对得上——中心极限定理不挑原始分布,这是它的全部威力所在。
  3. 把第六段的右偏数据换成一批正态数据(rg.normal(0, 1, 600)),重跑。 这回正态赢,对数正态会因为「不能取负数」而吃亏。 这说明选分布没有通用答案,只有「跟数据配不配」。

常见误区

  1. 以为「概率密度」就是「概率」。密度可以大于 1(比如 N(0, 0.1) 在 0 处的密度约 4.0), 因为它不是概率,是「单位长度上的概率」。要得到概率必须积分。 把密度直接当概率读,就会得出「密度 4.0,概率 400%」这种荒谬结论。
  2. 以为正态分布是「默认选项」。它只是因为中心极限定理在「求和」的场合特别好使。 涉及「等待时间」「金额」「人口」这类右偏的量,正态往往很糟—— Demo 第六段那个 229 的差距就是代价。
  3. 以为除以 n 才是「定义」,n−1 是个修正。两个都有人用: 除以 n 是「这批数据的方差」,除以 n−1 是「对总体方差的无偏估计」。问法不同,答案不同。 写代码时想清楚「我要描述这批数,还是要估计那个总体」。
  4. 以为极大似然一定最好。它只保证「让已观测的数据最不意外」, 不保证接近真值。样本小的时候它很容易给出极端答案(全是正面就给 1.0), 这正是下一节贝叶斯要修的地方。
自测三问(点开对答案) 1. 为什么二项分布和泊松分布长得像,却不能混用? —— 因为**二项有上限,泊松没有**。二项数的是「固定 n 次里成功几次」,成功次数不可能超过 n; **泊松数的是「一段时间里来几个」,理论上没有天花板。**当 n 很大、p 很小时, 两者数值上会非常接近(泊松本来就是二项的极限), **但「有没有上限」这件事在建模时是硬约束,不能含糊。** 2. 为什么方差公式要除以 n−1 而不是 n? —— 因为**算方差之前先用同一批数据算了均值**。 均值会往数据中心靠,**于是每个数到中心的距离都被系统性压短了一点**,除出来的方差就偏小。 Demo 里量出来这个偏差正好是「真值除以 n」(4/1000 = 0.004)。 **除以 n−1 就是把这一点补回来**——样本越小,补得越多。 3. 中心极限定理说的到底是哪件事? —— 说的是:**不管原始分布长什么样,只要各个样本独立、方差有限,样本均值就会趋近正态,** **波动按 1/√n 缩小。**注意它讲的是「均值」的分布, **不是原始数据的分布**——原始数据可以是指数分布、均匀分布、甚至双峰,均值照样趋近正态。 **这是「正态到处都是」的唯一原因,也是「多测几次取平均」的理论依据。**

这一节一直默认「参数是固定的,只是我们不知道」。 下一节换一个立场:参数本身也有分布。这个小小的转向,带出了先验、后验、收缩, 还有一个能真干活的分类器。

相关笔记