kmeans 订阅
k均值聚类算法(k-means clustering algorithm)是一种迭代求解的聚类分析算法,其步骤是,预将数据分为K组,则随机选取K个对象作为初始的聚类中心,然后计算每个对象与各个种子聚类中心之间的距离,把每个对象分配给距离它最近的聚类中心。聚类中心以及分配给它们的对象就代表一个聚类。每分配一个样本,聚类的聚类中心会根据聚类中现有的对象被重新计算。这个过程将不断重复直到满足某个终止条件。终止条件可以是没有(或最小数目)对象被重新分配给不同的聚类,没有(或最小数目)聚类中心再发生变化,误差平方和局部最小。 展开全文
k均值聚类算法(k-means clustering algorithm)是一种迭代求解的聚类分析算法,其步骤是,预将数据分为K组,则随机选取K个对象作为初始的聚类中心,然后计算每个对象与各个种子聚类中心之间的距离,把每个对象分配给距离它最近的聚类中心。聚类中心以及分配给它们的对象就代表一个聚类。每分配一个样本,聚类的聚类中心会根据聚类中现有的对象被重新计算。这个过程将不断重复直到满足某个终止条件。终止条件可以是没有(或最小数目)对象被重新分配给不同的聚类,没有(或最小数目)聚类中心再发生变化,误差平方和局部最小。
信息
提出时间
1967年
提出者
James MacQueen
类    型
聚类算法
中文名
K均值聚类算法
应    用
数据分析,信号处理,机器学习
外文名
k-means clustering algorithm
K均值聚类算法定义
聚类是一个将数据集中在某些方面相似的数据成员进行分类组织的过程,聚类就是一种发现这种内在结构的技术,聚类技术经常被称为无监督学习。k均值聚类是最著名的划分聚类算法,由于简洁和效率使得他成为所有聚类算法中最广泛使用的。给定一个数据点集合和需要的聚类数目k,k由用户指定,k均值算法根据某个距离函数反复把数据分入k个聚类中。
收起全文
精华内容
下载资源
问答
  • kmeans

    2020-07-29 23:58:14
    KMeans算法就只在一堆点中找出相同或相似性质的点,所以叫聚类。方法是随机找质点点,然后聚集周边聚类最近的点,然后计算这些点的平均数作为新的质点,直到质点不在变换。 KMeans追求的是,求解能够让簇内平方和...

    无监督学习与聚类算法
    KMeans算法就只在一堆点中找出相同或相似性质的点,所以叫聚类。方法是随机找质点点,然后聚集周边聚类最近的点,然后计算这些点的平均数作为新的质点,直到质点不在变换。
    KMeans追求的是,求解能够让簇内平方和最小化的质心。

    API:sklearn.cluster.KMeans
    class sklearn.cluster.KMeans (n_clusters=8, init=’k-means++’, n_init=10, max_iter=300, tol=0.0001, precompute_distances=’auto’, verbose=0, random_state=None, copy_x=True, n_jobs=None, algorithm=’auto’)
    重要参数:
    n_clusters
    n_clusters是KMeans中的k,表示着我们告诉模型我们要分几类。这是KMeans当中唯一一个必填的参数,默认为8 类,但通常我们的聚类结果会是一个小于8的结果。通常,在开始聚类之前,我们并不知道n_clusters究竟是多少, 因此我们要对它进行探索。
    random_state
    用于初始化质心的生成器。
    KMeans的首次探索
    当我们拿到一个数据集,如果可能的话,我们希望能够通过绘图先观察一下这个数据集的数据分布,以此来为我们聚类时输入的n_clusters做一个参考。 首先,我们来自己创建一个数据集使用make_blobs。这样的数据集是我们自己创建,所以是有标签的。

    from sklearn.datasets import make_blobs
    import matplotlib.pyplot as plt
    X,y = make_blobs(n_samples=500,n_features=2,centers=4,random_state=2020)
    
    plt.scatter
    fig,ax1 = plt.subplots(1)
    for i in range(8):
        ax1.scatter(X[y==i,0],X[y==i,1],)
    
    from sklearn.cluster import KMeans
    cluster = KMeans()
    cluster.fit(X)
    
    y_pred = cluster.labels_
    y_pred
    
    cluster.cluster_centers_
    
    cluster.inertia_
    
    finger,axis = plt.subplots(1)
    
    for i in range(18):
        axis.scatter(X[y_pred==i,0],X[y_pred==i,1],)
    
    
    from sklearn.metrics import silhouette_score,silhouette_samples
    
    silhouette_score(X,y)
    silhouette_samples(X,y)
    
    展开全文
  • Kmeans

    2020-06-13 22:58:46
    Kmeans聚类 K中心聚类 谱系聚类 EM聚类算法 基于密度的聚类 基于网格的聚类 Kmeans聚类分析 利用距离远近的思想将目标数据剧为指定的k个簇,簇类样本越相似,表明簇类效果越好。 Kmeans 具体实现 从数据中随机挑选...

    聚类算法(无监督的数据挖掘算法)

    作用

    1. 将数据实现分割
    2. 用于异常点的监控

    分类

    1. Kmeans聚类
    2. K中心聚类
    3. 谱系聚类
    4. EM聚类算法
    5. 基于密度的聚类
    6. 基于网格的聚类

    Kmeans聚类分析

    利用距离远近的思想将目标数据剧为指定的k个簇,簇类样本越相似,表明簇类效果越好。

    Kmeans 具体实现

    • 从数据中随机挑选k个样本点作为原始的簇中心。
    • 计算剩余样本与簇中心的距离,并把各样本标记为离k个簇中心最近的类别。
    • 重新计算各簇中样本点的均值,并以均值作为新的k个簇中心。
    • 不断重复(2)和(3),直到簇中心的变化趋于稳定,形成最终的k个簇。

    过程示意图

    子图1,从原始样本中随机挑选两个数据点作为初始的簇中心,即子图中的两个五角星;子图2,将其余样本点与这两个五角星分别计算距离(距离的度量可选择欧氏距离、曼哈顿距离等),然后将每个样本点划分到离五角星最近的簇,即子图中按虚线隔开的两部分;子图3,计算两个簇内样本点的均值,得到新的簇中心,即子图中的五角星;子图4,根据新的簇中心,继续计算各样本与五角星之间的距离,得到子图5的划分结果和子图6中新的簇内样本均值;以此类推,最终得到理想的聚类效果,如子图9所示,图中的五角星即最终的簇中心点。

    算法实现

    KMeans(n_clusters=8, init='k-means++', n_init=10, max_iter=300, tol=0.0001,
        precompute_distances='auto', verbose=0, random_state=None,
        copy_x=True, n_jobs=1, algorithm='auto')
    
    • n_clusters:用于指定聚类的簇数。
    • init:用于指定初始的簇中心设置方法,如果为’k-means++’,则表示设置的初始簇中心之间相距较远;如果为’random’,则表示从数据集中随机挑选k个样本作为初始簇中心;如果为数组,则表示用户指定具体的簇中心。
    • n_init:用于指定Kmeans算法运行的次数,每次运行时都会选择不同的初始簇中心,目的是防止算法收敛于局部最优,默认为10。
    • max_iter:用于指定单次运行的迭代次数,默认为300。
    • tol:用于指定算法收敛的阈值,默认为0.0001。
    • precompute_distances:bool类型的参数,是否在算法运行之前计算样本之间的距离,默认为’auto’,表示当样本量与变量个数的乘积大于1200万时不计算样本间距离。
    • verbose:通过该参数设置算法返回日志信息的频度,默认为0,表示不输出日志信息;如果为1,就表示每隔一段时间返回一次日志信息。
    • random_state:用于指定随机数生成器的种子。
    • copy_x:bool类型参数,当参数precompute_distances为True时有效,如果该参数为True,就表示提前计算距离时不改变原始数据,否则会修改原始数据。
    • n_jobs:用于指定算法运算时使用的CPU数量,默认为1,如果为-1,就表示使用所有可用的CPU。
    • algorithm:用于指定Kmeans的实现算法,可以选择’auto’‘full’和’elkan’,默认为’auto’,表示自动根据数据特征选择运算的算法。

    原理

    对于每个簇而言,就是保证这些簇的**离差平方和(方差)**的总和最小。

    当簇的个数与样本个数一致时(每个样本代表一个类),就可以得到最小值0。确实不假,簇被划分得越细,总和肯定会越小,但这样的簇不一定是合理的。所谓合理,就是随着簇的增加,离差平方和之和趋于稳定(波动小于某个给定的阈值)。

    该函数的表达式为:

    在这里插入图片描述

    cj表示第j个簇的簇中心,xi属于第j个簇的样本i,nj表示第j个簇的样本总量。对于该目标函数而言,cj是未知的参数。由于J为凸函数,可以通过求导获得cj。

    在这里插入图片描述

    在这里插入图片描述

    只有当簇中心cj为簇内的样本均值时,目标函数才会达到最小,获得稳定的簇。推导出来的簇中心正好与Kmeans聚类思想中的样本均值相吻合。

    最佳k值的确定

    对于Kmeans算法来说,如何确定簇数k值是一个至关重要的问题。

    分类

    • 拐点法
    • 轮廓系数法
    • 间隔统计量法

    拐点法

    Kmeans聚类算法的目标函数J,随着簇数量的增加,簇中的样本量会越来越少,进而导致目标函数J的值也会越来越小。通过可视化方法,重点关注的是斜率的变化,当斜率由大突然变小时,并且之后的斜率变化缓慢,则认为突然变化的点就是寻找的目标点,因为继续随着簇数k的增加,聚类效果不再有大的变化。

    绘制三组1000个点的散点图。

    # 导入第三方包
    import pandas as pd
    import numpy as np  
    import matplotlib.pyplot as plt
    from sklearn.cluster import KMeans
    from sklearn import metrics
    
    # 随机生成三组二元正态分布随机数 
    """
    函数可使得随机数具有预见性,
    即当参数相同时使得每次生成的随机数相同;
    """
    np.random.seed(1234)
    # 均值矩阵
    mean1 = [0.5, 0.5]
    # 协方差矩阵
    cov1 = [[0.3, 0], [0, 0.3]]
    #生成1000个点,满足mean1和cov1
    x1, y1 = np.random.multivariate_normal(mean1, cov1, 1000).T
    
    mean2 = [0, 8]
    cov2 = [[1.5, 0], [0, 1]]
    x2, y2 = np.random.multivariate_normal(mean2, cov2, 1000).T
    
    mean3 = [8, 4]
    cov3 = [[1.5, 0], [0, 1]]
    x3, y3 = np.random.multivariate_normal(mean3, cov3, 1000).T
    
    # 绘制三组数据的散点图
    plt.scatter(x1,y1)
    plt.scatter(x2,y2)
    plt.scatter(x3,y3)
    # 显示图形
    plt.show()
    

    在这里插入图片描述

    虚拟的数据呈现三个簇,接下来基于这个虚拟数据,使用拐点法,绘制簇的个数与总的簇内离差平方和之间的折线图,确定该聚为几类比较合适。

    # 构造自定义函数,用于绘制不同k值和对应总的簇内离差平方和的折线图
    def k_SSE(X, clusters):
        # 选择连续的K种不同的值
        K = range(1,clusters+1)
        # print(K)
        # 构建空列表用于存储总的簇内离差平方和
        TSSE = []
        for k in K:
            # 用于存储各个簇内离差平方和
            SSE = []
            # 传入簇数
            kmeans = KMeans(n_clusters=k)
            # 传入数据
            kmeans.fit(X)
            # 返回簇标签(返回array,即表示每个ID所属的簇)
            labels = kmeans.labels_
            # print(k,"==",labels)
            # 返回簇中心(返回k*2的array)
            centers = kmeans.cluster_centers_
            # print(k,"==",centers)
            # 计算各簇样本的离差平方和,并保存到列表中
            for label in set(labels):
                # append 将所有的参数视为一个列表元素插入到列表尾部
                SSE.append(np.sum((X.loc[labels == label,]-centers[label,:])**2))
            # 计算总的簇内离差平方和 
            TSSE.append(np.sum(SSE))
    
        # 中文和负号的正常显示
        plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
        plt.rcParams['axes.unicode_minus'] = False
        # 设置绘图风格
        plt.style.use('ggplot')
        # 绘制K的个数与GSSE的关系
        plt.plot(K, TSSE, 'b*-')
        plt.xlabel('簇的个数')
        plt.ylabel('簇内离差平方和之和')
        # 显示图形
        plt.show()
    
    # 将三组数据集汇总到数据框中
    # np.concatenate 按轴axis连接array组成一个新的array
    # pd.DataFrame Pandas库中的一种数据结构,它类似excel,是一种二维表。
    X = pd.DataFrame(np.concatenate([np.array([x1,y1]),np.array([x2,y2]),np.array([x3,y3])], axis = 1).T)
    # 自定义函数的调用
    k_SSE(X, 15)
    

    在这里插入图片描述

    当簇的个数为3时形成了一个明显的拐点,因为k值从1到3时,折线的斜率都比较大,但是k值为4时斜率突然就降低了很多,并且之后的簇对应的斜率都变动很小。所以,合理的k值应该为3。

    轮廓系数法

    考虑了簇的密集性分散性两个信息,如果数据集被分割为理想的k个簇,那么对应的簇内样本会很密集,而簇间样本会很分散。

    轮廓系数的计算公式可以表示为:

    在这里插入图片描述

    a(i)体现了簇内的密集性,代表样本i与同簇内其他样本点距离的平均值;b(i)反映了簇间的分散性,它的计算过程是,样本i与其他非同簇样本点距离的平均值,然后从平均值中挑选出最小值。当S(i)接近于-1时,说明样本i分配的不合理,需要将其分配到其他簇中;当S(i)近似为0时,说明样本i落在了模糊地带,即簇的边界处;当S(i)近似为1时,说明样本i的分配是合理的。

    需要对所有点的轮廓系数求平均值,得到总轮廓系数。当总轮廓系数小于0时,说明聚类效果不佳;当总轮廓系数接近于1时,说明簇内样本的平均距离a非常小,而簇间的最近距离b非常大,进而表示聚类效果非常理想。

    有关轮廓系数的计算,可以直接调用sklearn子模块metrics中的函数,即silhouette_score。需要注意的是,该函数接受的聚类簇数必须大于等于2。

    # 构造自定义函数,用于绘制不同k值和对应轮廓系数的折线图
    def k_silhouette(X, clusters):
        K = range(2,clusters+1)
        # 构建空列表,用于存储个中簇数下的轮廓系数
        S = []
        for k in K:
            kmeans = KMeans(n_clusters=k)
            kmeans.fit(X)
            labels = kmeans.labels_
            # 调用字模块metrics中的silhouette_score函数,计算轮廓系数
            # sklearn.metrics.silhouette_score(X, labels, *, metric='euclidean', sample_size=None, random_state=None, **kwds)
            # 适用于二维
            S.append(metrics.silhouette_score(X, labels, metric='euclidean'))
    
        # 中文和负号的正常显示
        plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
        plt.rcParams['axes.unicode_minus'] = False
        # 设置绘图风格
        plt.style.use('ggplot')    
        # 绘制K的个数与轮廓系数的关系
        plt.plot(K, S, 'b*-')
        plt.xlabel('簇的个数')
        plt.ylabel('轮廓系数')
        # 显示图形
        plt.show()
        
    # 自定义函数的调用
    k_silhouette(X, 15)
    

    间隔统计量法(Gap Statistic)

    学习中…

    Kmeans聚类的应用

    注意事项

    1. 聚类前必须指定具体的簇数k值,如果k值是已知的,可以直接调用cluster子模块中的Kmeans类,对数据集进行分割;如果k值是未知的,可以根据行业经验或前面介绍的三种方法确定合理的k值。

    2. 对原始数据集做必要的标准化处理,由于Kmeans的思想是基于点之间的距离实现“物以聚类”的,所以,如果原始数据集存在量纲上的差异,就必须对其进行标准化的预处理,否则可以不用标准化。数据集的标准化处理可以借助于sklearn子模块preprocessing中的scale函数或minmax_scale实现。

    展开全文
  • kMeans

    2018-08-01 01:34:10
    kMeans是一种简单的聚类算法,是一种无监督学习算法 聚类就是把同一类的数据聚在一起。意思是使同一类的数据相似度比较大,类别之间的数据相似度比较小。或者是距离。 聚类的基本思想: 以空间中k个点为形心进行...

    kMeans是一种简单的聚类算法,是一种无监督学习算法

    聚类就是把同一类的数据聚在一起。意思是使同一类的数据相似度比较大,类别之间的数据相似度比较小。或者是距离。

    聚类的基本思想:
    以空间中k个点为形心进行聚类,对最靠近他们的对象归类。通过迭代的方法,逐次更新各簇的类中心的值,直至得到最好的聚类结果。

    算法如下:
    (1)选择k个初始类中心
    (2)迭代:
    1)把每个样本归类
    2)更新类中心
    (3)迭代停止条件(满足一个即可):
    1)迭代次数达到设定的次数
    2)最小均方差小于设定值
    3)簇中心变化率到达设定值

    关键是:
    1. 类中心如何初始化?
    2. 数据的相似度/距离如何表示?曼哈顿距离还是欧式距离
    3. 类中心如何更新?平均值还是加权平均值还是中位数

    from sklearn.cluster import KMeans 
    import numpy as np
    X = np.array([[1, 2], [1, 4],[1, 0],[4, 2],[4, 4],[4, 0]])
    model= KMeans(n_clusters=2, random_state=0)
    model.fit(X)
    model.labels_
    # array([0, 0, 0, 1, 1, 1], dtype=int32)
    kmeans.predict([[0, 0], [4, 4]])
    # array([0, 1], dtype=int32)
    kmeans.cluster_centers_
    #array([[ 1.,  2.],
    #       [ 4.,  2.]])
    展开全文
  • Kmeans聚类算法详解

    万次阅读 多人点赞 2018-05-16 18:41:40
    摘要:本文通过图文详细介绍Kmeans聚类算法的原理和程序实现,以及如何选取类簇中心点。本文首先介绍利用该算法的原理及理解,详细介绍基于MATLAB设计一个自定义的Kmeans函数过程,然后利用该函数对UCI的数据集进行...

    摘要:本文详细介绍Kmeans聚类算法的原理和程序实现。首先介绍利用该算法的原理及理解,详细介绍基于MATLAB设计一个自定义的Kmeans函数过程,然后利用该函数对UCI的数据集进行聚类以测试聚类结果。后续章节将介绍的主要部分有:

    • Kmeans算法的原理及理解
    • 编程实现
    • 聚类结果评价
    • 类簇中心点的选取

    点击下载:本文Kmeans算法M函数及测试完整文件


    1. 前言

    作为无监督聚类算法中的代表——K均值聚类(Kmeans)算法,该算法的主要作用是将相似的样本自动归到一个类别中。所谓的监督算法,就是输入样本没有对应的输出或标签。聚类(clustering)试图将数据集中的样本划分为若干个通常是不相交的子集,每个子集称为一个“簇(cluster)”,聚类既能作为一个单独过程,用于找寻数据内在的分布结构,也可作为分类等其他学习任务的前去过程。——《Machine Learning》

    聚类算法也许是机器学习中“新算法”出现最多、最快的领域,一个重要的原因是聚类不存在客观标准,给定数据集总能从某个角度找到以往算法未覆盖的某种标准从而设计出新算法。Kmeans算法十分简单易懂而且非常有效,但是合理的确定K值和K个初始类簇中心点对于聚类效果的好坏有很大的影响。众多的论文基于此都提出了各自行之有效的解决方案,新的改进算法仍然不断被提出,此类文章大家可以在Web Of Science中搜索。

    尽管Kmeans算法在MATLAB、Python等语言的工具箱函数中都有自带的函数可供调用,但作为机器学习的研究者新来说要设计出新的算法,有时就得“定制”自己的Kmeans函数了。自己动手编写无疑也更加能理解算法的具体过程,接下来就让我们进入正题吧


    2. Kmeans算法的原理与理解

    Kmeans算法是最常用的聚类算法,主要思想是:在给定K值和K个初始类簇中心点的情况下,把每个点(亦即数据记录)分到离其最近的类簇中心点所代表的类簇中,所有点分配完毕之后,根据一个类簇内的所有点重新计算该类簇的中心点(取平均值),然后再迭代的进行分配点和更新类簇中心点的步骤,直至类簇中心点的变化很小,或者达到指定的迭代次数。

    2.1 基本原理

    假定给定数据样本X,包含了n个对象X={X1,X2,X3,...,Xn}X=\left \{ X_{1} ,X_{2},X_{3},...,X_{n}\right \},其中每个对象都具有m个维度的属性。Kmeans算法的目标是将n个对象依据对象间的相似性聚集到指定的k个类簇中,每个对象属于且仅属于一个其到类簇中心距离最小的类簇中。对于Kmeans,首先需要初始化k个聚类中心{C1,C2,C3,...,Ck},1<kn\left \{ C_{1} ,C_{2},C_{3},...,C_{k}\right \},1<k\leq n,然后通过计算每一个对象到每一个聚类中心的欧式距离,如下式所示dis(Xi,Cj)=t=1m(XitCjt)2dis(X_{i},C_{j})=\sqrt{\sum_{t=1}^{m}(X_{it}-C_{jt})^{2}}
    上式中,XiX_{i}表示第i个对象1in1\leq i\leq n,CjC_{j}表示第j个聚类中心的1jk1\leq j\leq kXitX_{it}表示第i个对象的第t个属性,1tm1\leq t\leq mCjtC_{jt}表示第j个聚类中心的第t个属性。

    依次比较每一个对象到每一个聚类中心的距离,将对象分配到距离最近的聚类中心的类簇中,得到k个类簇{S1,S2,S3,...,Sk}\left \{ S_{1},S_{2},S_{3},...,S_{k} \right \}

    Kmeans算法用中心定义了类簇的原型,类簇中心就是类簇内所有对象在各个维度的均值,其计算公式如下Ct=XiSlXiSlC_{t}=\frac{\sum_{X_{i}\in S_{l}}X_{i}}{\left | S_{l} \right |}
    式中,ClC_{l}表示第l个聚类的中心,1lk1\leq l\leq kSl\left | S_{l} \right |表示第l个类簇中对象的个数,XiX_{i}表示第l个类簇中第i个对象,1iSl1\leq i\leq\left | S_{l} \right |

    2.2 算法流程

    输入:样本集D={x1,x2,x3,...,xm}D=\left \{ x_{1},x_{2},x_{3},...,x_{m} \right \};聚类簇数k.
    过程:
    1:从D中随机选择k个样本作为初始均值向量{μ1,μ2,μ3,...,μk}\left \{ \mu _{1},\mu _{2},\mu _{3},...,\mu _{k} \right \}

    2:repeat
    3: 令Ci=(1ik)C_{i}=\varnothing (1\leqslant i\leqslant k)
    4: for j=1,2,…,m do
    5: 计算样本xjx_{j}与各均值向量μi(1ik)\mu_{i}(1\leqslant i\leqslant k)的距离:dji=xjμi2d_{ji}=\left \| x_{j}-\mu_{i} \right \|_{2};
    6: 根据距离最近的均值向量确定xjx_{j}的簇标记:λj=argmini{1,2,3,...,k}dji\lambda _{j}=arg min_{i\in \left \{ 1,2,3,...,k \right \}}d_{ji}
    7: 将样本xjx_{j}划入相应的簇:Cλj=Cλj{xj}C_{\lambda_{j}}=C_{\lambda_{j}}\cup \left \{ x_{j} \right \};
    8: end for

    9: for i=1,2,…,k do
    10: 计算新均值向量:μi=1CixCix\mu_{i}^{'}=\frac{1}{\left | C_{i} \right |}\sum _{x\in C_{i}}x;
    11: if μiμi\mu_{i}^{'}\neq \mu_{i} then
    12: 将当前均值向量 μi\mu_{i}更新为μi\mu_{i}^{'}
    13: else
    14: 保持当前均值不变
    15: end if

    16: end for
    17:until 当前均值向量均未更新
    输出:簇划分C={C1,C2,...,Ck}C=\left \{ C_{1} ,C_{2},...,C_{k} \right \}

    以上算法流程引自周志华《机器学习》,从流程来看K-means算法计算步骤基本上可以概括为两个部分:(1)计算每一个对象到类簇中心的距离;(2)根据类簇内的对象计算新的簇类中心。


    3. 编程实现

    为了方便应用我们将其编写为一个M函数KMeans(),首先需要确定函数的输入输出。这里输入参数为:data,K,iniCentriods,iterations(其中data为输入的不带标号的数据集数据矩阵,大小为numOfDatanumOfAttributes,K为数据分的类簇数目,iniCentriods为自行指定的初始聚类中心矩阵,大小为KnumOfAttributes,iterations为算法迭代次数。)
    输出参数为:Idx,centroids,DistanceIdx为返回的分类标号, centroids为每一类的中心,Distance为类内总距离)

    根据前面2.2节中的算法流程编写Kmeans算法的MATLAB程序如下

    %% Kmeans算法
    % 输入:
    % data 输入的不带分类标号的数据
    % K 数据一共分多少类
    % iniCentriods 自行指定初始聚类中心
    % iterations 迭代次数
    
    % 输出:
    % Idx 返回的分类标号
    % centroids 每一类的中心
    % Distance 类内总距离
    
     
    function [Idx,centroids,Distance]=KMeans(data,K,iniCentriods,iterations)
    [numOfData,numOfAttr]=size(data); % numOfData是数据个数,numOfAttr是数据维数
    centroids=iniCentriods;
    %% 迭代
    for iter=1:iterations
        pre_centroids=centroids;% 上一次求得的中心位置
        
        tags=zeros(numOfData,K);
        %% 寻找最近中心,更新中心
        for i=1:numOfData
            D=zeros(1,K);% 每个数据点与每个聚类中心的标准差
            Dist=D;
            
            % 计算每个点到每个中心点的标准差
            for j=1:K
                Dist(j)=norm(data(i,:)-centroids(j,:),2);
            end
            
            [minDistance,index]=min(Dist);% 寻找距离最小的类别索引
            tags(i,index)=1;% 标记最小距离所处的位置(类别)
        end
        
        
        %% 取均值更新聚类中心点
        for i=1:K
            if sum(tags(:,i))~=0
                % 未出现空类,计算均值作为下一聚类中心
                for j=1:numOfAttr
                    centroids(i,j)=sum(tags(:,i).*data(:,j))/sum(tags(:,i));
                end
            else % 如果出现空类,从数据集中随机选中一个点作为中心
                randidx = randperm(size(data, 1));
                centroids(i,:) = data(randidx(1),:);
                tags(randidx,:)=0;
                tags(randidx,i)=1;
            end
        end
        
       
        if sum(norm(pre_centroids-centroids,2))<0.001  % 不断迭代直到位置不再变化
            break;
        end
        
        
    end
    
    %% 计算输出结果
    Distance=zeros(numOfData,1);
    Idx=zeros(numOfData,1);
    for i=1:numOfData
        D=zeros(1,K);% 每个数据点与每个聚类中心的标准差
        Dist=D;
        % 计算每个点到每个中心点的标准差
        for j=1:K
            Dist(j)=norm(data(i,:)-centroids(j,:),2);
        end
        
        [distance,idx]=min(Dist);% 寻找距离最小的类别索引
        distance=Dist(idx);
        
        Distance(i)=distance;
        Idx(i)=idx;
    end
    Distance=sum(Distance,1);% 计算类内总距离
    end
    

    在以上代码中其最主要部分在于第18至58行,进行寻找最近中心和求取均值更新聚类中心点。值得注意的是,在聚类过程中可能会出现空类即代码第44行那样,为保证算法的继续运行,从数据集中随机选取一个点作为中心。

    4. 聚类结果评价

    为了验证编写的Kmeans函数的性能,这里对想用的UCI数据集Iris数据集进行聚类并计算聚类的准确率,Iris数据集可以在http://archive.ics.uci.edu/ml/index.php上下载得到。首先读取Iris数据集,自行指定初始聚类中心调用前面编写的KMeans函数进行聚类,然后计算聚类的准确率,其代码如下

    clear 
    data=load('Iris.txt');
    data=data(:,2:end);
    
    matrix=[5.9016,2.7484,4.3935,1.4339;6.8500,3.0737,5.7421,2.0711;5.0060,3.4280,1.4620,0.2460];
    [Idx,C,distance]=KMeans(data,3,matrix,500);
    Distance=sum(distance)
    
    c1=Idx(1:50,1);c2=Idx(51:100,1);c3=Idx(101:150,1);
    accuracy=(sum(c1==mode(Idx(1:50,1)))+sum(c2==mode(Idx(51:100,1)))+sum(c3==mode(Idx(101:150,1))))/150
    

    为方便使用Iris数据集经过了一些整理,这里将最后一列的带字符串的标签Iris-setosa,Iris-versicolor,Iris-virginica分别用数字1,2,3代替并移到了第一列,所以第三行选取的是从第二列至最后一列的数据。第5行中的matrix是查阅论文得到的一个初始聚类中心,正好用来比对聚类结果。第6行则调用KMeans()函数进行聚类,得到聚类标号和类内距离。对每类的类内距离求和即得到总的距离Distance,如第7行。准确率的计算有点麻烦,因为不能直接用KMeans计算后得到的标号跟原数据集中的标号对比计算准确率,KMeans只需要也只能将那些“相似”的数据点聚集到一类中,而给这一类数据的标号却是可能跟原数据集不同的。

    这里采用一个简单的方法,从原数据集的标签可以看出第1-50个数据点为一类(Iris-setosa),第51-100为一类(Iris-versicolor),第101-150为一类(Iris-virginica),因此只需确定每50个数据点中的聚类标号是不是一致。取它们之中数目最多的标号作为正确的个数,最终比上数据集的总数即为准确率。以上代码运行结果如下所示。

    5. 类簇中心点的选取

    KMeans算法本身思想比较简单,但是合理的确定K值和K个初始类簇中心点对于聚类效果的好坏有很大的影响。最简单的确定初始类簇中心点的方法是随机产生数据大小范围内的K个点作为初始的簇类中心点。随机产生初始点并进行测试的程序代码如下

    clear
    data=load('Iris.txt');
    data=data(:,2:end);
    K=3;
    
    
    %% 产生随机初始点
    [numOfData,numOfAttr]=size(data);   % numOfData是数据个数,numOfAttr是数据维数
    
    centroids=zeros(K,numOfAttr);       % 随机初始化,最终迭代到每一类的中心位置
    maxAttr=zeros(numOfAttr);        % 每一维最大的数
    minAttr=zeros(numOfAttr);        % 每一维最小的数
    for i=1:numOfAttr
        maxAttr(i)=max(data(:,i));    % 每一维最大的数
        minAttr(i)=min(data(:,i));    % 每一维最小的数
        for j=1:K
            centroids(j,i)=maxAttr(i)+(minAttr(i)-maxAttr(i))*rand();  % 随机初始化,选取每一维[min max]中初始化
        end
    end
    
    [Idx,C,distance]=KMeans(data,K,centroids,500);% 调用KMeans
    Distance=sum(distance)% 计算类内距离之和
    
    %% 计算准确率
    c1=Idx(1:50,1);c2=Idx(51:100,1);c3=Idx(101:150,1);
    Accuracy=(sum(c1==mode(Idx(1:50,1)))+sum(c2==mode(Idx(51:100,1)))+sum(c3==mode(Idx(101:150,1))))/numOfData
    

    可以多运行几次以上代码,可以看出由于初始点事随机选取的每次运行得到的结果有所差异。这也是基本Kmeans算法的一个缺点,随着众多改进算法的提出Kmeans算法的这一问题也得到改善,深入了解的朋友可以查阅相关论文。

    6. 结束语

    本博文的完整MATLAB程序文件与整理好的数据集文件已经上传,下载即可运行。下载地址如下

    点击下载:本文Kmeans算法M函数及测试完整文件

    公众号获取
        本人微信公众号已创建,扫描以下二维码并关注公众号“AI技术研究与分享”,后台回复“KM20180516”即可获取全部资源文件信息。

    由于编者能力有限,代码即使经过了多次校对,也难免会有疏漏之处。希望您能热心指出其中的错误,以便下次修改时能以一个更完美更严谨的样子,呈现在大家面前。同时如果有更好的实现方法也请您不吝赐教。

    展开全文
  • kmeans-源码

    2021-02-20 11:21:29
    kmeans
  • Kmeans算法

    2019-07-15 22:49:24
    Kmeans
  • 最近学习了,KmeansKmeans++,模糊Kmeans 看了几篇关于Kmeans的文献 首先讲解下各个算法的流程 Kmeans: ①随机选择K个对象作为初始的聚类中心 ②计算每个对象与各个聚类中心的距离 ③将对象分配给距离最近...
  • kmeans抠图

    2018-09-17 20:27:25
    练习kmeans分离目标物体
  • kmeans聚类

    2019-05-07 21:46:36
    多维kmeans聚类,有数据例程,有轮廓系数评价聚类效果
  • kmeans算法

    2019-04-22 15:23:31
    基本版本的kmeans算法的实现,附带wine数据集,并做了可视化
  • kmeans.py,python算法之Kmeans聚类分析
  • 模糊Kmeans

    2018-06-18 17:24:12
    模糊Kmeans,采用了JAVA语言编写,提供的可视化界面;
  • kmeans的PyTorch实现以利用GPU 入门 import torch import numpy as np from kmeans_pytorch import kmeans # data data_size, dims, num_clusters = 1000, 2, 3 x = np.random.randn(data_size, dims) / 6 x = torch...
  • KMeans Learn

    2021-01-10 11:00:42
    <p>How can I retrieve an array of indices the same as using method KMeans.Compute, but using KMeans.Learn? <p>I cannot find any example using KMeans.Learn <p>Thanks</p><p>该提问来源于开源项目:...
  • OpenCV kmeans

    2015-03-30 17:41:13
    OpenCV kmeans demos
  • Kmeans聚类

    2017-12-03 16:23:00
    Kmeans聚类可以支持2D和3D数据的处理,可以清晰观测聚类中心的移动过程,可以自选K的大小。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,069
精华内容 3,627
关键字:

kmeans