機器學習-聚類(clustering)算法:K-means算法


1. 歸類:

      聚類(clustering):屬於非監督學習(unsupervised learning)

      無類別標記(class label)

2. 舉例:

          

 

3. Kmeans算法

    3.1 clustering中的經典算法,數據挖掘十大經典算法之一

    3.2 算法接受參數k;將事先輸入的n個數據對象划分為k個類以便使得獲得的聚類滿足:同一類中對象之間相似度較高,不同類之間對象相似度較小。

    3.3 算法思想

         以空間中k個點為中心進行聚類,對最靠近他們的對象歸類。通過迭代的方法,逐次更新各聚類中心的值,直至得到最好的聚類結果。

    3.4 算法描述

        1) 選擇適當的c個類的初始中心;

        2) 在第k次迭代中,對任意一個樣本,求其到c各中心的距離,將該樣本划歸到距離最近的中心所在的類。

        3) 利用均值的方法更新該類的中心值,即通過求當前類所有點的均值來更新c的中心值

        4) 對所有的c個聚類中心,如果利用2),3)的迭代更新后,值仍然保持不變,則迭代結束,否則繼續迭代。

    3.5 算法流程

        輸入:k, data[n]

          1) 選擇k個初始中心點,例如c[0]=data[0]...c[k-1]=data[k-1]

          2) 對於data[0]...data[n],求出分別與c[0]...c[k-1]之間的距離,將其划分到距離最近的中心所屬的類,如data[j] 與c[i]距離最近,data[j]就標記為i。

          3) 采用均值思想更新類中心,如對於所有標記為i的點,重新計算c[i]={所有標記為i的data[i]之和}/標記為i的個數。

          4) 重復2) 3),直到所有的類中心值的變化小於給定閾值。

          流程圖:

           

 

      舉例:

             

      每個實例對應坐標:

 

 

 

                        

                        距離

                                           歸類

                                            中心點

                         更新后中心點

                           距離

                                                       歸類

                          更新中心點

                         更新后中心點

                        距離

                                                      歸類

                   停止!!!

           

 

    3.5 算法優缺點

       優點:速度快、簡單

       缺點:最終結果和初始點選擇有關,容易陷入局部最優,需要知道k值。

 

# -*- coding:utf-8 -*-

import numpy as np

def kmeans(x, k, maxIt):

    numPoints, numDim = x.shape

    dataSet = np.zeros((numPoints, numDim + 1))
    dataSet[:, : -1] = x #dataSet所有行,從第一列到倒數第二列都等於x

    #隨機選取中心點 所有數據點 隨機選k行
    centrods = dataSet[np.random.randint(numPoints, size = k), :]
    #中心點的最后一列初始化值(類標簽):1到k
    centrods[:, -1] = range(1, k+1)

    iterations = 0

    oldCentrods = None

    while not shouldStop(oldCentrods, centrods, iterations, maxIt):
        print("iteration: \n", iterations)
        print("dataSet: \n", dataSet)
        print("centroids: \n", centrods)

        #為什么用copy而不是= 因為后面會做修改 oldCentrods和centrods是兩部分內容
        oldCentrods = np.copy(centrods)
        iterations += 1

        #更新類標簽
        updateLabels(dataSet, centrods)

        #更新中心點
        centrods = getCentroids(dataSet, k)

    return dataSet


def shouldStop(oldCentroids, centroids, iterations, maxIt):
    if iterations > maxIt:
        return True
    return np.array_equal(oldCentroids, centroids)

def updateLabels(dataSet, centroids):
    numPoints, numDim = dataSet.shape
    for i in range(0, numPoints):
        dataSet[i, -1] = getLabelFromCosestCentroid(dataSet[i, : -1], centroids)

def getLabelFromCosestCentroid(dataSetRow, centroids):
    label = centroids[0, -1]#初始化本條數據類標簽為第一個中心點的類標簽
    minDis = np.linalg.norm(dataSetRow - centroids[0, : -1]) #調用內嵌的方法算距離 一直在更新
    for i in range(1, centroids.shape[0]):#求與每個中心點之間的距離
        dis = np.linalg.norm(dataSetRow - centroids[i, : -1])
        if dis < minDis:
            minDis = dis
            label = centroids[i, -1]
    print("minDist:", minDis)
    return label

#更新中心點
def getCentroids(dataSet, k):
    result = np.zeros((k, dataSet.shape[1]))
    for i in range(1, k + 1):
        oneCluster = dataSet[dataSet[:, -1] == i, : -1]#取出標記為i的數據(除最后一列)
        result[i - 1, : -1] = np.mean(oneCluster, axis=0)
        result[i - 1, -1] = i

    return result

x1 = np.array([1, 1])
x2 = np.array([2, 1])
x3 = np.array([4, 3])
x4 = np.array([5, 4])
testX = np.vstack((x1,x2,x3,x4))

result = kmeans(testX, 2 ,10)
print("result:" ,result)

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM