二分平均值聚类 java_二分K-均值聚类算法
#K-means聚類
from numpy import *
importmatplotlib.pyplot as plt
plt.ion()#開啟交互模式,實時繪制
plt.subplots()
plt.xlim(-6, 6)
plt.ylim(-6, 6)#plt.pause(5)
defloadDataSet(fileName):
dataMat=[]
fr=open(fileName)for line infr.readlines():
curLine= line.strip().split('\t')
fltLine=list(map(float,curLine))
dataMat.append(fltLine)returndataMatdefdistEclud(vecA, vecB):#print("vecA:",vecA,"vecB:",vecB)
return sqrt(sum(power(vecA-vecB, 2))) #歐式距離
#給定數(shù)據(jù)集構建一個包含k個隨機質(zhì)心的集合#該函數(shù)為給定數(shù)據(jù)集構建一個包含k個隨機質(zhì)心的集合#集合中的值位于min合max之間
defrandCent(dataSet, k):
n= shape(dataSet)[1]
centroids=mat(zeros((k,n)))for j inrange(n):
minJ=min(dataSet[:,j])
rangeJ= float(max(dataSet[:,j]) -minJ)
centroids[:,j]= minJ + rangeJ*random.rand(k,1)returncentroids'''k-均值聚類算法:
該算法會創(chuàng)建k個質(zhì)心,然后將每個點分配到最近的質(zhì)心。這個過程重復數(shù)次,直到數(shù)據(jù)點的簇分配結果不再改變?yōu)橹埂?/p>
這個接口的缺點是:質(zhì)心是隨機初始化的,雖然最后會通過劃分后的點加均值函數(shù)重新計算,但質(zhì)心沒有真正的進行最優(yōu)化收斂
k均值算法收斂(kMeans函數(shù))到了局部最小值,而非全局最小值
一種用于度量聚類效果的指標是SSE(Sum of Squared Error,誤差平方和),SSE值越小表示數(shù)據(jù)點越接近于它們的質(zhì)心,聚類
效果也就越好。因為對誤差取了平方,因此更加重視那些遠離中心的點,一種肯定可以降低SSE值的方法是怎加簇的個數(shù),
但這違背了聚類的目標。聚類的目標是在保持簇數(shù)目不變的情況下提高簇的質(zhì)量。'''
def kMeans(dataSet, k, distMeans=distEclud, createCent=randCent):
m=shape(dataSet)[0]
clusterAssment= mat(zeros((m, 2))) #記錄每個樣本點到質(zhì)心的最小距離,及最小距離質(zhì)心的索引
centroids =createCent(dataSet, k)
centroids_mean_before=centroids
plt_scatter(dataSet,centroids,clusterAssment)
clusterChanged=TruewhileclusterChanged:
clusterChanged=Falsefor i in range(m): #樣本數(shù)據(jù)按行遍歷
minDist = inf; minIndex = -1 #inf 表示正無窮
for j in range(k): #遍歷質(zhì)心,尋找最近質(zhì)心
distJI = distMeans(centroids[j,:], dataSet[i,:]) #計算i點到j質(zhì)心的距離
if distJI
minDist= distJI; minIndex=j #計算出每個樣本數(shù)據(jù)最近的質(zhì)心點與距離
if clusterAssment[i,0] != minIndex: clusterChanged =True
clusterAssment[i,:]= minIndex,minDist**2plt_scatter(dataSet,centroids_mean_before,clusterAssment)for cent in range(k): #遍歷所有的質(zhì)心并更新它們的取值
ptsInClust = dataSet[nonzero(clusterAssment[:,0].A ==cent)[0]]
centroids[cent,:]= mean(ptsInClust, axis=0)
centroids_mean_before=centroids
plt_scatter(dataSet,centroids,clusterAssment)returncentroids, clusterAssment#二分K-均值算法
'''為了克服k-均值算法收斂于局部最小值的問題,有人提出了另一個稱為二分K-均值的算法。
二分k-均值:首先將所有點作為一個簇,然后將該簇一分為二。之后選擇其中一個簇繼續(xù)進行劃分,
選擇哪個簇繼續(xù)劃分取決于對其劃分是否可以最大程度降低SSE的值。上述基于SSE的劃分過程不斷重復,
直到得到用戶指定的簇數(shù)目為止。'''
def biKmeans(dataSet, k, distMeas=distEclud):
m=shape(dataSet)[0]
clusterAssment= mat(zeros((m,2))) #創(chuàng)建一個m*2的零矩陣
#print('clusterAssment:',clusterAssment)
centroid0 = mean(dataSet, axis=0).tolist()[0] #tolist() 把mat轉為list
centList =[centroid0]
plt_scatter(dataSet, mat(centList), clusterAssment)#print('centList:', centList)
for j inrange(m):
clusterAssment[j,1] = distMeas(mat(centroid0), dataSet[j,:])**2 #記錄每個點到質(zhì)心的距離的平方
#print('clusterAssment:',clusterAssment)
while (len(centList)
lowestSSE= inf #正無窮
for i inrange(len(centList)):#以clusterAssment中第一列索引為i的行為索引,找到這些索引對應dataSet的的值返回。通俗講 就是找出第i個質(zhì)心關聯(lián)的點
ptsInCurrCluster = dataSet[nonzero(clusterAssment[:,0].A==i)[0],:]
centroidMat,splitClustAss= kMeans(ptsInCurrCluster, 2, distMeas)
sseSplit= sum(splitClustAss[:,1])
sseNotSplit= sum(clusterAssment[nonzero(clusterAssment[:,0].A!=i)[0],1]) #求劃分前其余(除i質(zhì)心之外的)質(zhì)心的sse值
print("sseSplit, and notSplit:",sseSplit, sseNotSplit)if (sseSplit + sseNotSplit)
bestCentToSplit=i
bestNewCents=centroidMat
bestClustAss=splitClustAss.copy()
lowestSSE= sseSplit + sseNotSplit #所有質(zhì)心(被分割的質(zhì)心加沒被分割的質(zhì)心)距離的平方
#更新bestClustAss簇的分配結果
bestClustAss[nonzero(bestClustAss[:,0].A == 1)[0],0] =len(centList)
bestClustAss[nonzero(bestClustAss[:,0].A== 0)[0],0] =bestCentToSplitprint("the bestCentToSplit is:",bestCentToSplit)print("the len of bestClustAss is:", len(bestClustAss))#將bestCentTosplit(最適合分割的質(zhì)心點),替換為分割后的第0個質(zhì)心點,分割后生成的另一個質(zhì)心點通過 append方法添加
centList[bestCentToSplit] = bestNewCents[0,:].tolist()[0] #python3修改
centList.append(bestNewCents[1,:].tolist()[0])#將被分割的質(zhì)心cluter索引和最小距離平方(minDist**2) 重新賦值
clusterAssment[nonzero(clusterAssment[:,0].A == bestCentToSplit)[0],:] =bestClustAss
plt_scatter(dataSet, mat(centList), clusterAssment)returnmat(centList),clusterAssment#繪圖接口
defplt_scatter(datMat,datCent,cluster):
plt.clf()#清空畫布
plt.xlim(-6, 6) #因為清空了畫布,所以要重新設置坐標軸的范圍
plt.ylim(-6, 6)
m=shape(datMat)[0]
n=shape(datCent)[0]
ms=['^','v','o','s','p','','1','2','3'] #數(shù)據(jù)點形狀
cs=['r','g','b','y','m','c','k','r','g','b'] #數(shù)據(jù)點的顏色
for i inrange(m):
k=int(cluster[i,0])
plt.scatter(datMat[i,0],datMat[i,1],c=cs[k],marker=ms[k],alpha=0.5)for j inrange(n):
plt.scatter(datCent[j,0],datCent[j,1],c=cs[j],marker='x',alpha=1.0)
plt.pause(0.3)if __name__ == '__main__':
datMat= mat(loadDataSet('testSet.txt'))#myCentroids,clusterAssing = kMeans(datMat, 4)
#plt_scatter(datMat,myCentroids,clusterAssing)
centList,myNewAssments=biKmeans(datMat,4)
plt_scatter(datMat,centList,myNewAssments)
plt.ioff()
plt.show()
總結
以上是生活随笔為你收集整理的二分平均值聚类 java_二分K-均值聚类算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: h2 java tcpip_windo
- 下一篇: 为什么酱香型白酒好?