python学习笔记(29)----k-means聚类

又是自闭的一天,一个下标没对找错误找的我怀疑人生`,一开始是下面这样的,就是因为更新质点的时候我将下标,i,j没区分开,导致的质点越算越少,到了最后只有一个质点,后面改掉才好的

import numpy as np
import matplotlib.pyplot as plt

# 载入数据
data = np.genfromtxt("kmeans.txt", delimiter=" ")

#样本总量和纬度
numsample,dim=data.shape

#计算距离
def eudistance(x,y):
    return np.sqrt(sum((x-y)**2))

#随机初始化K个类别的质心
def center(data,k):
    centers=np.zeros((k,dim))
    for i in range(k):
        index=int(np.random.uniform(0,numsample))
        centers[i,:]=data[index,:]

    return centers
'''

np.random.uniform()
功能:从一个均匀分布[low,high)中随机采样,注意定义域是左闭右开,即包含low,不包含high.
    low: 采样下界,float类型,默认值为0;
    high: 采样上界,float类型,默认值为1;
    size: 输出样本数目,为int或元组(tuple)类型,例如,size=(m,n,k), 则输出m*n*k个样本,缺省时输出1个值。
    
这里一开始没有int,然后系统报错,说.....整数或布尔数组是有效的索引   
'''

#对于每个样本,将其标记为距离类别中心Aj最近的类别j
def kmeans(data,k):
    #簇数据,存储样本属性,二列数据,第一列保存样本属于哪个簇,第二列保存样本和簇之间的误差,即欧氏距离
    clusterdata=np.array(np.zeros((numsample,2)))
    cluster_change=True #决定后续是否改变质心
    centers=center(data,k)#调用随机初始化质心的函数
    print('初始化质心:')
    print(centers)


    while cluster_change:
        cluster_change=False
        for i in range(numsample):
            minidistance=1000.0  #定义一个很大的初始距离,方便后续更新
            minindex=0           #定义初始化的类别都是0类
            for j in range(k):  #调用上面的函数计算每一个质点和该样本的距离
                distance=eudistance(data[j,:],centers[j,:])
                if distance<minidistance:
                    minidistance=distance  #更新最小距离,根据距离判断属于哪个簇
                    clusterdata[i,1]=minidistance
                    minindex=j             #更新簇

            #当当前样本i,与k个质点比较距离之后,判断出他当前属于J簇,现在更新簇
            if clusterdata[i,0]!=minindex:
                cluster_change=True#只要有一个样本的所属簇发生变化,其质心就需要从新计算
                clusterdata[i,0]=minindex
            #这样第i个样本与簇之间的误差和所属簇都更新完毕,下面进行第I+1的样本更新

        #当遍历完当前样本之后,就要对K个质点更新
        for j in range(k):
            #获取第j个簇的所有样本的索引
            centers_index=np.nonzero(clusterdata[:,0]==j)
            #j簇的所有的样本点
            allpoint=data[centers_index]
            #更新质点为每个簇的所有样本的均值
            centers[j,:]=np.mean(allpoint,axis=0)

    #返回质点和样本属性
    return centers,clusterdata


def showCluster(data,k,centers,clusterdata):


        # 用不同颜色形状来表示各个类别
    mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '<r', 'pr']


        # 画样本点
    for i in range(numsample):
        markIndex = int(clusterdata[i, 0])
        plt.plot(data[i, 0], data[i, 1], mark[markIndex])

        # 用不同颜色形状来表示各个类别
    mark = ['*r', '*b', '*g', '*k', '^b', '+b', 'sb', 'db', '<b', 'pb']
    # 画质心点
    for i in range(k):
        plt.plot(centers[i, 0], centers[i, 1], mark[i], markersize=20)

    plt.show()
k=4
centers, clusterdata= kmeans(data,k)

showCluster(data,k,centers,clusterdata)

在这里插入图片描述
这里是改正后的

import numpy as np
import matplotlib.pyplot as plt

# 载入数据
data = np.genfromtxt("kmeans.txt", delimiter=" ")

#样本总量和纬度
numsample,dim=data.shape

#计算距离
def eudistance(x,y):
    return np.sqrt(sum((x-y)**2))

#随机初始化K个类别的质心
def center(data,k):
    centers=np.zeros((k,dim))
    for i in range(k):
        index=int(np.random.uniform(0,numsample))
        centers[i,:]=data[index,:]

    return centers
'''

np.random.uniform()
功能:从一个均匀分布[low,high)中随机采样,注意定义域是左闭右开,即包含low,不包含high.
    low: 采样下界,float类型,默认值为0;
    high: 采样上界,float类型,默认值为1;
    size: 输出样本数目,为int或元组(tuple)类型,例如,size=(m,n,k), 则输出m*n*k个样本,缺省时输出1个值。
    
这里一开始没有int,然后系统报错,说.....整数或布尔数组是有效的索引   
'''

#对于每个样本,将其标记为距离类别中心Aj最近的类别j
def kmeans(data,k):
    #簇数据,存储样本属性,二列数据,第一列保存样本属于哪个簇,第二列保存样本和簇之间的误差,即欧氏距离
    clusterdata=np.array(np.zeros((numsample,2)))
    cluster_change=True #决定后续是否改变质心
    centers=center(data,k)#调用随机初始化质心的函数
    print('初始化质心:')
    print(centers)


    while cluster_change:
        cluster_change=False
        for i in range(numsample):
            minidistance=1000.0  #定义一个很大的初始距离,方便后续更新
            minindex=0           #定义初始化的类别都是0类
            for j in range(k):  #调用上面的函数计算每一个质点和该样本的距离
                distance=eudistance(data[i,:],centers[j,:])
                if distance<minidistance:
                    minidistance=distance  #更新最小距离,根据距离判断属于哪个簇
                    clusterdata[i,1]=minidistance
                    minindex=j             #更新簇

            #当当前样本i,与k个质点比较距离之后,判断出他当前属于J簇,现在更新簇
            if clusterdata[i,0]!=minindex:
                cluster_change=True#只要有一个样本的所属簇发生变化,其质心就需要从新计算
                clusterdata[i,0]=minindex
            #这样第i个样本与簇之间的误差和所属簇都更新完毕,下面进行第I+1的样本更新

        #当遍历完当前样本之后,就要对K个质点更新
        for j in range(k):
            #获取第j个簇的所有样本的索引
            centers_index=np.nonzero(clusterdata[:,0]==j)
            #j簇的所有的样本点
            allpoint=data[centers_index]
            #更新质点为每个簇的所有样本的均值
            centers[j,:]=np.mean(allpoint,axis=0)

    #返回质点和样本属性
    return centers,clusterdata


def showCluster(data,k,centers,clusterdata):


        # 用不同颜色形状来表示各个类别
    mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '<r', 'pr']


        # 画样本点
    for i in range(numsample):
        markIndex = int(clusterdata[i, 0])
        plt.plot(data[i, 0], data[i, 1], mark[markIndex])

        # 用不同颜色形状来表示各个类别
    mark = ['*r', '*b', '*g', '*k', '^b', '+b', 'sb', 'db', '<b', 'pb']
    # 画质心点
    for i in range(k):
        plt.plot(centers[i, 0], centers[i, 1], mark[i], markersize=20)

    plt.show()
k=4
centers, clusterdata= kmeans(data,k)

showCluster(data,k,centers,clusterdata)

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值