python的多元高斯生成起来好麻烦,所以只好用matlab先生成测试数据然后再进行测试了。cnblogs上面写公式好麻烦,所以就不多写了。上代码吧。
kmeans的基本思想就是通过迭代的方法,更新不同类别的的数据均值,从而达到聚类的目的,因为需要先固定一个均值μiold,然后再通过梯度的方法更新μ值。这就天然的包含了EM的思想。
kmeans对起始的均值设定比较敏感,因此并不能保证最终能够收敛到一个好的结果。而且考虑到它需要计算每个点到中心点的距离,计算复杂度非常高,因此,当数据点非常多,而且聚类数目比较多的时候,就会造成速度非常慢的结果。
#!/usr/bin/env python import numpy as np import nose import random from matplotlib import pylab def dist(x,y): return np.sqrt(np.sum((x-y)**2)) def distMat(X,Y): mat=[] for x in X: mat.append(map(lambda y:dist(x,y),Y)) return np.mat(mat) def sum_dist(data,label,center): s=0 for i in range(data.shape[0]): s+=dist(data[i],center[label[i]]) return s def kmeans(data,cluster,threshold=1.0e-19,maxIter=100): m=len(data) labels=np.zeros(m) center=np.array(random.sample(data,cluster)) s=sum_dist(data,labels,center) print s #iterator times n=0 print center while 1: n=n+1 tmp_mat=distMat(data,center) labels=tmp_mat.argmin(axis=1) color=['r*','w^','y+'] pylab.hold(False) for i in range(cluster): idx=(labels==i).nonzero() #print "idx is",idx[0] #print data[idx[0]] center[i]=np.mean(data[idx[0]],axis=1) #center[i]=data[idx[0]].mean(axis=0) d_i=data[idx[0]] d_i=d_i[0] #print 'd_i',d_i[0:-1,0] pylab.plot(d_i[0:-1,0],d_i[0:-1,1],color[i]) pylab.hold(True) print 'center[i] ',center[i][0] pylab.scatter(center[i][0],center[i][1],s=1000,marker='.',c='r') pylab.show() s1=sum_dist(data,labels,center) print s1 if s-s1<=threshold: break s=s1 if n>maxIter: break print n return center import scipy.io as si if __name__=='__main__': data=si.loadmat('a.mat') data=data['a'] center=kmeans(data,3) print center