K-means算法原理
K-means算法步骤
- 初始化:随机选择k个初始质心
- 分配:将每个数据点分配到距离最近的质心,形成k个簇。其中距离需要根据数据类型选择欧式距离、余弦相似度等度量方式
- 更新:用簇内所有点的均值,重新计算每个簇的质心
- 迭代:重复步骤2和3,直到质心不再发生变化或达到最大迭代次数
K-means优缺点及和其他算法的比较可参考:https://zhuanlan.zhihu.com/p/441168720
利用numpy实现K-means代码
实现代码
import numpy as np
def kmeans(data, k, max_iterations):
# 随机初始化中心点:
centers = data[np.random.choice(data.shape[0], k, replace=False)]
for i in range(max_iterations):
# 使用np.linalg.norm计算,每个样本到每个中心点的欧几里得距离
# data[:, None]形状为[样本数量, 1, 特征数量]
# data[:, None] - centers:广播机制,生成形状为 [样本数量, 中心点数量, 特征数量] 的矩阵,计算每个样本与每个中心的差
distances = np.linalg.norm(data[:, None] - centers, axis=2)
# 更新样本标签,为每个样本分配最近的中心点,计算距离最小的中心的索引
labels = np.argmin(distances, axis=1)
# 更新中心
new_centers = np.array([data[labels == i].mean(axis=0) for i in range(k)])
# 判断是否收敛,如果所有中心点不再变化,则认为聚类已经收敛,停止迭代
if np.all(centers == new_centers):
break
centers = new_centers
return labels, centers
结果验证
import matplotlib.pyplot as plt
# 生成数据验证
data = np.random.rand(100, 2)
labels, centers = kmeans(data, 3, 100)
plt.scatter(data[:, 0], data[:, 1], c=labels)
实现利用的numpy技巧-广播机制
numpy的广播机制(broadcasting)是一种强大的功能,它允许不同形状的数组在进行运算时能够自动地进行对齐和扩展,从而避免显式地复制数据。广播机制使得数组运算更加高效和简洁。广播机制遵循以下规则:
- 如果数组的维度数不同,将维度较小的数组形状前面补1,直到两个数组的维度数相同
- 从最后一个维度开始比较,两个数组在每一个维度上的大小必须相同,或者其中一个维度的大小为1
- 如果某个维度的大小为1,则可以在该维度上进行扩展,以匹配另一个数组在该维度上的大小