K-means聚类

来自集智百科
跳转到: 导航搜索


K-means算法是硬聚类算法,是典型的局域原型的目标函数聚类方法的代表,它是数据点到原型的某种距离作为优化的目标函数,利用函数求极值的方法得到迭代运算的调整规则。K-means算法以欧式距离作为相似度测度,它是求对应某一初始聚类中心向量V最有分类,使得评价指标J最小。算法采用误差平方和准则函数作为聚类准则函数。

目录

简介

K-means算法是很典型的基于距离的聚类算法,采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大。该算法认为簇是由距离靠近的对象组成的,因此把得到紧凑且独立的簇作为最终目标。

k个初始类聚类中心点的选取对聚类结果具有较大的影响,因为在该算法第一步中是随机的选取任意k个对象作为初始聚类的中心,初始地代表一个簇。该算法在每次迭代中对数据集中剩余的每个对象,根据其与各个簇中心的距离将每个对象重新赋给最近的簇。当考察完所有数据对象后,一次迭代运算完成,新的聚类中心被计算出来。如果在一次迭代前后,J的值没有发生变化,说明算法已经收敛。

公式.png

算法过程如下:

  1. 从N个文档随机选取K个文档作为质心
  2. 对剩余的每个文档测量其到每个质心的距离,并把它归到最近的质心的类
  3. 重新计算已经得到的各个类的质心
  4. 迭代2~3步直至新的质心与原质心相等或小于指定阈值,算法结束

具体如下: 输入:k,data[n]

  1. 选择k个初始中心点,例如c[0]=data[0],…c[k-1]=data[k-1];
  2. 对于data[0]….data[n],分别与c[0]…c[k-1]比较,假定与c[i]差值最少,就标记为i;
  3. 对于所有标记为i点,重新计算c[i]={所有标记为i的data[j]之和}/标记为i的个数;
  4. 重复(2)(3),直到所有c[i]值的变化小于给定阈值。

工作原理

输入:聚类个数k,以及包含n个数据对象的数据库。 输出:满足方差最小标准的k个聚类。

Julei.png

处理流程 (1)从n个数据对象任意选择k个对象作为初始聚类中心; (2)根据每个聚类对象的均值(中心对象),计算每个对象与这些中心对象的距离;并根据最小距离重新对相应对象进行划分; (3)重新计算每个(有变化)聚类的均值(中心对象) (4)循环(2)到(3)直到每个聚类不再发生变化为止

k-means算法接受输入量k;然后将n个数据对象划分为k个聚类以便使得所获得的聚类满足:同一聚类中的对象相似度较高;而不同聚类中的对象相似度较小。聚类相似度是利用各聚类中对象的均值所获得一个“中心对象”(引力中心)来进行计算的。

工作过程

k-means算法的工作过程 说明如下:首先从n个数据对象任意选择k个对象作为初始聚类中心;而对于所剩下其它对象,则根据它们与这些聚类中心的相似度(距离),分别将它们分配给与其最相似的(聚类中心所代表的)聚类;然后再计算每个所获新聚类的聚类中心(该聚类中所有对象的均值);不断重复这一过程直到标准测度函数开始收敛为止。一般都采用均方差作为标准测度函数.k个聚类具有以下特点:各聚类本身尽可能的紧凑,而各聚类之间尽可能的分开。 存在问题 K均值聚类:K-means算法的特点——采用两阶段反复循环过程算法,结束的条件是不再有数据元素被重新分配. 指定聚类:即指定数据到某一个聚类,使得它与这个聚类中心的距离比它到其它聚类中心的距离要近。 修改聚类中心:优点:本算法确定的K个划分到达平方误差最小。当聚类是密集的,且类与类之间区别明显时,效果较好。对于处理大数据集,这个算法是相对可伸缩和高效的,计算的复杂度为O(NKt),其中N是数据对象的数目,t是迭代的次数。一般来说,K<<N,t<<N。

k-means算法缺点

  1. 在K-means算法中K是事先给定的,这个K值的选定是非常难以估计的。很多时候,事先并不知道给定的数据集应该分成多少个类别才最合适。这也是K-means算法的一个不足。有的算法是通过类的自动合并和分裂,得到较为合理的类型数目K,例如ISODATA算法。关于K-means算法中聚类数目K值的确定在文献中,是根据方差分析理论,应用混合F统计量来确定最佳分类数,并应用了模糊划分熵来验证最佳分类数的正确性。在文献中,使用了一种结合全协方差矩阵的RPCL算法,并逐步删除那些只包含少量训练数据的类。而文献中使用的是一种称为次胜者受罚的竞争学习规则,来自动决定类的适当数目。它的思想是:对每个输入而言,不仅竞争获胜单元的权值被修正以适应输入值,而且对次胜单元采用惩罚的方法使之远离输入值。
  2. 在K-means算法中,首先需要根据初始聚类中心来确定一个初始划分,然后对初始划分进行优化。这个初始聚类中心的选择对聚类结果有较大的影响,一旦初始值选择的不好,可能无法得到有效的聚类结果,这也成为K-means算法的一个主要问题。对于该问题的解决,许多算法采用遗传算法(GA),例如文献中采用遗传算法(GA)进行初始化,以内部聚类准则作为评价指标。
  3. 从K-means算法框架可以看出,该算法需要不断地进行样本分类调整,不断地计算调整后的新的聚类中心,因此当数据量非常大时,算法的时间开销是非常大的。所以需要对算法的时间复杂度进行分析、改进,提高算法应用范围。在文献中从该算法的时间复杂度进行分析考虑,通过一定的相似性准则来去掉聚类中心的侯选集。而在文献中,使用的K-means算法是对样本数据进行聚类,无论是初始点的选择还是一次迭代完成时对数据的调整,都是建立在随机选取的样本数据的基础之上,这样可以提高算法的收敛速度。

使用python的sklearn包来实现kmeans聚类

本案例中使用kmeans方法来对手写阿拉伯数字图像进行分类(分为十类)。

首先是调用一些包

    import time
    import numpy as np
    import pylab as pl
    from sklearn import metrics
    from sklearn.cluster import KMeans
    from sklearn.datasets import load_digits
    from sklearn.decomposition import PCA
    from sklearn.preprocessing import scale

其次要准备数据,这个数据是在sklearn里自带的,是1767个手写数字的图像,每个图像是8*8的矩阵,如下图所示

每个像素都是一个特征,所以原始数据是64个特征。

 
    #-----prepare  data-----------
    np.random.seed(42)
    digits = load_digits()
    data = scale(digits.data)
    n_samples, n_features = data.shape
    n_digits = len(np.unique(digits.target))
    labels = digits.target
    sample_size = 300
 
    print("n_digits: %d, \t n_samples %d, \t n_features %d"
          % (n_digits, n_samples, n_features))
    print(79 * '_')
    print('% 9s' % 'init' ' time  inertia    homo   compl  v-meas     ARI AMI  silhouette')

上述统计量中有些用了简写:

              Shorthand	     full name
                homo	          homogeneity score
                compl	          completeness score
                v-meas	          V measure
                ARI	          adjusted Rand index
                AMI	          adjusted mutual information
                silhouette	  silhouette coefficient    

K-means聚类的结果会随着制定类别数和初始点的选择有所不同。我们这里总是聚成十类,因为手写数字一共有十种。至于初始点的选取我们定义三种,k-means++,随机,和PCA降到十个维度后的中心点。

    #---define function and fit data--------------
    def bench_k_means(estimator, name, data):
        t0 = time.clock()
        estimator.fit(data)
        print('% 9s   %.2fs    %i   %.3f   %.3f   %.3f   %.3f   %.3f    %.3f'
              % (name, (time.clock() - t0), estimator.inertia_,
                 metrics.homogeneity_score(labels, estimator.labels_),
                 metrics.completeness_score(labels, estimator.labels_),
                 metrics.v_measure_score(labels, estimator.labels_),
                 metrics.adjusted_rand_score(labels, estimator.labels_),
                 metrics.adjusted_mutual_info_score(labels,  estimator.labels_),
                 metrics.silhouette_score(data, estimator.labels_,
                                          metric='euclidean',
                                          sample_size=sample_size)))
 
    bench_k_means(KMeans(init='k-means++', n_clusters=n_digits, n_init=10),
                  name="k-means++", data=data)
    bench_k_means(KMeans(init='random', n_clusters=n_digits, n_init=10),
                  name="random", data=data)
    # in this case the seeding of the centers is deterministic, hence we run the
    # kmeans algorithm only once with n_init=1
    pca = PCA(n_components=n_digits).fit(data)
    bench_k_means(KMeans(init=pca.components_, n_clusters=n_digits, n_init=1),
                  name="PCA-based",
                  data=data)

上述程序运行完就会出现这样的结果:

       n_digits: 10,          n_samples 1797,         n_features 64
       _______________________________________________________________________________
       init    time  inertia    homo   compl  v-meas     ARI AMI  silhouette
       k-means++   1.40s    69432   0.602   0.650   0.625   0.465   0.598    0.146
          random   1.20s    69694   0.669   0.710   0.689   0.553   0.666    0.147
       PCA-based   0.04s    71820   0.673   0.715   0.693   0.567   0.670    0.150
       _______________________________________________________________________________

我们还可以将原始数据用PCA降到两维,这样所有的数据就可以在二维空间中画出来。然后我们再用降维后的只有两个特征的数据进行Kmeans分析,聚成十类,然后再画在Voronoi diagram图的背景上。效果如下所示:

Kmeans clustering 1.png

 
    #----Visualize the results on PCA-reduced data------------
 
    reduced_data = PCA(n_components=2).fit_transform(data)
    kmeans = KMeans(init='k-means++', n_clusters=n_digits, n_init=10)
    kmeans.fit(reduced_data)
    # Step size of the mesh. Decrease to increase the quality of the VQ.
    h = .02     # point in the mesh [x_min, m_max]x[y_min, y_max].
    # Plot the decision boundary. For that, we will assign a color to each
    x_min, x_max = reduced_data[:, 0].min() + 1, reduced_data[:, 0].max() - 1
    y_min, y_max = reduced_data[:, 1].min() + 1, reduced_data[:, 1].max() - 1
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
    # Obtain labels for each point in mesh. Use last trained model.
    Z = kmeans.predict(np.c_[xx.ravel(), yy.ravel()])
    # Put the result into a color plot
    Z = Z.reshape(xx.shape)
 
    pl.figure(1)
    pl.clf()
    pl.imshow(Z, interpolation='nearest',
              extent=(xx.min(), xx.max(), yy.min(), yy.max()),
              cmap=pl.cm.Paired,
              aspect='auto', origin='lower')
    pl.plot(reduced_data[:, 0], reduced_data[:, 1], 'k.', markersize=2)
    # Plot the centroids as a white X
    centroids = kmeans.cluster_centers_
    pl.scatter(centroids[:, 0], centroids[:, 1],
               marker='x', s=169, linewidths=3,
               color='w', zorder=10)
    pl.title('K-means clustering on the digits dataset (PCA-reduced data)\n'
             'Centroids are marked with white cross')
    pl.xlim(x_min, x_max)
    pl.ylim(y_min, y_max)
    pl.xticks(())
    pl.yticks(())

使用K-means聚类来进行问答类社区的帖子推荐

这里是一份示例python代码,使用了kmeans方法对问答类社区进行帖子推荐。

相关wiki

个人工具
名字空间
操作
导航
工具箱