python K-Means聚類算法的實現

K-Means 簡介

聚類算法有很多種(幾十種),K-Means是聚類算法中的最常用的一種,算法最大的特點是簡單,好理解,運算速度快,但是一定要在聚類前需要手工指定要分成幾類。
具體實現步驟如下:
給定n個訓練樣本{x1,x2,x3,…,xn}

  kmeans算法過程描述如下所示:

  1.創建k個點作爲起始質心點,c1,c2,…,ck
  2.重複以下過程直到收斂

    遍歷所有樣本xi,根據距離確定每一個樣本的類別。
    確定類別後,計算每一個樣本到各自質心的距離,然後求和。和用來和前一次計算出來的距離和比較,已確定是否收斂。
    對每一個類,計算所有樣本的均值並將其作爲新的質心(對於點而言,就是所有x座標的平均值作爲質心的x座標,所有y座標的平均值作爲y座標的均值)
        
根據以上步驟,實現的具體效果如下:
這裏寫圖片描述

完整代碼如下:

from matplotlib import pyplot
import numpy as np
#隨機生成K個質心
def randomCenter(pointers,k):
    indexs = np.random.random_integers(0,len(pointers)-1,k)
    centers = []
    for index in indexs:
        centers.append(pointers[index])
    return centers
#繪製最終的結果
def drawPointersAndCenters(pointers,centers):
    i = 0
    for classs in pointers:
        cs = np.zeros(4,dtype=np.int8)
        cs[i]=1
        cs[3]=1
        #將list轉爲numpy中的array,方便切片
        xy = np.array(classs)
        if(len(xy)>0):
            pyplot.scatter(xy[:,0],xy[:,1],c=cs)
        i += 1

    centers = np.array(centers)
    pyplot.scatter(centers[:, 0], centers[:, 1], c=[0,0,0],linewidths = 20)
    pyplot.show()



#計算兩個向量的距離,用的是歐幾里得距離
def distEclud(vecA, vecB):
    return np.sqrt(np.sum(np.power(vecA - vecB, 2)))

#求這一組數據座標的平均值,也就是新的質心
def getMean(data):
    xMean = np.mean(data[:,0])
    yMean = np.mean(data[:,1])
    return [xMean,yMean]

def KMeans(pointers,centers):
    diffAllNew = 100
    diffAllOld = 0
    afterClassfy = []
    while(abs(diffAllNew - diffAllOld)>1):
        #更新diffAllOld爲diffAllNEw
        diffAllOld = diffAllNew
        #先根據質心,對所有的數據進行分類
        afterClassfy = [[] for a in range(len(centers))]
        for pointer in pointers:
            dis = []
            for center in centers:
                dis.append(distEclud(pointer,center))
            minDis = min(dis)
            i=0
            for d in dis:
                if(minDis == d):
                    break
                else:
                    i += 1
            afterClassfy[i].append(pointer)
        afterClassfy = np.array(afterClassfy)

        #計算所有點到其中心距離的總的和
        diffAllNews = [[] for a in range(len(centers))]
        i=0
        for classs in afterClassfy:
            for center in centers:
                if len(classs) >0:
                    diffAllNews[i] += distEclud(classs,center)
            i+=1
        diffAllNew = sum(diffAllNews)

        #更新質心的位置
        i=0
        for classs in afterClassfy:
            classs = np.array(classs)
            if len(classs) > 0 :
                centers[i] = getMean(classs)
            i += 1

    drawPointersAndCenters(afterClassfy,centers)
    print(afterClassfy)



def randonGenerate15Pointer():
    ponters =[np.random.random_integers(0,10,2) for a in range(15)]
    np.save("data",ponters)
    print(ponters)
def loadData(fileName):
    return np.load(fileName)

def test():
    pointers = loadData("data.npy")
    centers = randomCenter(pointers,3)
    print(pointers)
    print(centers)
    KMeans(pointers, centers)

test()




loadData裝載的數據是通過randonGenerate15Pointer()方法隨機生成的15個點。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章