Kmeans(1)

2017/03/02
前一篇文章,在使用这个算法的时候,产生的训练数据都是数据顺序排好的,就是两个簇分的很开。这种在实际情况肯定是少见的,或者见不到的。
所以特意用打乱的数据测试了一次。不过,虽然大多数结果都是对的,但是还是有一次的数据只得到了一个簇,后悔没有记下来。


我现在要注意的是,我现在产生的数据都是很规整的,让人一看就觉得是一个簇,所以还需要以后多用一些实际数据进行下测试。


下面贴代码
(代码里面还是有不少值得借鉴的一些小操作,比如画图,打乱数组)

#! /usr/local/bin/python
#coding:utf-8
#17/03/02
#Auther:VChao
'''
This py file is designed to show the k-means algorithm.
There is more data than before.
'''
import os
import matplotlib
matplotlib.use('Agg')

import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets

from math import sqrt
import random

def RandPoint(data,k):
    #Get the k random point for the initial compution.
    PointMax = [max(data[:,0]),max(data[:,1])]
    PointMin = [min(data[:,0]),min(data[:,1])]

    Res = []
    for i in range(k):
        pointx = random.random()*(PointMax[0] - PointMin[0])+PointMin[0]
        pointy = random.random()*(PointMax[1] - PointMin[1])+PointMin[1]
        Res.append([pointx,pointy])
    return Res

def CalDis(point1,point2):
    #Calculate the distance of two points
    x1 = point1[0]
    y1 = point1[1]

    x2 = point2[0]
    y2 = point2[1]
    
    return sqrt(pow(x1-x2,2)+pow(y1-y2,2))

def kMeans(data):
    #To be honest, I don't know how to use the algorithm.
    #How to code!?
    #--------------------#
    #Return the cluster result and the central point.
    k = 2

    datanum = len(data)
    cenLoc = RandPoint(data,k)
    lastMatches = None
    #Iteration times.
    for t in range(20):
        #Every iteration,there'll be a total new array to hold the match result.
        bestMatches = [[] for p in range(k)]
        print 'Iteration %d' %t
        #For every item in data,calculating the nearest point.
        for j in range(datanum):
            point = data[j]
            bestMatch = 0
            for i in range(k):
                d = CalDis(point,cenLoc[i])
                if d < CalDis(point,cenLoc[bestMatch]): bestMatch = i
            #Get it in to the matched Cluster.
            bestMatches[bestMatch].append(j)
        #下面这个句子,开始我感觉是有错误的,数组位置不同也是不相等.
        #但是如果你仔细想想,因为每次循环都是从零开始的,这就是关键点.
        if lastMatches == bestMatches: break
        lastMatches = bestMatches
        #Recalculate the centrol point.
        for i in range(k):
            avgs = [0.0]*len(data[0])
            if len(bestMatches[i])>0:
                for item in bestMatches[i]:
                    for m in range(len(data[item])):
                        avgs[m] += data[item][m]
                for j in range(len(avgs)):
                    avgs[j]/=len(bestMatches[i])
                cenLoc[i] = avgs
#   print cenLoc    
    return bestMatches,cenLoc   
def PlotCluster(data,target,cen):
    Filename = 'Myfig.png'
    plt.scatter(data[:,0],data[:,1],c=target,s=25,cmap=plt.cm.Paired)
    plt.scatter(cen[:,0],cen[:,1],s = 80 ,facecolors = 'none')
    #plt.scatter(cen[:,0],cen[:,1],s = 80 )
    plt.savefig(Filename)
    os.system('sz '+Filename)
    os.system('rm -f '+Filename)
if __name__ == "__main__":

    #np.random.seed(0)
    data = np.r_[np.random.randn(20,2) - [2,2],np.random.randn(20,2) + [2,2]]
    #上面这个数据产生的过程其实,很不好,因为这个产生的数据已经将这部分数据都归好类了.
    #而且,我测试的过程偏偏又是一个一个测试的这样肯定也会产生不好的结果.
    #所以下面的代码就要试试,如果打乱这个顺序会发生什么结果.
    #这一试不要紧,虽然只有一次,没有分类成功,但也说明的却这个算法有问题.
    #就是我试了多次,有一次,这个结果只分类出了一个簇.
    #----------------------#
    np.random.shuffle(data) 
    #This function could reorder the array!Amazing.
    #----------------------#
    res,cen =  kMeans(data) 
    target = [0]*40
    for i in range(len(res)):
        for item in res[i]:
            target[item] = i
    target = [ i + 1 for i in target]
    print target
    PlotCluster(data,target,np.array(cen))
Kmeans(1)_第1张图片
Myfig.png

我觉得这部分的算法,我还是没有透彻的理解,因为只是我测试的数据还没有遇见什么难点,这就很尴尬。所以,下一步一定要深入了解这个算法的内涵和优缺点。
还有一点,就是我的算法,是不是真的就做对了!?


2017/03/06
本次实验,我继续对算法进行了分析,主要测试了一下如果是多簇数据的的效果图。
首先,这次使用的数据是利用sklearn库得到的,可控的条件还算不少。

Kmeans(1)_第2张图片
Algorithm.png

Kmeans(1)_第3张图片
Real.png

从图中可以看出,分类的效果还算不错?!
但有几个问题需要思考。
首先,实际数据集里面是有数据交叉在一起的,但是算法得出的这个是没有的。这一点也很容易理解,毕竟一个点不可能同时跟两个中心点产生关联。(空白的中心点始终是由算法产生的) 所以说,先前说这种方法比较适合球形的簇也是有些理论依据的。
其次,如果是产生了这种点,我应该怎么办!?(就是那种,边缘点插入到其他簇中。)
而且, 我还想到,是不是可以有概率的思想来判定这种在两个簇心之间的点。
有一点很重要,就是,我上面也提到,这算法会导致一些交叉的点无法判别出来。这里是我用自己画出来的图看到的,但是如果是那种高维的数据,我怎么来进行知道有这种不干净的数据,或者更近一步,我怎么能对这种点的处理方法有哪些?


这个算法,我觉得也算是学习完毕了。!?
不过那几个简单的问题,还是需要多看论文来真正掌握。


你可能感兴趣的:(Kmeans(1))