城市街角的画廊老板在闭店后面对一面布满彩色漆点的墙。墙角的油漆桶早已被搬走,只留下喷溅的痕迹。老板知道,这些漆点来自三只不同的喷漆桶:一只偏紫红、一只偏青绿、一只偏暖黄,每只桶的位置不同、喷口形状不同、出漆量也不同。他想从墙上的漆点反推出每只桶当初的位置、喷口大小和用量占比。这面墙是数据,三只桶是高斯分布,而“由点反推桶”的过程,正是高斯混合模型(GMM)与 EM 算法要做的事:先猜桶的参数,算出每滴漆更像哪只桶喷的,再根据这个“软归属”反过来调整桶的参数,如此反复,直到墙面被完美解释。这篇文章会带你用“喷漆桶”的视角,轻松走进 GMM 与 EM 的世界。

岗位关联

掌握 GMM 与 EM,你就能在用户分群、异常检测、语音识别等任务中输出“带置信度的聚类”,而不只是给出一个生硬标签。这是 AI 工程师从入门走向实战的必修课。

目录
  1. 可视化演示
  2. 一、高斯混合模型
  3. 二、软聚类思想
  4. 三、极大似然估计
  5. 四、隐变量视角
  6. 五、EM迭代流程
  7. 六、收敛性质
  8. 七、GMM聚类实践
  9. 八、局限与拓展
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

本节配有交互动效(进入视口后自动加载,约 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 算法。

p(x)=∑k=1Kπk N(x∣μk,Σk)\displaystyle p(x) = \sum_{k=1}^{K} \pi_k \, \mathcal{N}(x | \mu_k, \Sigma_k)
p(x)p(x) 表示数据点 xx 在混合模型下出现的概率密度,等于所有分布成分的加权叠加。
  1. 求和符号 ∑\sum把 K 只桶对所有漆点的贡献全部加起来,得到“整面墙”的密度。
    ∑k=1K\displaystyle \sum_{k=1}^{K}
  2. 混合权重 πk\pi_k第 k 只桶的出漆量占比,所有占比之和等于 1。
    πk≥0,∑k=1Kπk=1\displaystyle \pi_k \geq 0, \quad \sum_{k=1}^{K} \pi_k = 1
  3. 高斯密度 N(x∣μk,Σk)\mathcal{N}(x | \mu_k, \Sigma_k)第 k 只桶的喷溅规律,均值 μk\mu_k 决定桶的位置,协方差矩阵 Σk\Sigma_k 决定喷口的形状与朝向。
    N(x∣μk,Σk)\displaystyle \mathcal{N}(x | \mu_k, \Sigma_k)
  4. 整体含义每个漆点的概率密度,是所有桶贡献的加权平均,这也是“混合模型”名称的来源。
    p(x)=∑k=1Kπk N(x∣μk,Σk)\displaystyle p(x) = \sum_{k=1}^{K} \pi_k \, \mathcal{N}(x | \mu_k, \Sigma_k)

二、软聚类思想

老板盯着墙上一滴处于紫红与青绿交界处的漆点,眉头紧锁:它到底来自哪只桶?来自紫红桶 70%,还是青绿桶 70%?与其武断地给它贴一个“非此即彼”的标签,不如说它“七分像紫、三分像绿”。这种“按比例分配”的归属方式,就是软聚类思想——每个样本不是被硬性划给某一个簇,而是被赋予一组“属于各簇的概率”。

在 GMM 中,这个概率由贝叶斯公式给出:看到样本 xnx_n 后,它属于第 k 个成分的后验概率,记作 γnk\gamma_{nk}。分子是“桶 k 对样本的解释力度”(先验权重 × 该桶的密度),分母是所有桶解释力度之和。这样算出的后验概率天然满足归一化:每个样本对 K 个簇的概率加起来等于 1。

对比来看,K-Means 就像一位急性子的老板,把每滴漆点毫不犹豫地划给最近的一只桶;而 GMM 的软聚类会保留犹豫本身,把犹豫量化为概率。这种不确定性度量在风控、医疗等“宁可多问一句也不能拍板”的场景中格外宝贵。

γnk=πk N(xn∣μk,Σk)∑j=1Kπj N(xn∣μj,Σj)\displaystyle \gamma_{nk} = \frac{\pi_k \, \mathcal{N}(x_n | \mu_k, \Sigma_k)}{\sum_{j=1}^{K} \pi_j \, \mathcal{N}(x_n | \mu_j, \Sigma_j)}
γnk\gamma_{nk} 是“第 n 个漆点来自第 k 只桶”的软归属概率,也叫后验概率。
  1. 分子里的贡献度先验权重乘密度,表示“桶 k 独自解释这个漆点的能力”。
    πk N(xn∣μk,Σk)\displaystyle \pi_k \, \mathcal{N}(x_n | \mu_k, \Sigma_k)
  2. 分母的归一化把 K 只桶的解释能力求和,让概率总和为 1。
    ∑j=1Kπj N(xn∣μj,Σj)\displaystyle \sum_{j=1}^{K} \pi_j \, \mathcal{N}(x_n | \mu_j, \Sigma_j)
  3. 后验概率 γnk\gamma_{nk}表示样本 xnx_n 来自第 k 个成分的置信度,数值越接近 1 说明归属越明确,越接近 0.5 说明正好处于两类交界。
    γnk∈[0,1]\displaystyle \gamma_{nk} \in [0, 1]
  4. 软归属的意义不再输出 0/1 标签,而是输出一组概率向量,这就是“软聚类”。
    ∑k=1Kγnk=1\displaystyle \sum_{k=1}^{K} \gamma_{nk} = 1

三、极大似然估计

老板想调整三只桶的参数——位置、喷口形状、出漆量——让墙上的漆点分布看起来“尽可能像”自己没看见的那三只桶。在统计学家看来,这等价于最大化似然函数:找到一组参数,使观测数据出现的概率最大。如果只有一只桶,问题很简单:把样本均值当位置、把样本方差当喷口大小就行。但现在是多只桶的叠加,每个漆点的来源又未知,事情就复杂了。

先写出对数似然函数。假设 N 个样本独立同分布,所有样本的联合概率是每个样本概率的乘积,取对数后变成求和,既方便求导,又能避免连乘导致的数值下溢。GMM 的对数似然长这样:

为什么这么难?因为每个漆点的“桶来源标签”是缺失的。如果老板知道每滴漆来自哪只桶,他就能分组统计,三下五除二算出参数。可惜没人告诉他,于是他不得不借助一种“先猜标签、再调参数”的迭代策略——这正是隐变量视角和 EM 算法的起点。

ℓ(θ)=∑n=1Nln⁡(∑k=1Kπk N(xn∣θk))\displaystyle \ell(\theta) = \sum_{n=1}^{N} \ln \left( \sum_{k=1}^{K} \pi_k \, \mathcal{N}(x_n | \theta_k) \right)
ℓ(θ)\ell(\theta) 是在所有样本上累计的“解释程度”,数值越大说明当前参数越像那三只真实的桶。
  1. 样本独立乘积整批数据的似然是每个样本似然的连乘,所以外层是求和。
    ∏n=1Np(xn)  →  ∑n=1Nln⁡p(xn)\displaystyle \prod_{n=1}^{N} p(x_n) \;\rightarrow\; \sum_{n=1}^{N} \ln p(x_n)
  2. 取对数 ln⁡\ln把连乘变连加,并缓解极小概率相乘带来的数值下溢。
    ln⁡∏n=1Np(xn)=∑n=1Nln⁡p(xn)\displaystyle \ln \prod_{n=1}^{N} p(x_n) = \sum_{n=1}^{N} \ln p(x_n)
  3. 对数里的求和每个样本本身又由 K 个成分叠加,于是 ln⁡\ln 内出现求和。
    ln⁡(∑k=1Kπk N(xn∣θk))\displaystyle \ln \left( \sum_{k=1}^{K} \pi_k \, \mathcal{N}(x_n | \theta_k) \right)
  4. 求导困难ln⁡\ln 无法穿过内部的求和,直接对 θ\theta 求导得到的是非线性方程组,没有解析解。
    ∂ℓ(θ)∂μk=∑n=1NπkN(xn∣θk)∑jπjN(xn∣θj)Σk−1(xn−μk)\displaystyle \frac{\partial \ell(\theta)}{\partial \mu_k} = \sum_{n=1}^{N} \frac{\pi_k \mathcal{N}(x_n|\theta_k)}{\sum_j \pi_j \mathcal{N}(x_n|\theta_j)} \Sigma_k^{-1} (x_n - \mu_k)

四、隐变量视角

给每滴漆点贴上一条看不见的小标签:上面写着“我来自第 2 只桶”。标签看不见,但它真实存在,它决定了这滴漆的分布来源。在统计学中,这种无法观测却影响数据的变量叫隐变量,记作 zz。有了隐变量,数据被分成两个版本:能看到的部分 xx 叫"不完全数据",连同隐藏标签一起的 (x,z)(x, z) 叫“完全数据”。

GMM 的对数似然,本质上是把所有可能的标签情况都考虑进去:某个漆点可能来自桶 1,也可能来自桶 2、桶 3,于是要把所有标签对应的联合概率求和,把隐变量“边缘化”掉:

换个角度想:如果标签已知,问题退化成“每只桶分别统计自己的漆点”,一分钟就能算出均值和方差;如果完全无视标签,又没法把混合模型拆开。EM 的聪明之处就在于:不撕掉标签,而是给每滴漆算一个“可能的标签概率”,然后拿着这些概率去更新桶参数,再回头重新算概率,如此循环。

ln⁡p(X∣θ)=ln⁡∑Zp(X,Z∣θ)\displaystyle \ln p(X | \theta) = \ln \sum_{Z} p(X, Z | \theta)
观测数据的概率,需要通过把所有隐变量的取值加总(边缘化)得到。
  1. 隐变量 ZZ记录每个样本来源成分的全部标签,取值范围有限。
    Z={z1,z2,…,zN},zn∈{1,2,…,K}\displaystyle Z = \{z_1, z_2, \dots, z_N\}, \quad z_n \in \{1, 2, \dots, K\}
  2. 联合概率 p(X,Z∣θ)p(X, Z | \theta)完全数据下的概率,若标签已知则可以直接分解求导。
    p(X,Z∣θ)=∏n=1Np(xn∣zn) p(zn)\displaystyle p(X, Z | \theta) = \prod_{n=1}^{N} p(x_n | z_n) \, p(z_n)
  3. 边缘化求和对 Z 的所有可能取值求和,把看不见的标签消去,得到观测数据的概率。
    p(X∣θ)=∑Zp(X,Z∣θ)\displaystyle p(X | \theta) = \sum_{Z} p(X, Z | \theta)
  4. ln⁡\ln 在求和外对数无法直接穿进求和内部,导致极大似然估计没有解析解。
    ln⁡∑Zp(X,Z∣θ)≠∑Zln⁡p(X,Z∣θ)\displaystyle \ln \sum_{Z} p(X, Z | \theta) \neq \sum_{Z} \ln p(X, Z | \theta)

五、EM迭代流程

老板想出一个笨而管用的办法:先随便摆三只桶的位置,然后按当前桶的参数,给每滴漆点估计“来自各桶的概率”(这是 E 步);接着根据这些软归属,重新计算每只桶的位置、喷口形状和出漆量(这是 M 步);新参数会带来新的概率,新的概率又带来新的参数,每轮下来桶的位置都会更加贴近真实。这个“先猜标签、再调参数、交替迭代”的过程,就是期望最大化(EM)算法。

E 步计算的就是软聚类中的后验概率 γnk\gamma_{nk}。M 步则用这些后验概率对样本做加权统计:均值等于所有样本按软归属加权后的平均位置;协方差等于加权散度矩阵;混合权重等于各桶的“有效样本数”占比。三个更新公式如下:

动画演示里那两个椭圆就是这么“动”起来的:每一轮迭代,椭圆的位置被数据点拉动,形状被数据点的散布重塑,同时颜色逐渐区分开。现在你已经掌握了 GMM 聚类的核心流程,但还有一个关键问题:这套流程凭什么一定收敛?下一节揭晓。

μknew=∑n=1Nγnkxn∑n=1Nγnk,Σknew=∑n=1Nγnk(xn−μknew)(xn−μknew)T∑n=1Nγnk,πknew=NkN\displaystyle \mu_k^{new} = \frac{\sum_{n=1}^{N} \gamma_{nk} x_n}{\sum_{n=1}^{N} \gamma_{nk}}, \quad \Sigma_k^{new} = \frac{\sum_{n=1}^{N} \gamma_{nk} (x_n - \mu_k^{new})(x_n - \mu_k^{new})^T}{\sum_{n=1}^{N} \gamma_{nk}}, \quad \pi_k^{new} = \frac{N_k}{N}
M 步的更新公式让每只桶的参数重新对齐当前所有漆点的软归属分布。
  1. 有效数量 NkN_k先求出所有样本对第 k 只桶的后验概率之和,相当于这只桶“分到”的漆点总权重。
    Nk=∑n=1Nγnk\displaystyle N_k = \sum_{n=1}^{N} \gamma_{nk}
  2. 均值更新第 k 只桶的新位置,是所有漆点按后验权重加权的平均位置,软归属越高的漆点越有发言权。
    μknew=1Nk∑n=1Nγnkxn\displaystyle \mu_k^{new} = \frac{1}{N_k} \sum_{n=1}^{N} \gamma_{nk} x_n
  3. 协方差更新每个样本偏离新均值的误差向量乘以自身转置,再按后验权重求和,得到新的喷口形状。
    Σknew=1Nk∑n=1Nγnk(xn−μknew)(xn−μknew)T\displaystyle \Sigma_k^{new} = \frac{1}{N_k} \sum_{n=1}^{N} \gamma_{nk} (x_n - \mu_k^{new})(x_n - \mu_k^{new})^T
  4. 权重更新第 k 只桶的出漆量占比,等于它分到的有效漆点数占总样本数的比例。
    πknew=NkN\displaystyle \pi_k^{new} = \frac{N_k}{N}
  5. 交替迭代固定参数算后验(E),固定后验更新参数(M),直到对数似然的变化量小于某个阈值。
    ∣ℓ(θt+1)−ℓ(θt)∣<ε\displaystyle |\ell(\theta^{t+1}) - \ell(\theta^{t})| < \varepsilon

六、收敛性质

老板每调一次桶,都会重新检查一遍整面墙:有没有比上一轮“解释得更像”?如果调完反而更不像,他就不会采用那组参数。EM 算法自带这种“永不退步”的机制——它保证每一轮迭代后,对数似然值不会下降,只会单调不减。这是 EM 最令人安心的性质,但它并不等于能找到全局最优。

为什么会单调不减?关键在一个叫“下界”的概念。EM 每轮不是直接优化难以处理的 ln⁡p(X∣θ)\ln p(X|\theta),而是优化它的一个下界(ELBO)。利用 Jensen 不等式,对数似然可以放心地放缩为:

这解释了为什么老板每次调桶都不会更差,但也提醒我们:如果初始桶放得离谱,EM 可能停在某个“还行但没那么好”的局部最优。就像爬山时摸黑走,EM 保证你每一步都向上,但不保证你爬的是最高的那座山。因此初始化策略至关重要。

ln⁡p(X∣θ)≥∑Zq(Z)ln⁡p(X,Z∣θ)q(Z)\displaystyle \ln p(X | \theta) \geq \sum_{Z} q(Z) \ln \frac{p(X, Z | \theta)}{q(Z)}
右边是 ln⁡p(X∣θ)\ln p(X|\theta) 的下界,EM 的 E 步让下界贴近当前值,M 步把这个下界推高。
  1. 分布 q(Z)q(Z)当前对隐变量标签的估计分布,也就是 E 步算出的后验概率,它和后验越接近,下界越紧。
    q(Z)=p(Z∣X,θold)\displaystyle q(Z) = p(Z | X, \theta^{old})
  2. Jensen 不等式因为 ln⁡\ln 是凹函数,对数中的期望大于等于期望中的对数,从而得到下界。
    ln⁡Eq[p(X,Z∣θ)q(Z)]≥Eq[ln⁡p(X,Z∣θ)q(Z)]\displaystyle \ln \mathbb{E}_q \left[ \frac{p(X,Z|\theta)}{q(Z)} \right] \geq \mathbb{E}_q \left[ \ln \frac{p(X,Z|\theta)}{q(Z)} \right]
  3. ELBO 优化M 步通过更新参数让下界最大,而下界每轮抬高,真实的 ln⁡p(X∣θ)\ln p(X|\theta) 也被抬升。
    ℓ(θt+1)≥ℓ(θt)\displaystyle \ell(\theta^{t+1}) \geq \ell(\theta^{t})
  4. 结果与局限似然单调不减保证收敛到某个驻点,但驻点可能是局部极大,未必是全局最优。
    θ∗=arg⁡max⁡θℓ(θ),可能是局部极大值\displaystyle \theta^* = \arg\max_{\theta} \ell(\theta), \quad \text{可能是局部极大值}

七、GMM聚类实践

从理论回到工作室,老板要真正投入使用这套方法,得回答三个问题:用几只桶?桶口是什么形状?初始位置怎么摆?第一个问题对应聚类数 K 的选择,第二个问题对应协方差矩阵的类型,第三个问题对应参数初始化,每个都是影响聚类效果的关键旋钮。

先看完整的高斯密度函数,它把“喷口形状”用协方差矩阵 Σ\Sigma 刻画得淋漓尽致:

实践中,协方差矩阵有三种常见限制:球状(各向同性)、对角(各维独立)、完整矩阵(允许任意旋转)。球状最省参数但只能画圆,完整矩阵最灵活但易过拟合,对角矩阵是折中最常用。初始化一般是先跑一遍 K-Means,用它的聚类中心作为成分均值起点;聚类数则用 BIC 或交叉验证挑选。老板此时总算明白:桶的数量不是越多越好,喷口形状也要和现实匹配。

N(x∣μ,Σ)=1(2π)D/2∣Σ∣1/2exp⁡(−12(x−μ)TΣ−1(x−μ))\displaystyle \mathcal{N}(x | \mu, \Sigma) = \frac{1}{(2\pi)^{D/2} |\Sigma|^{1/2}} \exp\left( -\frac{1}{2}(x - \mu)^T \Sigma^{-1} (x - \mu) \right)
高斯密度由归一化系数与指数衰减项组成,决定了样本越偏离中心概率越低。
  1. 偏差向量 (x−μ)(x - \mu)样本相对桶中心的位置偏移,偏移越大越不像是这桶喷的。
    x−μ\displaystyle x - \mu
  2. 马氏距离二次型用协方差逆矩阵衡量偏移的距离,椭圆簇会被“拉长”到真实的数据散布方向。
    (x−μ)TΣ−1(x−μ)\displaystyle (x - \mu)^T \Sigma^{-1} (x - \mu)
  3. 指数衰减项偏移越远,出现在该处的概率越小,形成椭圆形的概率等高线。
    exp⁡(−12(x−μ)TΣ−1(x−μ))\displaystyle \exp\left( -\frac{1}{2}(x - \mu)^T \Sigma^{-1} (x - \mu) \right)
  4. 归一化系数行列式 ∣Σ∣|\Sigma| 和 (2π)D/2(2\pi)^{D/2} 保证密度函数在全空间积分为 1,是合格的“概率配方”。
    1(2π)D/2∣Σ∣1/2\displaystyle \frac{1}{(2\pi)^{D/2} |\Sigma|^{1/2}}

八、局限与拓展

如果老板贪心,把 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 教给他的,不只是一种聚类工具,更是一种“在不确定中反复迭代逼近真相”的思维方式。掌握了它,你也就掌握了无监督学习中最优雅的概率模型之一。

BIC=Mln⁡N−2ln⁡L^\displaystyle \text{BIC} = M \ln N - 2 \ln \hat{L}
BIC 把“解释得够好”和“参数尽量少”放在天平两端,数值越小,模型越值得选。
  1. 最大似然 L^\hat{L}模型在当前数据上能达到的最优解释程度,似然越大越好。
    L^=max⁡θp(X∣θ)\displaystyle \hat{L} = \max_{\theta} p(X | \theta)
  2. 参数个数 MMGMM 的参数包括所有权重、均值、协方差元素,K 越大 MM 越大。
    M=K(1+D+D(D+1)2)−1\displaystyle M = K \left(1 + D + \frac{D(D+1)}{2}\right) - 1
  3. 惩罚项 Mln⁡NM \ln N参数越多、样本越多,惩罚越重,防止模型钻数据空子。
    Mln⁡N\displaystyle M \ln N
  4. 模型选择规则在两个模型解释力相当时,BIC 更小的一方是更稳妥的选择。
    K∗=arg⁡min⁡KBIC(K)\displaystyle K^* = \arg\min_{K} \text{BIC}(K)

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 演示

python44 行
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))
目的:用 NumPy 从零实现 GMM 的 EM 算法,并与 scikit-learn 的 GaussianMixture 结果对比,验证手写实现正确。
  1. log_prob[:, k] = ...用公式计算每个样本属于第 k 个成分的对数概率,加上小常数防止行列式为 0。
  2. log_prob -= log_prob.max(axis=1, keepdims=True)减去每行最大值再做指数,避免数值下溢。
  3. gamma = gamma / gamma.sum(axis=1, keepdims=True)归一化得到软归属概率,即 E 步的后验。
  4. mu[k] = (gamma_k * X).sum(axis=0) / Nk[k]用后验概率加权平均更新第 k 个均值。
  5. cov[k] = ((gamma_k * diff).T @ diff) / Nk[k] + 1e-6 * np.eye(d)加权散度矩阵更新协方差,并加微小正则保证可逆。
  6. 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 中后验概率的主要作用是什么?

单选题 · easy

  • A.判断模型参数量是否过多
  • B.描述样本属于各成分的概率← 正确答案
  • C.输出样本的唯一聚类标签
  • D.计算协方差矩阵的行列式

答案:B。后验概率 γnk\gamma_{nk} 是样本 xnx_n 来自第 k 个高斯成分的软归属概率,这是 GMM 软聚类的核心。A 是模型选择关心的,C 是硬聚类行为,D 只是密度公式中的一步,都与后验概率的作用不符。

Q2. EM 算法中的 E 步主要计算什么?

单选题 · easy

  • A.使用当前参数计算后验概率← 正确答案
  • B.直接更新均值与协方差
  • C.随机初始化全部模型参数
  • D.计算数据的似然函数值

答案:A。E 步固定当前参数,计算每个样本属于各成分的后验概率,为 M 步的加权统计提供依据。B 是 M 步的工作,C 发生在 EM 开始前,D 是用于监控收敛的附带操作,并非 E 步目标。

Q3. 与硬聚类 K-Means 相比,GMM 的核心优势是什么?

单选题 · easy

  • A.不需要提前设置聚类数量
  • B.能输出软归属和不确定性← 正确答案
  • C.所有簇都呈圆形形状
  • D.计算速度比 K-Means 更快

答案:B。GMM 通过后验概率输出每个样本属于各簇的置信度,并可用协方差矩阵建模椭圆簇。K-Means 输出硬标签,且假设球状簇,通常速度也更快,所以 A、C、D 都不成立。

Q4. 为什么 GMM 难以直接求极大似然估计的解析解?

单选题 · mid

  • A.因为协方差矩阵可能不可逆
  • B.因为隐变量使对数中有求和← 正确答案
  • C.因为样本特征的维度太高
  • D.因为数据集中不存在噪声

答案:B。GMM 的对数似然 ℓ(θ)=∑nln⁡∑kπkN(xn∣θk)\ell(\theta)=\sum_n \ln \sum_k \pi_k \mathcal{N}(x_n|\theta_k) 中,ln⁡\ln 无法穿过对成分的求和,导致求导方程非线性。维度高只是技术挑战,A 与 D 不是根本原因。

Q5. EM 迭代能保证下列哪一项?

单选题 · mid

  • A.一定能够找到全局最优解
  • B.每次迭代后似然值单调不减← 正确答案
  • C.协方差矩阵一定保持可逆
  • D.聚类数量会自动进行缩减

答案:B。EM 的核心保证是每轮迭代都抬高对数似然的下界,因此似然单调不减并收敛到驻点。但驻点可能是局部极大,A 错误;协方差可逆需要正则化手段,C 并非算法保证;D 中成分数 K 固定不变。

Q6. 哪一项是 EM 算法对初始值敏感的主要原因?

单选题 · mid

  • A.因为目标函数是一个凸函数
  • B.因为似然函数存在多个局部极大值← 正确答案
  • C.因为样本数量总是严重不足
  • D.因为后验概率无法被计算

答案:B。GMM 的对数似然非凸,存在多个局部极大值,初始参数决定了最终落入哪一个。若目标函数是凸函数则初始值影响小,A 恰好说反;样本数量和后验概率计算都不是主因。

Q7. 以下哪些属于 GMM 模型需要估计的参数?

多选题 · mid

  • A.混合权重 π_k← 正确答案
  • B.均值向量 μ_k← 正确答案
  • C.协方差矩阵 Σ_k← 正确答案
  • D.样本的类别标签

答案:ABC。GMM 的参数是每只“喷漆桶”的权重、位置与形状,即 π、μ、Σ;样本的类别标签是隐变量,不是待求的全局参数,而是 EM 中需要推断的未知量,因此 D 不选。

Q8. 关于 EM 的 M 步参数更新,下列说法正确的是?

多选题 · hard

  • A.均值按后验权重加权更新← 正确答案
  • B.协方差由加权散度矩阵计算← 正确答案
  • C.混合权重按有效样本数占比← 正确答案
  • D.更新过程完全不需要隐变量

答案:ABC。M 步用 E 步得到的后验概率对样本加权,重新估计均值、协方差和权重,A、B、C 描述完全准确。D 错误,因为后验概率正是隐变量的软估计,更新过程离不开隐变量信息。

Q9. 若将 GMM 的协方差矩阵限定为对角矩阵,其含义是什么?

单选题 · hard

  • A.假设各特征维度彼此独立← 正确答案
  • B.聚类簇一定呈现球状形状
  • C.无需再估计任何模型参数
  • D.只适合高维稀疏数据场景

答案:A。对角协方差假设特征之间不相关,椭圆的主轴与坐标轴平行;若各对角元素相等才退化为球状,所以 B 错误。C 显然错误,对角矩阵仍需估计 D 个方差参数;D 与对角假设无关。

Q10. 关于 GMM 的局限与拓展,下列说法正确的有?

多选题 · extreme

  • A.簇数量需先验指定或模型选择← 正确答案
  • B.在特定条件下可退化为 K-Means← 正确答案
  • C.对孤立异常点完全免疫
  • D.训练复杂度一定随样本线性增长

答案:AB。GMM 的 K 不会自动涌现,常用 BIC/AIC 选择,A 正确;当协方差相等且趋向于 0、软归属退化为硬分配时,GMM 逼近 K-Means,B 正确。高斯分布的尾巴较厚,异常点会牵引参数,C 错误;完整协方差的求逆、矩阵运算使复杂度与维度 D 的非线性有关,不能说一定线性,D 错误。