K-Means
简介
K-Means算法是无监督的聚类算法,按照样本之间的距离大小,将样本集划分为K个簇。让簇内的点尽量紧密的连在一起,而让簇间的距离尽量的大。
输入输出
K-Means是根据样本之间距离的大小来判断是否属于同一个簇的,所以样本必须能够计算距离,即必须包含坐标信息。将样本集划分为K个簇,即参数为K。
输入依赖: 包含坐标信息的样本集、要划分为K个簇的K值,输出:给样本集标注每个样本分别属于哪一个K簇
思想
K-Means算法的思想很简单,对于给定的样本集,按照样本之间的距离大小,将样本集划分为K个簇。让簇内的点尽量紧密的连在一起,而让簇间的距离尽量的大。
执行过程
1.(随机)选择K个聚类的初始中心;
2.对任意一个样本点,求其到K个聚类中心的距离,将样本点归类到距离最小的中心的聚类,如此迭代n次;
3.每次迭代过程中,利用均值等方法更新各个聚类的中心点(质心);
4.对K个聚类中心,利用2,3步迭代更新后,如果位置点变化很小(可以设置阈值),则认为达到稳定状态,迭代结束。
优点 & 缺点
优点
- 原理比较简单,实现也是很容易,收敛速度快。
- 聚类效果较优。
- 算法的可解释度比较强。
- 主要需要调参的参数仅仅是簇数k。
缺点
- K值的选取不好把握
- 对于不是凸的数据集比较难收敛
- 如果各隐含类别的数据不平衡,比如各隐含类别的数据量严重失衡,或者各隐含类别的方差不同,则聚类效果不佳。
- 最终结果和初始点的选择有关,容易陷入局部最优。
- 对噪音和异常点比较的敏感。
代码注释
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
|
def distEclud(vecA, vecB): return sqrt(sum(power(vecA - vecB, 2)))
def randCent(dataSet, k): n = shape(dataSet)[1] centroids = mat(zeros((k,n))) for j in range(n): minJ = min(dataSet[:,j]) maxJ = max(dataSet[:,j]) rangeJ = float(maxJ - minJ) centroids[:,j] = minJ + rangeJ * random.rand(k, 1) return centroids
def kMeans(dataSet, k, distMeans =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 = distMeans(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) return centroids, clusterAssment
|
小结
K-Means是一个简单的聚类算法,仍有一定的问题,例如对初始点,异常点较为敏感,同时对于抽象的大数据集不易给出K值。
参考 & 引用
https://blog.csdn.net/weixin_42029738/article/details/81978038
https://blog.csdn.net/weixin_42029738/article/details/81978038