K-means 聚类算法详解:从原理到实战

发布时间:2026/6/30 22:49:41
K-means 聚类算法详解:从原理到实战 K-means 聚类算法详解从原理到实战什么是 K-means 聚类含义概念算法实现流程API 详解核心参数常用方法案例实战鸢尾花数据聚类效果评估方法肘部法则Elbow Method轮廓系数Silhouette ScoreCH 指数Calinski-Harabasz Index特征降维基本思想经典应用无监督学习中最经典、最常用的聚类算法之一凭借思想简洁、实现高效长期活跃在客户分群、图像压缩、异常检测等众多场景中。本文从直观理解出发依次讲解算法原理、sklearn API 用法、完整实现流程、效果评估方法以及如何借助 K-means 完成特征降维。什么是 K-means 聚类含义概念K-means 是一种无监督学习算法它会在没有标签的数据集中自动把相似的样本归到同一个簇使得同簇内样本尽可能相似不同簇之间尽可能不同。这里有两个关键角色K你想把数据分成多少个簇需要人为指定。means每个簇用一个均值点簇中心 / 质心centroid来代表质心就是该簇内所有样本坐标的平均值。其实K-means聚类算法和KNN算法思想很接近详情可以跳转-- KNN算法详解从原理到实践入门举例说明假设你是一家连锁超市的店长手里有 300 位会员的两项数据年消费金额和到店频次。你希望把顾客分成几类以便做精准营销。一开始这些点散落在坐标图上看不出明显规律。你猜测大概可以分成 3 类于是启动 K-means算法随机放上 3 个质心点可以理解为 3 面旗帜。每位顾客看看自己离哪面旗帜最近就站到那面旗下——这一步叫分配。每面旗下重新计算所有顾客的平均位置把旗帜移到这个新位置——这一步叫更新。旗帜移动后可能有些顾客发现另一面旗更近于是换队。重复分配→更新直到旗帜不再移动算法收敛。最终结果如下图所示顾客被清晰地分成了三个群体三个簇的现实含义非常直观红色簇消费低、到店少——可能是偶发顾客或流失边缘适合用优惠券唤醒。蓝色簇消费和频次中等——主力家庭客户重点维护。绿色簇消费高、频次高——VIP 高价值客户提供专属服务。这就是 K-means 的威力你不需要事先告诉算法谁是 VIP它仅凭数据本身的分布结构就能帮你发现群体。算法实现流程K-means 的标准流程可以归纳为以下四步循环执行直至收敛步骤 1选择 K 值并初始化由业务需求或数据探索决定簇的数量 K。这是 K-means 唯一的核心超参数后文会介绍如何用肘部法则、轮廓系数辅助选 K。然后从数据中随机挑选 K 个点作为初始质心。步骤 2分配样本对每个样本计算它到 K 个质心的欧氏距离把它分配给最近的那个质心所在的簇。步骤 3更新质心对每个簇重新计算簇内所有样本的均值作为新的质心。步骤 4判断收敛如果质心几乎不再移动变化量小于阈值tol或达到最大迭代次数max_iter算法停止否则回到步骤 2 继续迭代。整个过程的目标函数是最小化所有样本到其所属质心的平方距离之和称为 SSESum of Squared Errors也叫 inertiaJ ∑ j 1 K ∑ x ∈ C j ∥ x − μ j ∥ 2 J \sum_{j1}^{K} \sum_{x \in C_j} \left\| x - \mu_j \right\|^2Jj1∑K​x∈Cj​∑​∥x−μj​∥2需要说明的是K-means 只能保证收敛到一个局部最优而非全局最优。这也是为什么 sklearn 会用n_init参数多次运行取最优结果的原因。API 详解scikit-learn 提供了sklearn.cluster.KMeans类是目前 Python 生态中最常用的实现。大数据集用 MiniBatchKMeans。当样本量超过 1 万标准 K-means 会明显变慢。sklearn.cluster.MiniBatchKMeans用小批量样本更新质心速度提升数倍结果接近。核心参数classsklearn.cluster.KMeans(n_clusters8,initk-means,n_initauto,max_iter300,tol1e-4,verbose0,random_stateNone,copy_xTrue,algorithmlloyd)参数默认值说明n_clusters8聚类簇数 Kinitk-means质心初始化方式可选k-means、random、数组或可调用对象n_initauto用不同随机种子运行的次数取 inertia 最小的结果。auto时若initk-means则跑 1 次若initrandom则跑 10 次max_iter300单次运行的最大迭代次数tol1e-4质心变化的收敛阈值Frobenius 范数小于该值即停止random_stateNone随机种子设为整数可复现结果algorithmlloyd算法变体lloyd为经典 EM 风格elkan利用三角不等式在某些数据上更快但更耗内存常用方法fit(X)对数据 X 进行聚类。fit_predict(X)聚类并直接返回每个样本的簇标签等价于fit(X).labels_。predict(X)用已拟合的模型预测新样本属于哪个簇。transform(X)将 X 转换到到各质心距离的空间形状(n_samples, n_clusters)可用于特征降维。fit_transform(X)等价于fit(X).transform(X)但更高效。案例实战鸢尾花数据聚类下面用经典的鸢尾花数据集演示完整流程。虽然鸢尾花本身有标签但我们在聚类时假装不知道标签纯粹用四个特征花萼长宽、花瓣长宽做无监督聚类最后再和真实标签对比。完整代码importnumpyasnpimportmatplotlib.pyplotaspltfromsklearn.clusterimportKMeansfromsklearn.datasetsimportload_irisfromsklearn.metricsimportsilhouette_scorefromsklearn.preprocessingimportStandardScaler# 设置中文字体plt.rcParams[font.sans-serif][SimHei]plt.rcParams[axes.unicode_minus]False# 1. 加载数据irisload_iris()Xiris.data# 四个特征y_trueiris.target# 真实标签仅用于最后对比聚类时不使用# 2. 标准化K-means 基于距离对量纲敏感务必标准化scalerStandardScaler()X_scaledscaler.fit_transform(X)# 3. 用肘部法则选 Ksse[]sil[]K_rangerange(2,11)forkinK_range:kmKMeans(n_clustersk,random_state42,n_init10)km.fit(X_scaled)sse.append(km.inertia_)sil.append(silhouette_score(X_scaled,km.labels_))fig,axplt.subplots(1,2,figsize(12,4))ax[0].plot(K_range,sse,o-)ax[0].set_xlabel(K)ax[0].set_ylabel(SSE (inertia))ax[0].set_title(肘部法则)ax[1].plot(K_range,sil,o-)ax[1].set_xlabel(K)ax[1].set_ylabel(轮廓系数)ax[1].set_title(轮廓系数法)plt.tight_layout()plt.savefig(kmeans_eval.png,dpi120)plt.show()# 4. 选定 K3 进行聚类kmKMeans(n_clusters3,random_state42,n_init10)labelskm.fit_predict(X_scaled)centerskm.cluster_centers_# 5. 可视化取前两个特征画图plt.figure(figsize(8,6))scatterplt.scatter(X_scaled[:,0],X_scaled[:,1],clabels,cmapviridis,s50,alpha0.7)plt.scatter(centers[:,0],centers[:,1],cred,marker*,s300,label质心)plt.xlabel(花萼长度标准化)plt.ylabel(花萼宽度标准化)plt.title(K-means 鸢尾花聚类结果 (K3))plt.legend()plt.colorbar(scatter,label簇编号)plt.savefig(kmeans_result.png,dpi120)plt.show()# 6. 输出评估指标print(f最终 SSE (inertia):{km.inertia_:.4f})print(f轮廓系数:{silhouette_score(X_scaled,labels):.4f})print(f迭代次数:{km.n_iter_})运行后你会观察到肘部法则图在 K3 处出现明显拐点SSE 下降速度骤减。轮廓系数在 K2 或 K3 时达到峰值。聚类结果中三类鸢尾花被较好地分开其中一类Setosa几乎完全正确另外两类Versicolor 与 Virginica有少量样本重叠——这与它们在特征空间中的真实分布一致。这个案例体现了 K-means 的典型工作流标准化 → 选 K → 聚类 → 评估 → 可视化。效果评估方法聚类没有真实标签可用评估比监督学习更依赖内部指标。以下是三种常用方法。肘部法则Elbow Method绘制不同 K 值对应的 SSE 曲线寻找肘部拐点。SSE 随 K 增大单调下降当 K 超过真实簇数后下降幅度会明显变缓这个转折点就是较优的 K。肘部法则简单直观但拐点有时不明显需要结合其他方法交叉验证。轮廓系数Silhouette Score轮廓系数同时考虑簇内紧密度和簇间分离度取值范围[ − 1 , 1 ] [-1, 1][−1,1]s ( i ) b ( i ) − a ( i ) max ⁡ { a ( i ) , b ( i ) } s(i) \frac{b(i) - a(i)}{\max\{a(i), b(i)\}}s(i)max{a(i),b(i)}b(i)−a(i)​a ( i ) a(i)a(i)样本i ii到同簇其他样本的平均距离越小越好。b ( i ) b(i)b(i)样本i ii到最近的其他簇中样本的平均距离越大越好。解读标准接近1聚类效果好样本分到了正确的簇。接近0样本处于两个簇的边界。接近-1样本可能被分错了簇。sklearn 中调用方式fromsklearn.metricsimportsilhouette_score scoresilhouette_score(X,labels)CH 指数Calinski-Harabasz Index又称方差比准则计算簇间离散度与簇内离散度之比值越大说明簇间越分散、簇内越紧凑聚类效果越好。fromsklearn.metricsimportcalinski_harabasz_score scorecalinski_harabasz_score(X,labels)CH 指数计算速度快适合在大数据集上做快速评估。方法优点缺点适用场景肘部法则直观易懂拐点可能不明显主观性强初步探索 K轮廓系数同时考虑紧密度和分离度有明确取值范围计算复杂度高O ( n 2 ) O(n^2)O(n2)中小数据集精细评估CH 指数计算快值越大越好无固定取值范围仅适合横向比较大数据集快速评估特征降维K-means 除了聚类还有一个常被忽略的用途——特征降维在信号处理领域称为向量量化Vector Quantization。基本思想假设你有n nn个样本每个样本d dd维。K-means 聚类后得到 K 个质心我们可以把每个样本替换成它到这 K 个质心的距离于是样本维度从d dd变成了K KK。当K ≪ d K \ll dK≪d时就实现了降维。这正是 sklearn 中transform方法的用途kmKMeans(n_clusters50,random_state42)X_distkm.fit_transform(X)# 形状从 (n, d) 变为 (n, 50)X_dist[i][j]表示样本i ii到第j jj个质心的距离。这种距离特征往往比原始特征更具判别力常作为下游分类器的输入。经典应用图像压缩是 K-means 降维最直观的案例。一张彩色图片每个像素由 RGB 三个值0-255表示共有 1600 万种可能颜色。如果用 K-means 把所有像素颜色聚成 16 类每个像素只需记录它属于 16 个质心中的哪一个4 bit颜色种类从 1600 万压缩到 16文件体积大幅缩小而肉眼几乎看不出差别。importnumpyasnpfromsklearn.clusterimportKMeansimportmatplotlib.pyplotaspltfrommatplotlib.imageimportimread# 1. 读取图片把像素拉平成 (n_pixels, 3)imgimread(photo.jpg)h,w,cimg.shape pixelsimg.reshape(-1,3)# 2. 用 K-means 把颜色聚成 16 类kmeansKMeans(n_clusters16,random_state42,n_init10)labelskmeans.fit_predict(pixels)compressed_palettekmeans.cluster_centers_# 3. 用质心颜色重建图片compressed_imgcompressed_palette[labels].reshape(h,w,c)# 4. 对比展示fig,axplt.subplots(1,2,figsize(12,6))ax[0].imshow(img)ax[0].set_title(原始图片)ax[0].axis(off)ax[1].imshow(compressed_img/255)ax[1].set_title(压缩后16 色)ax[1].axis(off)plt.tight_layout()plt.savefig(image_compression.png,dpi120)plt.show()维度K-means 降维PCA 降维原理用到质心的距离替换原特征用主成分投影保留最大方差方向类型非线性基于聚类线性输出到 K 个质心的距离K 维投影到前 K 个主成分K 维适用场景簇结构明显、想做特征工程一般降维、去噪、可视化实际工程中两者经常组合使用先用 PCA 把高维数据降到几十维再用 K-means 聚类既能提升速度又能改善效果。