俗話說的好:「物以類聚,人以群分」,今天我們要講的聚類演算法很大程度上可以印證此話。聚類是一種非監督學習,什麼是非監督學習?與之前學習的分類和回歸不同(監督學習),監督學習是有有label標籤的,而非監督學習沒有。
我們再回到聚類上,聚類是把相似的物件歸到同一簇中,有點像全自動分類。聚類的應用場景有很多,例如在電商行業,通過使用者的購買歷史進行聚類,針對不同的使用者群體推送不同的廣告。
演算法流程
k-means聚類首先隨機確定 k 個初始點作為質心(這也是k-means聚類的乙個問題,這個k值的不合理選擇會使得模型不適應和解釋性差)。然後將資料集中的每個點分配到乙個簇中, 具體來講,就是為每個點找到距其最近的質心(這裡算的為歐式距離,當然也可以使用其他距離), 並將其分配該質心所對應的簇;這一步完成之後,每個簇的質心更新為該簇所有點的平均值;重複上述過程直到資料集中的所有點都距離它所對應的質心最近時結束。
演算法偽**
建立 k 個點作為起始質心(隨機選擇)
當任意乙個點的簇分配結果發生改變時(不改變時演算法結束)
對資料集中的每個資料點
對每個質心
計算質心與資料點之間的距離
將資料點分配到距其最近的簇
對每乙個簇, 計算簇中所有點的均值並將均值作為質心
實現**from numpy import *
def loaddataset(filename):
datamat =
fr = open(filename)
for line in fr.readlines():
curline = line.strip().split('\t')
fltline = list(map(float,curline))
return datamat
def disteclud(veca,vecb):
return sqrt(sum(power(veca - vecb,2)))
def randcent(dataset, k):
n = shape(dataset)[1]
centroids = mat(zeros((k,n)))
for j in range(n):
minj = min(dataset[:,j])
rangej = float(max(dataset[:,j]) - minj)
centroids[:, j] = minj + rangej * random.rand(k,1)
return centroids
def kmeans(dataset, k, distmeas=disteclud, createcent=randcent):
m = shape(dataset)[0]
clusterassment = mat(zeros((m,2)))
centroids = createcent(dataset,k)
clusterchanged = true
while clusterchanged:
clusterchanged = false
for i in range(m):
mindist = inf;minindex = -1
for j in range(k):
distji = distmeas(centroids[j,:], dataset[i,:])
if distji < mindist:
mindist = distji;minindex = j
if clusterassment[i,0] != minindex: clusterchanged=true
clusterassment[i,:] = minindex, mindist**2
print(centroids)
for cent in range(k):
ptsinclust = dataset[nonzero(clusterassment[:,0].a==cent)[0]]
centroids[cent,:] = mean(ptsinclust,axis=0)
return centroids, clusterassment
聚類結果如圖:
缺陷k-means演算法可能偶爾會陷入區域性最小值(區域性最優的結果,但不是全域性最優的結果),如圖所示。
出現這個問題有很多原因,可能是k值取的不合適,可能是距離函式不合適,可能是最初隨機選取的質心靠的太近,也可能是資料本身分布的問題。
為了解決k-means演算法的問題,提出了二分 k-means 聚類演算法。該演算法首先將所有點作為乙個簇,然後將該簇一分為二。之後選擇其中乙個簇繼續進行劃分,選擇哪乙個簇進行劃分取決於對其劃分時候可以最大程度降低 sse(平方和誤差)的值。上述基於 sse 的劃分過程不斷重複,直到得到使用者指定的簇數目為止。
**
def bikmeans(dataset, k, distmeas=disteclud):
m = shape(dataset)[0]
clusterassment = mat(zeros((m,2)))
centroid0 = mean(dataset, axis=0).tolist()[0]
centlist = [centroid0]
for j in range(m):
clusterassment[j,1] = distmeas(mat(centroid0), dataset[j,:]) ** 2
while (len(centlist) < k):
lowestsse = inf
for i in range(len(centlist)):
ptsincurrcluster = dataset[nonzero(clusterassment[:,0].a==i)[0],:]
centroidmat, splitclustass = kmeans(ptsincurrcluster, 2, distmeas)
ssesplit = sum(splitclustass[:,1])
ssenotsplit = sum(clusterassment[nonzero(clusterassment[:,0].a!=i)[0],1])
print("ssesplit, and notsplit: ",ssesplit,ssenotsplit)
if (ssesplit + ssenotsplit) < lowestsse:
bestcenttosplit = i
bestnewcents = centroidmat
bestclustass = splitclustass.copy()
lowestsse = ssesplit + ssenotsplit
bestclustass[nonzero(bestclustass[:,0].a == 1)[0],0] = len(centlist)
bestclustass[nonzero(bestclustass[:,0].a == 0)[0],0] = bestcenttosplit
print('the bestcenttosplit is: ',bestcenttosplit)
print('the len of bestclustass is: ', len(bestclustass))
centlist[bestcenttosplit] = bestnewcents[0,:].tolist()[0]
clusterassment[nonzero(clusterassment[:,0].a == bestcenttosplit)[0],:]= bestclustass
return mat(centlist), clusterassment
結果如圖所示:
聚類演算法 KMeans 機器學習實戰
直接上 coding utf8 time 2018 4 12 下午05 33 author yjfiejd file k means 3.py from numpy import import time import matplotlib.pyplot as plt 1 先定義3個函式,第乙個函式為...
機器學習之Kmeans聚類
本次學習總結 1 理解相似度度量的各種方法及其相互聯絡 2 掌握k means演算法思路及其使用條件 3 層次聚類的思路和方法 4 密度聚類並能夠應用於實踐 dbscan 密度最大值聚類 5 譜聚類演算法 譜聚類演算法與pca之間的關係 聚類的定義 聚類就是將大量未知標註的資料,按照資料的內在相似性...
機器學習之聚類演算法 K Means
參考 聚類演算法可以分為 中心點方法 層次聚類方法 基於密度方法 基於網格 基於模型方法。其中最為經典的是k means演算法 k means屬於中心點方法 也有叫劃分方法 演算法經典簡單。演算法 人工選取k值,並選取k個點作為k個簇的質心 對所有樣本分別計算到k個簇的質心的距離 歐式或者曼哈頓 取...