numpy手写kmeans
程序员文章站
2022-05-18 18:10:41
numpy手写kmeans,并可视化。由于可视化限制,拿二维数据进行示范。但该代码可适用于任意维的数据,同时可根据三种的计算距离公式(欧式距离,曼哈顿距离,余弦距离),提供不同的聚类结果。import numpy as npimport matplotlib.pyplot as pltdef distance_cal(x, y): #计算距离 if cal_type == "eclud": dis = np.sqrt(np.sum(np.square(x - y))) #欧...
numpy手写kmeans,并可视化。
由于可视化限制,拿二维数据进行示范。但该代码可适用于任意维的数据,同时可根据三种的计算距离公式(欧式距离,曼哈顿距离,余弦距离),提供不同的聚类结果。
import numpy as np
import matplotlib.pyplot as plt
def distance_cal(x, y): #计算距离
if cal_type == "eclud":
dis = np.sqrt(np.sum(np.square(x - y))) #欧氏距离
elif cal_type == "manhattan":
dis = np.sum(np.abs(x - y)) #Manhattan距离
elif cal_type == "cosin":
dis = np.dot(x, y) / (np.linalg.norm(x) * np.linalg.norm(y)) #余弦距离
return dis
def rand_cent(data, k): #初始化聚类中心点
'''
data: 聚类的数据集
k: 聚类的个数
'''
num_features = data.shape[1] #数据集的特征数,也就是列数
init_centers = np.zeros((k, num_features)) #确定聚类中心点的形状, 其可以理解成将数据压缩成k行数据,列数保持不变
for i in range(num_features): #遍历每列数据,来初始化聚类中心点
min_data = min(data[:, i]) #获得当前列的最小值,为一个数值
max_data = max(data[:, i])
range_data = max_data - min_data #获得该列数值的变动范围
init_centers[:, i] = min_data + range_data * np.random.rand(k) #一次性获得k个数值,作为当前列初始中心点
return init_centers
def kmeans(data, k): #进行kmeans聚类
num = data.shape[0] #获得数据量
cluster_centers = rand_cent(data, k) #获取初始化的聚类中心点,也可以完全随机初始化。只是该方法将初始点定位数据内部
cluster_assign = np.zeros((num, ))#创建数组,用于存放所属类别
change = True
while change:
change = False
for i in range(num): #遍历每行数据,来计算其与k个聚类中心点的距离,并判定其所属类别
min_dis = np.inf #初始化一个极大值作为最小距离
index = 0 #初始化所属类别
for j in range(k):
dis = distance_cal(data[i], cluster_centers[j]) #计算当前行与每个距离中心点的距离
if dis < min_dis:
min_dis = dis #重新给最小距离赋值
index = j #确定其所属类别
if cluster_assign[i] != index: #如果计算的类别与所属类别不符,则需重新训练,以计算距离
change = True
cluster_assign[i] = index
for j in range(k): #更新聚类中心点
cluster_data = data[np.nonzero(cluster_assign == j)] #提取同属一个类别的数据
if len(cluster_data): #确保该数组的数据非空
cluster_centers[j] = np.mean(cluster_data, axis = 0)#将该数组的均值作为聚类中心点
return cluster_centers, cluster_assign
if __name__ == "__main__":
data1 = np.random.uniform(0, 3, (100, 2))
data2 = np.random.uniform(4, 7, (100, 2))
data3 = np.random.uniform(8, 10, (100, 2))
data = np.r_[data1, data2, data3] #将数组进行纵向合并
k = 3
cal_type = "eclud" #计算距离的类别, ["eclud", "manhattan", "cosin"]
cluster_centers, cluster_assign = kmeans(data, k) #获得聚类中心点,及每行数据的所属类别
#可视化
plt.figure()
for j in range(k):
x = data[np.nonzero(cluster_assign == j), 0]
y = data[np.nonzero(cluster_assign == j), 1]
plt.scatter(x, y, s = 10 * (j+1), label = j)
plt.scatter(cluster_centers[:, 0], cluster_centers[:, 1], s = 150, marker = "x", c = 'm')
plt.legend()
plt.show()
本文地址:https://blog.csdn.net/lmw0320/article/details/107462413