城市街角的画廊老板在闭店后面对一面布满彩色漆点的墙。墙角的油漆桶早已被搬走,只留下喷溅的痕迹。老板知道,这些漆点来自三只不同的喷漆桶:一只偏紫红、一只偏青绿、一只偏暖黄,每只桶的位置不同、喷口形状不同、出漆量也不同。他想从墙上的漆点反推出每只桶当初的位置、喷口大小和用量占比。这面墙是数据,三只桶是高斯分布,而“由点反推桶”的过程,正是高斯混合模型(GMM)与 EM 算法要做的事:先猜桶的参数,算出每滴漆更像哪只桶喷的,再根据这个“软归属”反过来调整桶的参数,如此反复,直到墙面被完美解释。这篇文章会带你用“喷漆桶”的视角,轻松走进 GMM 与 EM 的世界。
掌握 GMM 与 EM,你就能在用户分群、异常检测、语音识别等任务中输出“带置信度的聚类”,而不只是给出一个生硬标签。这是 AI 工程师从入门走向实战的必修课。
可视化演示
本节配有交互动效(进入视口后自动加载,约 3KB)。
高斯混合模型:多个高斯分布的加权和 EM算法:E步计算责任值 → M步更新参数用当前参数计算每个样本属于各高斯的后验概率(责任值)用责任值加权更新均值、方差和混合权重p(x) = Σ π_k * N(x|μ_k, σ_k²)E步:γ(nk) = π_k*N(x...
一、高斯混合模型
想象一间手工喷漆工作室。墙角立着三只喷漆桶:一只是紫红色的,喷口大而散;一只是青绿色的,喷口扁而细长;还有一只是暖黄色的,出漆量很少。墙上的漆点从来不是某一只桶单独完成的,而是三只桶以不同比例、不同位置、不同形状的喷溅叠加出来的结果。在机器学习的世界里,这些漆点就是成千上万个数据点,而每一只喷漆桶的“喷溅规律”,正是一个高斯分布。
如果你只拿到墙上的漆点,却看不见桶,该怎么办?高斯混合模型(GMM)给出了回答:假设整面墙的漆点密度,是 K 个高斯分布按权重相加得到的。K 个分布对应 K 只桶,权重对应每只桶的出漆量占比。这个假设听起来直观,却非常强大——它让“由点反推桶”成为一道可以计算的数学题。
GMM 的概率密度函数写作:
当 K 取 2 或 3 时,GMM 就能描绘出动画演示里那两只“桶”不断移动、旋转、伸缩的过程。模型本身不告诉我们桶在哪,它只提供“用 K 只桶解释这面墙”的数学框架,真正找参数的任务交给了后面的 EM 算法。
- 求和符号 把 K 只桶对所有漆点的贡献全部加起来,得到“整面墙”的密度。
- 混合权重 第 k 只桶的出漆量占比,所有占比之和等于 1。
- 高斯密度 第 k 只桶的喷溅规律,均值 决定桶的位置,协方差矩阵 决定喷口的形状与朝向。
- 整体含义每个漆点的概率密度,是所有桶贡献的加权平均,这也是“混合模型”名称的来源。
二、软聚类思想
老板盯着墙上一滴处于紫红与青绿交界处的漆点,眉头紧锁:它到底来自哪只桶?来自紫红桶 70%,还是青绿桶 70%?与其武断地给它贴一个“非此即彼”的标签,不如说它“七分像紫、三分像绿”。这种“按比例分配”的归属方式,就是软聚类思想——每个样本不是被硬性划给某一个簇,而是被赋予一组“属于各簇的概率”。
在 GMM 中,这个概率由贝叶斯公式给出:看到样本 后,它属于第 k 个成分的后验概率,记作 。分子是“桶 k 对样本的解释力度”(先验权重 × 该桶的密度),分母是所有桶解释力度之和。这样算出的后验概率天然满足归一化:每个样本对 K 个簇的概率加起来等于 1。
对比来看,K-Means 就像一位急性子的老板,把每滴漆点毫不犹豫地划给最近的一只桶;而 GMM 的软聚类会保留犹豫本身,把犹豫量化为概率。这种不确定性度量在风控、医疗等“宁可多问一句也不能拍板”的场景中格外宝贵。
- 分子里的贡献度先验权重乘密度,表示“桶 k 独自解释这个漆点的能力”。
- 分母的归一化把 K 只桶的解释能力求和,让概率总和为 1。
- 后验概率 表示样本 来自第 k 个成分的置信度,数值越接近 1 说明归属越明确,越接近 0.5 说明正好处于两类交界。
- 软归属的意义不再输出 0/1 标签,而是输出一组概率向量,这就是“软聚类”。
三、极大似然估计
老板想调整三只桶的参数——位置、喷口形状、出漆量——让墙上的漆点分布看起来“尽可能像”自己没看见的那三只桶。在统计学家看来,这等价于最大化似然函数:找到一组参数,使观测数据出现的概率最大。如果只有一只桶,问题很简单:把样本均值当位置、把样本方差当喷口大小就行。但现在是多只桶的叠加,每个漆点的来源又未知,事情就复杂了。
先写出对数似然函数。假设 N 个样本独立同分布,所有样本的联合概率是每个样本概率的乘积,取对数后变成求和,既方便求导,又能避免连乘导致的数值下溢。GMM 的对数似然长这样:
为什么这么难?因为每个漆点的“桶来源标签”是缺失的。如果老板知道每滴漆来自哪只桶,他就能分组统计,三下五除二算出参数。可惜没人告诉他,于是他不得不借助一种“先猜标签、再调参数”的迭代策略——这正是隐变量视角和 EM 算法的起点。
- 样本独立乘积整批数据的似然是每个样本似然的连乘,所以外层是求和。
- 取对数 把连乘变连加,并缓解极小概率相乘带来的数值下溢。
- 对数里的求和每个样本本身又由 K 个成分叠加,于是 内出现求和。
- 求导困难 无法穿过内部的求和,直接对 求导得到的是非线性方程组,没有解析解。
四、隐变量视角
给每滴漆点贴上一条看不见的小标签:上面写着“我来自第 2 只桶”。标签看不见,但它真实存在,它决定了这滴漆的分布来源。在统计学中,这种无法观测却影响数据的变量叫隐变量,记作 。有了隐变量,数据被分成两个版本:能看到的部分 叫"不完全数据",连同隐藏标签一起的 叫“完全数据”。
GMM 的对数似然,本质上是把所有可能的标签情况都考虑进去:某个漆点可能来自桶 1,也可能来自桶 2、桶 3,于是要把所有标签对应的联合概率求和,把隐变量“边缘化”掉:
换个角度想:如果标签已知,问题退化成“每只桶分别统计自己的漆点”,一分钟就能算出均值和方差;如果完全无视标签,又没法把混合模型拆开。EM 的聪明之处就在于:不撕掉标签,而是给每滴漆算一个“可能的标签概率”,然后拿着这些概率去更新桶参数,再回头重新算概率,如此循环。
- 隐变量 记录每个样本来源成分的全部标签,取值范围有限。
- 联合概率 完全数据下的概率,若标签已知则可以直接分解求导。
- 边缘化求和对 Z 的所有可能取值求和,把看不见的标签消去,得到观测数据的概率。
- 在求和外对数无法直接穿进求和内部,导致极大似然估计没有解析解。
五、EM迭代流程
老板想出一个笨而管用的办法:先随便摆三只桶的位置,然后按当前桶的参数,给每滴漆点估计“来自各桶的概率”(这是 E 步);接着根据这些软归属,重新计算每只桶的位置、喷口形状和出漆量(这是 M 步);新参数会带来新的概率,新的概率又带来新的参数,每轮下来桶的位置都会更加贴近真实。这个“先猜标签、再调参数、交替迭代”的过程,就是期望最大化(EM)算法。
E 步计算的就是软聚类中的后验概率 。M 步则用这些后验概率对样本做加权统计:均值等于所有样本按软归属加权后的平均位置;协方差等于加权散度矩阵;混合权重等于各桶的“有效样本数”占比。三个更新公式如下:
动画演示里那两个椭圆就是这么“动”起来的:每一轮迭代,椭圆的位置被数据点拉动,形状被数据点的散布重塑,同时颜色逐渐区分开。现在你已经掌握了 GMM 聚类的核心流程,但还有一个关键问题:这套流程凭什么一定收敛?下一节揭晓。
- 有效数量 先求出所有样本对第 k 只桶的后验概率之和,相当于这只桶“分到”的漆点总权重。
- 均值更新第 k 只桶的新位置,是所有漆点按后验权重加权的平均位置,软归属越高的漆点越有发言权。
- 协方差更新每个样本偏离新均值的误差向量乘以自身转置,再按后验权重求和,得到新的喷口形状。
- 权重更新第 k 只桶的出漆量占比,等于它分到的有效漆点数占总样本数的比例。
- 交替迭代固定参数算后验(E),固定后验更新参数(M),直到对数似然的变化量小于某个阈值。
六、收敛性质
老板每调一次桶,都会重新检查一遍整面墙:有没有比上一轮“解释得更像”?如果调完反而更不像,他就不会采用那组参数。EM 算法自带这种“永不退步”的机制——它保证每一轮迭代后,对数似然值不会下降,只会单调不减。这是 EM 最令人安心的性质,但它并不等于能找到全局最优。
为什么会单调不减?关键在一个叫“下界”的概念。EM 每轮不是直接优化难以处理的 ,而是优化它的一个下界(ELBO)。利用 Jensen 不等式,对数似然可以放心地放缩为:
这解释了为什么老板每次调桶都不会更差,但也提醒我们:如果初始桶放得离谱,EM 可能停在某个“还行但没那么好”的局部最优。就像爬山时摸黑走,EM 保证你每一步都向上,但不保证你爬的是最高的那座山。因此初始化策略至关重要。
- 分布 当前对隐变量标签的估计分布,也就是 E 步算出的后验概率,它和后验越接近,下界越紧。
- Jensen 不等式因为 是凹函数,对数中的期望大于等于期望中的对数,从而得到下界。
- ELBO 优化M 步通过更新参数让下界最大,而下界每轮抬高,真实的 也被抬升。
- 结果与局限似然单调不减保证收敛到某个驻点,但驻点可能是局部极大,未必是全局最优。
七、GMM聚类实践
从理论回到工作室,老板要真正投入使用这套方法,得回答三个问题:用几只桶?桶口是什么形状?初始位置怎么摆?第一个问题对应聚类数 K 的选择,第二个问题对应协方差矩阵的类型,第三个问题对应参数初始化,每个都是影响聚类效果的关键旋钮。
先看完整的高斯密度函数,它把“喷口形状”用协方差矩阵 刻画得淋漓尽致:
实践中,协方差矩阵有三种常见限制:球状(各向同性)、对角(各维独立)、完整矩阵(允许任意旋转)。球状最省参数但只能画圆,完整矩阵最灵活但易过拟合,对角矩阵是折中最常用。初始化一般是先跑一遍 K-Means,用它的聚类中心作为成分均值起点;聚类数则用 BIC 或交叉验证挑选。老板此时总算明白:桶的数量不是越多越好,喷口形状也要和现实匹配。
- 偏差向量 样本相对桶中心的位置偏移,偏移越大越不像是这桶喷的。
- 马氏距离二次型用协方差逆矩阵衡量偏移的距离,椭圆簇会被“拉长”到真实的数据散布方向。
- 指数衰减项偏移越远,出现在该处的概率越小,形成椭圆形的概率等高线。
- 归一化系数行列式 和 保证密度函数在全空间积分为 1,是合格的“概率配方”。
八、局限与拓展
如果老板贪心,把 K 设成 100,会发生什么?每滴漆点都可能独享一只桶,模型完美“记住”了每一个点,却完全失去了概括能力——这就是过拟合。更糟的是,墙上若有一滴来自外人的意外颜料,它可能会把某只桶的位置拖拽很远,让结果失真。GMM 并非万能,它有自己的性格与边界。
先说好消息:GMM 与 K-Means 并不是对手。K-Means 可以看作 GMM 在“所有簇协方差相等且趋近于 0、软归属退化为硬归属”时的极限版本;反过来,GMM 是 K-Means 的“软版本”与“椭圆版本”。二者经常配合使用:先用 K-Means 初始化 GMM,再用 GMM 做精细建模。至于坏消息,GMM 的 E 步要对每个样本计算所有成分的密度,复杂度随样本数 N、成分数 K、特征维度 D 的增长而不菲,尤其完整协方差矩阵的求逆代价更高。
为了避免“桶越多越好”的陷阱,统计学家常用 BIC 做模型选择,它在拟合优度与模型复杂度之间取平衡:
回到喷漆工作室:聪明的老板会挑选刚好能解释墙面结构的最少桶数,会警惕意外的颜料滴,也会先快速粗分再精细调参。GMM 与 EM 教给他的,不只是一种聚类工具,更是一种“在不确定中反复迭代逼近真相”的思维方式。掌握了它,你也就掌握了无监督学习中最优雅的概率模型之一。
- 最大似然 模型在当前数据上能达到的最优解释程度,似然越大越好。
- 参数个数 GMM 的参数包括所有权重、均值、协方差元素,K 越大 越大。
- 惩罚项 参数越多、样本越多,惩罚越重,防止模型钻数据空子。
- 模型选择规则在两个模型解释力相当时,BIC 更小的一方是更稳妥的选择。
AI 应用场景
电商用户分群:给每位客户一份“概率归属”
阶段:无监督聚类与用户画像建模
解决的问题:传统 RFM 分群用硬性阈值把用户划入高价值/低价值,边界用户常被误分。GMM 输出“70% 高价值、30% 潜在价值”的软归属,让运营人员看到边界客户的不确定性,从而设计更精细的差异化策略。
具体案例:某电商对 100 万用户的客单价、购买频次、品类覆盖数做标准化后,用 GMM 聚成 4 类,并对软归属概率在 0.4~0.6 之间的用户单独做优惠券 AB 测试,转化率比硬分群提升 12%。
银行反欺诈:低密度区域的异常漆点
阶段:异常检测与风险控制
解决的问题:欺诈样本往往落在正常数据分布的“低密度区”。GMM 为每笔交易给出属于所有正常簇的后验概率,如果所有概率都极低,说明该点落在桶的稀疏边缘,可标记为疑似异常,比固定阈值更自适应。
具体案例:某银行对登录设备、交易金额、频次等特征建立 GMM,当某笔交易对所有成分的后验概率均低于 0.01 时触发二次验证,将盗刷拦截率从 30% 提升到 61%。
会议录音说话人分离:谁在什么时候说话
阶段:语音预处理与声纹聚类
解决的问题:多人会议录音交叠严重,直接做语音识别无法区分发言者。GMM 对语音特征向量做软聚类,输出每个片段属于各说话人的概率,再结合时序平滑确定说话人切换点。
具体案例:某会议纪要系统对 2 小时录音提取 MFCC 特征,用 GMM 聚出 3 个说话人,软概率超过 0.8 的片段用于自动标注发言人,转写准确率从 55% 提升至 82%。
Python 演示
import numpy as npfrom sklearn.datasets import make_blobsfrom sklearn.mixture import GaussianMixture def fit_gmm_manual(X, K=3, iters=50, seed=0): rng = np.random.RandomState(seed) n, d = X.shape # 初始化: 等权重, 随机选K个样本作均值, 单位协方差 pi = np.full(K, 1.0 / K) mu = X[rng.choice(n, K, replace=False)] cov = np.array([np.eye(d) for _ in range(K)]) for _ in range(iters): # E步: 计算后验概率 log_prob = np.zeros((n, K)) for k in range(K): diff = X - mu[k] inv_cov = np.linalg.inv(cov[k]) log_prob[:, k] = (-0.5 * (np.sum((diff @ inv_cov) * diff, axis=1) + np.log(np.linalg.det(cov[k]) + 1e-12) + d * np.log(2 * np.pi)) + np.log(pi[k])) log_prob -= log_prob.max(axis=1, keepdims=True) gamma = np.exp(log_prob) gamma = gamma / gamma.sum(axis=1, keepdims=True) Nk = gamma.sum(axis=0) # M步: 更新均值, 协方差, 权重 for k in range(K): gamma_k = gamma[:, k:k + 1] mu[k] = (gamma_k * X).sum(axis=0) / Nk[k] diff = X - mu[k] cov[k] = ((gamma_k * diff).T @ diff) / Nk[k] + 1e-6 * np.eye(d) pi[k] = Nk[k] / n return pi, mu, cov if __name__ == "__main__": X, _ = make_blobs(n_samples=300, centers=3, cluster_std=1.2, random_state=42) pi, mu, cov = fit_gmm_manual(X) model = GaussianMixture(n_components=3, random_state=0).fit(X) for k in range(3): print("手动EM 均值", np.round(mu[k], 2), "sklearn", np.round(model.means_[k], 2))
log_prob[:, k] = ...用公式计算每个样本属于第 k 个成分的对数概率,加上小常数防止行列式为 0。log_prob -= log_prob.max(axis=1, keepdims=True)减去每行最大值再做指数,避免数值下溢。gamma = gamma / gamma.sum(axis=1, keepdims=True)归一化得到软归属概率,即 E 步的后验。mu[k] = (gamma_k * X).sum(axis=0) / Nk[k]用后验概率加权平均更新第 k 个均值。cov[k] = ((gamma_k * diff).T @ diff) / Nk[k] + 1e-6 * np.eye(d)加权散度矩阵更新协方差,并加微小正则保证可逆。model = GaussianMixture(n_components=3, random_state=0).fit(X)调用 sklearn 标准实现,作为交叉验证参照。
常见误区
误区既然 EM 保证每一步似然都不减,那多迭代几次一定能找到全局最优的聚类结果吧?我的模型训练为什么会得到不一样的结果?
正解EM 只保证收敛到一个局部极大值或驻点,并不保证全局最优。就像摸黑爬山,算法保证每一步都向上,但你可能爬上的只是山腰的凸起,而不是最高峰。初始参数不同,最终停下的局部最优也不同,这也是为什么实践中要用 K-Means 初始化做多次尝试。
为何常见:初学者看到“单调不减”的数学保证,容易把它误读成“全局最优”,忽视了目标函数本身非凸的事实。
误区GMM 输出软归属,那是不是每个样本最终会被贴上多个类别标签?比如一个人既是高价值客户又是流失客户?
正解软聚类输出的不是多个标签,而是一组“概率”。概率可以用于决策,比如“高价值概率 0.7”,但在实际落库或规则触发时,仍可以按概率最高或设定阈值转成单个标签。软归属的价值在于它保留了不确定性的灰度信息,而不是真的把样本分身。
为何常见:把“软概率”等同于“多标签分类”,是混淆了聚类输出与分类任务的目标。
误区聚类数 K 设大一点,每个簇都更紧凑,似然也更高,效果应该更好吧?反正 GMM 能自动调参。
正解K 过大会导致过拟合——模型开始记住单个样本而非数据规律,泛化能力下降。BIC 的存在就是为了抑制这种贪婪:它用参数数量惩罚复杂度,K 不是越大越好,而是在“解释力”与“简洁性”之间取平衡。
为何常见:训练集上似然随 K 单调上升,让人误以为更多成分等于更强模型,忽略了测试集上的泛化表现。
误区EM 反正会迭代到收敛,初始参数是什么不重要,随便设个随机数就行。
正解EM 对初始值高度敏感。如果初始均值严重偏离真实簇,或在同一个簇里放了两只桶,EM 可能收敛到极差的局部最优,甚至让两个成分“合并”。常见做法是先跑 K-Means、用其中心初始化均值,再设置成分权重相等、协方差为单位阵。
为何常见:教科书常强调“EM 保证收敛”,却没强调“收敛到哪个解”依赖起点,导致学习者忽略初始化工程细节。
面试题
Q1. GMM 中后验概率的主要作用是什么?
- A.判断模型参数量是否过多
- B.描述样本属于各成分的概率← 正确答案
- C.输出样本的唯一聚类标签
- D.计算协方差矩阵的行列式
答案:B。后验概率 是样本 来自第 k 个高斯成分的软归属概率,这是 GMM 软聚类的核心。A 是模型选择关心的,C 是硬聚类行为,D 只是密度公式中的一步,都与后验概率的作用不符。
Q2. EM 算法中的 E 步主要计算什么?
- A.使用当前参数计算后验概率← 正确答案
- B.直接更新均值与协方差
- C.随机初始化全部模型参数
- D.计算数据的似然函数值
答案:A。E 步固定当前参数,计算每个样本属于各成分的后验概率,为 M 步的加权统计提供依据。B 是 M 步的工作,C 发生在 EM 开始前,D 是用于监控收敛的附带操作,并非 E 步目标。
Q3. 与硬聚类 K-Means 相比,GMM 的核心优势是什么?
- A.不需要提前设置聚类数量
- B.能输出软归属和不确定性← 正确答案
- C.所有簇都呈圆形形状
- D.计算速度比 K-Means 更快
答案:B。GMM 通过后验概率输出每个样本属于各簇的置信度,并可用协方差矩阵建模椭圆簇。K-Means 输出硬标签,且假设球状簇,通常速度也更快,所以 A、C、D 都不成立。
Q4. 为什么 GMM 难以直接求极大似然估计的解析解?
- A.因为协方差矩阵可能不可逆
- B.因为隐变量使对数中有求和← 正确答案
- C.因为样本特征的维度太高
- D.因为数据集中不存在噪声
答案:B。GMM 的对数似然 中, 无法穿过对成分的求和,导致求导方程非线性。维度高只是技术挑战,A 与 D 不是根本原因。
Q5. EM 迭代能保证下列哪一项?
- A.一定能够找到全局最优解
- B.每次迭代后似然值单调不减← 正确答案
- C.协方差矩阵一定保持可逆
- D.聚类数量会自动进行缩减
答案:B。EM 的核心保证是每轮迭代都抬高对数似然的下界,因此似然单调不减并收敛到驻点。但驻点可能是局部极大,A 错误;协方差可逆需要正则化手段,C 并非算法保证;D 中成分数 K 固定不变。
Q6. 哪一项是 EM 算法对初始值敏感的主要原因?
- A.因为目标函数是一个凸函数
- B.因为似然函数存在多个局部极大值← 正确答案
- C.因为样本数量总是严重不足
- D.因为后验概率无法被计算
答案:B。GMM 的对数似然非凸,存在多个局部极大值,初始参数决定了最终落入哪一个。若目标函数是凸函数则初始值影响小,A 恰好说反;样本数量和后验概率计算都不是主因。
Q7. 以下哪些属于 GMM 模型需要估计的参数?
- A.混合权重 π_k← 正确答案
- B.均值向量 μ_k← 正确答案
- C.协方差矩阵 Σ_k← 正确答案
- D.样本的类别标签
答案:ABC。GMM 的参数是每只“喷漆桶”的权重、位置与形状,即 π、μ、Σ;样本的类别标签是隐变量,不是待求的全局参数,而是 EM 中需要推断的未知量,因此 D 不选。
Q8. 关于 EM 的 M 步参数更新,下列说法正确的是?
- A.均值按后验权重加权更新← 正确答案
- B.协方差由加权散度矩阵计算← 正确答案
- C.混合权重按有效样本数占比← 正确答案
- D.更新过程完全不需要隐变量
答案:ABC。M 步用 E 步得到的后验概率对样本加权,重新估计均值、协方差和权重,A、B、C 描述完全准确。D 错误,因为后验概率正是隐变量的软估计,更新过程离不开隐变量信息。
Q9. 若将 GMM 的协方差矩阵限定为对角矩阵,其含义是什么?
- A.假设各特征维度彼此独立← 正确答案
- B.聚类簇一定呈现球状形状
- C.无需再估计任何模型参数
- D.只适合高维稀疏数据场景
答案:A。对角协方差假设特征之间不相关,椭圆的主轴与坐标轴平行;若各对角元素相等才退化为球状,所以 B 错误。C 显然错误,对角矩阵仍需估计 D 个方差参数;D 与对角假设无关。
Q10. 关于 GMM 的局限与拓展,下列说法正确的有?
- A.簇数量需先验指定或模型选择← 正确答案
- B.在特定条件下可退化为 K-Means← 正确答案
- C.对孤立异常点完全免疫
- D.训练复杂度一定随样本线性增长
答案:AB。GMM 的 K 不会自动涌现,常用 BIC/AIC 选择,A 正确;当协方差相等且趋向于 0、软归属退化为硬分配时,GMM 逼近 K-Means,B 正确。高斯分布的尾巴较厚,异常点会牵引参数,C 错误;完整协方差的求逆、矩阵运算使复杂度与维度 D 的非线性有关,不能说一定线性,D 错误。