機器學習實戰--k-均值聚類

一、聚類是一種無監督學習,他講類似的對象放到同一簇下,有點像自動分類。聚類方法幾乎能夠用到任何對象上,簇內的對象越類似,聚類結果就越好。算法

二、K均值聚類的優勢數組

  算法簡單容易實現app

  缺點:dom

  可能收斂到局部最小值,在大規模數據上收斂速度較慢ide

三、K-均值算法算法流程以及僞代碼性能

  首先隨機選擇k個初始點做爲質心。而後將數據集中的每一個點分配到一個簇中,具體來講,遍歷數據集計算數據與質心之間的距離找到最小的距離將該數據劃分到該簇內,完成後更新簇的質心。可是隻要有數據點的簇發生變化就須要繼續進行劃分,直到沒有點發生改變。學習

  僞代碼:spa

  建立K個點做爲起始質心(常常是隨機選擇,可是不能越界,下面的代碼有具體的作法)code

  當任意一個點的簇分配結果發生變化時對象

    對數據集中的每個數據點

      對每一個質心

        計算質心與數據點的距離

      將數據點分配到距離最近的簇

    對於每個簇,計算簇中全部點的均值並將均值做爲質心

  

from numpy import *

def loadDataSet(filename):
    dataMat=[]
    fr = open(filename)
    for line in fr.readlines():
        curLine = line.strip().split('\t')
        fltLine = list(map(float, curLine))
        #print(fltLine)
        dataMat.append(fltLine)
    return dataMat


def distEclud(vecA, vecB):
    return sqrt(sum(power(vecA - vecB, 2)))

def randCent(dataSet, k):
    n = shape(dataSet)[1]
    centroids = mat(zeros((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


def Kmeans(dataSet, k, distMeans = distEclud, createCent = randCent):
    m = shape(dataSet)[0]
    #創建一個m*2的矩陣位置0記錄聚類的索引,位置1記錄到聚類質心的距離
    clusterAssment = 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 = distMeans(centroids[j,:], dataSet[i,:])
                if distJI < minDist:
                    minDist = distJI; minIndex = j
            if clusterAssment[i, 0] != minIndex:
                clusterChanged = True
            clusterAssment[i, :] = minIndex, minDist**2
        #print(centroids)
        for cent in range(k):
            #經過數組過濾來得到給定簇的全部樣本,nozero返回一個0/1矩陣,而後取第一列的索引列
            ptsInClust = dataSet[nonzero(clusterAssment[:, 0].A == cent)[0]]
            centroids[cent, :] = mean(ptsInClust, axis = 0)
    return centroids, clusterAssment
#print(loadDataSet('testSet.txt'))
dataMat = mat(loadDataSet('testSet.txt'))
myCentroids, clustAssing = Kmeans(dataMat, 4)
print(myCentroids)
print(clustAssing)
K-均值算法

四、使用後處理提升聚類的性能

  K均值算法中的K是用戶給出的,如何衡量在給定K個聚類的狀況下聚類的性能。對於K均值算法可能會收斂到局部最小,而不能收斂到全局最小,所以可能聚類效果很差。在上邊的代碼中clusterAssment保存了每一個數據點的簇標號以及點到簇質心的偏差(就是距離)。那麼可使用SSE(sum of squared Erro,偏差平方和)做爲衡量聚類性能的指標,SSE的數值越小就表示數據點越接近他們的質心聚類效果也就越好,同時因爲對偏差取了平方因此越遠的點在SSE中就越受重視。

  怎麼下降SSE?一種簡單的方法是增長簇的數量,可是這樣很差啊,你是去聚類了你弄了和數據集同樣的簇,那還聚個啥。所以須要在不改變簇的數目的前提降低低SSE。一種可行的辦法是選擇SSE最大的簇,而後對其繼續進行K均值算法。同時爲了保證簇的數目不變,能夠將簇與簇進行合併。

  合併的方法:質心之間距離最近的合併;合併兩個簇而後計算總的SSE,合併可使SSE最小的簇。

五、二分 K均值算法

  爲了克服K均值算法收斂於局部最小的問題,有人提出了一個二分K均值的算法。回來繼續

相關文章
相關標籤/搜索