Numpy实现K_means算法(python)

代码所需数据
聚类就是根据数据之间的相似度将数据集划分为多个类别或组,使类别内的数据相似度较大而类别间的数据相似度较小。如下图所示,左边是原始数据,右边是聚类之后的效果,不同的颜色代表不同的类别。
在这里插入图片描述

对于本次代码聚类步骤如下(聚类算法大体步骤,可根据需求进行修改):

1.设置初始类别中心和类别数,初始化是要注意在题目所给数据的x、y的最小值和最大值进行。
2.根据类别中心对全部数据进行类别划分:每个点分到离自己距离最小的那个类
3.重新计算当前类别划分下每个类的中心:例如可以取每个类别里所有的点的平均值作为新的中心。如何求多个点的平均值? 分别计算X坐标的平均值,y坐标的平均值,从而得到新的点。注意:类的中心可以不是真实的点,虚拟的点也不影响。
4.在新的类别中心下继续进行类别划分;

如果连续两次的类别划分结果不变则停止算法; 否则循环2~5。例如当类的中心不再变化时,跳出循环。

import numpy as np
import matplotlib.pyplot as plt
%matplotlib

data = np.loadtxt('Lab4.dat')

def calSSE(X, cidx, ctrs) :
    SSE = 0
    for i, ctr in enumerate(ctrs) :
        SSE += np.sum(np.square(X[np.where(cidx == i + 1)] - ctr))

    return SSE / X.shape[0]

def kmeans(X, K) :
    center_point = []
    for i in range(K) :
        point_x = np.random.uniform(np.min(X, axis = 0)[0], np.max(X, axis = 0)[0])#随机初始化簇心
        point_y = np.random.uniform(np.min(X, axis = 0)[1], np.max(X, axis = 0)[1])
        center_point.append([point_x, point_y])
    center_point = np.array(center_point)
    cluter = np.zeros(X.shape[0]).astype(np.int32)#建立簇类初始化为0
    item = 5
    while item > 0:#迭代
        for i in range(X.shape[0]) :#计算每一组数据与每个簇心的欧氏距离,距离最小者记为此组数据为所标类别
            distance = center_point
            distance = np.sum(np.square(distance - X[i]), axis = 1)#注意x, y都计算所以要求和,注意求和维度
            cluter[i] = np.argmin(distance) + 1#最小值的下标
    
        New_center_point = np.zeros((K, 2))
        
        for i in range(K) :#更新簇心,取每一簇类的平均值作为新簇心
            New_center_point[i][0] = np.mean(X[np.where(cluter == i + 1), 0])
            New_center_point[i][1] = np.mean(X[np.where(cluter == i + 1), 1])
        if (New_center_point - center_point < 1e-7).all() :#当新簇心与之前的簇心近似相等时退出迭代
            break
        center_point = New_center_point
        item -= 1
    return cluter, center_point#返回每一组数据所对应的簇类和簇心

SSE = []
mark = [ 'r', 'c', 'y', 'k', 'm', 'g']

plt.ion()
for K in range(2, 7) :
    cidx, ctrs = kmeans(data, K)
    ctrs_set.append(ctrs)
    print(f'K为{K}时的簇心 : \n {ctrs}')
    SSE.append(calSSE(data, cidx, ctrs))#手肘法求最好分类的K值
    
    plt.subplot(2, 3, K - 1)
    for i in range(K) :
        plt.scatter(data[np.where(cidx == i + 1), 0], data[np.where(cidx == i + 1), 1], marker = '.', color = mark[i])#作图
    plt.scatter(ctrs[ : , 0], ctrs[ : , 1], marker = '*', color = 'g')#做出簇心
    plt.title(f'K is {K}')
    plt.tight_layout()
    plt.xticks([]), plt.yticks([])

    
plt.figure()
plt.plot(list(range(2, 7)), SSE, '+--')
plt.ioff()
plt.show()

效果:
在这里插入图片描述

在这里插入图片描述

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

八岁爱玩耍

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值