K-means 聚类是一种广泛应用的无监督学习算法,用于将数据集分成 K 个不同的簇,使得同一簇内的数据点相似度较高,而不同簇间的数据点相似度较低。它的基本思想是通过迭代的方式找到数据点的最优划分,从而最小化簇内的平方误差(通常称为“平方和”)。在本文中,我们将以多维数据的聚类为例,介绍 K-means 算法的实现以及如何绘制聚类结果的散点图。
K-means 算法基本步骤
- 初始化:随机选择 K 个初始聚类中心。
- 分配:对于每个数据点,根据其与 K 个聚类中心的距离,将其分配到最近的聚类中心。
- 更新:重新计算每个聚类的中心(即找到每个簇内所有点的均值)。
- 迭代:重复步骤 2 和 3,直到聚类中心不再变化或达到最大迭代次数。
实现 K-means 聚类
下面是一个 K-means 聚类的 Python 实现代码示例。我们将使用 numpy
和 matplotlib
这两个库来处理数据和绘制图形。
import numpy as np
import matplotlib.pyplot as plt
def kmeans(X, k, max_iters=100):
# 随机初始化聚类中心
np.random.seed(42)
centroids = X[np.random.choice(X.shape[0], k, replace=False)]
for _ in range(max_iters):
# 计算每个数据点到各个聚类中心的距离
distances = np.linalg.norm(X[:, np.newaxis] - centroids, axis=2)
# 分配每个数据点到最近的聚类中心
labels = np.argmin(distances, axis=1)
# 更新聚类中心
new_centroids = np.array([X[labels == i].mean(axis=0) for i in range(k)])
# 检查聚类中心是否变化
if np.all(centroids == new_centroids):
break
centroids = new_centroids
return labels, centroids
# 生成测试数据
def generate_data(n_samples=300, n_features=2, n_clusters=3):
X = np.random.rand(n_samples, n_features)
return X
# 绘制聚类结果
def plot_clusters(X, labels, centroids):
plt.figure(figsize=(10, 6))
unique_labels = np.unique(labels)
for label in unique_labels:
plt.scatter(X[labels == label][:, 0], X[labels == label][:, 1], label=f'Cluster {label}')
plt.scatter(centroids[:, 0], centroids[:, 1], color='red', marker='X', s=200, label='Centroids')
plt.title('K-means Clustering Result')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.legend()
plt.show()
# 主程序
if __name__ == "__main__":
# 生成数据
X = generate_data(n_samples=300)
# 设置聚类数
k = 3
# 运行 K-means 聚类
labels, centroids = kmeans(X, k)
# 绘制聚类结果
plot_clusters(X, labels, centroids)
代码解析
- 生成数据:
generate_data
函数生成一个随机数据点集,用于演示 K-means 聚类。 - K-means 聚类:
kmeans
函数实现了 K-means 算法的核心逻辑,包括初始化、分配、更新和迭代,最终返回数据点的标签和聚类中心。 - 绘制聚类结果:
plot_clusters
函数绘制散点图,显示不同簇的数据点及其聚类中心。
总结
在上述示例中,我们使用 K-means 聚类对随机生成的数据进行了处理,并通过散点图直观展示了聚类结果。K-means 聚类算法易于实现且计算效率较高,适用于处理大规模数据集。然而,它也存在一些局限性,例如对初始聚类中心的选择敏感,以及难以处理形状复杂的簇。在实际应用中,我们可以结合其他聚类算法,或对数据进行预处理,以提高聚类效果。