將資料集中的資料按照距離質心的遠近分到各個簇中
將各個簇中的資料求平均值,作為新的質心,重複上一步,直到所有的簇不再改變
from numpy import *
defloaddataset
(filename):
dataset =
f = open(filename)
for line in f.readlines():
curline = line.strip().split('\t')
fltline = map(float, curline)
return mat(dataset)
def
disteclud
(veca, vecb):
return sqrt(sum(power(veca - vecb, 2)))
def
randcent
(dataset, k):
n = shape(dataset)[1] #n是列數
centroids = mat(zeros((k, n)))
for j in range(n):
minj = min(dataset[:, j]) #找到第j列最小值
rangej = float(max(dataset[:, j]) - minj) #求第j列最大值與最小值的差
centroids[:, j] = minj + rangej * random.rand(k, 1) #生成k行1列的在(0, 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) #求同一簇的座標平均值,axis=0表示按列求均值
return centroids, clusterassment
import matplotlib.pyplot as plt
defshowcluster
(dataset, k, clusterassment, centroids):
fig = plt.figure()
plt.title("k-means")
ax = fig.add_subplot(111)
data =
for cent in range(k): #提取出每個簇的資料
ptsinclust = dataset[nonzero(clusterassment[:,0].a==cent)[0]] #獲得屬於cent簇的資料
for cent, c, marker in zip( range(k), ['r', 'g', 'b', 'y'], ['^', 'o', '*', 's'] ): #畫出資料點散點圖
ax.scatter(data[cent][:, 0], data[cent][:, 1], s=80, c=c, marker=marker)
ax.scatter(centroids[:, 0], centroids[:, 1], s=1000, c='black', marker='+', alpha=1) #畫出質心點
ax.set_xlabel('x label')
ax.set_ylabel('y label')
plt.show()
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): #只要聚類的個數小於等於k
lowestsse = inf
for i in range(len(centlist)):
ptsincurrcluster = dataset[nonzero(clusterassment[:,0].a==i)[0],:] #獲得屬於cent簇的資料
centroidmat, splitclustass = kmeans(ptsincurrcluster, 2, distmeas) #對乙個簇中的資料進行kmeans
ssesplit = sum(splitclustass[:,1]) #計算本次劃分誤差平方和
ssenotsplit = sum(clusterassment[nonzero(clusterassment[:,0].a!=i)[0],1]) #計算不屬於cent簇的誤差平方和
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()函式且指定的聚類數目為2時,會得到編號為0和1的兩個簇,將編號為0的簇編號改為輸入簇的編號,編號為1的簇編號改為所有簇的數目len(centlist),即在原先簇上追加乙個簇
k均值演算法需要使用者指定建立的簇數k
k均值演算法在大資料集上收斂較慢
k均值演算法有可能達到區域性最小值,為了達到更好的距離效果,可以使用二分k均值聚類
原始碼在我的github中,machinelearningaction
倉庫裡面有常見的機器學習演算法處理常見資料集的各種例項,希望能夠得到你的star
K均值 K means 聚類演算法
j.b.macqueen 在 1967 年提出的k means演算法 22 到目前為止用於科學和工業應用的諸多聚類演算法中一種極有影響的技術。它是聚類方法中乙個基本的劃分方法,常常採用誤差平方和準則函式作為聚類準則函式,誤差平方和準則函式定義為 3 1 其中,是類 中資料物件的均值,即 j 1,2,...
K 均值聚類演算法 K means
k means是一種無監督的學習,將相似的物件歸到同乙個簇中.可以將一批資料分為k個不同的簇,並且每個簇的中心採用簇中所含樣本的均值計算而成.k means演算法的k值需要由使用者指定,演算法開始時隨機選擇k個初始點作為質心,然後將資料集中的每個點分配到乙個簇中.那麼,如何確定某一組資料歸於哪個簇中...
kMeans演算法(K均值聚類演算法)
機器學習中有兩類的大問題,乙個是分類,乙個是聚類。分類是根據一些給定的已知類別標號的樣本,訓練某種學習機器,使它能夠對未知類別的樣本進行分類。這屬於supervised learning 監督學習 而聚類指事先並不知道任何樣本的類別標號,希望通過某種演算法來把一組未知類別的樣本劃分成若干類別,這在機...