香蕉树上第九根芭蕉——k-means算法实现及RuntimeWarning: Mean of empty slice错误的解决 - Go语言中文社区

香蕉树上第九根芭蕉——k-means算法实现及RuntimeWarning: Mean of empty slice错误的解决


k-means算法的原理作为无监督算法,看起来和knn算法挺像的,但是knn作为有监督算法,还是有一定区别至于k-means算法原理及其伪代码就不说了。在实现k-means算法中,还是有些地方需要注意的,废话少说,还是来先看看代码。

import numpy
import matplotlib.pyplot as plt
def readdata(filename):#读入数据
    zhuancun=[]
    ff=open(filename)
    for i in ff.readlines():
        temp1=i.split('n')[0].split('t')
        #关于数据转换,这两种写法都是可以的
        #写法一:
        temp=list(map(float,temp1))
        #写法二:
        #zhuancun.append(temp1)
        #zhuancun=[list(map(float,line)) for line in zhuancun]
        zhuancun.append(temp)
    return numpy.array(zhuancun)
def creat_cluter(dataset,dataset_lie_shu,tezhengshu):
        temp_cluter=numpy.array(numpy.zeros([tezhengshu,dataset_lie_shu]))
        for i in range(dataset_lie_shu):
            min_lie=numpy.min(dataset[:,i])
            max_lie=numpy.max(dataset[:,i])
            kuadu_lie=max_lie-min_lie
            ran_lie=kuadu_lie*(numpy.random.random())+min_lie
            temp_cluter[:,i]=ran_lie
        return numpy.array(temp_cluter)
def jisuan_distance(date1,date2):
    return numpy.sqrt(sum(pow(date1-date2,2)))
def kmeans(dataset,tezhengshu):
    dataset_lie_shu=numpy.shape(dataset)[1]
    dataset_hang_shu=numpy.shape(dataset)[0]
    #
    #这里非常关键,一定要将其设为1的矩阵,否则造成一次就退出了
    #
    #
    tongji_juzhen=numpy.array(numpy.ones([dataset_hang_shu,2]))
    #ll=numpy.ones([dataset_hang_shu, 1])
    #print(type(ll))
    #print_date(dataset,numpy.array(numpy.ones([dataset_hang_shu,1])).flatten())
    creat_random_juzhen=creat_cluter(dataset,dataset_lie_shu,4)
    clu_change=True
    lun_index=1
    while clu_change:
        #这句目的是一次迭代之后则改变标志位,如果中途没有哪个位分类错误了,则会导致整个迭代过程退出
        clu_change=False
        for i in range(dataset_hang_shu):
            juli_juzhen=[(jisuan_distance(creat_random_juzhen[j,:],dataset[i,:])) for j in range(4)]
            zhi_min_juli_juzhen=min(juli_juzhen)
            index_min_juli_juzhen=juli_juzhen.index(zhi_min_juli_juzhen)
            #如果这个点分类还是会改变说明还要继续分类,即继续迭代一次就是为了为了这个点,即采用新的簇之后,这是这个函数非常关键的地方
            if tongji_juzhen[i,0] != index_min_juli_juzhen:
                clu_change=True
            #将这个点的分类结果及距离他所属簇距离写入统计矩阵
            tongji_juzhen[i,:]=index_min_juli_juzhen,zhi_min_juli_juzhen
        for i in range(4):
            belong_juzhen=numpy.nonzero(tongji_juzhen[:,0] == i)[0]
            #print(belong_juzhen)
            belong_dataset=dataset[belong_juzhen]
            if len(belong_juzhen) != 0:
                creat_random_juzhen[i,]=numpy.mean(belong_dataset,axis=0)
                print("第%d轮第%d个簇点改变:"%(lun_index,i))
                print(creat_random_juzhen)
        lun_index+=1
    return creat_random_juzhen,tongji_juzhen
def print_date(dateset,lables):
    color=['b','c','g','k','m','r','w','y']
    kong_temp={}
    for i in lables:
        if i not in kong_temp.keys():
            kong_temp[i]=0
        kong_temp[i]+=1
    kong_temp[5]=90
    print(kong_temp)
    print("*******")
    print(list(kong_temp.keys()))
    for index,ky in enumerate(list(kong_temp.keys())):
        kong_temp[ky]=color[index]
    print(kong_temp)
    #print(kong_temp)
    fig=plt.figure()
    ax=fig.add_subplot(111)
    plt.title('The third graph')
    plt.xlabel('X')
    plt.ylabel('Y')
    ax.scatter(dataset[:,0],dataset[:,1],s=10*lables,c='g')
    plt.show()
def print_data_test(dataset,tongji_juzhen,cluter_juzhen):
    color=['b','c','g','k','m','r','w','y']
    fig = plt.figure()
    ax = fig.add_subplot(111)
    plt.title('The third graph')
    plt.xlabel('X')
    plt.ylabel('Y')
    print(tongji_juzhen[:,0])
    print_juzhen=numpy.zeros([numpy.shape(dataset)[0],1])
    #
    #这里也是非常关键的,由于要将每个数据的归类转换为颜色标签,这样写非常简便
    #
    print_juzhen=numpy.array([list(map(str,juzhen)) for juzhen in print_juzhen]).flatten()
    #
    for i in range(4):
        print_juzhen[tongji_juzhen[:,0] == i]=color[i]
    print(print_juzhen)
    print(type(tongji_juzhen[:,0]))
    ax.scatter(dataset[:, 0], dataset[:, 1],c=print_juzhen)
    ax.scatter(cluter_juzhen[:,0],cluter_juzhen[:,1],s=120,c='r',marker='<')
    plt.show()
dataset=readdata('testSet-kmeans.txt')
cluter_juzhen,tongji_juzhen=kmeans(dataset,4)
print_data_test(dataset,tongji_juzhen,cluter_juzhen)

 运行结果如图:

 但是这里还是有几个点需要注意的。

第一点:第一次产生的统计样本集特征矩阵必须是全是1,至少这个矩阵记录每个样本属于哪个类必须是1,这样能够避免错误,否则会产生一些后果。比如迭代一次之后就不会再去迭代了。

第二点:这里非常关键的一点就是继续迭代的条件,如果现在迭代错误,才会继续迭代下去。

第三点:对于将已经分类好的矩阵tongji_juzhen[:,0],取出第0列之后,若要将其第0列的值与颜色标签对应起来,怎么写更简化呢?

期间还发生了一个错误:

发生 原因是在选出其他分类所对应的数据集时,由于会产生空的数组,传入mean()函数中。

 解决方法就是先判断,不为空才传入!

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_34327821/article/details/81664244
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2021-06-12 21:01:50
  • 阅读 ( 1765 )
  • 分类:算法

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢