K-Means聚类算法完全教程
1. 算法概述
1.1 什么是K-Means算法?
K-Means是一种无监督学习的聚类算法,用于将未标记的数据集划分为K个不同的簇。它的核心思想是"物以类聚" - 相似的数据点应该被分配到同一个簇中。
1.2 基本概念
- 簇(Cluster):相似数据点的集合
- 质心(Centroid):簇的中心点(所有点的均值)
- 惯性(Inertia):每个点到其质心的距离平方和,衡量簇内紧密度
2. 算法原理
2.1 数学目标
最小化损失函数(惯性/簇内平方和):
\[J = \sum_{i=1}^{K} \sum_{x \in C_i} ||x - \mu_i||^2
\]
其中:
- \(K\):簇的数量
- \(C_i\):第i个簇
- \(\mu_i\):第i个簇的质心
- \(x\):数据点
2.2 算法步骤
步骤1:初始化
随机选择K个数据点作为初始质心
输入:数据集X,簇数K
输出:K个簇及其质心
1. 从X中随机选择K个点作为初始质心 μ₁, μ₂, ..., μₖ
步骤2:分配数据点
将每个数据点分配到最近的质心所在的簇
for 每个数据点x in X:
计算x到每个质心μᵢ的距离
将x分配到距离最近的质心对应的簇
步骤3:更新质心
重新计算每个簇的质心(取均值)
for 每个簇Cᵢ:
计算新的质心 μᵢ = 均值(Cᵢ)
步骤4:迭代
重复步骤2-3,直到满足停止条件:
- 质心变化小于阈值(收敛)
- 达到最大迭代次数
- 簇的分配不再改变
3. 关键细节与参数选择
3.1 距离度量
常用的距离度量方法:
- 欧氏距离(最常用):\[d(x, y) = \sqrt{\sum_{i=1}^{n}(x_i - y_i)^2} \]
- 曼哈顿距离:\[d(x, y) = \sum_{i=1}^{n}|x_i - y_i| \]
- 余弦相似度:适用于文本数据
3.2 如何选择K值?
方法1:肘部法则(Elbow Method)
计算不同K值对应的惯性值(SSE)
绘制K-SSE曲线,选择"肘部"拐点
方法2:轮廓系数(Silhouette Score)
\[s(i) = \frac{b(i) - a(i)}{\max(a(i), b(i))}
\]
其中:
- \(a(i)\):点i到同簇其他点的平均距离
- \(b(i)\):点i到最近其他簇所有点的平均距离
取值范围:[-1, 1],越接近1效果越好
方法3:间隙统计量(Gap Statistic)
比较实际数据与随机均匀分布的聚类效果差异
3.3 初始质心选择问题
问题:随机初始化可能导致:
- 收敛到局部最优
- 收敛速度慢
- 结果不稳定
解决方案:K-Means++初始化
1. 随机选择一个点作为第一个质心
2. 对于每个点x,计算其与最近质心的距离D(x)
3. 按照D(x)²的概率选择下一个质心
4. 重复直到选出K个质心
4. 算法变体与改进
4.1 K-Means++
- 优点:更好的初始质心选择,加速收敛
- 缺点:计算初始质心时需额外计算距离
4.2 Mini-Batch K-Means
使用数据子集(小批量)更新质心:
适用于大数据集
牺牲精度换取速度
支持在线学习
4.3 K-Medoids(PAM算法)
- 使用实际数据点作为中心点(medoid)
- 对异常值更鲁棒
- 计算成本更高(O(n²))
4.4 二分K-Means(Bisecting K-Means)
1. 将所有点作为一个簇
2. 重复直到有K个簇:
a. 选择SSE最大的簇进行二分
b. 使用K-Means(K=2)划分该簇
5. 算法优缺点
5.1 优点
- 简单高效:时间复杂度O(n×K×I×d),适合大数据
- 可解释性强:每个簇有明确的中心点
- 收敛快:通常少量迭代即可收敛
- 可扩展性好:易于并行化实现
5.2 缺点
- 需要预先指定K值
- 对初始质心敏感(可用K-Means++缓解)
- 对异常值敏感
- 假设簇为凸形、各向同性,对非球形簇效果差
- 不适合处理类别型数据
6. 实践应用
6.1 应用场景
- 客户细分:基于购买行为对客户分组
- 图像压缩:减少颜色数量(颜色量化)
- 文档聚类:新闻分类、主题发现
- 异常检测:离群点检测
- 推荐系统:用户分群进行个性化推荐
- 社交网络分析:社区发现
6.2 Python实现示例
基础版本
import numpy as np
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
# 生成示例数据
np.random.seed(42)
X = np.random.randn(300, 2)
X[:100] += 5
X[100:200] += 10
# K-Means聚类
kmeans = KMeans(n_clusters=3, init='k-means++', n_init=10, max_iter=300)
kmeans.fit(X)
# 结果可视化
plt.scatter(X[:, 0], X[:, 1], c=kmeans.labels_, cmap='viridis')
plt.scatter(kmeans.cluster_centers_[:, 0],
kmeans.cluster_centers_[:, 1],
s=200, marker='X', c='red')
plt.title('K-Means聚类结果')
plt.show()
完整实践:客户分群
import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import silhouette_score
# 1. 加载数据
data = pd.read_csv('customer_data.csv')
# 2. 特征选择与预处理
features = ['Annual_Income', 'Spending_Score']
X = data[features].values
# 3. 数据标准化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 4. 确定最佳K值(肘部法则)
inertia = []
K_range = range(2, 11)
for k in K_range:
kmeans = KMeans(n_clusters=k, random_state=42)
kmeans.fit(X_scaled)
inertia.append(kmeans.inertia_)
# 可视化肘部曲线
plt.plot(K_range, inertia, 'bo-')
plt.xlabel('K值')
plt.ylabel('惯性值')
plt.title('肘部法则')
plt.show()
# 5. 使用最佳K值进行聚类
optimal_k = 5 # 根据肘部法则确定
kmeans = KMeans(n_clusters=optimal_k, init='k-means++', random_state=42)
clusters = kmeans.fit_predict(X_scaled)
# 6. 评估聚类效果
silhouette_avg = silhouette_score(X_scaled, clusters)
print(f'轮廓系数: {silhouette_avg:.3f}')
# 7. 分析聚类结果
data['Cluster'] = clusters
cluster_summary = data.groupby('Cluster').mean()
print(cluster_summary)
7. 高级技巧与注意事项
7.1 数据预处理
- 标准化:确保不同特征具有相同尺度
from sklearn.preprocessing import StandardScaler scaler = StandardScaler() X_scaled = scaler.fit_transform(X) - 处理缺失值
- 特征选择:去除无关特征
7.2 评估聚类质量
- 内部指标:轮廓系数、Davies-Bouldin指数
- 外部指标(需要真实标签):调整兰德指数、互信息
- 业务评估:结合实际业务意义
7.3 处理非凸簇
当数据不是球形分布时:
- 考虑使用DBSCAN或谱聚类
- 使用核K-Means将数据映射到高维空间
7.4 大数据集处理
# 使用MiniBatchKMeans
from sklearn.cluster import MiniBatchKMeans
mbk = MiniBatchKMeans(n_clusters=10, batch_size=100)
mbk.fit(X_large)
8. 常见问题与解决方案
Q1: K-Means收敛到局部最优怎么办?
解决方案:
- 多次运行,选择最佳结果(
n_init参数) - 使用K-Means++初始化
- 增加迭代次数
Q2: 如何处理不同大小的簇?
解决方案:
- 调整样本权重
- 使用层次聚类作为预处理
- 考虑使用GMM(高斯混合模型)
Q3: 如何解释聚类结果?
方案:
- 分析每个簇的特征统计量
- 可视化降维后的结果(PCA/t-SNE)
- 结合业务知识进行标签定义
9. 算法扩展与相关算法
9.1 模糊C-Means
- 允许数据点以不同概率属于多个簇
- 适用于边界模糊的数据
9.2 层次聚类
- 不需要预先指定K值
- 生成树状聚类结构
9.3 DBSCAN
- 基于密度的聚类
- 可发现任意形状的簇
- 自动处理异常值
9.4 GMM(高斯混合模型)
- 基于概率模型的软聚类
- 假设每个簇服从高斯分布
10. 总结
K-Means是最经典、最常用的聚类算法之一,它的优势在于简单高效,特别适合处理大规模数据集。但在实际应用中需要注意:
- 数据预处理是关键步骤
- 合理选择K值直接影响结果
- 多次运行避免局部最优
- 结合业务理解解释聚类结果
虽然K-Means有局限性,但通过合适的改进(如K-Means++)和参数调优,它仍然是解决实际聚类问题的有力工具。
附录:数学推导
质心更新公式推导
对于第i个簇\(C_i\),质心\(\mu_i\)的最优解为:
\[\mu_i = \frac{1}{|C_i|} \sum_{x \in C_i} x
\]
这个结果通过最小化损失函数\(J\)对\(\mu_i\)求导得到:
\[\frac{\partial J}{\partial \mu_i} = -2 \sum_{x \in C_i} (x - \mu_i) = 0
\]
解得:
\[\mu_i = \frac{1}{|C_i|} \sum_{x \in C_i} x
\]
浙公网安备 33010602011771号