K-means algorithm原理及使用

来源:互联网 发布:java登录验证码实现 编辑:程序博客网 时间:2024/06/05 01:53

    K-means clustering algorithm,K-means聚类算法,它是无监督聚类的一种,可以用距离度量来将样本集分成K个类。

1. 关于K-means algorithm

    假如有如下的样本分布情况(左图),那么对这些样本进行聚类,我们人为做会怎么做(右图)。


    那么如果,样本的分布情况是这样的:

    

    人为怎么来进行聚类呢,或者出现样本中数据的维度超过三维了,维度很高,那么我们人为又怎么来进行分类呢?

    所以,我们需要一个聚类的算法,然后让计算机来替我们完成分类工作,我们看结果就行了。所以,有了K-means algorithm。K-means algorithm的过程如下:

    1)首先要考虑我们要将样本集分成几类,即K=?。决定了K以后,就好办了。我们随机选择K个样本作为K个中心。

    2)计算样本集中所有样本到这些中心的距离,假如某个样本找到距离最近的中心,就把这个样本归类给这个中心,直到所有的样本都归类完毕。

    3)这样就得到了K个类。现在要移动之前的中心点,移动到的位置是所在类的质心。质心的位置可以通过对所有样本进行求和平均得到。

    4)重复2)、3),直到迭代次数到达限值或者中心点不再移动整个过程稳定。

    图示K-means algorithm:

  

    我们贴一下Andrew Ng的K-means algorithm的伪代码:


    其中,c(i)指的是每个样本到最近的中心点的距离。

    

    以上就是K-means algorithm的原理了。

2. K-means algorithm改进

    但是这样的K-means algorithm是有待改善的。有两个地方:第一个是以上的算法很依赖于第一次随机选择的中心点,假如第一次随机选择的中心点是这样的:


    那么这样的聚类效果肯定是很差的。针对这样的问题,我们的做法是多进行几次上述的K-means算法过程,那么在里面选择效果最棒的,50次,100次都可以,意思就是多随机几十次。那么怎么样算是分类效果好呢,我们不能把每一次的分类结果都拿出来看吧,太累了。聚类效果越是好,那么中心点和样本的分布是很合理的,和第一节中的图一样,那么它的所有c(i)的和必定是最小的。也就是说,我们选取的聚类效果最好的标准是:

    

    我们再来看一下Andrew Ng给出的伪代码:


   第二个,是选择K等于几比较好。

    那么一个可取的做法是,把K=2的J求出来,把K=3的求出来,K=4的求出来,K=5的求出来。。。假如,


    是左边一幅图的情况,随着K的增加,J的变化有个转折点,那么这个就是我们要找的合理的K。(随着K的增加,J势必是会降低的,类越来越多,那么就分的越细,类间总距离会减小)而如果是右边一幅图,我们就不知道该找哪个K比较合适了。

    那么另一个做法就是根据实际情况来,假如酒厂造酒,它的酒准备面向三类客户,一类是居家消费类,一类是宴会类,一类是面向专业人士的,那么就取K为3好了,如果它想细化一些,那么就4类,5类,没有问题。

2. K-means algorithm的使用举例

    Matlab提供了一个K-means算法的example。

--------------------------------------------------------------------------

% matlab example
X = [randn(100,2)+ones(100,2);randn(100,2)-ones(100,2)]; %100行2列矩阵,代表100个样本
opts = statset('Display','final'); % 作为kmeans函数的参数,效果是在kmeans过程中展示每一次进行kmeans的结果
[idx,ctrs,sumd,~] = kmeans(X,2,'Distance','sqEuclidean','Replicates',50,'Options',opts); %调用matlab kmeans内部函数,欧式,50次重复
plot(X(idx==1,1),X(idx==1,2),'r.','MarkerSize',12) % 下面都是用上面的数据绘图
hold on
plot(X(idx==2,1),X(idx==2,2),'b.','MarkerSize',12)
plot(ctrs(:,1),ctrs(:,2),'kx','MarkerSize',12,'LineWidth',2)
plot(ctrs(:,1),ctrs(:,2),'ko','MarkerSize',12,'LineWidth',2)
legend('Cluster 1','Cluster 2','Centroids','Location','NW')

-------------------------------------------------------------------------------------

    结果如下:


    好了,到这里就是完成了K=2时候的对100行样本进行的聚类。我为什么说完成了K=2时候的呢,这是因为1)matlab内部的kmeans可没有这么弱鸡,它是克服了第二节中的第一个缺陷的;2)它只进行了K=2时候的K-means。

    首先,为什么说它克服了第一次随机取中心点的缺陷,因为它进行了50次kmeans,次数我自己设定的,那么就进行了50次kemeans,第一次得到一个聚类结果,第二次得到一个,。。。,第50次得到一个聚类结果,从中找到效果最好的。从命令行窗口也可以看到最后matlab自己选择的是总类间样本到中心点距离之和最小的一个。而且,我们来看一下kmeans的算法实现描述:


    看一下就知道我说的对不对了。

    其次,只进行了K=2时候的K-means是真的,因为这个函数就是实现这样的功能,那么我们把K=3时候的distance得到,K=4,K=5。。。然后我们绘图,从图上看。(或者我们就是有需求要进行K(确定值)聚类)

    咱们可以自己实现K-means算法,不需要用它的kmeans()函数,大家先自己写吧,实现了就分享一下啊,最近太忙了,等闲一点了一定把程序都补上。

    PS: 此博文任何人可以转载。