K-means算法是一种常用的聚类算法,用于将数据集划分为K个不同的类别。每个类别由其质心(centroid)表示,该质心是类别内所有数据点的平均值。K-means算法的目标是最小化数据点与其所属类别质心之间的平方距离。
K-means算法在各个领域广泛应用,包括数据分析、图像处理、模式识别等。它是一种简单而高效的聚类算法,但在处理非凸形状的数据集或存在噪声的情况下可能表现不佳。有一些改进的K-means算法,如K-means++和Mini-Batch K-means,可以用来改善初始质心选择和处理大规模数据集的效率。
以下是K-means算法的基本步骤:
-
初始化:选择要划分的类别数K,并随机选择K个数据点作为初始质心。
-
分配:对于每个数据点,计算其与所有质心之间的距离,并将数据点分配给最近的质心所代表的类别。
-
更新:对于每个类别,计算其所有数据点的平均值,以得到新的质心位置。
-
重复:重复步骤2和步骤3,直到质心不再变化或达到预定的迭代次数。
-
输出:得到最终的类别划分结果和质心位置。
伪代码如下
此出有个可视化网站可以帮助我们更好理解:https://www.naftaliharris.com/blog/visualizing-k-means-clustering/
下面是用python实现:
import numpy as np
import matplotlib.pyplot as plt
# 随机初始中心点
def randCent(data, k):
N, D = data.shape
centroids = np.zeros((k,D)) # 创建k个中心点
for i in range(k):
index = np.random.randint(0, N)
# 随机一个数,将该数作为data的索引,赋给中心点
centroids[i, :] = data[index, :]
return centroids
# 距离计算
def distance(x, y):
return np.linalg.norm(x - y) # return np.sqrt((x - y)**2)
def KMeans(data, k ,max_iter=200 ,show=False):
"""
:param data: 需要训练的数据
:param k: 需要分为几类
:param max_iter: 最大迭代次数,默认为200
:param show: 展示算法过程
:return: 返回聚类结果,仅返回分类结果
"""
N, D = data.shape # shape函数查看数组维度
centroids = randCent(data, k)
labels = np.zeros(N, dtype=int)
for pic in range(max_iter): # 迭代次数
for i in range(N): # 更新簇的分类
min_dis = 100000 # min_dis作为中间值,用于比较
# min_dis = distance(data[i, :], centroids[0, :])这样写更严谨,但更复杂
for j in range(k):
d = distance(data[i, :], centroids[j, :])
if d < min_dis:
min_dis = d
index = j
labels[i] = index
for i in range(k): # 更新各簇的中心点
labels_data = data[labels == i] # 索引出同一簇的数据
# 对其求均值,注意axis,默认为None,即对所有求均值,0对列求均值,1对行求
centroids[i, :] = np.mean(labels_data, axis=0)
if show:
# 该过程是展示聚类过程,每迭代50次,画一张图展示所有点的分类情况已经中心点的位置
if pic % 50 == 0:
plt.scatter(data[:, 0], data[:, 1], c=labels)
plt.scatter(centroids[:, 0], centroids[:, 1], marker='x', s=200,
linewidths=3, color='b')
plt.show()
return labels
导入数据:
data = np.loadtxt(r"data/aggregation.txt")
data = data[:, :-1]
k = 5
labels = KMeans(data, k, show=True, max_iter=200)
plt.show()
过程如下:
我们可以观察得到:其实迭代到后面基本就不变了,我们可以设计一下,当中心点不发生变化时就停止迭代
K值对聚类结果的影响:
这个很容易理解,不同的k表示分成多少类,即导致聚类结果不一样
随机中心点的局限
我们可以看到多次进行kmeans聚类,聚类结果也是不同的
这是因为我们每次初始化的中心点是随机的,这就会导致我们的结果也会不同
不同数据在KMeans算法下的聚类效果