算法一 Kmeans聚类
原理:
K-Means 是一种非常经典的聚类算法,其基本思想是:基于给定的数据点集合,通过迭代过程寻找 k 个聚类中心,使得各数据点到其最近聚类中心的距离之和最小。
方法概述:
- 初始化:随机选择 k个数据点作为初始的聚类中心。
- 分配:将每个数据点分配给最近的聚类中心。
- 更新:根据分配的结果,重新计算每个聚类的中心。
- 重复:重复步骤2和步骤3,直到聚类中心不再改变或达到最大迭代次数
代码实现
import numpy as np
def initialize_centroids(data, k):
"""随机初始化中心点"""
indices = np.random.choice(data.shape[0], k, replace=False)
return data[indices]
def assign_clusters(data, centroids):
"""分配数据点到最近的中心"""
distances = np.sqrt(((data - centroids[:, np.newaxis])**2).sum(axis=2))
return np.argmin(distances, axis=0)
def update_centroids(data, assignments, k):
"""更新中心点"""
new_centroids = np.array([data[assignments == i].mean(axis=0) for i in range(k)])
return new_centroids
def kmeans(data, k, max_iter=100):
"""K-Means算法的实现"""
centroids = initialize_centroids(data, k)
for _ in range(max_iter):
assignments = assign_clusters(data, centroids)
new_centroids = update_centroids(data, assignments, k)
if np.all(centroids == new_centroids):
break
centroids = new_centroids
return centroids, assignments
# 生成样本数据
np.random.seed(42)
data1 = np.random.randn(50, 2) + np.array([1, 2])
data2 = np.random.randn(50, 2) + np.array([5, 5])
data3 = np.random.randn(50, 2) + np.array([8, 1])
data = np.vstack([data1, data2, data3])
# 执行K-Means聚类
centroids, assignments = kmeans(data, k=3)
# 打印结果
print("Centroids:")
print(centroids)
# 可视化
import matplotlib.pyplot as plt
plt.scatter(data[:, 0], data[:, 1], c=assignments, cmap='viridis', marker='o')
plt.scatter(centroids[:, 0], centroids[:, 1], s=300, c='red', marker='x')
plt.title('K-Means Clustering')
plt.xlabel('X')
plt.ylabel('Y')
plt.show()
效果如下
关键部分解释
initialize_centroids
函数通过从数据中随机选择 k 个点作为初始中心。assign_clusters
函数计算每个点到每个中心的距离,并将每个点分配给最近的中心。update_centroids
函数根据当前的分配情况重新计算每个簇的中心。kmeans
函数是整个 K-Means 算法的主控制函数,它调用其他函数并管理迭代过程。
最主要的是算出欧氏距离
核心部分就是
def assign_clusters(data, centroids):
distances = np.sqrt(((data - centroids[:, np.newaxis])**2).sum(axis=2))
return np.argmin(distances, axis=0)
在 K-Means 算法中,这一行代码是用来计算所有数据点与所有聚类中心之间的欧几里得距离的关键步骤。这句话包含了多个计算步骤,我们可以逐一拆解以便更好地理解每个部分是如何工作的:
1. 广播机制 (data - centroids[:, np.newaxis]
)
2. **计算平方差 ((...)2)
3. 沿特定轴求和 (.sum(axis=2))
- 这一步在每个差值平方后,对最内层的轴 (axis=2,也就是每个点的坐标轴) 进行求和。对于二维数据,这相当于计算
,即每个数据点到每个聚类中心的平方距离。
4. 开平方 np.sqrt(...)
- 最后一步是对上一步得到的每个平方距离求平方根,这给出了实际的欧几里得距离 。这就是每个数据点到每个聚类中心的距离。