当前位置:   article > 正文

K均值算法【K-means】_k—means均值算法步骤

k—means均值算法步骤

一、K-Means算法流程

K均值算法是学习无监督学习的第一个算法,这个算法理解和实现都比较简单,算法的目的是将数据分成K组。

为了达到这个目的,算法首先随机初始化k个数据点(聚类中心),然后遍历所有数据,计算出每一个数据到k个点的距离,找到最小的距离,则该点属于这个类。之后计算每一组中的平均值,然后更新聚类中心,直到中心点不再发生变化。

下面是算法的运行过程:

  1. 输入:没有标签的数据X,大小为m,要将数据划分成k组。
  2. u1,u2,u3,...,uk为聚类中心
  3. x1,x2,...,xm为m个数据
  4. 初始化聚类中心u1,u2,...,uk
  5. Repeat{
  6. for i=1 到m:
  7. for j=1 到k:
  8. 计算xi到uj之间的距离,找到最小的距离
  9. 将数据xi划分到产生最小距离的uj组里面
  10. for i=1到k:
  11. 计算每一组的均值,更新u1,u2,...,uk
  12. }

 

二、K-Means算法python实现

下面是python的代码实现:

  1. import matplotlib.pyplot as plt
  2. import seaborn as sns
  3. import pandas as pd
  4. import scipy.io as sio
  5. import numpy as np
  6. #读入数据,将数据转化为DataFrame
  7. mat = sio.loadmat('ex7data2.mat')
  8. data = pd.DataFrame(mat.get('X'),columns=['X1','X2'])
  9. # 将数据可视化
  10. sns.set(context='notebook',style='white')
  11. sns.lmplot('X1','X2',data=data,fit_reg=False)

数据如下图所示:

  1. #计算两个向量之间的距离
  2. def distEclud(vecA,vecB):
  3. return np.sqrt(np.sum(np.power(vecA-vecB,2)))
  4. #随机选择K个聚类中心,进行初始化化
  5. def randCent(dataSet,k):
  6. # n是数据的维数
  7. n = np.shape(dataSet)[1]
  8. centroids = np.mat(np.zeros((k,n)))
  9. for j in range(n):
  10. minJ = min(dataSet[:,j])
  11. rangeJ = float(max(dataSet[:,j])-minJ)
  12. centroids[:,j] = minJ + rangeJ*np.random.rand(k,1)
  13. return centroids
  14. def KMeans(dataSet,k,distMeans=distEclud,createCent=randCent):
  15. m = np.shape(dataSet)[0]
  16. clusterAssment = np.zeros((m,2))
  17. centroids = createCent(dataSet,k)
  18. clusterChanged = True
  19. while clusterChanged:
  20. clusterChanged = False
  21. # 遍历所有样本
  22. for i in range(m):
  23. minDist = np.inf
  24. minIndex = -1
  25. # 对于一个样本,计算他和每一个聚类中心的距离,找到最小的距离
  26. for j in range(k):
  27. distJI = distMeans(centroids[j,:],dataSet[i,:])
  28. if distJI < minDist:
  29. minDist = distJI
  30. minIndex = j
  31. if clusterAssment[i,0] != minIndex:
  32. clusterChanged=True
  33. clusterAssment[i,:] = minIndex,minDist**2
  34. print(centroids)
  35. #求每一个组的均值,更新聚类中心
  36. for cent in range(k):
  37. ptsInClust = dataSet[np.nonzero(clusterAssment[:,0]==cent)[0]]
  38. centroids[cent,:] = np.mean(ptsInClust,axis=0)
  39. return centroids,clusterAssment
  1. #调用函数,进行聚类
  2. myCentroids,clustAssing =KMeans(data.values,3)
  3. #将类别添加到数据中
  4. data['C'] = clustAssing[:,0]
  5. #绘制分类后的数据
  6. sns.lmplot('X1','X2',hue='C',data=data,fit_reg=False)

最后的聚类结果:

 

 

三、K-Means算法的优缺点及适用范围

1>算法对于符合高斯分布的数据,聚类效果比较好。二维的高斯分布在平面上是一个圆形或者椭圆的形状,如果数据服从这个分布,则用K-Means算法效果比较好。

2>算法对于初值的选择比较敏感,需要多次尝试。可以看到,数据明显分为了三类,但是这是在我们知道算法的类别是3的情况下,如果我们初始化的类别不是3,算法就不会有这么好的效果。特别是对于高维数据,我们无法将数据可视化的情况下,需要多次运行算法,查看算法表现,如果将聚类中心初始化为6,效果就没有那么好了,如下图所示,对于初始点的位置对于算法会有影响,所以提出了改进的K-Means++算法。

3>算法对于异常点比较敏感,比如数据为1,2,3,4,10,100,他们的聚类中心为20,显然这个时候聚类中心离大多数数据比较远,这个时候需要对聚类中心进行改进,选用中位数作为聚类中心,效果会比较好,这就是K-mean的改进算法k-Mediods算法。

四、K-Means算法中的EM思想

将K-Means算法用损失函数表示出来:

                                                J(c,u)=i=1m||xiuci||2

上面表示的是每一个样本点到他的聚类中心距离的最小值。直接求解上面的算法是一个NP难的问题,所以一般选择启发式的规则进行。

如果选取要想使得上面的损失函数值变得更小,有两种方法。第一种方法是是保持xi所属的类别不变,更改聚类中心的值。第二种方法。保持聚类中心u不变,改变xi所属的类别。

一开始我们不知道xi对应的最佳聚类中心ui是那一个,所以一开始随便指定一个ui,为了让J最小,我们更新聚类中心ui的值。更新后发现xi有更好的聚类中心uj,这个时候更新xi所属聚类中心为uj。不断重复上述过程。而上述过程对应的是EM算法中的E步和M步,E步就是确定隐含变量类别(即聚类中心),M步就是更新其他参数来最小化J。

 

参考资料:1>吴恩达机器学习K-means作业

        2>机器学习实战

        3>pluskid聚类博客

        4>CS229机器学习笔记

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/715892
推荐阅读
相关标签
  

闽ICP备14008679号