聚類將給定的樣例集劃分為若干個互不相交的子集。直觀來看,好的聚類結果,一定表現出簇內相似度高、簇間相似度低的特徵。那麼如何來量化這個所謂的「相似度」,我們一般採用的方法是計算樣本間的「距離」。
給定兩個樣本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個物件,每個物件代表了起中心,對於剩下的物件,將其賦給最近的簇,...