一、K-Means算法简介
聚类是一个将数据集中在某些方面相似的数据成员进行分类组织的过程,聚类就是一种发现这种内在结构的技术,聚类技术属于机器学习中的无监督学习。k-means聚类是最著名的划分聚类算法,由于简洁和效率使得他成为所有聚类算法中最广泛使用的。给定一个数据点集合和需要的聚类数目k,k由用户指定,k均值算法根据某个距离函数反复把数据分入k个聚类中。
二、算法基本思想
k-means算法比较简单。在k-means算法中,用cluster来表示簇;容易证明k-means算法收敛等同于所有质心不再发生变化。基本的k-means算法流程如下:
- 选取k个初始质心(作为初始cluster,每个初始cluster只包含一个点);
- repeat:
- 对每个样本点,计算得到距离最近的质心,将其类别标为该质心所对应的cluster;
- 重新计算k个cluster个对应的质心(质心是cluster样本点的均值);
- until 质心不再发生改变;
k-means的目标函数:
K-measn的目标是最小化畸变(样本点与簇中心的距离之和):
S表示k个簇,代表第i个簇的质心,表示第j个样本点。
三、K-means举例
1.举例展示算法过程:
2. 再看一个例子
下面这幅图是对粒子进行聚类,并给出代码供大家参考:
# coding:utf-8
import numpy as np
import matplotlib.pyplot as plt
def loadDataSet(fileName):
'''
加载测试数据集,返回一个列表,列表的元素是一个坐标
'''
dataList = []
with open(fileName) as fr:
for line in fr.readlines():
curLine = line.strip().split('\t')
fltLine = list(map(float,curLine))
dataList.append(fltLine)
return dataList
def randCent(dataSet, k):
'''
随机生成k个初始的质心
'''
n = np.shape(dataSet)[1] # n表示数据集的维度
centroids = np.mat(np.zeros((k,n)))
for j in range(n):
minJ = min(dataSet[:,j])
rangeJ = float(max(dataSet[:,j]) - minJ)
centroids[:,j] = np.mat(minJ + rangeJ * np.random.rand(k,1))
return centroids
def kMeans(dataSet, k):
'''
KMeans算法,返回最终的质心坐标和每个点所在的簇
'''
m = np.shape(dataSet)[0] # m表示数据集的长度(个数)
clusterAssment = np.mat(np.zeros((m,2)))
centroids = randCent(dataSet, k) # 保存k个初始质心的坐标
clusterChanged = True
iterIndex=1 # 迭代次数
while clusterChanged:
clusterChanged = False
for i in range(m):
minDist = np.inf; minIndex = -1
for j in range(k):
distJI = np.linalg.norm(np.array(centroids[j,:])-np.array(dataSet[i,:]))
if distJI < minDist:
minDist = distJI; minIndex = j
if clusterAssment[i,0] != minIndex: clusterChanged = True
clusterAssment[i,:] = minIndex,minDist**2
print("第%d次迭代后%d个质心的坐标:\n%s"%(iterIndex,k,centroids)) # 第一次迭代的质心坐标就是初始的质心坐标
iterIndex+=1
for cent in range(k):
ptsInClust = dataSet[np.nonzero(clusterAssment[:,0].A==cent)[0]]#get all the point in this cluster
centroids[cent,:] = np.mean(ptsInClust, axis=0)
return centroids, clusterAssment
def showCluster(dataSet, k, centroids, clusterAssment):
'''
数据可视化,只能画二维的图(若是三维的坐标图则直接返回1)
'''
numSamples, dim = dataSet.shape
if dim != 2:
return 1
mark = ['or', 'ob', 'og', 'ok','oy','om','oc', '^r', '+r', 'sr', 'dr', '<r', 'pr']
# draw all samples
for i in range(numSamples):
markIndex = int(clusterAssment[i, 0])
plt.plot(dataSet[i, 0], dataSet[i, 1], mark[markIndex])
mark = ['Pr', 'Pb', 'Pg', 'Pk','Py','Pm','Pc','^b', '+b', 'sb', 'db', '<b', 'pb']
# draw the centroids
for i in range(k):
plt.plot(centroids[i, 0], centroids[i, 1], mark[i], markersize = 12)
plt.show()
if __name__ == '__main__':
dataMat = np.mat(loadDataSet('G:/test/K-mean./testSet')) #mat是numpy中的函数,将列表转化成矩阵
k = 4 # 选定k值,也就是簇的个数(可以指定为其他数)
cent, clust = kMeans(dataMat, k)
showCluster(dataMat, k, cent, clust)
测试数据集获取地址:
https://github.com/fuqiuai/datamining_algorithms/blob/master/K-means/testSet
四、K-means算法的特点
1.简单高效:时间复杂度为O(tkn),其中n为数据数,k 为群数,t为迭代次数。
2. 需要用户指定群的个数k
3.聚类的结果往往是局部最优
4.初始中心点的选择对聚类的结果影响非常大
2019年3月26日于科学馆