第 08 章:概率模型聚类

第 08 章:概率模型聚类

“上帝不掷骰子,但数据科学家掷。” —— 改编自爱因斯坦

之前的聚类算法(K-Means, DBSCAN)都有一个共同特征:硬聚类 (Hard Clustering)
一个样本要么属于 A,要么属于 B,没有中间地带。
这就像把人简单分为“好人”和“坏人”,丢失了人性的复杂灰度。

在实际的文本分析场景中,我们经常遇到这种情况:

用户工单:”快递员态度太差了,而且还不给我送上楼,我要退款!”

这句话既涉及【物流服务】,又涉及【退款流程】。如果硬把它归为某一类,就会丢失另一半信息。
本章我们将介绍 高斯混合模型 (GMM, Gaussian Mixture Model),它引入了 软聚类 (Soft Clustering) 的概念,告诉我们:这个样本 70% 是物流问题,30% 是退款问题。

GMM 软聚类示意图
(图注:软聚类允许一个点同时属于多个簇。颜色混合的区域表示不确定性高的“骑墙派”。)


1. 核心概念:世界是由“钟形曲线”组成的

1.1 什么是 GMM?

GMM 的核心假设非常简单:数据不是一堆无规律的石头,而是一堆叠加在一起的
具体来说,所有数据都是由 $K$ 个高斯分布(Gaussian Distribution,也就是正态分布/钟形曲线)混合而成的。

想象你在操场上看到一堆人。

  • 有一群打篮球的男生,平均身高 180cm(波峰),但也有些矮个和高个(波宽)。
  • 有一群跳健美操的女生,平均身高 165cm。
  • 如果你只看身高数据,你会看到两个叠加在一起的“钟形曲线”。

GMM 的任务就是把这两个混在一起的钟形曲线拆解出来。

1.2 三个关键参数:给簇“塑形”

为了描述一个高斯分布(一个簇),我们需要三个参数。我们可以把这想象成捏泥人:

  1. $\mu$ (均值 Mean)位置。决定了钟形曲线的最高点(簇中心)在哪里。
  2. $\Sigma$ (协方差 Covariance)形状
    • 决定了钟形曲线是胖是瘦,是圆是扁。
    • 这是 GMM 相比 K-Means 的最大优势。K-Means 只能找正圆形的簇,而 GMM 通过协方差矩阵,可以拟合细长的椭圆形。
  3. $\pi$ (权重 Weight)高度。决定了这个簇里有多少人。

$$ P(x) = \sum_{k=1}^K \pi_k \mathcal{N}(x | \mu_k, \Sigma_k) $$

(公式含义:任意一个点出现的概率,等于它属于第1个簇的概率 + 属于第2个簇的概率 + …)

GMM 三大参数
(图注:μ 决定簇的位置,Σ 决定簇的形状(圆形/椭圆),π 决定簇的权重大小。)


2. 怎么解?EM 算法的“食堂打饭”隐喻

我们要解出这三个参数,但是有个“鸡生蛋,蛋生鸡”的难题:

  • 蛋 (标签):如果我们知道每个人属于哪一队(篮球/健美操),我们就能算出每一队的平均身高 ($\mu$) 和身形标准差 ($\Sigma$)。
  • 鸡 (参数):如果我们知道每一队的平均身高和身形标准差,我们就能算出某个人属于哪一队的概率。
  • 死锁:现在我们既不知道标签,也不知道参数。

于是我们有了 EM 算法 (Expectation-Maximization)。这就好比食堂排队打饭:

EM 算法流程
(图注:EM 算法是一个迭代优化的过程。E步计算归属概率,M步更新分布参数,以此往复直到收敛。)

  1. 初始化 (瞎猜):随便先画两个圈,假装这是两个队。
  2. E-Step (期望步 / 站队)
    • 根据目前的圈(参数),每个人计算自己属于每个圈的概率。
    • “我身高 175,看起来有 60% 的可能属于篮球队,40% 的可能属于健美操队。”(注意:这里不是非黑即白,而是按比例站队)。
  3. M-Step (最大化步 / 调整圈)
    • 根据大家站队的结果(加权),重新计算每个圈的中心和形状。
    • “既然这 0.6 个人属于篮球队,那篮球队的平均身高得往他这边挪一点点。”
  4. Loop (循环):重复 2 和 3,直到大家都不再换队,圈也不再移动(收敛)。

3. 技术对比:K-Means vs GMM

特性 K-Means GMM (高斯混合模型)
聚类性质 硬聚类 (0 或 1) 软聚类 (概率分布,如 [0.8, 0.2])
簇形状 只能是正圆 (球体) 可以是任意方向的椭圆
参数量 少 (只有中心) 多 (中心 + 协方差矩阵)
计算速度 快 (线性复杂度) 较慢 (涉及矩阵求逆,迭代次数多)
适用场景 大规模数据,简单的硬划分 需要概率输出,簇有重叠,形状扁长
本质关系 K-Means 是 GMM 的特例 当 GMM 的方差极小且相等时,就变成了 K-Means

K-Means vs GMM 簇形状对比
(图注:左图 K-Means 强行把扁长的簇切成了两半;右图 GMM 完美拟合了椭圆形的分布。)


4. 实际应用场景:模糊地带的价值

虽然在通用聚类任务上 K-Means 是老大,但在以下场景中,GMM 的“骑墙派”特性具有极大的商业价值。

场景 A:用户画像中的“多重身份”

有些用户是复杂的。

  • K-Means:把用户 A 强行归为“价格敏感型”。
  • GMM:告诉我们用户 A [0.6 价格敏感, 0.4 品质追求]
  • 决策:对于这种用户,我们不仅要推优惠券(满足 0.6),还要推一些高性价比的品牌货(满足 0.4),而不是只推 9.9 包邮的垃圾。

场景 B:异常检测与风控

GMM 可以输出每个样本的似然度 (Likelihood),也就是“这个样本属于当前这个世界的概率”。

  • 如果一个样本算出来的概率极低(比如 $10^{-5}$),说明它不属于任何一个现有的正常簇。
  • 结论:这大概率是一笔欺诈交易或者一个异常工单

场景 C:不确定性筛选

  • 策略:筛选出那些最大概率小于 0.6 的样本(即 max(probs) < 0.6)。
  • 含义:这些样本是模型“拿不准”的。它们往往是脏数据,或者是蕴含了新趋势的边缘案例,值得在这个子集上投入人工复核。

GMM 应用场景
(图注:软聚类的概率输出在用户画像、异常检测、不确定性筛选中具有独特价值。)


5. 模型选择:奥卡姆剃刀

GMM 也面临和 K-Means 一样的问题:K (n_components) 选多少?
K 越大,模型肯定拟合得越好(误差越小),但这可能只是死记硬背(过拟合)。我们需要一个裁判,在“拟合得好”和“模型简单”之间找平衡。这叫奥卡姆剃刀原理如无必要,勿增实体。

我们引入两个信息准则作为裁判:AICBIC

5.1 核心公式拆解

它们的公式长得很像,都由两部分组成:

$$ \text{Score} = \underbrace{-2\ln(\hat{L})}{\text{坏处:拟合误差}} + \underbrace{\alpha \cdot k}{\text{惩罚:模型复杂度}} $$

  1. 第一项(拟合误差):$\hat{L}$ 是似然度,代表模型对数据的解释能力。拟合得越好,$\hat{L}$ 越大,$-2\ln(\hat{L})$ 就越小。我们希望这项越小越好
  2. 第二项(复杂度惩罚):$k$ 是参数个数(模型越复杂,$k$ 越大)。我们希望这项也越小越好

所以,我们的目标是找一个 K 值,使得 AIC 或 BIC 最小

5.2 AIC vs BIC:选哪个裁判?

准则 全称 惩罚力度 倾向性 隐喻
AIC 赤池信息量准则 宽松 ($\alpha=2$) 允许模型稍微复杂一点,只要预测得准。 “实用主义者”:只要衣服穿着好看,贵点也没关系。
BIC 贝叶斯信息量准则 严厉 ($\alpha=\ln(n)$) 随着样本量 $n$ 增加,惩罚极重。倾向于更简单的模型。 “极简主义者”:衣服必须性价比极高,稍微贵一点都不要。

👑 推荐:在聚类任务中,我们通常希望找到数据的“真实结构”,而不只是为了预测。而且聚类很容易过拟合。因此,BIC 是更好的选择。它能帮你砍掉那些不必要的簇,给你一个最精简的分类。

BIC 模型选择
(图注:BIC 曲线在最佳 K 处达到最低点,平衡了拟合程度和模型复杂度。)


6. 代码实战:Scikit-Learn 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
from sklearn.mixture import GaussianMixture
from sklearn.datasets import make_blobs
import numpy as np

# 1. 准备数据
X, _ = make_blobs(n_samples=500, centers=3, cluster_std=1.5)

# 2. 训练 GMM
# n_components: 簇的数量 (K)
# covariance_type='full': 允许任意形状的椭圆 (最灵活但参数最多)
gmm = GaussianMixture(n_components=3, covariance_type='full', random_state=42)
gmm.fit(X)

# 3. 结果分析

# A. 硬聚类结果 (和 K-Means 类似,返回 0, 1, 2)
labels = gmm.predict(X)

# B. 软聚类概率 (GMM 的灵魂)
# 返回 shape (N, 3),每一行加起来等于 1
probs = gmm.predict_proba(X)

# 看看第一个点的情况
print(f"样本 0 的归属概率: {probs[0]}")
# 可能输出: [0.05, 0.90, 0.05] -> 很有把握是簇 1
# 可能输出: [0.40, 0.50, 0.10] -> 骑墙派,位于簇 0 和 1 的交界处

# 4. 模型选择 (AIC/BIC)
n_components_range = range(1, 10)
bics = []
for n in n_components_range:
    gmm_test = GaussianMixture(n_components=n, random_state=42).fit(X)
    bics.append(gmm_test.bic(X))

# 找 BIC 最小的那个 K
best_k = n_components_range[np.argmin(bics)]
print(f"BIC 建议的最佳簇数: {best_k}")

7. 实践要点

  1. 预热 (Warm Start):EM 算法很容易陷入局部最优。聪明的做法是先跑一遍 K-Means,用 K-Means 找到的中心点作为 GMM 的初始均值 ($\mu$)。sklearn 默认就是这么做的 (init_params='kmeans')。
  2. 维度灾难预警
    • GMM 的参数量随着维度平方级增长(因为要算 $D \times D$ 的协方差矩阵)。
    • 禁忌:千万不要在 768 维的 BERT 向量上直接跑 covariance_type='full' 的 GMM。矩阵会不可逆,模型会过拟合。
    • 对策:必须先降维(如 PCA 到 50 维以内),或者强制把协方差矩阵设为 diag(只算对角线,假设特征独立)或 spherical(球形,退化为类似 K-Means)。

下一章预告

我们讲了 K-Means, DBSCAN, 层次聚类, GMM…
每种算法跑出来的结果都不一样。

  • K-Means 说分 5 类好。
  • DBSCAN 说分 3 类好,还有一堆噪声。
  • GMM 说分 4 类 BIC 最小。

到底哪个结果是好的?没有标准答案(真实标签)的情况下,我们如何给无监督学习打分?
这需要引入一套全新的评估体系

👉 第 09 章:聚类评估方法

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×