相关定义

聚类是一种无监督的学习,它将相似的对象归到同一个簇中。聚类方法几乎可以应用到所有的对象,簇内的对象越相似,聚类的效果越好。
K-均值(K-means)聚类是指将数据划分成k个不同的簇,且每个簇的中心采用簇中所含数据的均值计算而成。
聚类和分类最大不同在于,分类的目标事物已知,而聚类不一样。因为其产生的结果与分类相同,而只是类别没有预先定义,聚类有时候也被称为无监督分类。

K-均值聚类算法

K-均值是发现给定数据集的k个簇的算法。簇的个数k是用户给定的,每个簇通过其质心,即簇中所有点的中心来描述。
算法的工作流程如下:首先,随机确定k个初始点作为质心。然后将数据集中的每个点分配到一个簇中。这一步完成后,每个簇的质心更新为该簇所有点的平均值。流程的伪代码如下:

创建k个点作为初试质心
当任意一点的簇分配结果发生改变时:对数据集中的每个数据点:对每个质心:计算数据点与质心直接的距离将该数据点分配到距离最近的簇对每一个簇:更新质心坐标

该段代码涉及到的辅助函数如下:

def create_data(fname):     #导入数据datam=[]f=open(fname)for line in f.readlines():curline=line.strip().split('\t')floatarr=list(map(float,curline))datam.append(floatarr)return datamdef distEclud(va,vb):   #计算两点之间的距离return np.sqrt(np.power(va-vb,2).sum())def randCen(datas,k):   #创建k个随机点当作质点n=datas.shape[1]    #获取数据特征数centP=np.mat(np.zeros((k,n)))   #创建k*n的质点矩阵for i in range(n):  #对于数据每一个特征值minp=min(datas[:,i])rangep=float(max(datas[:,i])-minp)centP[:,i]=minp+rangep*np.random.rand(k,1)      #通过k*1的随机向量来生成k个介于该特征值最大最小值之间的随机数return centP

辅助函数创建完毕后就可以写完整的k-means函数了。该算法会创建k个质心,然后将每个点分配到最近的质心,再重新计算质心。整个过程重复数次,直到数据点的簇分配结果不再发生改变为止,具体代码如下:

def k_means(dataset,k,disfun=distEclud,createP=randCen):    #普通k均值聚类m=dataset.shape[0]          #获取数据集的个数clusterAssment=np.mat(np.zeros((m,2)))  #创建矩阵,该矩阵共两列,第一列是每个数据点对应的簇的索引值,第二列是距离簇的距离centroids=createP(dataset,k)    #初始质心clusterChanged=True     #判断簇的分配是否变化cnt=0while clusterChanged:   #当分配发生变化时循环cnt+=1print(cnt)clusterChanged=False    #先置为falsefor i in range(m):      #对于每个数据minDist=np.inf      #初始化最小距离minIndex=-1         #初始化索引值for j in range(k):  #对于k个质心distJ=disfun(centroids[j,:],dataset[i,:])   #计算第i个数据到第j个质心之间的距离if distJ<minDist:       #如果当前值小于最小值,更新相关变量minDist=distJminIndex=j#当前已经找到距离当前数据点数据最近的质点if clusterAssment[i,0]!=minIndex:   #如果索引值发生了改变clusterChanged=TrueclusterAssment[i,:]=minIndex,minDist**2 #存储当前数据点对应的簇的相关信息print(centroids)#所有数据都执行完毕后,要更新质心坐标for cent in range(k):   #对于k个质心ptsInclust=dataset[np.nonzero(clusterAssment[:,0].A==cent)[0]]      #获取全部数据集中对应当前质心的子集centroids[cent,:]=np.mean(ptsInclust,axis=0)        #取该簇族中所有数据的平均值来充当新的质心return centroids,clusterAssment

下面引入一组数据,分布如下:

可以看出该数据集大体分为4类,在执行k-means聚类代码后得到的结果如下:

1
[[ 4.47211349  2.54595758][ 4.16590074  0.07622815][ 1.73687885  2.83815469][-0.48675348 -0.0258452 ]]
2
[[ 3.718828    3.72065725][ 3.31153765 -2.50129665][ 1.62862683  3.18453722][-2.6530681  -0.6180039 ]]
...
6
[[ 2.6265299   3.10868015][ 2.65077367 -2.79019029][-2.46154315  2.78737555][-3.53973889 -2.89384326]]

可以看出程序经过6次循环后收敛,得到了4个质心坐标,他们的分布如下:

可以看出整体聚类效果较好,但这种算法仍存在一些问题。

算法不足与改进

由于k-means聚类一开始的质心选择是随机的,所以可能会出现一些问题,如下面的聚类结果:

K-均值算法收敛但聚类效果差的原因是,该算法仅收敛到局部最小值,并非全局最小值(局部最小值结果还可以但不是最好结果,全局最小值是可能的最好结果)。
一种度量聚类效果好坏的指标是SSE(误差平方和),它对应的是上面算法中的clusterAssment矩阵中的第二列的平方和。SSE值越小表示数据点越接近它们的质心,聚类效果也越好。因为取了距离的平方,所以更加重视那些远离质心的点。一种可能可以降低SSE的方法就是增加簇的个数,但显然是违背目标的,聚类的目标就是不改变簇数目的前提下提高簇的质量。
另一种办法就是将具有最大SSE值的簇划分成两个簇。可以将最大簇包含的点过滤出来并在这些点上运行K-均值聚类,此时的k为2。
为了保证簇总数不变,可以将某两个簇进行合并。有两种量化方法:合并最近的质心,或者合并两个使得SSE增幅最小的质心。第一种通过计算所有质心之间的距离,然后合并距离最近的两个点。第二种方法需要合并两个簇然后计算中SSE值。必须在所有可能的两个簇上重复上述处理过程,直到找到合并最佳的两个簇为止。接下来将改进上面的方法。

二分K-均值算法

为了克服K-均值算法的收敛到局部最小值的问题,采用二分K-均值算法。首先将所有点作为一个簇,然后将簇一分为二。之后选择其中一个簇继续进行划分,选择哪一个簇进行划分取决于对其划分是否可以最大程度的降低SSE的值。不断重复上面的划分过程,直到划分数目达到用户指定的簇数目为止。
该过程的伪代码如下:

将所有点看成一个簇
当簇数目小于k时:对于每一个簇:计算总误差在给定的簇上面进行K-均值聚类(k=2)计算将该簇一分为二后的总误差选择使得误差最小的那个簇进行划分操作

下面是具体的实现代码:

def biKmeans(dataset,k,distmeas=distEclud):     #二分K-均值算法m=dataset.shape[0]          #获取数据集行数clusterAssment=np.mat(np.zeros((m,2)))      #与上面的clusterAssment矩阵效果一样centP0=np.mean(dataset,axis=0).tolist()[0]  #将当前数据集所有点看成一个簇,计算质心坐标centlist=[centP0]       #将质心坐标加入到队列中for j in range(m):      #对于每一个数据点clusterAssment[j:1]=distmeas(np.mat(centP0),dataset[j,:])**2    #更新数据点到质心距离while (len(centlist))<k:        #当没有达到用户给定的簇数目时循环lowestSSE=np.inf            #初始化最小SSEfor i in range(len(centlist)):  #对于每一个质心ptsInCurrCluster=dataset[np.nonzero(clusterAssment[:,0].A==i)[0],:]     #获取当前簇的所有数据构成的子集centroidMat,splitClustAss=k_means(ptsInCurrCluster,2,distmeas)          #对该子集进行划分sseSplit=sum(splitClustAss[:,1])    #划分后的新的两部分SSE值之和sseNoSplit=sum(clusterAssment[np.nonzero(clusterAssment[:,0].A!=i)[0],1])   #没有参加划分的数据点SSE总和if (sseNoSplit+sseSplit)<lowestSSE:     #如果两部分SSE相加小于当前最小值,更新相关变量bestCentToSplit=ibestNewP=centroidMatbestClustAss=splitClustAss.copy()lowestSSE=sseNoSplit+sseSplit#到此已经找到要划分的簇,下面进行更新簇的分配bestClustAss[np.nonzero(bestClustAss[:,0].A==1)[0],0]=len(centlist)bestClustAss[np.nonzero(bestClustAss[:, 0].A == 0)[0], 0] = bestCentToSplit#更新簇分配结束# 下面更新质心队列centlist[bestCentToSplit]=bestNewP[0,:].tolist()[0]centlist.append(bestNewP[1,:].tolist()[0])#队列更新结束# 下面更新矩阵clusterAssment[np.nonzero(clusterAssment[:,0]==bestCentToSplit)[0],:]=bestClustAss#矩阵更新结束return np.mat(centlist),clusterAssment

在更新簇分配的过程中,由于上面已经将要划分的簇一分为二,这时的bestClustAss矩阵中第一列只有01这两个索引。现在要更新到全局变量中,需要将01值替换,我们假定将1的索引值当做新的一个质心坐标加入进去(因为队列索引从0到n-1,新加入的索引值就是n,即数组长度),将0的索引值替换掉原来的索引值(原来的索引值就是划分前这个簇的质心索引值)。
在更新质心队列过程中。根据上面簇分配的结果,要划分的簇的质心坐标被划分后索引值为0的质心坐标替换。划分后质心坐标的索引值为1的当作新的执行坐标添加到队列中。因此按上面代码进行更新。
最后更新矩阵,因为已经没有了bestCentToSplit对应的相关数据,直接将质心索引为它的数据子集替换成上面更新好的bestClustAss矩阵。

至此新的二分K-均值算法已经完成,现在再用上面没有得到较好聚类效果的数据来做示范,发现聚类效果得到显著提升。

它具体的工作流程如下:

k-均值聚类算法总结相关推荐

  1. 【模式识别】K均值聚类算法应用实验报告及MATLAB仿真

    一. 实验目的 1.掌握K均值聚类算法的原理和实现过程: 2.掌握K均值聚类算法的应用方法. 二. 实验内容 1.彩色图像分割 选择一幅图像,分别按三种颜色数进行彩色图像分割的结果(原图和分割图).步 ...

  2. k均值聚类算法优缺点_Grasshopper实现K均值聚类算法

    本文很长很长,有很多很多图,包含以下部分: 1.算法简介 2.如何分类平面点 3.如何分类空间点 4.如何分类多维数据 5.后记 提醒:以下内容包括:智障操作,无中生友,重复造轮子 等 1.算法简介 ...

  3. K-Means(K均值聚类算法)

    K-Means(K均值聚类算法) 1.前言 要学习聚类算法就要知道聚类学习算法是什么,为什么要学习聚类学习聚类学习算法,有什么用途,下面就简单的做一下介绍,并且详细的说明k-means均值聚类学习算法 ...

  4. K均值聚类算法(HCM,K-Means)

    K均值聚类核心思想如下: 算法把n个向量分为个组,并求每组的聚类中心,使得非相似性(或距离)指标的价值函数(或目标函数)达到最小.当选择欧几里德距离为组j中向量与相应聚类中心间的非相似性指标时,价值函 ...

  5. K均值聚类算法(Kmeans)讲解及源码实现

    K均值聚类算法(Kmeans)讲解及源码实现 算法核心 K均值聚类的核心目标是将给定的数据集划分成K个簇,并给出每个数据对应的簇中心点.算法的具体步骤描述如下. 数据预处理,如归一化.离群点处理等. ...

  6. k均值聚类算法python_K均值和其他聚类算法:Python快速入门

    k均值聚类算法python This post was originally published here 这篇文章最初发表在这里 Clustering is the grouping of obje ...

  7. python(scikit-learn)实现k均值聚类算法

    k均值聚类算法原理详解 示例为链接中的例题 直接调用python机器学习的库scikit-learn中k均值算法的相关方法 from sklearn.cluster import KMeans imp ...

  8. 机器学习之无监督学习-K均值聚类算法

    机器学习之无监督学习-K均值聚类算法 对于无监督学习,有两类重要的应用,一个是聚类,一个是降维.我们今天主要学习聚类中的K均值聚类. 我们先看看下图,图a为原始的数据点,我们想要对图a的数据点进行分类 ...

  9. Thinking in SQL系列之五:数据挖掘K均值聚类算法与城市分级

    原创: 牛超   2017-02-21   Mail:10867910@qq.com 引言:前一篇文章开始不再介绍简单算法,而是转到数据挖掘之旅.感谢CSDN将我前一篇机器学习C4.5决策树算法的博文 ...

  10. 机器学习实战-61:K均值聚类算法(K-Means)

    K均值聚类算法(K-Means) 深度学习原理与实践(开源图书)-总目录,建议收藏,告别碎片阅读! 机器学习分为监督学习.无监督学习和半监督学习(强化学习).无监督学习最常应用的场景是聚类(clust ...

最新文章

  1. 腾讯AR开放平台今日正式开放,提供识别、追踪、展现等多项能力
  2. 自学python网站推荐-推荐自学python必入的神仙网站
  3. c、c++、Java和gcc写Hello World
  4. android纹理存储,android纹理文本
  5. Opencv、OpenCV2.x、Opencv3.x个版本的进化,与VS各个版本的匹配问题
  6. Invalid signature file digest for Manifest main attributes
  7. 【Scala】Scala中特殊函数的使用(代码)
  8. centos上部署java环境
  9. matplotlib——直方图
  10. 跟涛哥(张开涛)聊聊技术人的发展
  11. flash buidler 4.5 序列号
  12. 2019年香港科大EMBA校友会年度盛会在珠海圆满落幕
  13. Goole Tag Manager 介绍
  14. 大一c语言论文700字,大二学年学生自我鉴定范文700字
  15. 由一道竞赛题再论电介质受力和静电场能量问题
  16. python写入文件没反应_python写入文本 如何用python将变量及其值写入文本文件?...
  17. 调整音频模型以实现更好的语音识别
  18. 百度地图开发参数设置正确,却定位到大西洋海域去了,定位失败解决方案
  19. Android 实现简易下载管理器 (暂停、断点续传、多线程下载)
  20. 第二讲 系统研究手段

热门文章

  1. PCB相关知识-焊盘Pad
  2. mac双系统w ndows8,Mac安装win8.1双系统多个分区教程
  3. 大数据中为什么使用Scala?
  4. 论文阅读:(NFM)Neural Factorization Machines for Sparse Predictive Analytics
  5. Mac 移动硬盘突然自己异常退出了(一)
  6. RSCP RSRP RSRQ
  7. 移动UI设计-表单设计
  8. *关键字retry:很像goto语句,跳到标记处
  9. 四川农大2020计算机专业录取分数线,2020四川农业大学研究生分数线汇总(含2016-2019历年复试)...
  10. 【我Linux服务器被ddos了】记一次ddos防御+溯源+反击