k-meanas原理自实现

import numpy as np
import matplotlib.pyplot as plt

def build_data():
    """
    准备数据
    :return:准备好的数据
    """
    data_list = []
    # 加载数据
    with open("./test.txt") as f:
        # 将所有的元素读成一个列表
        lines = f.readlines()
        # 循环对每一行元素进行单独处理
        for line in lines:
            # print(line)
            # 去除line 前后的空白字符
            line_obj = line.strip().split('	')
            # print(line_obj)
            # print(type(line_obj))
            # print("*"*20)
            # 把 line_obj 里面的每一个元素 转化为float,追加到一列表中
            data_list.append([float(line_obj[0]), float(line_obj[1])])

    # 列表嵌套列表的数据 ,每一个列表元素是原来的每一行元素
    # print(data_list)
    # 将列表嵌套列表转化为二维数组
    data_array = np.array(data_list)
    # print(data_array)
    # 将二维数组 转化为矩阵
    data = np.mat(data_array)
    # print(data)
    # print(type(data))
    return data


def center_init(data, k):
    """
    初始化聚类中心
    :param data: 所有的样本数据
    :param k: 聚类的类别数目
    :return: 聚类中心
    """
    # 随机在 data中挑选4行 作为初始化的聚类中心
    # 获取data 的列数
    columns_num = data.shape[1]
    # 获取data 的行数
    index_num = data.shape[0]
    # 先初始化一个全为0 的中心,然后,后续替换里面的值
    center = np.zeros(shape=(k, columns_num))
    # 每次初始化一个聚类中心,需要循环初始化k次
    for i in range(k):
        #  随机在80行里面选一个下标
        # np.random.uniform() --->默认生成【0,1) 小数,可以更改最小值与最大值
        r = int(np.random.uniform(0, index_num))

        center[i, :] = data[r, :]

    return center


def distance(v1, v2):
    """
    计算点1 跟点2 的距离
    :param v1: 点1
    :param v2: 点2
    :return: 距离
    """

    dist = np.sqrt(np.sum(np.power((v1 - v2), 2)))

    return dist


def k_means_owns(data, k):
    """
    自实现聚类算法
    :param data: 所有的样本数据
    :param k: 聚类的类别数目
    :return: 聚类中心 、每一个样本属于哪一类别
    """


    # 获取data 的 行数
    index_num = data.shape[0]
    columns_num = data.shape[1]
    # 1、初始化聚类中心
    center = center_init(data, k)
    # print(center)

    #  需要将这个样本属于哪一类,而且距离也要保存起来吧
    new_data = np.zeros(shape=(index_num,columns_num))
    # 2、计算距离
    # 每一个样本 都与每一个聚类中心进行计算距离
    # 设置开关
    flag = True
    while flag:
        flag = False # 关闭开关
        for i in range(index_num):
            min_dist = 10000000000
            min_index = -1
            # i 代表每一行的样本的下标
            for j in range(k):
                # 每一个样本需要 与每一个聚类中心进行计算距离
                # 样本点data[i,:]   聚类中心center[j,:]
                dist = distance(data[i,:],center[j,:])

                if dist < min_dist :
                    min_dist = dist
                    min_index = j
            if new_data[i,1] != min_index:
                flag = True # 打开
                new_data[i,:] = min_dist,min_index
        # 调整聚类中心
        for p in range(k):
            # p  0 1 2 3
            # 找出属于同一类别
            p_clustor = data[new_data[:,1] == p,:]

            # 计算这一类别的中心
            #  先找出 这一类的簇第0 列的均值,与第1列的均值分别作为center 的行、列
            center[p,:] = p_clustor[:,0].mean(),p_clustor[:,1].mean()

    return  new_data,center


def show_res(data,new_data,center):
    """
    结果展示
    :param data: 原始数据
    :param new_data: 主要包含了聚类距离与最终类别的数据
    :param center: 最终的聚类中心
    :return: None
    """
    # 1、创建画布
    plt.figure()
    # 2、绘图
    # 获取原始数据的行数
    index_num = data.shape[0]

    #
    colors = ['r','g','pink','y']
    # 绘制散点图
    # 一个点的绘制,需要给该点进行添加颜色
    for i in range(index_num):
        plt.scatter(data[i,0],data[i,1],c=colors[int(new_data[i,1])])

    # 绘制聚类中心
    #
    plt.plot(center[:,0],center[:,1],'bx',markersize=12)
    # print(center[:,0])
    # print(center[:,1])
    # 3、展示
    plt.show()



def main():
    """
    主函数
    :return:
    """
    # 1、构建数据
    data = build_data()

    # 2、进行自实现k-means
    # 确定聚类的类别数目
    k = 4
    new_data, center = k_means_owns(data, k)

    print(new_data)
    print("*" * 80)
    print(center)

    # 3、结果展示
    # 进行绘制结果图形展示
    show_res(data,new_data,center)


if __name__ == '__main__':
    main()

  

原文地址:https://www.cnblogs.com/wutanghua/p/11537135.html