K-均值(K-means)聚類算法
阿新 • • 發佈:2017-09-10
簡單 read 原理 包含 append 添加 url 學習 readlines
聚類是一種無監督的學習,它將相似的對象歸到同一個簇中。
這篇文章介紹一種稱為K-均值的聚類算法,之所以稱為K-均值是因為它可以發現k個不同的簇,且每個簇的中心采用簇中所含值的均值計算而成。
聚類分析視圖將相似對象歸入同一簇,將不相似對象歸到不同簇。
下面用Python簡單演示該算法實現的原理:
函數loadDataSet先將文本文件導入到一個列表中,並添加到dataSet中,返回的結果即為需加載的訓練數據。
def loadDataSet(fileName): dataMat = [] fr = open(fileName) for line in fr.readlines(): curLine = line.strip().split(‘\t‘) fltLine = map(float,curLine) dataMat.append(list(fltLine)) return dataMat
函數distEclud用於計算兩個向量的距離:
def distEclud(vecA, vecB): return sqrt(sum(power(vecA - vecB, 2))) # 計算距離 def randCent(dataSet,k): n = shape(dataSet)[1] # 列數 centroids = mat(zeros((k,n))) # k為簇質心的數量 n為每個點對應的坐標的數量 for j in range(n): minJ = min(dataSet[:,j]) # 每列的最小值 rangeJ = float(max(dataSet[:,j]) - minJ) # 變化區間 centroids[:,j] = minJ + rangeJ * random.rand(k,1) # 生成坐標 return centroids
函數randCent有兩個參數,其中k為用戶指定的質心的數量(即最後分成的類的個數),該函數的作用是為給定的數據集dataSet構建一個包含k個隨機質心的集合(centroids)。
上面三個為輔助函數,下面為完整的K-均值算法:
def kMeans(dataSet,k,disMeas = distEclud, createCent = randCent): m = shape(dataSet)[0] # 訓練數據集的數量 clusterAssent = mat(zeros((m,2))) # 用於保存每個點對應的質心 centroids = createCent(dataSet,k) #初始化質心並保存 clusterChanged = True while clusterChanged: clusterChanged = False for i in range(m): # 遍歷所有數據點 計算每一個數據點到每個質心的距離 minDist = inf minIndex = -1 for j in range(k): # 遍歷所有的質心點 distJI = disMeas(centroids[j,:], dataSet[i ,:]) if distJI < minDist: minDist = distJI minIndex = j if clusterAssent[i,0] != minIndex: clusterChanged = True # 任何一個點對應的質心發生變化需要重新遍歷計算 clusterAssent[i,:] = minIndex,minDist ** 2 print(centroids) for cent in range(k): # 更新質心的位置 ptsInClust = dataSet[nonzero(clusterAssent[:,0].A == cent)[0]] centroids[cent : ] = mean(ptsInClust, axis= 0) return centroids,clusterAssent
思路大概為:
- 遍歷所有訓練數據點(m個數據點)
- 對所有質心(k個質心)
- 計算該數據點與質心之間的距離,並保存該數據點最近的質心
- 對比之前保存的該數據點的質心(即該數據點所屬的簇,保存在clusterAssent中),若發生更改,則證明未收斂,結束後需要從頭開始循環
- 對所有質心(k個質心)
- 對於每一個簇,計算簇中所有點的均值作為質心。
K-均值算法有時候會出現聚類效果較差,收斂到了局部最小值,而非全局最小值。一種用於度量聚類效果的指標是SSE(Sum of Squared Error,誤差平方和),SSE越小表示數據點越接近於它們的質心,聚類效果也越好。因此,要對聚類的結果進行改進的方法可以將具有最大SSE值的簇劃分為兩個簇,同時為了保持簇總數不變,可以將某兩個簇進行合並。
K-均值(K-means)聚類算法