zoukankan      html  css  js  c++  java
  • cluster by fast search and find of density peaks

    说实在的这篇文章一发出来就遭到很多同行的鄙视,具体可以见Science上的评论,作为小菜,我还是保持沉默,好好学习为好。今天终于挤出时间来写这篇文章,闲话少说,直接上干货吧。


     

    聚类是根据距离来进行的,关于距离也可以用一篇很长的文章来叙述,但是这篇文章不是关注这个方面,我们只关注有了距离dij以后,怎么更好的进行聚类,首先说一下这篇文章的优点吧:

    a) 简单,里边不包含任何高深的迭代、梯度、隐函数等高深的词汇,基本上是个工科学生就能看懂;

    b) 效率高,因为没有上述的过程,所以处理起来较为简单;

    c) 能用对多种复杂的数据;

    d) 对类别比较多时不敏感,这一点是很多经典的方法比不了的(kmean)。

    这是我发现的优点,既然优点这么多,我们来具体看一下怎么实现的吧:

    1. 计算局部密度

    用dij代表数据点i和j之间的距离,i点的密度计算公式为

     p_{i}= sum X(d_{ij}-d_{c})

    上式中,X为一个符号函数,定义为:X(x)=1 如果x<0,否则X(x)=0。

    关于dc的确定,文章指出,dc可以选择为平均每个点的邻居局部密度为数据总数的1-2%(具体做实验时还得调整,这可能不是特别让人满意)

    代码如下:

     1 function y=get_P(dis,dc,label)
     2 [m,n]=size(dis);
     3 y=zeros(m,1);
     4 for i=1:m
     5     y(i)=0;
     6    for j=1:m
     7       if(i~=j)
     8           if label==0
     9              if(dis(i,j)-dc<0)
    10                  y(i)=y(i)+1;
    11              end    
    12           else
    13               y(i)=y(i)+exp(-(dis(i,j)/dc)^2);
    14           end
    15       end      
    16    end    
    17 end

     

    确定dc

     1 function y=get_dc(dis,percentage,kernel)
     2 max_dis=max(max(dis))/2;
     3 [m,n]=size(dis);
     4 i=0;
     5 for i=0:max_dis/1000:max_dis
     6     p=get_P(dis,i,kernel);
     7     p_ave=sum(p)/m;
     8     if(p_ave>m*percentage)
     9         break;
    10     end
    11 end
    12 y=i;
    13     
    14     

    2. 计算局部密度比本身大且距离本身最小的点

    这个主要用于聚类,往后就会看到,聚类算法采用的是一种依附的策略,采用递归方法得到自身的类别,现在先做个铺垫。

    对于每一个点来说,只要有密度比他大的点,那么这个phi一定存在;那么对于局部密度最大的点如何计算呢:

    想想作者还是蛮聪明的,这样计算的话直接把密度最大的点给识别出来了。

    上matlab代码

     1 function y=get_phi(dis,p)
     2 [m,n]=size(dis);
     3 y=zeros(m,2);
     4 [p1,index]=sort(p);
     5 for i=1:m-1
     6     tmp_dis=dis(index(i),:);
     7     tmp_dis(index(1:i))=max(max(dis));
     8     [a,b]=min(tmp_dis);   
     9     y(index(i),:)=[a,b];
    10 end
    11 y(index(m),1)=max(dis(index(m),:));
    12 y(index(m),2)=index(m);

    具体编写程序的时候还是有一些技巧的。

    ok 有了pi,就可以画出一个decision graph的东西,文章中给出的是A:

    越靠近右上角的点越容易被认为是聚类中心点(广义上的),或者我们也可以计算

    画出来的图是B

    实际上,在做实验的过程中,我发现通过B这个图更容易看出聚类中心有几个。

    上面找到了聚类中心,剩下的问题就是如何聚类了。

    3. 聚类过程

    上面我们得到了聚类中心,每个点的比其密度大的最近的点,我们利用这两个信息进行聚类:

    举个例子:

    这个例子中的聚类中心是1和10,对18这个点进行聚类。

    a)首先初始化1和10的label,分别为label_1和label_2,其他的不是聚类中心的点都没有聚类的label

    b) 比18密度大的最近的点是4,这时如果4是有label的,那么将4的label赋给18,聚类完成;显然此时18没有聚类,那么进入 c)

    c)比4密度大的最近的点是1,而1是有label的,那么将18的label标识为label_1,完成。

    实际操作中可能b)和c)要进行很多次循环才行,但是这个肯定是个线性的,并且递归的深度也不会太深,这样就完成了聚类过程。

    代码:

     1 function new_label=cluster_density(phi_index,r,cluster_num)
     2 
     3 m=length(phi_index);
     4 new_label=zeros(m,1);
     5 [r1,index_r1]=sort(r,'descend');
     6 
     7 for i=1:cluster_num
     8     new_label(index_r1(i))=i;
     9     tt=index_r1(i);
    10 end
    11 
    12 for i=1:m
    13     if (new_label(i)==0)
    14         j=i;
    15         while(new_label(j)==0)
    16             j=phi_index(j);
    17         end
    18         new_label(i)=new_label(j);
    19     end
    20     
    21 end

    算法到这里大体完成了,下面给出几个聚类结果的例子:

    原始和决策图

    结果

    文章链接:

    Alex Rodriguez and Alessandro Laio, Clustering by fast search and find of density peaks, Science 344, 1492(2014)

    http://www.sciencemag.org/content/344/6191/1492.full

    原创文章,转载请注明出处,谢谢!

  • 相关阅读:
    数据库-第十章 数据库恢复技术-10.8 小结
    数据库-第十章 数据库恢复技术-10.7 数据库镜像
    数据库-第十章 数据库恢复技术-10.6 具有检查点的恢复技术
    SpringCloud系列之集成分布式事务Seata应用篇
    Redis数据迁移同步工具(redis-shake)
    SpringCloud系列之集成Dubbo应用篇
    SpringCloud系列之网关(Gateway)应用篇
    SpringCloud系列之服务注册发现(Eureka)应用篇
    SpringCloud系列之配置中心(Config)使用说明
    webService-axis开发jar包
  • 原文地址:https://www.cnblogs.com/taokongcn/p/4034348.html
Copyright © 2011-2022 走看看