查看全课大纲(第 55 / 82 节)
- 1.函数与数据泛化
- 2.向量:从几何直觉到高维空间
- 3.矩阵与张量
- 4.特征值与特征向量:矩阵变换的不动方向
- 5.凸函数:从向量求导的矩阵记号到好优化的函数形状
- 6.概率与统计:机器学习的数学基础
- 7.独立性与随机变量:贝叶斯公式与二项分布
- 8.期望、方差与协方差:随机变量的数字画像
- 9.联合概率:当一条轴不够用的时候
- 10.概率分布(一):从伯努利到伽马函数
- 11.概率分布(二):贝塔、泊松、正态与两个贝叶斯故事
- 12.机器学习的模型:找输入与输出的关系
- 13.机器学习的应用
- 14.过拟合
- 15.机器学习的分类
- 16.有监督学习:从房价预测说起
- 17.损失函数
- 18.梯度下降(上):更新规则与学习速率
- 19.梯度下降(2)
- 20.牛顿方法
- 21.KNN简介
- 22.距离测算
- 23.朴素贝叶斯
- 24.朴素贝叶斯的实际应用
- 25.信息熵:决策树构建的度量基础
- 26.信息增益与决策树的构建
- 27.ID3算法
- 28.决策树节点的划分
- 29.CART树
- 30.Bagging
- 31.Boosting:自适应提升算法
- 32.Gradient Boosting
- 33.线性模型:回归与分类的同一副骨架
- 34.最小二乘:把最优参数直接解出来
- 35.最小二乘法的几何与概率视角
- 36.极大似然:给最小二乘一个概率出身
- 37.逻辑回归(1):把线性模型接到分类上
- 38.逻辑回归(2):损失函数与多分类
- 39.---- 手造数据: 5 个样本, 2 个特征; x2 几乎 = 2*x1 (偏差手工指定, 无随机) ----
- 40.讲师例: 向量 "23014" -- 三把范数尺子量同一个向量
- 41.优化方法(1):坐标下降与前向选择
- 42.优化方法(2):前向策略与最小角回归
- 43.拉格朗日乘子法(1):从无约束到等式约束
- 44.拉格朗日乘子法(2):等式约束下的平行条件与拉格朗日函数
- 45.拉格朗日乘子法(3):不等式约束与 KKT 条件
- 46.最大间隔:把分类问题变成优化问题
- 47.拉格朗日对偶问题:把 w 和 b 全部换成 α
- 48.支持向量:边界上的少数派
- 49.SVM 计算过程:一笔到底算完,再走进核方法
- 50.贝叶斯公式:概率即信念
- 51.隐含变量和概率模型:给看不见的原因建模
- 52.EM 算法:期望与最大化的迭代
- 53.琴生不等式:EM 的数学钥匙
- 54.三个硬币问题:EM 的复盘与衔接
- 55.高斯混合模型:用隐变量解释双峰数据
- 56.隐马尔可夫模型
- 57.隐马尔可夫模型(2):前向算法与动态混合模型
- 58.隐马尔可夫模型在 NLP 中的运用
- 59.EM 算法:把「为什么收敛」推到底
- 60.HMM 在 NLP 中的运用:从分词到机器翻译
- 61.HMM 参数估计:Baum-Welch 的三块拉格朗日
- 62.高维下的高斯模型
- 63.主题模型:从词袋到隐含主题
- 64.Dirichlet 分布(1)
- 65.Dirichlet 分布(2)
- 66.统计学习内容回顾
- 67.K-means 算法
- 68.PCA 降维
- 69.SVD 降维
- 70.从聚类到流形
- 71.局部线性嵌入
- 72.随机邻域嵌入:SNE 与 t-SNE
- 73.无参模型:让数据自己说话
- 74.高斯过程:函数空间里的正态分布
- 75.高斯过程(2):噪声、正则化与核的线性组合
- 76.神经网络简介:从感知器到自编码器
- 77.反向传播:把误差一层层传回去
- 78.卷积神经网络(CNN):让特征自己学出来
- 79.循环神经网络(RNN):给网络装上记忆
- 80.深度学习回顾:静态一类,动态一类
- 81.增强学习(1):蒙特卡洛、树搜索与 Q-learning
- 82.强化学习(2):从乌鸦吃核桃到井字棋的 value 回传
高斯混合模型:用隐变量解释双峰数据
约 23 分钟
小象实战讲义 · 机器学习算法精讲
上一节的三硬币问题里,概率为 和 的两个伯努利分布,被权重 和 “混合”到了一起——本质上那是一个混合伯努利模型。本节把混合的”配料”从伯努利换成高斯,就得到机器学习里最常用的概率模型之一:高斯混合模型(Gaussian Mixture Model,GMM)。学完本节,你能用它解释”全班身高”这类双峰数据,并用 EM 算法亲手把参数拟合出来。
💡 核心导读
- 三硬币是”混合伯努利模型”;把伯努利换成高斯,就是高斯混合模型 GMM
- GMM 的本质:几个高斯分布按权重叠加,能描述单个高斯搞不定的多峰数据
- 隐变量 标记”每个样本来自哪个高斯”——整个推导与三硬币完全同构
- E 步算”责任”(样本属于各成分的后验概率),M 步用责任加权更新全部参数
- 成分个数可以从 2 推广到 :有隐变量的混合模型,拟合套路完全一致
一、为什么需要混合模型:单峰解释不了的双峰
先回忆三硬币的骨架:观察到的序列由硬币 B、C 两个伯努利分布”混合”生成,谁占多少由 决定。既然配料可以是伯努利,自然也可以换成别的分布。
来看两个身边的例子。全校同学的眼镜度数大致服从一个单峰的正态分布:大多数人集中在 450 度上下,100 度和 1000 度的人都很少——一个高斯就能描述。但把全班同学的身高记录下来画成直方图,形状就变了:它看起来仍然像”钟形”,却有两个峰,一个在 164 左右,一个在 174 左右——恰好对应这个年龄段女生与男生的平均身高。
原因很直白:女生身高是一个高斯,男生身高是另一个高斯,两群人混在一个教室里,直方图就成了两个高斯的叠加。而且这两群人之间有很大的重叠带(overlap)——一个身高 1 米 72 的人,可能是女生,更可能是男生。像这样”两个高斯的混合”,就是最简单的 GMM;单个人群内部的”配料”还可以继续换成别的分布,混合模型是一整个家族。
二、GMM 的数学形式:5 个参数的混合分布
单个高斯由均值 和方差 决定;两个高斯混合,还要再加一个权重。写成公式:
其中 是正态分布的密度函数:
所以一个两成分 GMM 共有 5 个参数:。对比三硬币的 3 个参数 ——三硬币最多还能在三维空间里穷举搜索,这里就得到五维空间去穷搜,代价陡增;这也是我们必须借助 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 这个”谷底值”——它既不代表女生也不代表男生。混合模型要解决的,就是从这个谷底里把两个真实的峰恢复出来。
三、隐变量视角:与三硬币完全同构
给定数据 ,我们想求极大似然估计:
关键一步与三硬币一模一样:引入隐变量 ,它只取 0 与 1 两个值,标记每个样本到底来自哪个高斯(哪个值只是标识,0/1 对调不影响任何结论)。于是:
把两种取值展开: 时样本服从第一个高斯、先验概率为 ; 时服从第二个高斯、先验为 。代进去,正好回到第二节的混合公式——GMM 就是三硬币把”伯努利”换成”高斯”后的版本,推导没有一个字需要重写。
换一个角度理解这个模型的”生成过程”:先按 与 抽一次成分——直观地说, 就是女生占全班的比例;选中成分后,再在该高斯的概率密度附近采出一个具体数值。重复 次,就得到我们观察到的身高数据。这就是生成模型(generative model)的视角:先假设数据由某个过程生成,再由观察到的数据反推过程参数。它和”给你一堆数据、估计均匀分布的区间端点”是同一类问题——GMM 只是过程复杂一些,要先选成分、再按密度采样。二维情形完全同理:先按权重选一个二维高斯”山包”,再在山包上采点。
四、EM 拟合 GMM:E 步算责任,M 步更新参数
框架还是 EM。E 步要用当前参数算”责任”(responsibility;讲师板书记作 )——即给定观测 ,它来自第一个高斯的后验概率:
M 步则用责任加权,闭式地重新估计全部参数:
、 同理,把 换成 即可。把这些公式原样落成纯 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 人)三个观察:
- 对数似然单调上升()——这正是上一章 EM 的收敛性保证在 GMM 上的体现。
- 两个均值收敛到 160.56 与 175.22,紧贴构造真值 160/175——EM 确实从谷底均值 167.23 里把两个峰恢复了出来。
- 软归属是 34/26,不是 30/30。这不是拟合失败:重叠带里的样本本就”两可”,GMM 输出的是概率归属(责任 ),落在重叠带的样本 接近 0.5,硬以 0.5 切一刀必有少数样本划到另一侧。软分配,恰是混合模型与硬聚类的本质区别。
五、从 2 到 K:更一般的混合模型
两个成分之外,再举一个例子:把一所特大学校的小学生、初中生、高中生放在一起测跳远成绩,成绩分布就会呈现三个峰——三个高斯的混合。此时隐变量 取 0、1、2 三个值,模型变成:
参数从 5 个涨到 8 个(三个均值、三个方差、两个自由权重—— 的约束省掉一个),穷举搜索要进八维空间,更加不现实;而 EM 的 E 步/M 步公式只需把”两个成分”推广成”求和号下 项”,套路原封不动。三硬币是伯努利混合、本节是高斯混合——任何”观测由隐变量选择成分、成分再生成数据”的混合模型,都按同一套 EM 流程拟合。
📝 动手练一练
练习 1(概念辨析):假如每个身高样本都带着性别标签,我们还需要 EM 吗?没有标签时,为什么不能直接套”均值 = 总和除以个数”这类公式?
👉 点击查看参考答案
不需要。有标签相当于三硬币里”每个结果都染了色”:按性别分成两组,各组直接统计均值、方差,权重就是男女比例,一步到位。没有标签时,每个样本的归属本身是未知的——若无视结构硬算,得到的是 167.23 这种落在谷底的”全班均值”,谁也不代表;EM 的作用正是用责任 给每个样本软分配归属,再迭代逼近”如果知道标签会得到的”那组参数。
练习 2(动手改代码):把块 2 的初始值改成 全班平均身高(方差也取全班方差),再跑一遍,观察会发生什么。
👉 点击查看参考答案
实测:两个成分初值完全相同时,每轮算出的责任恒为 0.5,参数纹丝不动——logL 五轮全部停在 ,,EM 卡死在对称不动点上(对比正常初值能收敛到 )。这说明 EM 的结果依赖初始化:实践中要么把初始均值分得足够开(比如本例取最小值/最大值),要么多次随机重启取似然最高的一组。
本章小结
- GMM 是 个高斯按权重叠加的混合分布;两成分时有 5 个参数 。
- 隐变量 标记样本来自哪个成分;GMM 与三硬币(混合伯努利)的推导完全同构。
- 生成视角两步走:先按权重选成分( ≈ 人群比例),再在选定高斯内按密度采样。
- E 步算责任 (样本归属的后验概率),M 步用责任加权闭式更新 、、。
- 对数似然每轮不减(EM 收敛性);但初值不当可能卡在对称不动点,实践中用分开的初值或随机重启。
- 推广到 个成分:参数变多、公式结构不变——隐变量混合模型的拟合套路是通用的。
📋 行动清单
- 把块 2 改造成三成分 GMM(跳远成绩:小学生/初中生/高中生),对照第五节公式扩展 E 步与 M 步
- 打印每一轮重叠带样本的责任 ,确认它们接近 0.5 而非 0/1
- 对照上一节三硬币的 E/M 步公式,逐项写出两套公式的同构对应关系
—— 小象教研组
配套资料 · 直接下载
课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。
- 下载第13章笔记:期望最大化(EM)算法