查看全课大纲(第 55 / 82 节)
  1. 1.函数与数据泛化
  2. 2.向量:从几何直觉到高维空间
  3. 3.矩阵与张量
  4. 4.特征值与特征向量:矩阵变换的不动方向
  5. 5.凸函数:从向量求导的矩阵记号到好优化的函数形状
  6. 6.概率与统计:机器学习的数学基础
  7. 7.独立性与随机变量:贝叶斯公式与二项分布
  8. 8.期望、方差与协方差:随机变量的数字画像
  9. 9.联合概率:当一条轴不够用的时候
  10. 10.概率分布(一):从伯努利到伽马函数
  11. 11.概率分布(二):贝塔、泊松、正态与两个贝叶斯故事
  12. 12.机器学习的模型:找输入与输出的关系
  13. 13.机器学习的应用
  14. 14.过拟合
  15. 15.机器学习的分类
  16. 16.有监督学习:从房价预测说起
  17. 17.损失函数
  18. 18.梯度下降(上):更新规则与学习速率
  19. 19.梯度下降(2)
  20. 20.牛顿方法
  21. 21.KNN简介
  22. 22.距离测算
  23. 23.朴素贝叶斯
  24. 24.朴素贝叶斯的实际应用
  25. 25.信息熵:决策树构建的度量基础
  26. 26.信息增益与决策树的构建
  27. 27.ID3算法
  28. 28.决策树节点的划分
  29. 29.CART树
  30. 30.Bagging
  31. 31.Boosting:自适应提升算法
  32. 32.Gradient Boosting
  33. 33.线性模型:回归与分类的同一副骨架
  34. 34.最小二乘:把最优参数直接解出来
  35. 35.最小二乘法的几何与概率视角
  36. 36.极大似然:给最小二乘一个概率出身
  37. 37.逻辑回归(1):把线性模型接到分类上
  38. 38.逻辑回归(2):损失函数与多分类
  39. 39.---- 手造数据: 5 个样本, 2 个特征; x2 几乎 = 2*x1 (偏差手工指定, 无随机) ----
  40. 40.讲师例: 向量 "23014" -- 三把范数尺子量同一个向量
  41. 41.优化方法(1):坐标下降与前向选择
  42. 42.优化方法(2):前向策略与最小角回归
  43. 43.拉格朗日乘子法(1):从无约束到等式约束
  44. 44.拉格朗日乘子法(2):等式约束下的平行条件与拉格朗日函数
  45. 45.拉格朗日乘子法(3):不等式约束与 KKT 条件
  46. 46.最大间隔:把分类问题变成优化问题
  47. 47.拉格朗日对偶问题:把 w 和 b 全部换成 α
  48. 48.支持向量:边界上的少数派
  49. 49.SVM 计算过程:一笔到底算完,再走进核方法
  50. 50.贝叶斯公式:概率即信念
  51. 51.隐含变量和概率模型:给看不见的原因建模
  52. 52.EM 算法:期望与最大化的迭代
  53. 53.琴生不等式:EM 的数学钥匙
  54. 54.三个硬币问题:EM 的复盘与衔接
  55. 55.高斯混合模型:用隐变量解释双峰数据
  56. 56.隐马尔可夫模型
  57. 57.隐马尔可夫模型(2):前向算法与动态混合模型
  58. 58.隐马尔可夫模型在 NLP 中的运用
  59. 59.EM 算法:把「为什么收敛」推到底
  60. 60.HMM 在 NLP 中的运用:从分词到机器翻译
  61. 61.HMM 参数估计:Baum-Welch 的三块拉格朗日
  62. 62.高维下的高斯模型
  63. 63.主题模型:从词袋到隐含主题
  64. 64.Dirichlet 分布(1)
  65. 65.Dirichlet 分布(2)
  66. 66.统计学习内容回顾
  67. 67.K-means 算法
  68. 68.PCA 降维
  69. 69.SVD 降维
  70. 70.从聚类到流形
  71. 71.局部线性嵌入
  72. 72.随机邻域嵌入:SNE 与 t-SNE
  73. 73.无参模型:让数据自己说话
  74. 74.高斯过程:函数空间里的正态分布
  75. 75.高斯过程(2):噪声、正则化与核的线性组合
  76. 76.神经网络简介:从感知器到自编码器
  77. 77.反向传播:把误差一层层传回去
  78. 78.卷积神经网络(CNN):让特征自己学出来
  79. 79.循环神经网络(RNN):给网络装上记忆
  80. 80.深度学习回顾:静态一类,动态一类
  81. 81.增强学习(1):蒙特卡洛、树搜索与 Q-learning
  82. 82.强化学习(2):从乌鸦吃核桃到井字棋的 value 回传

高斯混合模型:用隐变量解释双峰数据

约 23 分钟

📺 正在播放小象官方高清录播(支持倍速与清晰度调节)

小象实战讲义 · 机器学习算法精讲

上一节的三硬币问题里,概率为 pp 和 qq 的两个伯努利分布,被权重 π\pi 和 1−π1-\pi “混合”到了一起——本质上那是一个混合伯努利模型。本节把混合的”配料”从伯努利换成高斯,就得到机器学习里最常用的概率模型之一:高斯混合模型(Gaussian Mixture Model,GMM)。学完本节,你能用它解释”全班身高”这类双峰数据,并用 EM 算法亲手把参数拟合出来。

💡 核心导读

  • 三硬币是”混合伯努利模型”;把伯努利换成高斯,就是高斯混合模型 GMM
  • GMM 的本质:几个高斯分布按权重叠加,能描述单个高斯搞不定的多峰数据
  • 隐变量 zz 标记”每个样本来自哪个高斯”——整个推导与三硬币完全同构
  • E 步算”责任”(样本属于各成分的后验概率),M 步用责任加权更新全部参数
  • 成分个数可以从 2 推广到 KK:有隐变量的混合模型,拟合套路完全一致

一、为什么需要混合模型:单峰解释不了的双峰

先回忆三硬币的骨架:观察到的序列由硬币 B、C 两个伯努利分布”混合”生成,谁占多少由 π\pi 决定。既然配料可以是伯努利,自然也可以换成别的分布。

来看两个身边的例子。全校同学的眼镜度数大致服从一个单峰的正态分布:大多数人集中在 450 度上下,100 度和 1000 度的人都很少——一个高斯就能描述。但把全班同学的身高记录下来画成直方图,形状就变了:它看起来仍然像”钟形”,却有两个峰,一个在 164 左右,一个在 174 左右——恰好对应这个年龄段女生与男生的平均身高。

原因很直白:女生身高是一个高斯,男生身高是另一个高斯,两群人混在一个教室里,直方图就成了两个高斯的叠加。而且这两群人之间有很大的重叠带(overlap)——一个身高 1 米 72 的人,可能是女生,更可能是男生。像这样”两个高斯的混合”,就是最简单的 GMM;单个人群内部的”配料”还可以继续换成别的分布,混合模型是一整个家族。

二、GMM 的数学形式:5 个参数的混合分布

单个高斯由均值 μ\mu 和方差 σ2\sigma^2 决定;两个高斯混合,还要再加一个权重。写成公式:

P(x)=π N(x∣μ1,σ12)+(1−π) N(x∣μ2,σ22)P(x) = \pi\,\mathcal{N}(x \mid \mu_1, \sigma_1^2) + (1-\pi)\,\mathcal{N}(x \mid \mu_2, \sigma_2^2)

其中 N\mathcal{N} 是正态分布的密度函数:

N(x∣μ,σ2)=12πσ2exp⁡(−(x−μ)22σ2)\mathcal{N}(x \mid \mu, \sigma^2) = \frac{1}{\sqrt{2\pi\sigma^2}} \exp\left(-\frac{(x-\mu)^2}{2\sigma^2}\right)

所以一个两成分 GMM 共有 5 个参数:θ=(π, μ1, μ2, σ12, σ22)\theta = (\pi,\ \mu_1,\ \mu_2,\ \sigma_1^2,\ \sigma_2^2)。对比三硬币的 3 个参数 (π,p,q)(\pi, p, q)——三硬币最多还能在三维空间里穷举搜索,这里就得到五维空间去穷搜,代价陡增;这也是我们必须借助 EM 这类迭代算法的现成理由。

先把”全班身高”的数据造出来(真实场景里就是量出来的,这里为了可复现,用 Box-Muller 变换手工生成正态样本,全程只用标准库):

# GMM 演示 · 块1:构造"男女生身高"双峰数据 + 正态密度函数(自包含可运行)
import math
import random

random.seed(42)

def randn(mu, sigma):
    """Box-Muller 变换:从均匀随机数生成正态样本(不依赖第三方库)"""
    u1 = random.random() or 1e-12
    u2 = random.random()
    return mu + sigma * math.sqrt(-2.0 * math.log(u1)) * math.cos(2.0 * math.pi * u2)

girls = [randn(160.0, 5.0) for _ in range(30)]
boys = [randn(175.0, 7.0) for _ in range(30)]
data = girls + boys
random.shuffle(data)

def norm_pdf(x, mu, sigma2):
    """正态分布密度 N(mu, sigma2)"""
    return math.exp(-((x - mu) ** 2) / (2 * sigma2)) / math.sqrt(2 * math.pi * sigma2)

print(f"女生样本均值 = {sum(girls) / 30:.2f}(构造真值 160)")
print(f"男生样本均值 = {sum(boys) / 30:.2f}(构造真值 175)")
print(f"全班均值 = {sum(data) / 60:.2f}(落在双峰之间的谷底附近——单高斯无法描述双峰)")

运行输出:

女生样本均值 = 159.94(构造真值 160)
男生样本均值 = 174.51(构造真值 175)
全班均值 = 167.23(落在双峰之间的谷底附近——单高斯无法描述双峰)

注意最后一行:如果无视混合结构、直接对全班算均值,得到的是 167.23 这个”谷底值”——它既不代表女生也不代表男生。混合模型要解决的,就是从这个谷底里把两个真实的峰恢复出来。

三、隐变量视角:与三硬币完全同构

给定数据 x1,…,xNx_1, \ldots, x_N,我们想求极大似然估计:

θ^=arg⁡max⁡θ∑j=1Nlog⁡P(xj∣θ)\hat{\theta} = \arg\max_\theta \sum_{j=1}^{N} \log P(x_j \mid \theta)

关键一步与三硬币一模一样:引入隐变量 zz,它只取 0 与 1 两个值,标记每个样本到底来自哪个高斯(哪个值只是标识,0/1 对调不影响任何结论)。于是:

P(x∣θ)=∑zP(x∣z,θ) P(z∣θ)P(x \mid \theta) = \sum_{z} P(x \mid z, \theta)\, P(z \mid \theta)

把两种取值展开:z=0z=0 时样本服从第一个高斯、先验概率为 π\pi;z=1z=1 时服从第二个高斯、先验为 1−π1-\pi。代进去,正好回到第二节的混合公式——GMM 就是三硬币把”伯努利”换成”高斯”后的版本,推导没有一个字需要重写。

换一个角度理解这个模型的”生成过程”:先按 π\pi 与 1−π1-\pi 抽一次成分——直观地说,π\pi 就是女生占全班的比例;选中成分后,再在该高斯的概率密度附近采出一个具体数值。重复 NN 次,就得到我们观察到的身高数据。这就是生成模型(generative model)的视角:先假设数据由某个过程生成,再由观察到的数据反推过程参数。它和”给你一堆数据、估计均匀分布的区间端点”是同一类问题——GMM 只是过程复杂一些,要先选成分、再按密度采样。二维情形完全同理:先按权重选一个二维高斯”山包”,再在山包上采点。

四、EM 拟合 GMM:E 步算责任,M 步更新参数

框架还是 EM。E 步要用当前参数算”责任”(responsibility;讲师板书记作 wjw_j)——即给定观测 xjx_j,它来自第一个高斯的后验概率:

γj=π N(xj∣μ1,σ12)π N(xj∣μ1,σ12)+(1−π) N(xj∣μ2,σ22)\gamma_j = \frac{\pi\,\mathcal{N}(x_j \mid \mu_1, \sigma_1^2)}{\pi\,\mathcal{N}(x_j \mid \mu_1, \sigma_1^2) + (1-\pi)\,\mathcal{N}(x_j \mid \mu_2, \sigma_2^2)}

M 步则用责任加权,闭式地重新估计全部参数:

π=1N∑j=1Nγj,μ1=∑jγjxj∑jγj,σ12=∑jγj(xj−μ1)2∑jγj\pi = \frac{1}{N}\sum_{j=1}^{N}\gamma_j, \qquad \mu_1 = \frac{\sum_j \gamma_j x_j}{\sum_j \gamma_j}, \qquad \sigma_1^2 = \frac{\sum_j \gamma_j (x_j - \mu_1)^2}{\sum_j \gamma_j}

μ2\mu_2、σ22\sigma_2^2 同理,把 γj\gamma_j 换成 1−γj1-\gamma_j 即可。把这些公式原样落成纯 Python(与块 1 相同的确定性数据构造,保证结果可复现):

# GMM 演示 · 块2:EM 拟合两成分 GMM(自包含可运行;数据构造与块1完全一致)
import math
import random

random.seed(42)

def randn(mu, sigma):
    u1 = random.random() or 1e-12
    u2 = random.random()
    return mu + sigma * math.sqrt(-2.0 * math.log(u1)) * math.cos(2.0 * math.pi * u2)

girls = [randn(160.0, 5.0) for _ in range(30)]
boys = [randn(175.0, 7.0) for _ in range(30)]
data = girls + boys
random.shuffle(data)

def norm_pdf(x, mu, sigma2):
    return math.exp(-((x - mu) ** 2) / (2 * sigma2)) / math.sqrt(2 * math.pi * sigma2)

# 固定初始值(保证结果可复现):均值取两端、方差取 20、权重对半
pi = 0.5
mu1, mu2 = min(data), max(data)
s1 = s2 = 20.0

for it in range(1, 9):
    # ---- E 步:算每个样本属于成分 1 的责任 gamma ----
    gam = []
    ll = 0.0
    for x in data:
        p1 = pi * norm_pdf(x, mu1, s1)
        p2 = (1 - pi) * norm_pdf(x, mu2, s2)
        tot = p1 + p2
        ll += math.log(tot)
        gam.append(p1 / tot)
    # ---- M 步:用责任加权更新全部参数 ----
    n1 = sum(gam)
    n2 = len(data) - n1
    mu1 = sum(g * x for g, x in zip(gam, data)) / n1
    mu2 = sum((1 - g) * x for g, x in zip(gam, data)) / n2
    s1 = sum(g * (x - mu1) ** 2 for g, x in zip(gam, data)) / n1
    s2 = sum((1 - g) * (x - mu2) ** 2 for g, x in zip(gam, data)) / n2
    pi = n1 / len(data)
    print(f"第 {it} 轮:logL = {ll:9.2f} | pi = {pi:.3f} | mu1 = {mu1:6.2f}, sigma1^2 = {s1:6.2f} | mu2 = {mu2:6.2f}, sigma2^2 = {s2:6.2f}")

# 软归属统计:责任 > 0.5 视为成分 1
belong1 = sum(1 for g in gam if g > 0.5)
print(f"\n按 gamma>0.5 归属:成分1 有 {belong1} 人,成分2 有 {len(data) - belong1} 人(真实:各 30 人)")

运行输出:

第 1 轮:logL =   -404.01 | pi = 0.621 | mu1 = 161.23, sigma1^2 =  24.84 | mu2 = 177.07, sigma2^2 =  25.92
第 2 轮:logL =   -216.65 | pi = 0.606 | mu1 = 161.21, sigma1^2 =  27.00 | mu2 = 176.49, sigma2^2 =  31.01
第 3 轮:logL =   -215.98 | pi = 0.594 | mu1 = 161.13, sigma1^2 =  27.32 | mu2 = 176.14, sigma2^2 =  33.78
第 4 轮:logL =   -215.78 | pi = 0.583 | mu1 = 161.03, sigma1^2 =  27.00 | mu2 = 175.90, sigma2^2 =  35.55
第 5 轮:logL =   -215.67 | pi = 0.573 | mu1 = 160.92, sigma1^2 =  26.39 | mu2 = 175.70, sigma2^2 =  36.80
第 6 轮:logL =   -215.57 | pi = 0.563 | mu1 = 160.80, sigma1^2 =  25.66 | mu2 = 175.52, sigma2^2 =  37.76
第 7 轮:logL =   -215.49 | pi = 0.554 | mu1 = 160.68, sigma1^2 =  24.88 | mu2 = 175.36, sigma2^2 =  38.58
第 8 轮:logL =   -215.41 | pi = 0.545 | mu1 = 160.56, sigma1^2 =  24.11 | mu2 = 175.22, sigma2^2 =  39.31

按 gamma>0.5 归属:成分1 有 34 人,成分2 有 26 人(真实:各 30 人)

三个观察:

  1. 对数似然单调上升(−404→−215.4-404 \to -215.4)——这正是上一章 EM 的收敛性保证在 GMM 上的体现。
  2. 两个均值收敛到 160.56 与 175.22,紧贴构造真值 160/175——EM 确实从谷底均值 167.23 里把两个峰恢复了出来。
  3. 软归属是 34/26,不是 30/30。这不是拟合失败:重叠带里的样本本就”两可”,GMM 输出的是概率归属(责任 γ\gamma),落在重叠带的样本 γ\gamma 接近 0.5,硬以 0.5 切一刀必有少数样本划到另一侧。软分配,恰是混合模型与硬聚类的本质区别。

五、从 2 到 K:更一般的混合模型

两个成分之外,再举一个例子:把一所特大学校的小学生、初中生、高中生放在一起测跳远成绩,成绩分布就会呈现三个峰——三个高斯的混合。此时隐变量 zz 取 0、1、2 三个值,模型变成:

P(x)=π1N(x∣μ1,σ12)+π2N(x∣μ2,σ22)+(1−π1−π2) N(x∣μ3,σ32)P(x) = \pi_1 \mathcal{N}(x \mid \mu_1, \sigma_1^2) + \pi_2 \mathcal{N}(x \mid \mu_2, \sigma_2^2) + (1-\pi_1-\pi_2)\,\mathcal{N}(x \mid \mu_3, \sigma_3^2)

参数从 5 个涨到 8 个(三个均值、三个方差、两个自由权重——π1+π2+π3=1\pi_1+\pi_2+\pi_3=1 的约束省掉一个),穷举搜索要进八维空间,更加不现实;而 EM 的 E 步/M 步公式只需把”两个成分”推广成”求和号下 KK 项”,套路原封不动。三硬币是伯努利混合、本节是高斯混合——任何”观测由隐变量选择成分、成分再生成数据”的混合模型,都按同一套 EM 流程拟合。

📝 动手练一练

练习 1(概念辨析):假如每个身高样本都带着性别标签,我们还需要 EM 吗?没有标签时,为什么不能直接套”均值 = 总和除以个数”这类公式?

👉 点击查看参考答案

不需要。有标签相当于三硬币里”每个结果都染了色”:按性别分成两组,各组直接统计均值、方差,权重就是男女比例,一步到位。没有标签时,每个样本的归属本身是未知的——若无视结构硬算,得到的是 167.23 这种落在谷底的”全班均值”,谁也不代表;EM 的作用正是用责任 γ\gamma 给每个样本软分配归属,再迭代逼近”如果知道标签会得到的”那组参数。

练习 2(动手改代码):把块 2 的初始值改成 μ1=μ2=\mu_1 = \mu_2 = 全班平均身高(方差也取全班方差),再跑一遍,观察会发生什么。

👉 点击查看参考答案

实测:两个成分初值完全相同时,每轮算出的责任恒为 0.5,参数纹丝不动——logL 五轮全部停在 −218.16-218.16,μ1=μ2=167.23\mu_1 = \mu_2 = 167.23,EM 卡死在对称不动点上(对比正常初值能收敛到 −215.41-215.41)。这说明 EM 的结果依赖初始化:实践中要么把初始均值分得足够开(比如本例取最小值/最大值),要么多次随机重启取似然最高的一组。

本章小结

  • GMM 是 KK 个高斯按权重叠加的混合分布;两成分时有 5 个参数 (π,μ1,μ2,σ12,σ22)(\pi, \mu_1, \mu_2, \sigma_1^2, \sigma_2^2)。
  • 隐变量 zz 标记样本来自哪个成分;GMM 与三硬币(混合伯努利)的推导完全同构。
  • 生成视角两步走:先按权重选成分(π\pi ≈ 人群比例),再在选定高斯内按密度采样。
  • E 步算责任 γj\gamma_j(样本归属的后验概率),M 步用责任加权闭式更新 π\pi、μ\mu、σ2\sigma^2。
  • 对数似然每轮不减(EM 收敛性);但初值不当可能卡在对称不动点,实践中用分开的初值或随机重启。
  • 推广到 KK 个成分:参数变多、公式结构不变——隐变量混合模型的拟合套路是通用的。

📋 行动清单

  • 把块 2 改造成三成分 GMM(跳远成绩:小学生/初中生/高中生),对照第五节公式扩展 E 步与 M 步
  • 打印每一轮重叠带样本的责任 γ\gamma,确认它们接近 0.5 而非 0/1
  • 对照上一节三硬币的 E/M 步公式,逐项写出两套公式的同构对应关系

—— 小象教研组

配套资料 · 直接下载

课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。

  • 第13章笔记:期望最大化(EM)算法
    下载