k-means算法

import numpy as np
import matplotlib.pyplot as plt


# 要进行聚类, 得有样本
# 加载样本数据
data = []
with open('test.txt', 'r') as f:
    lines = f.readlines()
    # print(lines)
    for line in lines:
        line_obj = line.strip().split('\t')
        # 进行去除空格和\t,返回line_obj列表
        # print(line_obj)
        # str类型 ---》float类型,在以类表的形式存储到data里面
        data.append([float(line_obj[0]), float(line_obj[1])])
# 列表嵌套列表形式
# print(data)
# 将二维数组转化成矩阵
data = np.mat(data)  # data为矩阵数据
# print(data)
# print(type(data))

# 确定聚为几类
k = 4  # 聚为4类


def distance(v1, v2):
    """
    计算点与点之间的距离
    :param v1: 点1
    :param v2: 点2
    :return: 点与点之间的距离
    """
    # np.power(v1-v2,2)
    # 对于两个点进行距离的计算,可以使用power()
    # np.power(np.array([1,2]-np.array([2,3],2)))
    # np.sqrt() 开平方
    dist = np.sqrt(np.sum(np.power(v1-v2, 2)))
    return dist


def center_init(data, K):
    """
    初始化聚类中心
    :param data: 原始矩阵数据
    :param K: 聚类数量
    :return: 聚类中心
    """
    # 获取data列数
    col_num = data.shape[1]
    index_num = data.shape[0]
    # 先初始化一个center,然后全部元素为0, 后面替换元素就可以了
    # 形状为(4,2)的二维数组
    center = np.zeros((k, col_num))
    # print(center)
    # 循环初始化聚类中心
    for i in range(k):
        # pass
        # np.random.uniform() -->随机初始化一个小数
        r = int(np.random.uniform(0, index_num))
        center[i, :] = data[r, :]
    # print(center)
    return center


def k_means(data, k):
    """
    自实现k-means聚类
    :param data: 原始矩阵数据
    :param k: 聚类数量
    :return:
    """
    # 初始化聚类中心, 调用center_init初始化
    center = center_init(data, k)

    # 计算点与各个聚类中心的相似度 --》距离的计算
    # 循环计算
    # 获取data行数、列数
    index_num = data.shape[0]  # 80
    col_num = data.shape[1]  # 2
    # 进行初始化一个数组, 保存80个点距离聚类中心的距离,和是哪个中心的距离
    # [min_dist,min_index]
    new_data = np.zeros([index_num, col_num])
    flag = True
    while flag:
        flag = False
        for i in range(index_num):  # 循环80次 每次进行距离聚类中心计算
            min_index = -1
            # 每一个点要与聚类中心进行距离计算,计算4次
            min_dist = 10000
            for j in range(k):
                dist = distance(data[i, :], center[j, :])
                # 拿到距离之后 --》进行点到距离中心的比对
                # 设置一个最小距离, 拿到点与每一个聚类中心的距离之后,
                # 与最小距离进行比对,如果小于最小距离,赋值给最小距离,
                # 经过四次,那么点与这四个聚类中心的最小距离就是min_dist
                # 最小距离获取到了
                if dist < min_dist:
                    min_dist = dist
                    min_index = j  #0,1,2,3
                    # --> 属于哪一个聚类中心的点

            # 需要把每一个点的min_dist,min_index保存起来
            if new_data[i, 1] != min_index:
                flag = True
                new_data[i, :] = min_dist, min_index  # 循环80次,那里面存的就是

        # 聚类中心调整
        for p in range(k):
            # 确定同一类别的所有数据
            point_clu = data[np.where(new_data[:, 1] == p)[0]]
            # print(point_clu,type(point_clu))
            # print("----------------------------------")

            # 对这群里的点进行求取均值
            center[p, :] = np.mean(point_clu, axis=0)

    return new_data, center


def show_res(data, new_data, k , center):
    """
    图形绘制
    :param data: 原矩阵
    :param new_data: 保存着属于哪一类的数据
    :param k: 聚类中心个数
    :param center: 聚类中心
    :return: none
    """
    # 创建画布
    plt.figure()

    # 获取data的行数
    index_num = data.shape[0]
    # print(index_num)

    color = ['r', 'g', 'b', 'y']

    colors = []

    for i in range(index_num):
        # print(new_data[i, 1])
        colors.append(color[int(new_data[i, 1])])
        # print(colors)


    # 准备循环 --》散点图
    for i in range(index_num):

        # x,y --->对应的点进行绘制
        # print("index",data[i,0])
        # print("value",data[i,1])
        plt.scatter(data[i, 0], data[i, 1], c=colors[i])

    # 绘制聚类中心

    plt.plot(center[:, 0], center[:, 1], 'bx', markersize=12)

    plt.show()


new_data, center = k_means(data, k)
show_res(data, new_data, k, center)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值