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