1. 引言
在机器学习领域,聚类是一种无监督学习的技术,用于将数据集分组成若干个类别,使得同组数据之间具有更高的相似性。这种技术在各个领域都有广泛的应用,比如客户细分、图像压缩和市场分析等。聚类的目标是使得同类样本之间的相似性最大化,而不同类样本之间的相似性最小化。
K 均值聚类 (K-Means Clustering) 是一种基于距离度量的迭代优化算法,通过选择若干个质心 (centroid) 来对数据进行分组,使得每个数据点所属的聚类内距离质心的距离之和最小化。由于其算法的简单性和高效性,K 均值在数据分析中被广泛使用。
在现实生活中,我们可以将 K 均值聚类应用于客户细分,以帮助企业识别具有相似购买行为的客户群体,或者用于图像压缩,通过将图像像素点聚类来减少颜色的数量。在这篇文章中,我们将深入探讨 K 均值聚类的数学原理、算法实现步骤,并提供 Python 代码示例来帮助读者理解其实际应用。
2. 什么是 K 均值聚类?
K 均值聚类是一种基于质心的聚类算法,它通过反复迭代的方式将数据点分配到 K 个聚类中。每个质心代表一个聚类的中心位置,算法会不断调整质心的位置,直到满足一定的收敛条件。K 均值聚类的目标是最小化每个聚类内部所有点到其质心的距离之和。
具体来说,K 均值聚类的步骤可以概括如下:
- 随机选择 K 个初始质心。
- 将每个数据点分配到离它最近的质心所在的聚类。
- 重新计算每个聚类的质心,即对聚类中的所有数据点取平均值。
- 重复步骤 2 和 3,直到质心的位置不再发生变化,或者达到预设的迭代次数。
K 均值聚类的最终结果是 K 个聚类,每个聚类由一个质心及其所有属于该聚类的数据点组成。其目标是使得每个聚类内的数据点与质心之间的总距离最小。
3. K 均值聚类的数学原理
K 均值聚类的目标是最小化每个数据点到所属质心的距离的平方和 (Sum of Squared Errors, SSE):

其中:
- $K$:聚类的数量。
- $C_i$:第 i 个聚类。
- $\mu_i$:第 i 个聚类的质心。
- $x_j$:属于聚类 $C_i$ 的数据点。
这个优化问题的目标是通过不断调整每个聚类的质心来最小化 SSE。该过程通过交替进行两步:分配 (Assignment) 和更新 (Update),直到达到收敛条件。
4. 算法实现步骤详解
K 均值聚类算法主要包含以下步骤:
步骤 1:选择 K 值
K 值是指要将数据分成的聚类数。选择合适的 K 值是 K 均值聚类算法中一个非常重要的步骤,因为不合适的 K 值会影响聚类的效果。通常可以通过 "肘部法则 (Elbow Method)" 来确定合适的 K 值。
步骤 2:初始化质心
可以随机选择 K 个数据点作为初始质心,或者使用一些启发式的方法,如 K-Means++,以更好地初始化质心,减少随机性对聚类效果的影响。
步骤 3:分配数据点
将每个数据点分配到离它最近的质心所在的聚类中。通常使用欧几里得距离来计算数据点与质心之间的距离。
步骤 4:更新质心
对于每一个聚类,重新计算其质心的位置。具体来说,将聚类中的所有数据点的坐标进行平均,得到新的质心位置。
步骤 5:收敛判断
判断质心是否发生变化。如果质心位置不再变化,或者达到预设的最大迭代次数,算法停止。此时的聚类结果即为最终的聚类划分。
5. Python 代码实现
下面我们用 Python 及其常用库 NumPy 和 Matplotlib 实现 K 均值聚类算法:
import numpy as np
import matplotlib.pyplot plt
sklearn.datasets make_blobs
np.random.seed()
X, y = make_blobs(n_samples=, centers=, cluster_std=, random_state=)
plt.scatter(X[:, ], X[:, ], s=)
plt.xlabel()
plt.ylabel()
plt.title()
plt.show()
:
():
.k = k
.max_iters = max_iters
.tol = tol
():
.centroids = X[np.random.choice((X.shape[]), .k, replace=)]
_ (.max_iters):
.clusters = ._assign_clusters(X)
new_centroids = ._compute_centroids(X)
np.(np.linalg.norm(.centroids - new_centroids, axis=) < .tol):
.centroids = new_centroids
():
distances = np.linalg.norm(X[:, np.newaxis] - .centroids, axis=)
np.argmin(distances, axis=)
():
np.array([X[.clusters == i].mean(axis=) i (.k)])
():
distances = np.linalg.norm(X[:, np.newaxis] - .centroids, axis=)
np.argmin(distances, axis=)
kmeans = KMeans(k=)
kmeans.fit(X)
y_pred = kmeans.predict(X)
plt.scatter(X[:, ], X[:, ], c=y_pred, cmap=, s=)
plt.scatter(kmeans.centroids[:, ], kmeans.centroids[:, ], s=, c=, marker=)
plt.xlabel()
plt.ylabel()
plt.title()
plt.show()


