1. 程式人生 > >K-均值(K-means)聚類算法

K-均值(K-means)聚類算法

簡單 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-均值算法有時候會出現聚類效果較差,收斂到了局部最小值,而非全局最小值。一種用於度量聚類效果的指標是SSE(Sum of Squared Error,誤差平方和),SSE越小表示數據點越接近於它們的質心,聚類效果也越好。因此,要對聚類的結果進行改進的方法可以將具有最大SSE值的簇劃分為兩個簇,同時為了保持簇總數不變,可以將某兩個簇進行合並。

K-均值(K-means)聚類算法