1. 引言
K-means 聚类是机器学习领域最经典、应用最广泛的无监督学习算法之一。它通过迭代计算,将数据集划分为 K 个互斥的簇(cluster),使得同一簇内的数据点尽可能相似,而不同簇间的数据点尽可能不同。由于其思想直观、实现简单、效率较高,K-means 被广泛应用于客户分群、图像分割、文档归类、异常检测等诸多场景。
本文将系统性地梳理 K-means 聚类的完整知识点,涵盖其核心思想、数学原理、算法步骤、关键参数与优化、优缺点分析以及 Python 实战示例,帮助你从零开始全面掌握这一重要算法。
2. 核心思想与目标
K-means 算法的核心思想可以概括为“物以类聚”。给定一个包含 N 个数据点的数据集和预设的簇数量 K,算法的目标是:
- 将每个数据点分配到离其最近的“簇中心”(centroid)所代表的簇中。
- 根据每个簇中所有数据点的位置,重新计算该簇的簇中心(通常取均值)。
- 不断迭代上述两个步骤,直到簇中心的位置不再发生显著变化(或达到最大迭代次数),此时认为算法收敛。
其优化的目标函数是最小化簇内平方和(Within-Cluster Sum of Squares, WCSS),也称为畸变(Distortion):
J=∑i=1K∑x∈Ci∣∣x−μi∣∣2 J = \sum_{i=1}^{K} \sum_{\mathbf{x} \in C_i} ||\mathbf{x} - \boldsymbol{\mu}_i||^2J=i=1∑Kx∈Ci∑∣∣x−μi∣∣2
其中:
- KKK是簇的个数。
- CiC_iCi是第iii个簇。
- μi\boldsymbol{\mu}_iμi是第iii个簇的质心(均值向量)。
- x\mathbf{x}x是簇CiC_iCi中的一个数据点。
- ∣∣x−μi∣∣2||\mathbf{x} - \boldsymbol{\mu}_i||^2∣∣x−μi∣∣2是数据点到其所属簇质心的欧氏距离的平方。
算法通过不断调整数据点的分配和簇中心的位置,来最小化这个目标函数JJJ。
3. 算法步骤详解
标准的 K-means 算法遵循以下步骤:
步骤 1:初始化
随机从数据集中选择 K 个点作为初始簇中心(质心)。
步骤 2:分配阶段
对于数据集中的每一个数据点,计算其到 K 个簇中心的距离(通常使用欧氏距离),并将其分配给距离最近的簇中心所对应的簇。
步骤 3:更新阶段
对于每一个簇,重新计算其质心。新的质心是该簇所有数据点的均值向量。
步骤 4:迭代
重复步骤 2(分配)和步骤 3(更新),直到满足停止条件。常见的停止条件有:
- 质心的位置变化小于某个阈值。
- 目标函数JJJ的变化小于某个阈值。
- 达到预设的最大迭代次数。
下面的流程图清晰地展示了这一迭代过程:
4. 关键参数与优化
4.1 如何选择 K 值?
K 是一个需要预先指定的超参数,其选择至关重要。
- 肘部法则(Elbow Method):绘制不同 K 值对应的 WCSS 曲线。WCSS 会随着 K 增大而减小,当 K 增加到真实簇数时,WCSS 的下降幅度会突然变缓,曲线形似“肘部”,该点对应的 K 值可作为参考。
- 轮廓系数(Silhouette Score):结合了簇内的凝聚度和簇间的分离度。轮廓系数的取值范围为 [-1, 1],值越大表示聚类效果越好。可以计算不同 K 值下的平均轮廓系数,选择使其最大化的 K。
- 业务理解:很多时候,K 值由实际应用场景决定(例如,将客户分为高、中、低价值3类)。
4.2 初始化的改进:K-means++
随机初始化可能导致算法收敛到局部最优解。K-means++ 是一种智能初始化方法:
- 随机选择第一个质心。
- 对于每个数据点,计算其与已选质心的最短距离D(x)D(x)D(x)。
- 按照D(x)2D(x)^2D(x)2的概率分布,随机选择下一个质心(距离越远的点被选中的概率越大)。
- 重复步骤 2-3,直到选出 K 个质心。
这种方法能使初始质心彼此远离,通常能获得更快、更好的收敛结果。sklearn中的KMeans默认使用init='k-means++'。
4.3 距离度量
默认使用欧氏距离,适用于连续数值型数据。对于其他类型的数据,可以考虑曼哈顿距离、余弦相似度等,但标准的 K-means 算法基于均值计算质心,与欧氏距离最小化在数学上等价。
5. 算法的优缺点
5.1 优点
- 原理简单,易于理解和实现。
- 对于大数据集,计算效率相对较高(时间复杂度约为O(N⋅K⋅I⋅d)O(N \cdot K \cdot I \cdot d)O(N⋅K⋅I⋅d),其中NNN为样本数,III为迭代次数,ddd为维度)。
- 当簇的形状为凸球形且大小相近时,效果很好。
5.2 缺点与局限性
- 需要预先指定 K 值,且 K 值选择不当会影响结果。
- 对初始质心敏感,可能收敛到局部最优(使用 K-means++ 可缓解)。
- 对噪声和离群点敏感,因为它们会显著影响均值的计算。
- 不适合发现非凸形状的簇(如环形、月牙形)。
- 对数据尺度敏感,在应用前通常需要进行标准化(如 Z-score 标准化)。
6. Python 实战示例
下面我们使用scikit-learn和matplotlib库,演示一个完整的 K-means 聚类流程。
6.1 环境准备与数据生成
importnumpyasnpimportmatplotlib.pyplotaspltfromsklearn.datasetsimportmake_blobsfromsklearn.clusterimportKMeansfromsklearn.metricsimportsilhouette_scorefromsklearn.preprocessingimportStandardScaler# 生成模拟数据X,y_true=make_blobs(n_samples=300,centers=4,cluster_std=0.60,random_state=0)plt.scatter(X[:,0],X[:,1],s=50)plt.title("原始数据")plt.show()6.2 使用肘部法则选择 K 值
# 肘部法则wcss=[]foriinrange(1,11):kmeans=KMeans(n_clusters=i,init='k-means++',max_iter=300,n_init=10,random_state=0)kmeans.fit(X)wcss.append(kmeans.inertia_)# inertia_ 属性即 WCSSplt.plot(range(1,11),wcss)plt.title('肘部法则')plt.xlabel('簇的数量 (K)')plt.ylabel('WCSS')plt.show()观察图形,WCSS 下降的“肘部”通常出现在 K=4 附近。
6.3 训练 K-means 模型并可视化
# 根据肘部法则,选择 K=4kmeans=KMeans(n_clusters=4,init='k-means++',max_iter=300,n_init=10,random_state=0)y_kmeans=kmeans.fit_predict(X)# 可视化聚类结果plt.scatter(X[y_kmeans==0,0],X[y_kmeans==0,1],s=50,c='lightblue',label='簇 1')plt.scatter(X[y_kmeans==1,0],X[y_kmeans==1,1],s=50,c='orange',label='簇 2')plt.scatter(X[y_kmeans==2,0],X[y_kmeans==2,1],s=50,c='green',label='簇 3')plt.scatter(X[y_kmeans==3,0],X[y_kmeans==3,1],s=50,c='red',label='簇 4')# 绘制质心plt.scatter(kmeans.cluster_centers_[:,0],kmeans.cluster_centers_[:,1],s=200,c='black',marker='X',label='质心')plt.title('K-means 聚类结果')plt.legend()plt.show()print(f"簇中心坐标:\n{kmeans.cluster_centers_}")print(f"轮廓系数:{silhouette_score(X,y_kmeans):.4f}")6.4 对非球形数据的局限性演示
fromsklearn.datasetsimportmake_moons# 生成月牙形数据X_moons,_=make_moons(n_samples=200,noise=0.05,random_state=0)kmeans_moons=KMeans(n_clusters=2,random_state=0)y_moons_pred=kmeans_moons.fit_predict(X_moons)plt.scatter(X_moons[:,0],X_moons[:,1],c=y_moons_pred,s=50,cmap='viridis')plt.scatter(kmeans_moons.cluster_centers_[:,0],kmeans_moons.cluster_centers_[:,1],s=200,c='red',marker='X')plt.title('K-means 对非凸形状聚类效果不佳')plt.show()可以看到,K-means 无法正确划分月牙形数据,此时应考虑 DBSCAN 或谱聚类等算法。
7. 总结与扩展
K-means 是聚类分析的基石。掌握其原理、实现和局限性,是学习更复杂聚类算法(如 DBSCAN、层次聚类、高斯混合模型)的良好起点。
在实际应用中,请注意:
- 数据预处理:务必进行标准化/归一化。
- 多次运行:由于随机初始化,可以多次运行算法(
n_init参数)并选择最优结果。 - 结合业务验证:聚类结果最终需要结合业务知识进行解读和验证。
- 探索变体:如 K-medoids(对离群点更鲁棒)、Mini-Batch K-means(适用于大数据集)。
希望这篇完整的知识点梳理能帮助你深入理解并有效应用 K-means 聚类算法。