1. 程式人生 > >python K-Means聚類演算法的實現

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個點。