轉(zhuǎn)載鏈接:https://blog.csdn.net/hanxia159357/article/details/81530361
本文完成程序及測(cè)試數(shù)據(jù)集詳細(xì)見:https://github.com/HanXia001/k-means-python3-
本文主要內(nèi)容:
? ? ? ? ? ? ? ? 1.k-means解決的問題;
? ? ? ? ? ? ? ? 2.k-means原理介紹;
? ? ? ? ? ? ? ? 3.k-means的簡(jiǎn)單實(shí)現(xiàn)。
1.k-means解決的問題
? ? ? ? ?k-means算法屬于無監(jiān)督學(xué)習(xí)的一種聚類算法,其目的為:在不知數(shù)據(jù)所屬類別及類別數(shù)量的前提下,依據(jù)數(shù)據(jù)自身所暗含的特點(diǎn)對(duì)數(shù)據(jù)進(jìn)行聚類。對(duì)于聚類過程中類別數(shù)量k的選取,需要一定的先驗(yàn)知識(shí),也可根據(jù)“類內(nèi)間距小,類間間距大“(一種聚類算法的理想情況)為目標(biāo)進(jìn)行實(shí)現(xiàn)。
2.k-means原理介紹
? ? ? ? k-means算法以數(shù)據(jù)間的距離作為數(shù)據(jù)對(duì)象相似性度量的標(biāo)準(zhǔn),因此選擇計(jì)算數(shù)據(jù)間距離的計(jì)算方式對(duì)最后的聚類效果有顯著的影響,常用計(jì)算距離的方式有:余弦距離、歐式距離、曼哈頓距離等。本文以歐式距離為例(會(huì)一種,其余也就會(huì)了)。
歐式距離公式:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
例子:若數(shù)據(jù)為其計(jì)算歐式距離如下(可理解為D表示維度,i,j表示行數(shù)):
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ?通過公式(1)可計(jì)算出每對(duì)數(shù)據(jù)對(duì)象間的距離,根據(jù)距離的遠(yuǎn)近進(jìn)行聚類成指定的類別數(shù)K。對(duì)每一類中的數(shù)據(jù)初步選取類心,取的方式有多種如:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?1.該類所有數(shù)據(jù)的均值;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?2.隨機(jī)取k個(gè)數(shù)據(jù)作為類心;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?3.選取距離最遠(yuǎn)的k個(gè)點(diǎn)作為類心等。
以上方法均需要對(duì)初步的類心進(jìn)行迭代,當(dāng)類心變化緩慢時(shí)便可認(rèn)為收斂,此時(shí)該點(diǎn)便為最終的類型。本文以方法1為例:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
表示第k類,表示第k類中數(shù)據(jù)對(duì)象的個(gè)數(shù)。類心迭代過程如下:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
通常迭代終止的條件有兩種:1)達(dá)到指定的迭代次數(shù)T;2)類心不再發(fā)生明顯的變化,即收斂。
3.k-means的簡(jiǎn)單實(shí)現(xiàn)
原理講過,此處直接上代碼(python3實(shí)現(xiàn)):
import numpy as np
import matplotlib.pyplot as plt
# 加載數(shù)據(jù)
def loadDataSet(fileName):
data = np.loadtxt(fileName,delimiter='\t')
return data
# 歐氏距離計(jì)算
def distEclud(x,y):
return np.sqrt(np.sum((x-y)**2)) # 計(jì)算歐氏距離
# 為給定數(shù)據(jù)集構(gòu)建一個(gè)包含K個(gè)隨機(jī)質(zhì)心的集合
def randCent(dataSet,k):
m,n = dataSet.shape
centroids = np.zeros((k,n))
for i in range(k):
index = int(np.random.uniform(0,m)) #
centroids[i,:] = dataSet[index,:]
return centroids
# k均值聚類
def KMeans(dataSet,k):
m = np.shape(dataSet)[0] #行的數(shù)目
# 第一列存樣本屬于哪一簇
# 第二列存樣本的到簇的中心點(diǎn)的誤差
clusterAssment = np.mat(np.zeros((m,2)))
clusterChange = True
# 第1步 初始化centroids
centroids = randCent(dataSet,k)
while clusterChange:
clusterChange = False
# 遍歷所有的樣本(行數(shù))
for i in range(m):
minDist = 100000.0
minIndex = -1
# 遍歷所有的質(zhì)心
#第2步 找出最近的質(zhì)心
for j in range(k):
# 計(jì)算該樣本到質(zhì)心的歐式距離
distance = distEclud(centroids[j,:],dataSet[i,:])
if distance < minDist:
minDist = distance
minIndex = j
# 第 3 步:更新每一行樣本所屬的簇
if clusterAssment[i,0] != minIndex:
clusterChange = True
clusterAssment[i,:] = minIndex,minDist**2
#第 4 步:更新質(zhì)心
for j in range(k):
pointsInCluster = dataSet[np.nonzero(clusterAssment[:,0].A == j)[0]] # 獲取簇類所有的點(diǎn)
centroids[j,:] = np.mean(pointsInCluster,axis=0) # 對(duì)矩陣的行求均值
print("Congratulations,cluster complete!")
return centroids,clusterAssment
def showCluster(dataSet,k,centroids,clusterAssment):
m,n = dataSet.shape
if n != 2:
print("數(shù)據(jù)不是二維的")
return 1
mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '
len(mark):
print("k值太大了")
return 1
# 繪制所有的樣本
for i in range(m):
markIndex = int(clusterAssment[i,0])
plt.plot(dataSet[i,0],dataSet[i,1],mark[markIndex])
mark = ['Dr', 'Db', 'Dg', 'Dk', '^b', '+b', 'sb', 'db', '
效果如圖:
? ? ? ? ? ? ? ? ? ?
版權(quán)聲明:本文為CSDN博主「寒夏12」的原創(chuàng)文章,遵循CC 4.0 by-sa版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/hanxia159357/article/details/81530361
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
