分钟搞懂K-Means聚类:核心原理与Python实战代码
什么是聚类?
聚类(Clustering),说白了就是一种无监督学习方法。它的目标很直白:在没有标签的情况下,把数据样本按照相似程度分到不同的组里,让同一组内的样本尽可能相似,不同组之间差异尽可能大。常见的算法分好几类,比如基于划分的K-Means、基于层次的层次聚类,还有基于密度的DBSCAN、OPTICS等等。聚类这东西,应用范围相当广——用户分群、市场细分、文本主题发现、图像分割,都能看到它的身影。可以说,它是数据挖掘和探索性分析里一把相当趁手的工具。
K-Means 聚类
要说最经典的聚类算法,K-Means绝对排得上号。它属于基于划分的方法,思路非常直白:通过不断迭代优化目标函数,把数据分成K个簇,让同一个簇里的样本彼此靠得近,不同簇之间离得远。什么叫“簇”?其实就是一组同类的东西。打个比方,苹果、香蕉、橘子属于“水果”那一簇,彭于晏、刘亦菲和你们呢?属于“帅哥美女”那一簇——这么理解就容易多了。因为简单又高效,K-Means在数据挖掘、文本分析、图像分割这些领域里,几乎成了最常用的基础工具。
K-Means要优化的目标,是让簇内平方误差(Within-Cluster Sum of Squares,WCSS)最小化,公式长这样:
其中:
- 是簇的个数
- 是第 个簇
- 是簇 的质心(也就均值向量)
- 是样本点与簇中心之间的欧式距离
核心思路说白了就是不断调整簇的划分和质心位置,直到目标函数不再明显下降——也就是收敛。
K-Means的算法流程其实相当好理解,一共就四步:
- 初始化:随机选 个样本作为初始质心。
- 分配样本:把每个样本划分到离它最近的簇中心。
- 更新质心:针对每个簇,计算所有样本的均值,作为新的质心。
- 迭代:重复第2和第3步,直到簇划分不再变化,或者目标函数收敛。
光说理论可能有点抽象,下面拿Scikit-learn写一段示例代码,跑一遍就懂了:
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
# 1. 生成模拟数据
X, y = make_blobs(n_samples=300, centers=4, cluster_std=0.6, random_state=42)
# 2. 训练 K-Means
kmeans = KMeans(n_clusters=4, random_state=42, n_init=10)
y_pred = kmeans.fit_predict(X)
# 3. 可视化结果
plt.scatter(X[:, 0], X[:, 1], c=y_pred, s=30, cmap='viridis')
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1],
c='red', marker='X', s=200, label='Centroids')
plt.legend()
plt.title("K-Means Clustering")
plt.show()
运行之后的效果图是这样的:不同颜色代表不同簇,红色的X标记就是聚类中心。
最后总结一下。K-Means作为经典的无监督学习方法,效率高、直觉性强,一直是最常用的聚类算法之一。不过在实际应用中,有几个地方得多留个心眼:簇数怎么选?初始点敏感怎么办?面对复杂分布的数据还能不能顶住?针对这些不足,后来研究者也提出了不少改进方案,比如K-Means++、Mini-Batch K-Means,让它在大规模机器学习任务中依然站得住脚。