K-Means 聚类:划分式聚类与肘部法则
K-Means 聚类:划分式聚类与肘部法则
什么是聚类?为什么需要 K-Means?
聚类是一种无监督学习技术,目标是将数据集中的样本划分成若干个互不相交的子集(簇),使得同一簇内的样本彼此相似,不同簇之间的样本差异尽可能大。与分类不同,聚类不需要预先标注的标签,完全依靠数据本身的分布特征进行模式发现。
K-Means 是聚类算法中最经典、应用最广泛的划分式聚类方法。它的名字来源于:
- K:需要预先指定的簇数量
- Means:每个簇由其内部所有点的均值(中心)来表示
如果你第一次接触聚类,可以把 K-Means 想象成“把一堆彩色小球自动分成 K 堆,每堆围绕一个中心点”的过程。
划分式聚类:一种“硬分配”策略
在聚类算法大家族中,主要有以下几种思路:
- 划分式聚类:预先指定簇数,迭代优化分配,典型代表就是 K-Means 和 K-Medoids。
- 层次聚类:自下而上合并或自上而下分裂,形成树状结构,无需预设 K。
- 密度聚类:如 DBSCAN,根据样本分布的密度连接区域形成簇,能识别噪声。
- 模型聚类:假设数据由若干概率分布混合生成,如高斯混合模型(GMM)。
划分式聚类的特点在于:每个样本必须且只能属于一个簇(硬聚类),算法通过不断调整分配和更新中心来最小化簇内误差。这种方式简单高效,特别适合处理凸形、大小相近、密度均匀的簇。
K-Means 算法核心原理
目标函数:最小化簇内误差平方和
K-Means 优化的目标是用数学语言寻找一种划分 ( C = {C_1, C_2, \dots, C_K} ),使得所有样本到其所属簇中心的距离平方和(Sum of Squared Errors, SSE)最小:
[ SSE = \sum_{i=1}^{K} \sum_{x \in C_i} | x - \mu_i |^2 ]
其中 ( \mu_i ) 是第 ( i ) 个簇的中心(均值向量),( | \cdot | ) 表示欧氏距离。直观上说,SSE 越小,簇内样本越紧凑,聚类效果越好。
算法步骤详解
K-Means 通过迭代执行以下两步来逼近最优解:
-
初始化:随机选择 K 个样本点作为初始聚类中心 ( \mu_1, \mu_2, \dots, \mu_K )。
(更健壮的做法是使用 K-Means++ 初始化,让初始中心尽可能远离彼此,避免陷入不良局部最优。) -
分配步骤(Assignment Step):
遍历每个样本 ( x ),计算它到所有 K 个中心的距离,将其分配到距离最近的中心所对应的簇: [ C_i^{(t)} = \left{ x : | x - \mu_i^{(t)} |^2 \le | x - \mu_j^{(t)} |^2, \forall j \ne i \right} ] -
更新步骤(Update Step):
对每个簇,重新计算该簇内所有样本的均值,并将该均值作为新的聚类中心: [ \mu_i^{(t+1)} = \frac{1}{|C_i^{(t)}|} \sum_{x \in C_i^{(t)}} x ] -
判断收敛:重复步骤 2 和 3,直到中心点不再变化(或变化极小),或者达到最大迭代次数。此时算法收敛,输出最终的簇划分。
整个过程的动态效果就像每个中心点慢慢“移动”到各簇的几何中心,样本则在一次次分配中逐渐稳定。
关键问题:如何确定“K”值?——肘部法则
K-Means 必须预先给定簇的数量 K。选得太小,不同性质的样本会被强行合并;选得太大,簇会过度分裂,失去聚类的意义。肘部法则(Elbow Method) 是最直观、最常用的 K 值选择方法。
肘部法则的步骤
- 对一系列候选 K 值(例如 1 到 10),分别运行 K-Means 算法。
- 记录每个 K 对应的最终 SSE(或称为畸变程度 distortion)。
- 以 K 为横坐标,SSE 为纵坐标绘制折线图。
- 观察曲线的“拐点”——随着 K 增大,SSE 自然下降(因为簇越多,每个簇内部越紧凑),但下降幅度会逐渐减小。拐点前后的斜率变化剧烈,形似人的肘部,这个点对应的 K 就是相对合理的簇数。
示例理解
假设我们对一组二维数据计算 K=1 到 K=6 的 SSE,得到:
- K=1:SSE=1200
- K=2:SSE=800
- K=3:SSE=520
- K=4:SSE=480
- K=5:SSE=450
- K=6:SSE=430
绘制曲线后发现在 K=3 处下降最陡,之后趋于平缓,则肘部法建议采用 K=3。
注意事项
肘部法则并非万能:
- 有时曲线下降平滑,拐点不明显,难以肉眼判断。
- 可配合轮廓系数(Silhouette Coefficient) 等更客观的指标交叉验证。
- 实际业务需求往往比统计指标更重要——有时 K 需要由应用场景直接规定。
K-Means 的优缺点
优点:
- 原理简单,实现容易,计算速度快,适合大规模数据集。
- 对凸形簇、分布紧凑的数据效果很好。
- 结果易于解释,每个簇都有明确的中心点。
缺点:
- 必须预先指定 K,选择不当影响结果。
- 对初始中心点敏感,随机初始化可能导致不同的聚类结果(使用 K-Means++ 可缓解)。
- 对异常值/噪声敏感:少量极端值会严重拉偏中心,因为均值不具备稳健性(可考虑改用 K-Medoids)。
- 假设簇是球形、大小相近,对细长形、环形等不规则分布效果差。
- 欧氏距离在高维空间中可能失效,需注意维度灾难和特征标准化。
实战:Python 代码速览
以下通过 scikit-learn 快速演示 K-Means 及肘部法则的应用(示例在二维数据上)。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
# 生成模拟数据
X, y = make_blobs(n_samples=300, centers=4, cluster_std=0.6, random_state=0)
# 肘部法则:计算不同 K 的 SSE
sse = []
for k in range(1, 11):
kmeans = KMeans(n_clusters=k, init='k-means++', random_state=42)
kmeans.fit(X)
sse.append(kmeans.inertia_) # inertia_ 就是 SSE
# 绘制肘部曲线
plt.figure(figsize=(8, 5))
plt.plot(range(1, 11), sse, marker='o')
plt.xlabel('Number of clusters (K)')
plt.ylabel('SSE')
plt.title('Elbow Method for Optimal K')
plt.show()
# 根据肘部法选择 K=4,训练最终模型
kmeans = KMeans(n_clusters=4, init='k-means++', random_state=42)
y_kmeans = kmeans.fit_predict(X)
# 可视化聚类结果
plt.scatter(X[:, 0], X[:, 1], c=y_kmeans, cmap='viridis', s=50, alpha=0.8)
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1],
c='red', marker='x', s=200, label='Centroids')
plt.legend()
plt.title('K-Means Clustering (K=4)')
plt.show()
运行后你会看到肘部曲线在 K=4 处有明显拐点,聚类结果中红色叉号就是最终的簇中心。
进阶须知:让 K-Means 更好工作
-
特征标准化
如果特征尺度差异大(比如身高单位 cm,体重单位 kg),距离计算会被大尺度的特征主导。必须使用标准化(如 StandardScaler)将所有特征缩放到相似范围。 -
K-Means++ 初始化
不要用纯粹的随机初始化,改用init='k-means++',它能显著提高收敛速度并减少陷入局部最优的概率。 -
高维数据注意
维度超过几十维后,欧氏距离会趋于一致,聚类效果变差。可先用 PCA 降维,或考虑子空间聚类等方法。 -
评估不止 SSE
肘部法是选择 K 的起点,但还应结合轮廓系数、戴维森堡丁指数或具体业务指标,才能做出可靠决策。 -
异常值处理
如果数据中存在极端离群点,可先进行异常检测并剔除,或改用对离群点鲁棒的 K-Medoids 算法。
总结
K-Means 作为划分式聚类的代表,凭借其简洁高效的特性,在客户分群、图像压缩、文档归类、异常检测预处理等众多领域获得了广泛应用。通过肘部法则,初学者也能较科学地确定合适的簇数,迈出聚类分析的第一步。掌握其核心思想、目标函数、初始化策略以及局限性,你就能在实际项目中灵活调优,挖掘出数据中隐含的群体结构。
现在,不妨找一份感兴趣的数据集,亲手实现一次完整的 K-Means 聚类流程,从数据预处理到 K 值选择,再到结果解释——实践是深入理解的最佳途径!