python實現kMeans演算法的詳解

來源:互聯網
上載者:User
聚類是一種無監督的學習,將相似的對象放到同一簇中,有點像是全自動分類,簇內的對象越相似,簇間的對象差別越大,則聚類效果越好。本文主要為大家詳細介紹了python實現kMeans演算法,具有一定的參考價值,感興趣的小夥伴們可以參考一下,希望能協助到大家。

1、k均值聚類演算法

k均值聚類將資料分為k個簇,每個簇通過其質心,即簇中所有點的中心來描述。首先隨機確定k個初始點作為質心,然後將資料集分配到距離最近的簇中。然後將每個簇的質心更新為所有資料集的平均值。然後再進行第二次劃分資料集,直到聚類結果不再變化為止。

虛擬碼為

隨機建立k個簇質心
當任意一個點的簇分配發生改變時:
對資料集中的每個資料點:
對每個質心:
計算資料集到質心的距離
將資料集分配到最近距離質心對應的簇
對每一個簇,計算簇中所有點的均值並將均值作為質心

python實現


import numpy as npimport matplotlib.pyplot as pltdef loadDataSet(fileName):  dataMat = []  with open(fileName) as f:  for line in f.readlines():   line = line.strip().split('\t')   dataMat.append(line) dataMat = np.array(dataMat).astype(np.float32) return dataMatdef distEclud(vecA,vecB): return np.sqrt(np.sum(np.power((vecA-vecB),2)))def randCent(dataSet,k): m = np.shape(dataSet)[1] center = np.mat(np.ones((k,m))) for i in range(m):  centmin = min(dataSet[:,i])  centmax = max(dataSet[:,i])  center[:,i] = centmin + (centmax - centmin) * np.random.rand(k,1) return centerdef kMeans(dataSet,k,distMeans = distEclud,createCent = randCent): m = np.shape(dataSet)[0] clusterAssment = np.mat(np.zeros((m,2))) centroids = createCent(dataSet,k) clusterChanged = True while clusterChanged:  clusterChanged = False  for i in range(m):   minDist = np.inf   minIndex = -1   for j in range(k):    distJI = distMeans(dataSet[i,:],centroids[j,:])    if distJI < minDist:     minDist = distJI     minIndex = j   if clusterAssment[i,0] != minIndex:    clusterChanged = True   clusterAssment[i,:] = minIndex,minDist**2  for cent in range(k):   ptsInClust = dataSet[np.nonzero(clusterAssment[:,0].A == cent)[0]]   centroids[cent,:] = np.mean(ptsInClust,axis = 0) return centroids,clusterAssmentdata = loadDataSet('testSet.txt')muCentroids, clusterAssing = kMeans(data,4)fig = plt.figure(0)ax = fig.add_subplot(111)ax.scatter(data[:,0],data[:,1],c = clusterAssing[:,0].A)plt.show()print(clusterAssing)

2、二分k均值演算法

K均值演算法可能會收斂到局部最小值,而非全域最小。一種用於度量聚類效果的指標為誤差平方和(SSE)。因為取了平方,更加重視原理中心的點。為了克服k均值演算法可能會收斂到局部最小值的問題,有人提出來二分k均值演算法。
首先將所有點作為一個簇,然後將該簇一分為二,然後選擇所有簇中對其劃分能夠最大程度減低SSE的值的簇,直到滿足指定簇數為止。

虛擬碼

將所有點看成一個簇
計算SSE
while 當簇數目小於k時:
for 每一個簇:
計算總誤差
在給定的簇上進行k均值聚類(k=2)
計算將該簇一分為二的總誤差
選擇使得誤差最小的那個簇進行劃分操作

python實現


import numpy as npimport matplotlib.pyplot as pltdef loadDataSet(fileName):  dataMat = []  with open(fileName) as f:  for line in f.readlines():   line = line.strip().split('\t')   dataMat.append(line) dataMat = np.array(dataMat).astype(np.float32) return dataMatdef distEclud(vecA,vecB): return np.sqrt(np.sum(np.power((vecA-vecB),2)))def randCent(dataSet,k): m = np.shape(dataSet)[1] center = np.mat(np.ones((k,m))) for i in range(m):  centmin = min(dataSet[:,i])  centmax = max(dataSet[:,i])  center[:,i] = centmin + (centmax - centmin) * np.random.rand(k,1) return centerdef kMeans(dataSet,k,distMeans = distEclud,createCent = randCent): m = np.shape(dataSet)[0] clusterAssment = np.mat(np.zeros((m,2))) centroids = createCent(dataSet,k) clusterChanged = True while clusterChanged:  clusterChanged = False  for i in range(m):   minDist = np.inf   minIndex = -1   for j in range(k):    distJI = distMeans(dataSet[i,:],centroids[j,:])    if distJI < minDist:     minDist = distJI     minIndex = j   if clusterAssment[i,0] != minIndex:    clusterChanged = True   clusterAssment[i,:] = minIndex,minDist**2  for cent in range(k):   ptsInClust = dataSet[np.nonzero(clusterAssment[:,0].A == cent)[0]]   centroids[cent,:] = np.mean(ptsInClust,axis = 0) return centroids,clusterAssmentdef biKmeans(dataSet,k,distMeans = distEclud): m = np.shape(dataSet)[0] clusterAssment = np.mat(np.zeros((m,2))) centroid0 = np.mean(dataSet,axis=0).tolist() centList = [centroid0] for j in range(m):  clusterAssment[j,1] = distMeans(dataSet[j,:],np.mat(centroid0))**2 while (len(centList)<k):  lowestSSE = np.inf  for i in range(len(centList)):   ptsInCurrCluster = dataSet[np.nonzero(clusterAssment[:,0].A == i)[0],:]   centroidMat,splitClustAss = kMeans(ptsInCurrCluster,2,distMeans)   sseSplit = np.sum(splitClustAss[:,1])   sseNotSplit = np.sum(clusterAssment[np.nonzero(clusterAssment[:,0].A != i)[0],1])   if (sseSplit + sseNotSplit) < lowestSSE:    bestCentToSplit = i    bestNewCents = centroidMat.copy()    bestClustAss = splitClustAss.copy()    lowestSSE = sseSplit + sseNotSplit  print('the best cent to split is ',bestCentToSplit)#  print('the len of the bestClust')  bestClustAss[np.nonzero(bestClustAss[:,0].A == 1)[0],0] = len(centList)  bestClustAss[np.nonzero(bestClustAss[:,0].A == 0)[0],0] = bestCentToSplit  clusterAssment[np.nonzero(clusterAssment[:,0].A == bestCentToSplit)[0],:] = bestClustAss.copy()  centList[bestCentToSplit] = bestNewCents[0,:].tolist()[0]  centList.append(bestNewCents[1,:].tolist()[0]) return np.mat(centList),clusterAssmentdata = loadDataSet('testSet2.txt')muCentroids, clusterAssing = biKmeans(data,3)fig = plt.figure(0)ax = fig.add_subplot(111)ax.scatter(data[:,0],data[:,1],c = clusterAssing[:,0].A,cmap=plt.cm.Paired)ax.scatter(muCentroids[:,0],muCentroids[:,1])plt.show()print(clusterAssing)print(muCentroids)

代碼及資料集下載:K-means

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.