import numpy as np
def get_dist(vec1, vec2): # 两个向量之间的欧几里德距离
return np.sqrt(np.sum(np.power(vec1 - vec2, 2)))
def rand_cent(dataSet, k): # 返回初始化得到的k个质心向量
n = np.shape(dataSet)[1] # 得到数据样本的维度
centroids = np.mat(np.zeros((k, n))) # 初始化为一个(k,n)的全零矩阵
# k个质心向量的第j维数据值随机为位于(最小值,最大值)内的某一值
for j in range(n): # 遍历数据集的每一个维度
minJ = np.min(dataSet[:, j]) # 得到该列数据的最小值,最大值
maxJ = np.max(dataSet[:, j])
rangeJ = float(maxJ - minJ) # 得到该列数据的范围(最大值-最小值)
centroids[:, j] = minJ + rangeJ * np.random.rand(k, 1) # k个在0 1之间的二维矩阵
return centroids # 返回初始化得到的k个质心向量
def kMeans(dataSet, k):
m = np.shape(dataSet)[0] # 获取数据集样本数
result = np.mat(np.zeros((m, 2))) # 初始化(m,2)全零矩阵 (属于哪一簇,距离质心距离)
centroids = rand_cent(dataSet, k) # 创建初始的k个质心向量
changed = True # 聚类结果是否发生变化的布尔类型
while changed: # 只要聚类结果一直发生变化,就一直执行聚类算法,直至所有数据点聚类结果不发生变化
changed = False # 聚类结果变化布尔类型置为False
for i in range(m): # 遍历数据集每一个样本向量
minDist = float('inf') # 初始化最小距离为正无穷,最小距离对应的索引为-1
minIndex = -1
for j in range(k): # 循环k个类的质心
dist = get_dist(dataSet[i, :], centroids[j, :]) # 计算数据点到质心的欧氏距离
if dist < minDist: # 如果距离小于当前最小距离
minDist = dist # 当前距离为最小距离,最小距离对应索引应为j(第j个类)
minIndex = j
if result[i, 0] != minIndex: # 当前聚类结果中第i个样本的聚类结果发生变化:布尔值置为True,继续聚类算法
changed = True
result[i, :] = minIndex, minDist**2 # 更新当前变化样本的聚类结果和平方误差
for cent in range(k): # 遍历每一个质心
points = dataSet[np.nonzero(result[:, 0].A == cent)[0]] # 所有属于当前质心类的样本
centroids[cent, :] = np.mean(points, axis=0) # 计算当前质心类的均值(axis=0:求列均值),作为该类质心向量
return centroids, result # 返回质心,属于哪一簇 距离质心距离
kmeans
最新推荐文章于 2022-07-13 16:03:58 发布