Kmeans算法的原理

K-means聚类属于原型聚类(基于原型的聚类,prototype-based clustering)。原型聚类算法假设聚类结构能够通过一组原型进行刻画,在现实聚类任务中极为常用。通常情况下,原型聚类算法对原型进行初始化,然后对原型进行迭代更新求解。

k-means算法以k为参数,把n个对象分成k个簇,使簇内具有较高的相似度,而簇间的相似度较低。

k-means算法的处理过程如下:

首先,随机地选择k个对象,每个对象初始地代表了一个簇的平均值或中心,即选择K个初始质心;对剩余的每个对象,根据其与各簇中心的距离,将它赋给最近的簇;然后重新计算每个簇的平均值。 这个过程不断重复,直到准则函数收敛,直到质心不发生明显的变化。通常,采用平方误差准则,误差的平方和SSE作为全局的目标函数,即最小化每个点到最近质心的欧几里得距离的平方和。此时,簇的质心就是该簇内所有数据点的平均值。

K-Means 算法的详细过程

选择K个点作为初始质心
repeat  将每个点指派到最近的质心,形成K个簇  重新计算每个簇的质心
until 簇不发生变化或达到最大迭代次数  

时间复杂度:O(tKmn),其中,t为迭代次数,K为簇的数目,m为记录数,n为维数
空间复杂度:O((m+K)n),其中,K为簇的数目,m为记录数,n为维数

[kmeans这么做的原因,数学推导参考K-Means聚类]

从上图中,我们可以看到,A, B, C, D, E 是五个在图中点,而灰色的点是我们的种子点,也就是我们用来找点群的点。有两个种子点,所以K=2。
然后,K-Means的算法如下:
①随机在图中取K(这里K=2)个种子点。
②然后对图中的所有点求到这K个种子点的距离,假如点Pi离种子点Si最近,那么Pi属于Si点群。(我们可以看到A,B属于上面的种子点,C,D,E属于下面中部的种子点)
③接下来,我们要移动种子点到属于他的“点群”的中心。(见图上的第三步)
④然后重复第2)和第3)步,直到,种子点没有移动(我们可以看到图中的第四步上面的种子点聚合了A,B,C,下面的种子点聚合了D,E)。
聚类的效果如下图,折线是历次循环时3个簇的质心的更新轨迹,黑点是初始质心:

我们查看基本K均值算法实现步骤及上面的聚类效果可以发现,该聚类算法将所有数据点都进行了指派,不识别噪音点。另外选择适当的初试质心是基本K均值过程的关键。

k均值的优缺点及分类

优点:1,简单,易于理解和实现;2,时间复杂度低

缺点:

1)kmeans要手工输入类数目,对初始值的设置很敏感;所以有了k-means++、intelligent k-means、genetic k-means;
2)k-means对噪声和离群值非常敏感,所以有了k-medoids和k-medians;
3)k-means只用于numerical类型数据,不适用于categorical类型数据,所以k-modes;
4)k-means不能解决非凸(non-convex)数据,所以有了kernel k-means。
5)k-means主要发现圆形或者球形簇,不能识别非球形的簇。
3、k-means与DBSCAN的区别
k-means聚类算法的初始点选择不稳定,是随机选取的,这就引起聚类结果的不稳定。k-means属于动态聚类,往往聚出来的类有点圆形或者椭圆形。kmeans对于圆形区域聚类效果较好,dbscan基于密度,对于集中区域效果较好。对于不规则形状,kmeans完全无法用,dbscan可以起到很好的效果。

k值如何确定?

kmenas算法首先需要选择K个初始质心,其中K是用户指定的参数(簇的个数)。很多情况下,我们并不知道数据的分布情况,实际上聚类就是我们发现数据分布的一种手段。如何有效的确定K值,这里大致提供几种方法:
1 与层次聚类结合[2]
        经常会产生较好的聚类结果的一个有趣策略是,首先采用层次凝聚算法决定结果粗的数目,并找到一个初始聚类,然后用迭代重定位来改进该聚类。
2 稳定性方法[3]
       稳定性方法对一个数据集进行2次重采样产生2个数据子集,再用相同的聚类算法对2个数据子集进行聚类,产生2个具有k个聚类的聚类结果,计算2个聚类结果的相似度的分布情况。2个聚类结果具有高的相似度说明k个聚类反映了稳定的聚类结构,其相似度可以用来估计聚类个数。采用次方法试探多个k,找到合适的k值。
3 系统演化方法[3]
        系统演化方法将一个数据集视为伪热力学系统,当数据集被划分为K个聚类时称系统处于状态K。系统由初始状态K=1出发,经过分裂过程和合并过程,系统将演化到它的稳定平衡状态Ki,所对应的聚类结构决定了最优类数Ki。系统演化方法能提供关于所有聚类之间的相对边界距离或可分程度,适用于明显分离的聚类结构和轻微重叠的聚类结构。
4 使用canopy算法进行初始划分[4]
         基于CanopyMethod的聚类算法将聚类过程分为两个阶段
        Stage1、聚类最耗费计算的地方是计算对象相似性的时候,CanopyMethod在第一阶段选择简单、计算代价较低的方法计算对象相似性,将相似的对象放在一个子集中,这个子集被叫做Canopy,通过一系列计算得到若干Canopy,Canopy之间可以是重叠的,但不会存在某个对象不属于任何Canopy的情况,可以把这一阶段看做数据预处理;
         Stage2、在各个Canopy内使用传统的聚类方法(如K-means),不属于同一Canopy 的对象之间不进行相似性计算。
从这个方法起码可以看出两点好处:首先,Canopy 不要太大且Canopy 之间重叠的不要太多的话会大大减少后续需要计算相似性的对象的个数;其次,类似于K-means这样的聚类方法是需要人为指出K的值的,通过Stage1得到的Canopy 个数完全可以作为这个K值,一定程度上减少了选择K的盲目性。
        其他方法如贝叶斯信息准则方法(BIC)可参看文献[5]。

5 ml学习课程中的方法:What is the right value of K?

 

Note:there actually isn't a great way of answering this or doing this automatically and by far the most common way of choosing the number of clusters, is still choosing it manually by looking at visualizations or by looking at the output of the clustering algorithm or something else.Choosing the value of K


Note:

1. Elbow: distortion goes down rapidly until K equals 3, really goes down very slowly after that.So let's pick K equals 3.
2. 这种方法不是对所有聚类案例有效:but just as often, you end up with a plot that looks like the one on the right and is not clear where the ready location of the elbow is. It  makes it harder to choose a number of clusters using this method.

3. Too many clusters will still overfit the data, as it will find "structure" that is purely ficticious and not truly present in the data.

Note:

1. if that later, downstream purpose,such as market segmentation.then often, a better way to determine the number of clusters, is to see how well different numbers of clusters serve that later downstream purpose.

2. 衣服大小越细分,成本越高;这就取决于市场。总结:

the better way to think about how to choose the number of clusters is to ask, for what purpose are you running K-means?And then to think, what is the number of clusters K that serves that, you know, whatever later purpose that you actually run the K-means for.

还可以定义一个指标「例如簇平均直径」,通过二分搜索来确定最佳k。

[(stackoverflow)k-means聚类k值的确定 : How do I determine k when using k-means clustering?]

[用parametric bootstrap寻找K-means最佳K值]

[Machine Learning - XIII. Clustering聚类 (Week 8)]

初始质心的选取

kmeans的一个缺点是最开始的种子点的选择的好坏会影响到聚类结果,选择适当的初始质心是基本kmeans算法的关键步骤。

1 常见的方法是随机的选取初始质心,但是这样簇的质量常常很差。处理选取初始质心问题的一种常用技术是:多次运行,每次使用一组不同的随机初始质心,然后选取具有最小SSE(误差的平方和)的簇集。这种策略简单,但是效果可能不好,这取决于数据集和寻找的簇的个数。

2 kmeans++

基本原则是使得各个种子点之间的距离尽可能的大,但是又得排除噪声的影响。基本思路:

1、从输入的数据点集合(要求有k个聚类)中随机选择一个点作为第一个聚类中心
2、对于数据集中的每一个点x,计算它与最近聚类中心(指已选择的聚类中心)的距离D(x)
3、选择一个新的数据点作为新的聚类中心,选择的原则是:D(x)较大的点,被选取作为聚类中心的概率较大(即从不同权重的N个元素中随机选择一个的权重随机选择算法)
4、重复2和3直到k个聚类中心被选出来
5、利用这k个初始的聚类中心来运行标准的k-means算法

[python代码:K-means算法的改进:K-means++]

[python和matlab代码:浅入浅出:从Kmeans到Kmeans++]

3 取一个样本,并使用层次聚类技术对它聚类。从层次聚类中提取K个簇,并用这些簇的质心作为初始质心。该方法通常很有效,但仅对下列情况有效:(1)样本相对较小,例如数百到数千(层次聚类开销较大);(2)K相对于样本大小较小
4 第三种选择初始质心的方法,随机地选择第一个点,或取所有点的质心作为第一个点。然后,对于每个后继初始质心,选择离已经选取过的初始质心最远的点。使用这种方法,确保了选择的初始质心不仅是随机的,而且是散开的。但是,这种方法可能选中离群点。此外,求离当前初始质心集最远的点开销也非常大。为了克服这个问题,通常该方法用于点样本。由于离群点很少(多了就不是离群点了),它们多半不会在随机样本中出现。计算量也大幅减少。

5 第四种方法就是上面提到的canopy算法。

其它问题

距离的度量

常用的距离度量方法包括:欧几里得距离和余弦相似度。两者都是评定个体间差异的大小的。欧几里得距离度量会受指标不同单位刻度的影响,所以一般需要先进行标准化,同时距离越大,个体间差异越大;空间向量余弦夹角的相似度度量不会受指标刻度的影响,余弦值落于区间[-1,1],值越大,差异越小。但是针对具体应用,什么情况下使用欧氏距离,什么情况下使用余弦相似度?
         从几何意义上来说,n维向量空间的一条线段作为底边和原点组成的三角形,其顶角大小是不确定的。也就是说对于两条空间向量,即使两点距离一定,他们的夹角余弦值也可以随意变化。感性的认识,当两用户评分趋势一致时,但是评分值差距很大,余弦相似度倾向给出更优解。举个极端的例子,两用户只对两件商品评分,向量分别为(3,3)和(5,5),这两位用户的认知其实是一样的,但是欧式距离给出的解显然没有余弦值合理。
质心的计算
        对于距离度量不管是采用欧式距离还是采用余弦相似度,簇的质心都是其均值,即向量各维取平均即可。
算法停止条件
        一般是目标函数达到最优或者达到最大的迭代次数即可终止。对于不同的距离度量,目标函数往往不同。当采用欧式距离时,目标函数一般为最小化对象到其簇质心的距离的平方和;当采用余弦相似度时,目标函数一般为最大化对象到其簇质心的余弦相似度和。
空聚类的处理
          如果所有的点在指派步骤都未分配到某个簇,就会得到空簇。如果这种情况发生,则需要某种策略来选择一个替补质心,否则的话,平方误差将会偏大。一种方法是选择一个距离当前任何质心最远的点。这将消除当前对总平方误差影响最大的点。另一种方法是从具有最大SSE的簇中选择一个替补的质心,这将分裂簇并降低聚类的总SSE。如果有多个空簇,则该过程重复多次。另外,编程实现时,要注意空簇可能导致的程序bug。

皮皮blog

代码实现

python直接实现

import random
import numpy as npdef k_means(dataset, k, iter):# init kernelcmean = [dataset[i] for i in random.sample(range(len(dataset)), k)]cs = [[] for _ in range(k)]for _ in range(iter):# cluster pointscs = [[] for _ in range(k)]for i in dataset:min_edist = 2 ** 32 - 1ci = 0for ide, j in enumerate(cmean):# Euclid distanceedist = np.linalg.norm(np.asarray(i) - np.asarray(j))if edist < min_edist:min_edist = edistci = idecs[ci].append(i)cmean = []for i in cs:x = [ii[0] for ii in i]y = [ii[1] for ii in i]cmean.append((sum(x) / len(x), sum(y) / len(y)))return cs
from matplotlib import pyplot as plt# test data1
dataset = []
fileIn = open('a.txt')
for line in fileIn.readlines():lineArr = line.strip().split('\t')dataset.append([float(lineArr[0]), float(lineArr[1])])# test data2
# data = """
# 1,0.697,0.46,2,0.774,0.376,3,0.634,0.264,4,0.608,0.318,5,0.556,0.215,
# 6,0.403,0.237,7,0.481,0.149,8,0.437,0.211,9,0.666,0.091,10,0.243,0.267,
# 11,0.245,0.057,12,0.343,0.099,13,0.639,0.161,14,0.657,0.198,15,0.36,0.37,
# 16,0.593,0.042,17,0.719,0.103,18,0.359,0.188,19,0.339,0.241,20,0.282,0.257,
# 21,0.748,0.232,22,0.714,0.346,23,0.483,0.312,24,0.478,0.437,25,0.525,0.369,
# 26,0.751,0.489,27,0.532,0.472,28,0.473,0.376,29,0.725,0.445,30,0.446,0.459
# """
# a = data.split(',')
# dataset = [[float(a[i]), float(a[i + 1])] for i in range(1, len(a) - 1, 3)]print(dataset)C = k_means(dataset, 3, 500)colValue = ['r', 'y', 'g', 'b', 'c', 'k', 'm']
for i in range(len(C)):coo_X = []  # x坐标列表coo_Y = []  # y坐标列表for j in range(len(C[i])):coo_X.append(C[i][j][0])coo_Y.append(C[i][j][1])plt.scatter(coo_X, coo_Y, marker='x', color=colValue[i % len(colValue)], label=i)
plt.show()

a.txt

1.658985    4.285136
-3.453687  3.424321
4.838138   -1.151539
-5.379713  -3.362104
0.972564   2.924086
-3.567919  1.531611
0.450614   -3.302219
-3.487105  -1.724432
2.668759   1.594842
-3.156485  3.191137
3.165506   -3.999838
-2.786837  -3.099354
4.208187   2.984927
-2.123337  2.943366
0.704199   -0.479481
-0.392370  -3.963704
2.831667   1.574018
-0.790153  3.343144
2.943496   -3.357075
-3.195883  -2.283926
2.336445   2.875106
-1.786345  2.554248
2.190101   -1.906020
-3.403367  -2.778288
1.778124   3.880832
-1.688346  2.230267
2.592976   -2.054368
-4.007257  -3.207066
2.257734   3.387564
-2.679011  0.785119
0.939512   -4.023563
-3.674424  -2.261084
2.046259   2.735279
-3.189470  1.780269
4.372646   -0.822248
-2.579316  -3.497576
1.889034   5.190400
-0.798747  2.185588
2.836520   -2.658556
-3.837877  -3.253815
2.096701   3.886007
-2.709034  2.923887
3.367037   -3.184789
-2.121479  -4.232586
2.329546   3.179764
-3.284816  3.273099
3.091414   -3.815232
-3.762093  -2.432191
3.542056   2.778832
-1.736822  4.241041
2.127073   -2.983680
-4.323818  -3.938116
3.792121   5.135768
-4.786473  3.358547
2.624081   -3.260715
-4.009299  -2.978115
2.493525   1.963710
-2.513661  2.642162
1.864375   -3.176309
-3.171184  -3.572452
2.894220   2.489128
-2.562539  2.884438
3.491078   -3.947487
-2.565729  -2.012114
3.332948   3.983102
-1.616805  3.573188
2.280615   -2.559444
-2.651229  -3.103198
2.321395   3.154987
-1.685703  2.939697
3.031012   -3.620252
-4.599622  -2.185829
4.196223   1.126677
-2.133863  3.093686
4.668892   -2.562705
-2.793241  -2.149706
2.884105   3.043438
-2.967647  2.848696
4.479332   -1.764772
-4.905566  -2.911070

结果:

sklearn实现

[Scikit-learn:聚类clustering​​​​​​​]

from: 皮皮blog

ref: [机器学习算法与Python实践之(五)k均值聚类(k-means)]

[k-means算法详解及python代码]*

聚类算法:kmeans相关推荐

  1. 《菜菜的机器学习sklearn课堂》聚类算法Kmeans

    聚类算法 聚类算法 无监督学习与聚类算法 sklearn中的聚类算法 KMeans KMeans是如何工作的 簇内误差平方和的定义和解惑 sklearn.cluster.KMeans 重要参数 n_c ...

  2. 机器学习-Sklearn-07(无监督学习聚类算法KMeans)

    机器学习-Sklearn-07(无监督学习聚类算法KMeans) 学习07 1 概述 1.1 无监督学习与聚类算法 聚类算法又叫做"无监督分类",其目的是将数据划分成有意义或有用的 ...

  3. 聚类算法——kmeans和meanshift

    聚类算法--kmeans和meanshift [转] 1. meanshift 转于http://www.cnblogs.com/liqizhou/archive/2012/05/12/2497220 ...

  4. matlab中的聚类算法,kmeans聚类算法matlab matlab 聚类算法silhouette

    怎样用matlab实现多维K-means聚类算法小编觉得一个好的周末应该是这样的:睡到中午醒来,在床上躺着玩两个小时手机,起床随便吃点东西,下午去超市买一大堆零食,五六点的时候去约小伙伴们吃火锅烧烤, ...

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

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

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

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

  7. 用人话讲明白聚类算法kmeans

    文章目录 1.什么是聚类 2.K-Means步骤 3.K-Means的数学描述 4.初始中心点怎么确定 5.K值怎么确定 6.小结 1.什么是聚类 先来回顾一下本系列第一篇就讲到的机器学习的种类. 监 ...

  8. 离线轻量级大数据平台Spark之MLib机器学习库聚类算法KMeans实例

    1.KMeans算法 所谓聚类问题,就是给定一个元素集合D,其中每个元素具有n个可观察属性,使用某种算法将D划分成k个子集,要求每个子集内部的元素之间相异度尽可能低,而不同子集的元素相异度尽可能高.其 ...

  9. 聚类算法K-Means, K-Medoids, GMM, Spectral clustering,Ncut .

    聚类算法是ML中一个重要分支,一般采用unsupervised learning进行学习,本文根据常见聚类算法分类讲解K-Means, K-Medoids, GMM, Spectral cluster ...

  10. 聚类算法K-Means, K-Medoids, GMM, Spectral clustering,Ncut

    聚类算法是ML中一个重要分支,一般采用unsupervised learning进行学习,本文根据常见聚类算法分类讲解K-Means, K-Medoids, GMM, Spectral cluster ...

最新文章

  1. python 学习笔记8 (模块)
  2. MyBatis传入多个参数的问题 - mingyue1818
  3. stl vector 函数_在C ++ STL中使用vector :: begin()和vector :: end()函数打印矢量的所有元素...
  4. SpringBoot 2 要不要升级
  5. FJUT Home_W的gcd(乱搞)题解
  6. HTML5 postMessage解决跨域|跨窗口通信
  7. 迹中元素可交换性的证明tr(AB)=tr(BA)
  8. 用python简单处理图片(3):添加水印
  9. 主题:web.config中AppSettings和ConnectionStrings的区别
  10. 点石成金_Index
  11. 嵌入式ARM(Allwinner H3)下使用rtl8188eus无线网卡
  12. iWebOffice2015入门(一)
  13. 我的世界 Unity3D MineCraft 用Unity3D制作类似MineCraft我的世界的游戏 正经梳理一下开发01
  14. 【沧海拾昧】微机原理:存储器系统
  15. 柠檬智慧 java,智慧职教2020Java程序设计基础(哈尔滨职业技术学院)作业答案
  16. 小白Java笔记——注释
  17. 【10大基础算法】广度优先搜索-NO7
  18. enable 华为交换机ntdp_华为交换机设置
  19. 对于产业互联网的认识,直接关系着我们究竟会以怎样的心态来看待它
  20. 百度地图,开启marker点拖拽,并监听拖拽后的坐标位置

热门文章

  1. Process when we start our testing work
  2. Vmware Workstation常用操作和常见问题
  3. 把项目通过maven生产源码包和文档包并发布到自己的私服上
  4. 基准对象object中的基础类型----元组 (五)
  5. 【OS】Process Thread
  6. 【BZOJ2839】集合计数【BZOJ3622】已经没有什么好害怕的了
  7. 查看apt-get安装软件的版本
  8. 2015,鬼王Xun和GGL比赛,带给我们无尽的欢乐
  9. tfs 解除锁定命令
  10. 难于传播的正能量,来点干货