Chapter 09

聚类分析

发现数据中隐藏的分组结构——从 K-means 到密度聚类与降维可视化

01

核心概念

聚类(Clustering)是一种无监督学习方法,目标是将数据样本划分为若干组(簇),使得同组样本相似度高,不同组样本差异大。与分类不同,聚类事先不知道类别标签,完全由数据自身结构驱动。

K-means 算法

K-means 是最经典、最常用的划分式聚类算法。其核心思想是:给定簇数 K,迭代优化每个样本到所属簇中心的距离之和。

K-means 迭代步骤
  1. 随机选择 K 个样本作为初始簇中心(centroids)。
  2. 分配步骤:将每个样本指派到距离最近的簇中心,形成 K 个簇。
  3. 更新步骤:重新计算每个簇的均值,作为新的簇中心。
  4. 重复步骤 2-3,直到簇中心不再显著变化或达到最大迭代次数。
J = \sum_{i=1}^{K} \sum_{x \in C_i} \| x - \mu_i \|^2

其中 J 为 inertia(簇内平方和),\mu_i 为第 i 个簇的中心。K-means 的目标是最小化 J。

K 值选择:肘部法则

实际应用中 K 往往未知。肘部法则(Elbow Method)通过绘制不同 K 对应的 inertia,寻找曲线的"肘部"——即 inertia 下降速率明显变缓的点,作为合理的 K 值。

层次聚类

层次聚类不需要预先指定 K,它通过自底向上(凝聚式)或自顶向下(分裂式)的方式构建树状结构(Dendrogram)。凝聚式从每个样本作为一个簇开始,逐步合并最相近的簇,直到所有样本归于一个簇。

距离度量与链接方式

层次聚类的关键在于如何定义簇间距离。常用链接方式包括:单链接(最近邻)、全链接(最远邻)、平均链接、Ward 法(最小化合并后的簇内方差)。Ward 法在实践中效果较为稳健。

DBSCAN 密度聚类

DBSCAN(Density-Based Spatial Clustering of Applications with Noise)基于密度而非距离,能够发现任意形状的簇,并自动识别噪声点。它不需要预设簇数,但需要两个参数:

DBSCAN 将样本分为三类:核心点(邻域内样本数 \ge min_samples)、边界点(在核心点邻域内但自身不是核心点)、噪声点(非核心点也非边界点)。

轮廓系数

轮廓系数(Silhouette Coefficient)衡量聚类效果,取值范围为 [-1, 1]。对于单个样本 i:

s(i) = \frac{b(i) - a(i)}{\max\{a(i), b(i)\}}

其中 a(i) 为样本 i 到同簇其他样本的平均距离(凝聚度),b(i) 为样本 i 到最近异簇样本的平均距离(分离度)。s(i) 接近 1 表示聚类合理,接近 -1 表示样本可能被分错簇。

高斯混合模型 GMM

GMM 假设数据由 K 个高斯分布混合生成,通过期望最大化(EM)算法迭代估计每个分布的均值、协方差和混合权重。与 K-means 的硬分配不同,GMM 给出样本属于每个簇的概率(软分配),对椭圆形状簇更友好。

降维可视化

高维数据的聚类结果难以直观理解。PCA(主成分分析)通过线性变换将数据投影到低维空间,保留最大方差;t-SNE 通过概率分布匹配保留局部邻域结构,更适合聚类结果的可视化展示。

02

算法原理与计算方法

K-means 迭代计算示例

假设二维空间有 6 个样本,设 K=2,初始中心为 (1,1) 和 (4,4):

迭代簇中心 1簇中心 2Inertia
0(1.0, 1.0)(4.0, 4.0)
1(1.3, 1.3)(4.2, 4.0)2.84
2(1.3, 1.3)(4.5, 4.0)2.56
3(1.3, 1.3)(4.5, 4.0)2.56(收敛)

每次迭代中,先按欧氏距离分配样本,再按簇内均值更新中心。当两次迭代的中心位移小于阈值时停止。

轮廓系数计算流程

以样本 i 为例:

  1. 计算 a(i):样本 i 到同簇所有其他样本距离的平均值。
  2. 对每个其他簇 C,计算 i 到 C 中所有样本距离的平均值,取最小值作为 b(i)。
  3. 代入公式计算 s(i)。
  4. 所有样本的 s(i) 的均值为整体轮廓系数。
工程应用场景
  • 客户细分:根据消费行为将用户分群,实现精准营销。
  • 异常检测:远离所有簇中心或无法归入任何密度簇的样本即为异常。
  • 文档聚类:对新闻、论文进行主题聚类,辅助信息检索。
  • 图像分割:基于颜色或纹理特征将像素聚类,实现区域分割。
  • 基因表达聚类:发现功能相近的基因群组,辅助生物标记物识别。
03

Python 代码实践

使用 sklearn 进行 K-means 聚类

Python
from sklearn.cluster import KMeans from sklearn.datasets import make_blobs import matplotlib.pyplot as plt # 生成模拟数据:3个中心 X, y_true = make_blobs(n_samples=300, centers=3, cluster_std=0.60, random_state=42) # 训练 K-means kmeans = KMeans(n_clusters=3, random_state=42, n_init='auto') labels = kmeans.fit_predict(X) centers = kmeans.cluster_centers_ # 可视化 plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis', s=30) plt.scatter(centers[:, 0], centers[:, 1], c='red', s=200, marker='X', label='Centers') plt.title('K-means Clustering (K=3)') plt.legend() plt.show() # 输出 inertia print(f"Inertia: {kmeans.inertia_:.2f}")

肘部法则选 K

Python
import numpy as np inertias = [] K_range = range(1, 10) for k in K_range: km = KMeans(n_clusters=k, random_state=42, n_init='auto') km.fit(X) inertias.append(km.inertia_) plt.plot(K_range, inertias, 'bo-') plt.xlabel('Number of Clusters K') plt.ylabel('Inertia') plt.title('Elbow Method') plt.show()

DBSCAN 密度聚类

Python
from sklearn.cluster import DBSCAN from sklearn.preprocessing import StandardScaler # 数据标准化 X_scaled = StandardScaler().fit_transform(X) # DBSCAN 聚类 dbscan = DBSCAN(eps=0.5, min_samples=5) db_labels = dbscan.fit_predict(X_scaled) # 统计结果 n_clusters = len(set(db_labels)) - (1 if -1 in db_labels else 0) n_noise = list(db_labels).count(-1) print(f"Estimated clusters: {n_clusters}, Noise points: {n_noise}")

轮廓系数评估与 PCA 可视化

Python
from sklearn.metrics import silhouette_score from sklearn.decomposition import PCA # 轮廓系数 score = silhouette_score(X, labels) print(f"Silhouette Score: {score:.3f}") # PCA 降维可视化 pca = PCA(n_components=2) X_pca = pca.fit_transform(X) plt.scatter(X_pca[:, 0], X_pca[:, 1], c=labels, cmap='Set2', edgecolor='k', s=40) plt.title('PCA Projection of Clusters') plt.xlabel(f"PC1 ({pca.explained_variance_ratio_[0]:.1%})") plt.ylabel(f"PC2 ({pca.explained_variance_ratio_[1]:.1%})") plt.show()
04

例题与解析

例题 1:K-means 聚类计算

给定一维数据点 {2, 4, 10, 12, 20, 22},设 K=2,初始中心为 {3, 18}。请执行一次 K-means 迭代(分配 + 更新),给出新的簇中心。

解析

分配步骤:计算各点到中心 3 和 18 的距离。

  • 2:|2-3|=1, |2-18|=16 → 簇1
  • 4:|4-3|=1, |4-18|=14 → 簇1
  • 10:|10-3|=7, |10-18|=8 → 簇1
  • 12:|12-3|=9, |12-18|=6 → 簇2
  • 20:|20-3|=17, |20-18|=2 → 簇2
  • 22:|22-3|=19, |22-18|=4 → 簇2

更新步骤:簇1 = {2,4,10},均值 = (2+4+10)/3 = 5.33;簇2 = {12,20,22},均值 = (12+20+22)/3 = 18。

答案:新中心为 5.33 和 18.0。注意 10 虽然在数值上接近 12,但在本次迭代中仍被分到簇1。
例题 2:肘部法则选 K

某数据集在不同 K 下的 inertia 如下表,请用肘部法则选择最合适的 K。

K123456
Inertia8003201501109582
解析

计算相邻 K 的 inertia 下降量:K=1→2 下降 480,2→3 下降 170,3→4 下降 40,4→5 下降 15,5→6 下降 13。

从 K=2 到 K=3 仍有较大下降,但从 K=3 到 K=4 下降明显变缓(仅 40),曲线在 K=3 处形成"肘部"。

答案:K=3 是肘部点,是最合理的选择。继续增加 K 带来的收益递减,且可能导致过拟合。
例题 3:DBSCAN 密度聚类判断

设 eps=2,min_samples=3。某样本点 p 的 eps 邻域内包含 2 个样本(含自身共 3 个)。另一样本 q 距离 p 为 1.5,但 q 的 eps 邻域内只有自身 1 个样本。请问 p 和 q 分别属于什么类型?

解析

对于 p:eps 邻域内有 3 个样本,满足 min_samples=3,因此 p 是核心点

对于 q:虽然 q 在 p 的 eps 邻域内,但 q 自身的 eps 邻域内只有 1 个样本(< 3),不满足核心点条件。由于 q 位于核心点 p 的邻域内,q 是边界点

答案:p 为核心点,q 为边界点。若某点不在任何核心点的 eps 邻域内,则为噪声点。
例题 4:轮廓系数评估

某样本 i 到同簇 3 个其他样本的距离分别为 2, 3, 5;到最近异簇 4 个样本的距离分别为 6, 7, 8, 9。计算 s(i)。

解析

a(i) = (2 + 3 + 5) / 3 = 10 / 3 ≈ 3.33

b(i) = (6 + 7 + 8 + 9) / 4 = 30 / 4 = 7.5

s(i) = (7.5 - 3.33) / max(3.33, 7.5) = 4.17 / 7.5 ≈ 0.556

答案:s(i) ≈ 0.556,说明该样本聚类效果较好(大于 0.5)。
← 上一章:决策树与集成学习 下一章:神经网络与深度学习 →