zoukankan      html  css  js  c++  java
  • 聚类算法:K均值

    在数据挖掘中,K-Means算法是一种cluster analysis的算法,其主要是来计算数据聚集的算法,主要通过不断地取离种子点最近均值的算法。

        基本K均值:选择K个初始质心,其中K是用户指定的参数,即所期望的簇的个数。每次循环中,每个点被指派到最近的质心,指派到同一个质心的点集构成一个簇。然后,根据指派到簇的点,更新每个簇的质心。重复指派和更新操作,直到质心不发生明显的变化。

         为了定义二维空间的数据点之间的“最近”概念,我们使用欧几里得距离的平方,即点A(x1,y1)与点B(x2,y3)的距离为dist(A,B)=(x1-x2)2+(y1-y2)2。另外我们使用误差的平方和SSE作为全局的目标函数,即最小化每个点到最近质心的欧几里得距离的平方和。在设定该SSE的情况下,可以使用数学证明,簇的质心就是该簇内所有数据点的平均值。

    问题

    K-Means算法主要解决的问题如下图所示。我们可以看到,在图的左边有一些点,我们用肉眼可以看出来有四个点群,但是我们怎么通过计算机程序找出这几个点群来呢?于是就出现了我们的K-Means算法(Wikipedia链接

    K-Means要解决的问题

    算法概要

    这个算法其实很简单,如下图所示: 

    从上图中,我们可以看到,A,B,C,D,E是五个在图中点。而灰色的点是我们的种子点,也就是我们用来找点群的点。有两个种子点,所以K=2。

    然后,K-Means的算法如下:

    1. 随机在图中取K(这里K=2)个种子点。
    2. 然后对图中的所有点求到这K个种子点的距离,假如点Pi离种子点Si最近,那么Pi属于Si点群。(上图中,我们可以看到A,B属于上面的种子点,C,D,E属于下面中部的种子点)
    3. 接下来,我们要移动种子点到属于他的“点群”的中心。(见图上的第三步)
    4. 然后重复第2)和第3)步,直到,种子点没有移动(我们可以看到图中的第四步上面的种子点聚合了A,B,C,下面的种子点聚合了D,E)。

    这个算法很简单,但是有些细节我要提一下,求距离的公式我不说了,大家有初中毕业水平的人都应该知道怎么算的。我重点想说一下“求点群中心的算法”。

    求点群中心的算法

    一般来说,求点群中心点的算法你可以很简的使用各个点的X/Y坐标的平均值。不过,我这里想告诉大家另三个求中心点的的公式:

    1)Minkowski Distance公式——λ可以随意取值,可以是负数,也可以是正数,或是无穷大。

    2)Euclidean Distance公式——也就是第一个公式λ=2的情况

    3)CityBlock Distance公式——也就是第一个公式λ=1的情况

    这三个公式的求中心点有一些不一样的地方,

    我们看下图(对于第一个λ在0-1之间)。

     

    (1)Minkowski Distanc   (2)Euclidean Distance    (3) CityBlock Distance

    上面这几个图的大意是他们是怎么个逼近中心的,第一个图以星形的方式,第二个图以同心圆的方式,第三个图以菱形的方式。

    实现代码如下:

    [python] view plain copy
     
    1. # scoding=utf-8  
    2. import pylab as pl  
    3.    
    4. points = [[int(eachpoint.split("#")[0]), int(eachpoint.split("#")[1])] for eachpoint in open("points","r")]  
    5.    
    6. # 指定三个初始质心  
    7. currentCenter1 = [20,190]; currentCenter2 = [120,90]; currentCenter3 = [170,140]  
    8.    
    9. pl.plot([currentCenter1[0]], [currentCenter1[1]],'ok')  
    10. pl.plot([currentCenter2[0]], [currentCenter2[1]],'ok')  
    11. pl.plot([currentCenter3[0]], [currentCenter3[1]],'ok')  
    12.    
    13. # 记录每次迭代后每个簇的质心的更新轨迹  
    14. center1 = [currentCenter1]; center2 = [currentCenter2]; center3 = [currentCenter3]  
    15.    
    16. # 三个簇  
    17. group1 = []; group2 = []; group3 = []  
    18.    
    19. for runtime in range(50):  
    20.     group1 = []; group2 = []; group3 = []  
    21.     for eachpoint in points:  
    22.         # 计算每个点到三个质心的距离  
    23.         distance1 = pow(abs(eachpoint[0]-currentCenter1[0]),2) + pow(abs(eachpoint[1]-currentCenter1[1]),2)  
    24.         distance2 = pow(abs(eachpoint[0]-currentCenter2[0]),2) + pow(abs(eachpoint[1]-currentCenter2[1]),2)  
    25.         distance3 = pow(abs(eachpoint[0]-currentCenter3[0]),2) + pow(abs(eachpoint[1]-currentCenter3[1]),2)  
    26.            
    27.         # 将该点指派到离它最近的质心所在的簇  
    28.         mindis = min(distance1,distance2,distance3)  
    29.         if(mindis == distance1):  
    30.             group1.append(eachpoint)  
    31.         elif(mindis == distance2):  
    32.             group2.append(eachpoint)  
    33.         else:  
    34.             group3.append(eachpoint)  
    35.        
    36.     # 指派完所有的点后,更新每个簇的质心  
    37.     currentCenter1 = [sum([eachpoint[0] for eachpoint in group1])/len(group1),sum([eachpoint[1] for eachpoint in group1])/len(group1)]  
    38.     currentCenter2 = [sum([eachpoint[0] for eachpoint in group2])/len(group2),sum([eachpoint[1] for eachpoint in group2])/len(group2)]  
    39.     currentCenter3 = [sum([eachpoint[0] for eachpoint in group3])/len(group3),sum([eachpoint[1] for eachpoint in group3])/len(group3)]  
    40.        
    41.     # 记录该次对质心的更新  
    42.     center1.append(currentCenter1)  
    43.     center2.append(currentCenter2)  
    44.     center3.append(currentCenter3)  
    45.    
    46. # 打印所有的点,用颜色标识该点所属的簇  
    47. pl.plot([eachpoint[0] for eachpoint in group1], [eachpoint[1] for eachpoint in group1], 'or')  
    48. pl.plot([eachpoint[0] for eachpoint in group2], [eachpoint[1] for eachpoint in group2], 'oy')  
    49. pl.plot([eachpoint[0] for eachpoint in group3], [eachpoint[1] for eachpoint in group3], 'og')  
    50.    
    51. # 打印每个簇的质心的更新轨迹  
    52. for center in [center1,center2,center3]:  
    53.     pl.plot([eachcenter[0] for eachcenter in center], [eachcenter[1] for eachcenter in center],'k')  
    54.    
    55. pl.show()  
  • 相关阅读:
    Linux熟悉命令
    Spring boot
    python jdbc操作数据库
    python 获取异常
    EntityFramework6 in github
    Java classloader机制测试命令
    SinalR
    asp.net httpmodule问题
    VMVare虚拟机的异常处理---内部错误
    Oracle11g客户端安装及plsql配置
  • 原文地址:https://www.cnblogs.com/gswang/p/7506663.html
Copyright © 2011-2022 走看看