K Means聚類分析及其Python實現

2021-08-09 04:07:00 字數 3404 閱讀 3468

聚類將給定的樣例集劃分為若干個互不相交的子集。直觀來看,好的聚類結果,一定表現出簇內相似度高、簇間相似度低的特徵。那麼如何來量化這個所謂的「相似度」,我們一般採用的方法是計算樣本間的「距離」。

給定兩個樣本xi

=(xi

1,xi

2,..

.,xi

n)與xj=

(xj1

,xj2

,...

,xjn

) ,其minkowski距離定義為: di

stmk

(xi,

xj)=

(∑u=

1n∣∣

xiu−

xju∣

∣p)1

p 當p

=2時,上式便是我們非常熟悉的歐氏距離,也就是xi

−xj 的二範數: di

sted

(xi,

xj)=

∥∥xi

−xj∥

∥2=∑

u=1n

∣∣xi

u−xj

u∣∣2

−−−−

−−−−

−−−−

√ 通過上式,我們可以量化兩個樣本之間的距離。對於樣本的某些屬性,如果其取值連續,比如降水量等,可以直接按照上式計算;如果屬性離散,比如像出行方式這樣的屬性,我們一般採用vdm(value difference metric)來計算,其本質是利用某一簇樣本中某屬性上取值為a的樣本個數佔所有樣本中該屬性取值為a的樣本的比例,來計算這一屬性中兩個離散值之間的距離。那麼,當樣本中含有連續和離散兩種混合屬性的時候,對連續屬性採用minkowski距離計算,對離散屬性採用vdm距離計算,將其累加,從而得到兩個樣本的距離。

有了距離來衡量樣本間的相似度,接下來我們介紹一下k-means演算法。該演算法的主要目的是針對劃分後的簇,最小化其平方誤差,這個誤差代表了簇內所有樣本圍繞簇均值向量的乙個緊密程度,誤差越小,簇的所有樣本都很集中,簇內樣本的相似度也就越高,具體表示如下: e=

∑i=1

k∑x∈

ci∥∥

x−μi

∥∥22

其中,μi

=1|c

i|∑x

∈cix

,代表了該簇的均值向量。然而,最小化上式是乙個np-hard問題,因此,k-means演算法採用貪心演算法,通過迭代優化來求解上式。

python原始碼

# !/usr/bin/env python3

# coding=utf-8

"""k-means

author :chai zheng

blog :

github :

email :[email protected]

date :2017.10.8

"""import random

import numpy as np

from sklearn import preprocessing

#選擇初始均值向量

defselectinitmeanvec

(data,k):

indexinitmeanvec = random.sample(range(m),k)

initmeanvec = data[indexinitmeanvec,:]

return initmeanvec

#計算距離並歸入簇中

defcalcdistance

(data,k,meanvec):

dist = np.zeros((k,1))

label = np.zeros((m,1))

for i in range(m):

for j in range(k):

a = data[i,:]-meanvec[j,:]

dist[j] = np.sqrt(sum(a**2))

label[i] = np.argmin(dist)

return label

#更新均值向量

defupdatemeanvec

(data,label,k,oldmeanvec):

newmeanvec = np.zeros((k,n))

numsamples = np.zeros((k,1),dtype = int)

for i in range(k):

num = 0

d = np.zeros((k,0))

for j in range(m):

if label[j] == i:

num += 1

numsamples[i] = num

d = np.reshape(d,(-1,n))

newmeanvec[i,:] = np.mean(d,axis=0)

#如果本次更新後某一簇中無樣本,取上一次均值向量為本次均值向量

if num == 0:

newmeanvec[i,:] = oldmeanvec[i,:]

return newmeanvec,numsamples

if __name__ == '__main__':

data = np.loadtxt("wine.txt",delimiter=',')[:,1:14]

data = preprocessing.scale(data)

k = 3

global m,n

m,n = data.shape

initmeanvec = selectinitmeanvec(data,k)

oldmeanvec = initmeanvec.copy()

label = calcdistance(data,k,initmeanvec)

for i in range(200):

newmeanvec,numsamples = updatemeanvec(data,label,k,oldmeanvec)

oldmeanvec = newmeanvec.copy()

label = calcdistance(data,k,newmeanvec)

print('---第%d輪迭代完成'%(i+1))

print(label)

print(numsamples)

在測試程式的時候,我採用了葡萄酒三類別資料集。這樣可以方便驗證我們的聚類效果。

已知三類的數量分別是59、71、48,k-means給出的聚類結果分別是59、65+3+3、48。代表了class1的59個樣本和class3的48個樣本被完全正確聚類,class2聚類對了65個,其餘6個被誤分至其他類。

總體來看,相比於原始資料的類別,我們得到的結果中三類共178個樣本只有6個被錯誤聚類,其中兩類完全正確,可見k-means的聚類效果之突出。

k means聚類分析

k means演算法是machine learning領域內比較常用的演算法之一。首先從n個資料物件任意選擇 k 個物件作為初始聚類中心 而對於所剩下其它物件,則根據它們與這些聚類中心的相似度 距離 分別將它們分配給與其最相似的 聚類中心所代表的 聚類 然 後再計算每個所獲新聚類的聚類中心 該聚類中...

K means聚類分析

主成分分析 pca pca n components 0.9 data pca.fit transform cross 降維x data 500 x.shape 對類別預設為4 km kmeans n clusters 4 km.fit x predict km.predict x 顯示聚類結果 p...

聚類分析 K Means演算法

k means演算法 這是基於劃分的聚類演算法,該演算法效率較高,對大規模資料進行聚類時被廣泛使用。基本思路 把資料集劃分成k 個簇,每個簇內部的樣本非常相似,不同簇之間的差異非常大。k means演算法是乙個迭代演算法,先隨機選擇 k個物件,每個物件代表了起中心,對於剩下的物件,將其賦給最近的簇,...