python K-Means聚類演算法的實現
阿新 • • 發佈:2019-01-10
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個點。