欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

numpy手写kmeans

程序员文章站 2022-12-20 16:36:05
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

相关标签: 机器学习基础