K-Means 算法详解
简单高效, 时间复杂度低, 容易解释
适用于大数据量的集合, 但是特征维度不要太高
指定k值(簇的数量), 随机选择初始聚类中心
只能处理凸形簇,不能处理非凸形簇(比如环形数据集)
一、算法逻辑
K-Means 是一种无监督聚类算法,核心目标是将数据集划分为 K 个簇,使得同一簇内的数据点相似度高,不同簇间的数据点相似度低。其流程如下:
-
初始化中心点
- 随机选择
K个数据点作为初始聚类中心(质心)。
- 随机选择
-
迭代优化
- 分配步骤:将每个数据点分配到距离最近的质心对应的簇。
- 更新步骤:重新计算每个簇的质心(取簇内所有点的均值,这个时候计算出来的新的质心可能不是簇内的一个真实的数据点)。
- 重复上述步骤,直到质心不再显著变化(或达到最大迭代次数)。
-
终止条件
- 质心变化小于阈值,或达到预设的最大迭代次数。
# 伪代码示例
初始化 K 个质心
while 未收敛:
将每个点分配到最近的质心对应的簇
重新计算每个簇的质心
二、优缺点分析
| 优点 | 缺点 |
|---|---|
| 1. 简单高效,时间复杂度低(O(NKT)) | 1. 需预先指定 K 值,选择不当可能导致效果差 |
| 2. 适用于大数据集 | 2. 对初始质心敏感,可能收敛到局部最优 |
| 3. 结果易于解释 | 3. 对噪声和异常值敏感(可用 K-Medoids 改进) |
| 4. 只能处理凸形簇,对非凸簇效果差(如环形数据) |
三、适用场景
- 数据分布均匀,簇形状接近球形。
- 数据量较大但特征维度不高。
- 典型应用:客户分群、图像分割、文档分类、异常检测。
四、K-Means++ 算法的改进
核心改进:优化初始质心的选择,减少算法对初始化的依赖。
步骤:
- 随机选择第一个质心。
- 后续质心的选择概率与当前点到最近质心的距离平方成正比(距离越远,概率越高)。
- 重复直到选出
K个质心。
优势:
- 初始质心更分散,覆盖不同簇。
- 减少迭代次数,提高收敛速度和稳定性。
- 在多数情况下,聚类效果优于原始 K-Means。
完整 Python 代码示例
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
# 生成模拟数据
X, y = make_blobs(n_samples=500, centers=3, cluster_std=0.8, random_state=42)
# K-Means++ 聚类
kmeans_pp = KMeans(n_clusters=3, init='k-means++', n_init=10, random_state=42)
kmeans_pp.fit(X)
labels_pp = kmeans_pp.labels_
centers_pp = kmeans_pp.cluster_centers_
# 原始 K-Means 对比(随机初始化)
kmeans = KMeans(n_clusters=3, init='random', n_init=1, random_state=42)
kmeans.fit(X)
labels = kmeans.labels_
centers = kmeans.cluster_centers_
# 可视化结果
plt.figure(figsize=(12, 5))
# K-Means++
plt.subplot(1, 2, 1)
plt.scatter(X[:, 0], X[:, 1], c=labels_pp, cmap='viridis', s=50, alpha=0.6)
plt.scatter(centers_pp[:, 0], centers_pp[:, 1], c='red', s=200, marker='X')
plt.title("K-Means++")
# 原始 K-Means
plt.subplot(1, 2, 2)
plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis', s=50, alpha=0.6)
plt.scatter(centers[:, 0], centers[:, 1], c='red', s=200, marker='X')
plt.title("K-Means (Random Init)")
plt.show()
代码说明
- 数据生成:使用
make_blobs生成 3 个高斯分布的簇。 - 模型训练:分别使用 K-Means++ 和随机初始化的 K-Means。
- 可视化:对比两种初始化方法的聚类效果,红色叉号表示质心位置。
输出效果:
- K-Means++ 的质心通常更准确地分布在簇中心。
- 随机初始化的 K-Means 可能因初始质心不佳导致次优聚类。
总结
- K-Means 简单高效,但对初始化和噪声敏感。
- K-Means++ 通过优化初始化显著提升稳定性,是实际应用中的推荐方法。
- 在 Scikit-Learn 中,
KMeans默认使用 K-Means++ 初始化(init='k-means++')。