Update: spark版本的实现在这里。
说明:该实现参照了SCAN作者的另一篇论文 :
Zhao, W., Martha, V., & Xu, X. (2013, March). PSCAN: a parallel Structural clustering algorithm for big networks in MapReduce. In Advanced Information Networking and Applications (AINA), 2013 IEEE 27th International Conference on (pp. 862-869). IEEE
可以实现在亿级别节点的图的聚类。
实现代码在这里下载。
Paper: 《SCAN: A Structural Clustering Algorithm for Networks》
Auther: Xiaowei Xu, Nurcan Yuruk, Zhidan Feng, Thomas A. J. Schweiger
Conference: SIGKDD 2007
SCAN算法是由机器学习里的基于密度的聚类算法DBSCAN改进而来的一种非重叠社团发现算法,具有线性时间复杂度。其一大亮点在于能发现社团中桥节点(hub)和离群点(outlier)。
主要思想在于,在考虑两点之间的关系的时候,不仅考虑它们的直接链接,而是利用它们的邻居节点来作为聚类的标准。也就是说,节点根据它们共享邻居方式而聚类。
由图可知,节点0、5共享了4个节点,节点9、13只共享了2个节点,显然它们在聚类是应采取不同的聚类方式。
节点相似度定义为两个节点共同邻居的数目与两个节点邻居数目的几何平均数的比值(这里的邻居均包含节点自身)。
节点的 ϵ ϵ - 邻居定义为与其相似度不小于 ϵ ϵ 的节点所组成的集合。
核节点是指 ϵ ϵ 邻居的数目大于 μ μ 的节点。
节点 w w 是核节点 v v 的 ϵ ϵ 邻居,那么称从 v v 直接可达 w w .
节点 v v 可达 w w ,当且仅当存在一个节点链 v1,…,vn∈V,v1=v,vn=w v 1 , … , v n ∈ V , v 1 = v , v n = w ,使得 vi+1 v i + 1 是 从 vi v i 直接可达的。
若核节点u可达节点v和节点w,则称节点v和节点w相连.
如果一个非空子图C中的所有节点是相连的,并且C是满足可达的最大子图,那么称C是一个相连聚类。
与至少两个聚类相邻的孤立节点.
只与一个聚类相邻或不与任何聚类相邻的孤立节点.
如果 v v 是一个核节点,那么从 v v 可达的节点集是一个结构相连聚类
C C 是一个结构相连聚类, p p 是 C C 中的一个核节点。那么 C C 等于从 p p 结构可达的节点集。
1、对于每个未分配社团的节点 v v ,检查 v v 是否是核节点,是核节点则将其直接可达节点分配到一个社团中(社团标号记为该节点),并将其 ϵ ϵ -邻居放进队列中,重复进行1步骤(类似于对直接可达节点进行DFS)。
2、若 v v 不是核节点则将其标志为non-member。
3、最后检查所有的non-menber节点,若其相邻节点存在于两个及以上的社团中,则将其标为hub节点,否则标为outlier。
ALGORITHM SCAN(G=, ε, μ)
// all vertices in V are labeled as unclassified;
for each unclassified vertex v ∈ V do
// STEP 1. check whether v is a core;
if COREε,μ(v) then
// STEP 2.1. if v is a core, a new cluster is expanded;
generate new clusterID;
insert all x ∈ Nε (v) into queue Q;
while Q ≠ 0 do
y = first vertex in Q;
R = {x ∈ V | DirREACHε,μ(y, x)};
for each x ∈ R do
if x is unclassified or non-member then
assign current clusterID to x;
if x is unclassified then
insert x into queue Q;
remove y from Q;
else
// STEP 2.2. if v is not a core, it is labeled as non-member
label v as non-member;
end for.
// STEP 3. further classifies non-members
for each non-member vertex v do
if (∃ x, y ∈ Γ(v) ( x.clusterID ≠ y.clusterID) then
label v as hub
else
label v as outlier;
end for.
end SCAN.