K-means 算法核心原理
·
一、K-means 算法核心原理
1. 算法目标
将 n 个样本划分到 k 个簇中,使得每个样本到所属簇中心的距离平方和最小。
2. 数学公式
目标函数(SSE,簇内平方误差):
J=∑i=1k∑x∈Ci∥x−μi∥2 J = \sum_{i=1}^k \sum_{x \in C_i} \|x - \mu_i\|^2 J=i=1∑kx∈Ci∑∥x−μi∥2
其中:
- CiC_iCi 表示第 iii 个簇
- μi\mu_iμi 表示第 iii 个簇的质心
二、算法步骤详解
三、Python 代码实现
1. 手动实现(理解原理)
import numpy as np
from sklearn.datasets import make_blobs
class KMeans:
def __init__(self, k=3, max_iter=100):
self.k = k
self.max_iter = max_iter
def fit(self, X):
# 随机初始化质心
self.centroids = X[np.random.choice(X.shape[0], self.k, replace=False)]
for _ in range(self.max_iter):
# 分配样本到最近质心
distances = np.sqrt(((X - self.centroids[:, np.newaxis])**2).sum(axis=2))
labels = np.argmin(distances, axis=0)
# 更新质心
new_centroids = np.array([X[labels == i].mean(axis=0) for i in range(self.k)])
# 收敛判断
if np.allclose(self.centroids, new_centroids):
break
self.centroids = new_centroids
return labels
# 生成测试数据
X, y = make_blobs(n_samples=300, centers=3, cluster_std=0.6, random_state=42)
# 使用手写模型
kmeans = KMeans(k=3)
labels = kmeans.fit(X)
2. Scikit-learn 生产级实现
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
# 数据标准化(重要!)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 建模
kmeans = KMeans(n_clusters=3, init='k-means++', n_init=10)
kmeans.fit(X_scaled)
labels = kmeans.labels_
四、关键参数解析
| 参数 | 作用 | 推荐值 |
|---|---|---|
n_clusters | 指定簇的数量 K | 通过肘部法则确定 |
init | 初始化方法 | 'k-means++'(默认优化) |
n_init | 随机初始化的次数 | 10-50(避免局部最优) |
max_iter | 最大迭代次数 | 300-500(复杂数据) |
五、聚类质量评估
1. 轮廓系数 (Silhouette Score)
s=b−amax(a,b) s = \frac{b - a}{\max(a, b)} s=max(a,b)b−a
- aaa:样本到同簇其他样本的平均距离
- bbb:样本到最近其他簇样本的平均距离
- 取值范围:[-1, 1],值越大越好
from sklearn.metrics import silhouette_score
score = silhouette_score(X_scaled, labels)
print(f"轮廓系数:{score:.2f}")
2. 肘部法则 (Elbow Method)
import matplotlib.pyplot as plt
sse = []
k_range = range(1, 10)
for k in k_range:
kmeans = KMeans(n_clusters=k)
kmeans.fit(X_scaled)
sse.append(kmeans.inertia_)
plt.plot(k_range, sse, 'bx-')
plt.xlabel('K')
plt.ylabel('SSE')
plt.title('肘部法则')
plt.show()
六、算法优缺点分析
| 优点 | 缺点 |
|---|---|
| 简单高效,时间复杂度 O(nkt) | 需要预先指定 K 值 |
| 适合球形簇结构 | 对噪声和异常值敏感 |
| 可扩展性强(MiniBatch 变体) | 初始质心选择影响结果 |
| 结果易于解释 | 不适合非凸形状簇 |
七、工业级优化技巧
1. 数据预处理
- 标准化:确保各特征量纲一致
- 降维:对高维数据先用 PCA 降维
from sklearn.decomposition import PCA pca = PCA(n_components=0.95) X_pca = pca.fit_transform(X_scaled)
2. 改进初始化方法
使用 K-means++(Scikit-learn 默认方法):
- 随机选择第一个质心
- 后续质心选择距离已有质心较远的点
3. 处理大数据集
使用 MiniBatch K-means:
from sklearn.cluster import MiniBatchKMeans
mb_kmeans = MiniBatchKMeans(n_clusters=3, batch_size=100)
mb_kmeans.fit(X_scaled)
八、应用案例:客户分群
1. 数据特征
- 年龄、消费金额、购买频率、浏览次数等
2. 实施步骤
3. 分群结果分析
| 客户群 | 特征 | 营销策略 |
|---|---|---|
| 群组1 | 高消费、低频次 | 推送高端产品 |
| 群组2 | 低消费、高频次 | 发放优惠券 |
| 群组3 | 中等消费、浏览量大 | 推荐热门商品 |
九、常见问题解答
Q1:如何选择最佳 K 值?
- 优先使用 轮廓系数(定量评估)
- 结合 肘部法则 和业务理解
- 尝试 Gap Statistic 等高级方法
Q2:如何处理非球形数据?
- 使用 谱聚类 或 DBSCAN 替代
- 通过 核方法 将数据映射到高维空间
from sklearn.cluster import SpectralClustering spec = SpectralClustering(n_clusters=3, affinity='nearest_neighbors') labels = spec.fit_predict(X)
Q3:如何解释聚类结果?
- 分析每个簇的 特征分布
- 计算各特征的 簇间差异
df['cluster'] = labels print(df.groupby('cluster').mean())
十、进阶学习建议
- 深入研究:K-means++ 初始化原理
- 对比算法:学习 DBSCAN、层次聚类等
- 可视化工具:掌握 Plotly、Seaborn 的聚类可视化方法
- 实战项目:尝试电商用户分群、新闻主题聚类等案例
更多推荐



所有评论(0)