2019-12-29

K-Means聚类算法

1、原理

第一步:选K个初始聚类中心,z1(1),z2(1),…,zK(1),其中括号内的序号为寻找聚类中心的迭代运算的次序号。聚类中心的向量值可任意设定,例如可选开始的K个模式样本的向量值作为初始聚类中心。

第二步:逐个将需分类的模式样本{x}按最小距离准则分配给K个聚类中心中的某一个zj(1)。

假设i=j时, ,则 ,其中k为迭代运算的次序号,第一次迭代k=1,Sj表示第j个聚类,其聚类中心为zj。

第三步:计算各个聚类中心的新的向量值,zj(k+1),j=1,2,…,K

求各聚类域中所包含样本的均值向量:

其中Nj为第j个聚类域Sj中所包含的样本个数。以均值向量作为新的聚类中心,可使如下聚类准则函数最小:

在这一步中要分别计算K个聚类中的样本均值向量,所以称之为K-均值算法。

第四步:若 ,j=1,2,…,K,则返回第二步,将模式样本逐个重新分类,重复迭代运算;

若 ,j=1,2,…,K,则算法收敛,计算结束。

2、程序实现

def biKmeans(dataSet, k, distMeas=distEclud):

    m = shape(dataSet)[0]

    # 这里第一列为类别,第二列为SSE

    clusterAssment = mat(zeros((m,2)))

    # 看成一个簇是的质心

    centroid0 = mean(dataSet, axis=0).tolist()[0]

    centList =[centroid0] #create a list with one centroid

    for j in range(m):    #计算只有一个簇是的误差

        clusterAssment[j,1] = distMeas(mat(centroid0), dataSet[j,:])**2

    # 核心代码

    while (len(centList) < k):

        lowestSSE = inf

        # 对于每一个质心,尝试的进行划分

        for i in range(len(centList)):

            # 得到属于该质心的数据

            ptsInCurrCluster =\ dataSet[nonzero(clusterAssment[:,0].A==i)[0],:]

            # 对该质心划分成两类

            centroidMat, splitClustAss = kMeans(ptsInCurrCluster, 2, distMeas)

            # 计算该簇划分后的SSE

            sseSplit = sum(splitClustAss[:,1])

            # 没有参与划分的簇的SSE

            sseNotSplit = sum(clusterAssment[nonzero(clusterAssment[:,0].A!=i)[0],1])

            print "sseSplit, and notSplit: ",sseSplit,sseNotSplit

            # 寻找最小的SSE进行划分

            # 即对哪一个簇进行划分后SSE最小

            if (sseSplit + sseNotSplit) < lowestSSE:

                bestCentToSplit = i

                bestNewCents = centroidMat

                bestClustAss = splitClustAss.copy()

                lowestSSE = sseSplit + sseNotSplit

        # 较难理解的部分

        bestClustAss[nonzero(bestClustAss[:,0].A == 1)[0],0] = len(centList) #change 1 to 3,4, or whatever

        bestClustAss[nonzero(bestClustAss[:,0].A == 0)[0],0] = bestCentToSplit

        print 'the bestCentToSplit is: ',bestCentToSplit

        print 'the len of bestClustAss is: ', len(bestClustAss)

        centList[bestCentToSplit] = bestNewCents[0,:].tolist()[0]#replace a centroid with two best centroids

        centList.append(bestNewCents[1,:].tolist()[0])

        clusterAssment[nonzero(clusterAssment[:,0].A == bestCentToSplit)[0],:]= bestClustAss#reassign new clusters, and SSE

    return mat(centList), clusterAssment

3、结论1. K值需要预先给定,属于预先知识,很多情况下K值的估计是非常困难的,对于像计算全部微信用户的交往圈这样的场景就完全的没办法用K-Means进行。对于可以确定K值不会太大但不明确精确的K值的场景,可以进行迭代运算,然后找出Cost Function最小时所对应的K值,这个值往往能较好的描述有多少个簇类。

2. K-Means算法对初始选取的聚类中心点是敏感的,不同的随机种子点得到的聚类结果完全不同

3. K均值算法并不是很所有的数据类型。它不能处理非球形簇、不同尺寸和不同密度的簇,银冠指定足够大的簇的个数是他通常可以发现纯子簇。

4. 对离群点的数据进行聚类时,K均值也有问题,这种情况下,离群点检测和删除有很大的帮助。


参考文献:https://blog.csdn.net/taoyanqi8932/article/details/53727841

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • javaSE java程序结构 Java源程序一般由一个或多个编译单元组成,每个编译单元只能包含以下内容(空格和注...
    西沉_阅读 2,915评论 0 0
  • 1.环境 python 3.7 2.安装指导,缺少对nccl的安装指导 https://github.com/op...
    Joyner2018阅读 4,434评论 0 0
  • 《我,铅笔的故事》 作者:伦纳德 里德 翻译:秋风 本文原题《I,Pencil》,刊于经济教育基金会(the Fo...
    十八子睿阅读 2,563评论 0 0
  • 数的分类 目前为我们所学过自然数小数和分数,那么如果要将它分为两大类,应该是分成哪两大类呢?首先分类标准是不重不漏...
    山海不是小学生阅读 1,225评论 0 0
  • 一 2016年7月的一个中午,急救中心接到电话,一位女性称,家人突发昏迷,不知生死。我看着刚打好的饭菜,忍不住抱怨...
    真实故事计划阅读 4,097评论 3 8

友情链接更多精彩内容