资讯动态

【实战解析】K-Means聚类算法:从原理到Python代码实现

发布时间:2026/8/22 15:17:34 来源:尧图企业网站定制
1. 初识K-Means聚类算法中的分班老师第一次听说K-Means算法时我脑海中浮现的是小学时的分班场景。想象你是一位班主任面前站着20个新生需要把他们分成2个班级。最直观的做法是什么先随机选两个学生当班长然后让其他学生选择离自己最近的班长这样就形成了初始的两个班级。接着重新计算每个班级的平均身高和体重更新班长的位置。重复这个过程直到班长位置不再变化——这就是K-Means最朴素的工作原理。在实际项目中我常用它来处理客户分群。比如电商平台有10万用户消费数据通过K-Means可以自动将用户分成高消费低频、低消费高频等群体。算法会找到数据中自然的聚集点就像老师根据学生特征分班一样。不过要注意和真实分班不同K-Means要求你事先确定要分几个班即K值这是它的主要局限之一。2. 算法原理拆解三步看懂K-Means2.1 初始化随机选出班长算法开始时需要指定K个初始中心点就像随机指定班长。这里有个常见陷阱如果初始点选得不好可能导致最终分组不合理。我在某次用户分群项目中就遇到过同样的数据跑三次得到完全不同的分群结果。后来改用K-Means算法后文会介绍才解决这个问题。数学上初始化过程可以表示为centroids X[np.random.choice(range(len(X)), k, replaceFalse)]其中X是数据集k是预设的聚类数量。2.2 分配阶段学生选择最近的班长对于每个数据点计算它与所有中心点的距离将其分配到最近的中心点所属的簇。距离计算通常采用欧式距离distance √[(x2 - x1)² (y2 - y1)²]这个阶段会产生临时分组相当于学生暂时站到各自选择的班长身后。2.3 更新阶段重新选举班长计算每个簇中所有点的均值将该均值作为新的中心点。用代码表示就是new_centroids [cluster.mean(axis0) for cluster in clusters]这个过程会不断重复直到中心点变化小于某个阈值比如0.001或达到最大迭代次数。我通常设置max_iter300实践中很少有需要超过200次迭代的情况。3. Python实战手把手实现客户分群3.1 数据准备与可视化我们先模拟一个电商用户数据集import numpy as np import matplotlib.pyplot as plt from sklearn.datasets import make_blobs # 生成1000个二维数据点分为3个簇 X, y make_blobs(n_samples1000, centers3, cluster_std0.8, random_state42) plt.scatter(X[:,0], X[:,1], s10) plt.title(原始数据分布) plt.show()这段代码会生成明显分为三组的散点图。实际项目中数据可能来自CSV文件import pandas as pd data pd.read_csv(user_behavior.csv) X data[[purchase_freq, avg_spend]].values3.2 使用sklearn实现K-Means用sklearn实现只需要几行代码from sklearn.cluster import KMeans kmeans KMeans(n_clusters3, initk-means, max_iter300) kmeans.fit(X) # 查看结果 labels kmeans.labels_ centroids kmeans.cluster_centers_ # 可视化 plt.scatter(X[:,0], X[:,1], clabels, s10) plt.scatter(centroids[:,0], centroids[:,1], cred, s100, markerx) plt.title(K-Means聚类结果) plt.show()这里我特意使用了initk-means这是改进版的初始化方法能有效避免普通K-Means的局部最优问题。3.3 模型评估与调优没有真实标签时可以用轮廓系数评估聚类效果from sklearn.metrics import silhouette_score score silhouette_score(X, labels) print(f轮廓系数{score:.3f})一般轮廓系数在0.5以上说明聚类效果不错。如果效果不好可以尝试数据标准化from sklearn.preprocessing import StandardScaler X_scaled StandardScaler().fit_transform(X)寻找最佳K值scores [] for k in range(2, 8): kmeans KMeans(n_clustersk) kmeans.fit(X_scaled) scores.append(silhouette_score(X_scaled, kmeans.labels_)) plt.plot(range(2,8), scores) plt.xlabel(K值) plt.ylabel(轮廓系数) plt.show()4. 进阶技巧与避坑指南4.1 K-Means更聪明的初始化传统K-Means随机初始化可能导致收敛速度慢陷入局部最优聚类结果不稳定K-Means的改进在于随机选择第一个中心点后续中心点选择时优先选择距离现有中心点较远的点这相当于在分班时先随机选一个班长然后故意找和现有班长差别最大的学生当下一个班长。sklearn中默认就是使用k-means所以前面代码我们不需要额外设置。4.2 常见问题解决方案问题1如何确定K值除了轮廓系数还可以用肘部法则inertias [] for k in range(1, 10): kmeans KMeans(n_clustersk) kmeans.fit(X) inertias.append(kmeans.inertia_) # 样本到最近聚类中心的距离平方和 plt.plot(range(1,10), inertias) plt.xlabel(K值) plt.ylabel(距离平方和) plt.show()选择曲线拐点对应的K值。问题2处理非球形分布数据K-Means假设簇是凸形的对于流形数据效果不好。这时可以考虑使用谱聚类先用PCA降维改用DBSCAN算法问题3处理分类与数值混合数据可以先对分类变量进行独热编码然后统一标准化from sklearn.compose import ColumnTransformer from sklearn.preprocessing import OneHotEncoder preprocessor ColumnTransformer( transformers[ (num, StandardScaler(), [age,income]), (cat, OneHotEncoder(), [gender,city]) ]) X_processed preprocessor.fit_transform(data)5. 真实案例电商用户行为分析去年我参与了一个电商用户分群项目目标是识别不同类型的用户以实现精准营销。数据包含最近购买时间天购买频率次/月平均订单金额元浏览商品数量次/天经过多次实验我们最终确定了5个用户群体高价值活跃用户8%高频高消费需VIP服务维护潜在价值用户15%中等消费但频率在提升流失风险用户25%曾经活跃但最近减少低频低价用户40%偶尔购买特价商品新用户12%需要引导转化实现代码关键部分user_data pd.read_csv(user_behavior.csv) features [last_purchase,freq,avg_spend,page_views] # 数据预处理 X user_data[features] X StandardScaler().fit_transform(X) # 聚类分析 kmeans KMeans(n_clusters5, random_state42) user_data[segment] kmeans.fit_predict(X) # 分析各群体特征 segment_profiles user_data.groupby(segment).mean()这个案例中我们通过聚类发现了原本人工分析难以识别的用户群体特别是潜在价值用户的发现使得营销ROI提升了30%。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价