Louvain算法是基于模块度的社区发现算法,该算法在效率和效果上都表现较好,并且能够发现层次性的社区结构,其优化目标是最大化整个社区网络的模块度。

模块度(Modularity

  模块度是评估一个社区网络划分好坏的度量方法,它的物理含义是社区内节点的连边数与随机情况下的边数只差,它的取值范围是 [−1/2,1),其定义如下:

$$Q = \frac{1}{2m}\sum_{i,j}[A_{ij} - \frac{k_ik_j}{2m}]\delta(c_i,c_j)$$

$$\delta(u,v) = \{_{0\ else}^{1 when\ u == v}$$

  其中,$A_{ij}$节点i和节点j之间边的权重,网络不是带权图时,所有边的权重可以看做是1;$k_i = \sum_jA_{ij}$表示所有与节点i相连的边的权重之和(度数);$c_i$表示节点i所属的社区;$m=\frac{1}{2}\sum_{ij}A_{ij}$表示所有边的权重之和(边的数目)。

  公式中$A_{ij} - \frac{k_ik_j}{2m}=A_{ij} - k_i\frac{k_j}{2m}$,节点j连接到任意一个节点的概率是$\frac{k_j}{2m}$,现在节点i有$k_i$的度数,因此在随机情况下节点i与j的边为$k_i\frac{k_j}{2m}$.

  模块度的公式定义可以作如下简化:

$$Q = \frac{1}{2m}\sum_{i,j}[A_{ij} - \frac{k_ik_j}{2m}]\delta(c_i,c_j)$$

$$ = \frac{1}{2m}[\sum_{i,j}A_{ij} - \frac{\sum_ik_i\sum_jk_j}{2m}]\delta(c_i,c_j)$$

$$ =  \frac{1}{2m}\sum_c[\Sigma in-\frac{{(\Sigma tot)}^2}{2m}]$$

其中$\Sigma in$表示社区c内的边的权重之和,$\Sigma tot$表示与社区c内的节点相连的边的权重之和。

  上面的公式还可以进一步简化成:

$$Q =  \sum_c[\frac{\Sigma in}{2m}-(\frac{\Sigma tot}{2m})^2]$$

$$ =  \sum_c[e_c-{a_c}^2]$$

  这样模块度也可以理解是社区内部边的权重减去所有与社区节点相连的边的权重和,对无向图更好理解,即社区内部边的度数减去社区内节点的总度数。

  基于模块度的社区发现算法,都是以最大化模块度Q为目标。

Louvain算法

  Louvain算法的思想很简单:

  1)将图中的每个节点看成一个独立的社区,次数社区的数目与节点个数相同;

  2)对每个节点i,依次尝试把节点i分配到其每个邻居节点所在的社区,计算分配前与分配后的模块度变化$\Delta Q$,并记录$\Delta Q$最大的那个邻居节点,如果$max\Delta Q>0$,则把节点i分配$\Delta Q$最大的那个邻居节点所在的社区,否则保持不变;

  3)重复2),直到所有节点的所属社区不再变化;

  4)对图进行压缩,将所有在同一个社区的节点压缩成一个新节点,社区内节点之间的边的权重转化为新节点的环的权重,社区间的边权重转化为新节点间的边权重;

  5)重复1)直到整个图的模块度不再发生变化。

  从流程来看,该算法能够产生层次性的社区结构,其中计算耗时较多的是最底一层的社区划分,节点按社区压缩后,将大大缩小边和节点数目,并且计算节点i分配到其邻居j的时模块度的变化只与节点i、j的社区有关,与其他社区无关,因此计算很快。在论文中,把节点i分配到邻居节点j所在的社区c时模块度变化为:

$$\Delta Q = [\frac{\sum_{in}+k_{i,in}}{2m}-(\frac{\sum_{tot}+k_i}{2m})^2]-[\frac{\sum_{in}}{2m}-(\frac{\sum_{tot}}{2m})^2-(\frac{k_i}{2m})^2]$$

其中$k_{i,in}$是社区c内节点与节点i的边权重之和,注意对$k_{i,in}$是对应边权重加起来再乘以2,这点在实现时很容易犯错。

  $Delta Q$分了两部分,前面部分表示把节点i加入到社区c后的模块度,后一部分是节点i作为一个独立社区和社区c的模块度,这里有一个困惑我的地方,虽然我按照这个公式实现的分群算法效果很好,但是我认为$Delta Q$少了把节点i从其原来社区删除这一步,因为后面的划分时,节点i所在的社区可能有多个节点。

  在实现的时候模块度变化还可以简化,把上面的公式展开,很多项就抵消了,化简之和:

$$\Delta Q = [\frac{k_{i,in}}{2m}-\frac{\sum_{tot}k_i}{2m^2}]$$

  论文中指出,算法第2)步节点的顺序会对分群结果又一定影响,但分群效果差距不大,只是会影响算法的时间效率,还有论文指出按度数从到的小的顺序处理速度最快,不过我在1K边上的图测试,差距不大。

分布式实现  

  我实现了Louvain算法的Spark版本和单机版,单机版在算法的第2)步中,节点i的社区变更会在节点i+1的社区分配时可见,但分布式实现,这一点不能满足,因为在分布式环境下,节点i和节点i+1的社区变更可能是在不同机器上同时进行,不能进行实时传递,因此在分布式实现时,节点i+1看到只能是节点i的上一轮的社区,因为这个原因,会导致一些节点互换社区,比如1号节点分到了2号节点所在的社区,而2号节点又分配到了节点1所在的社区,解决这个问题我是参考淘宝的一个实现,用节点id和和社区id构成的边组成新图,再用联通图来调整节点的社区。

  最后,工作了不能像上学的时候随意把代码放出来了,So.没有源代码分享~

欢迎评论,转账请注明出处:www.cnblogs.com/fengfenggirl

模块度与Louvain社区发现算法的更多相关文章

  1. 社区发现算法 - Fast Unfolding(Louvian)算法初探

    1. 社团划分 0x1:社区是什么 在社交网络中,用户相当于每一个点,用户之间通过互相的关注关系构成了整个网络的结构. 在这样的网络中,有的用户之间的连接较为紧密,有的用户之间的连接关系较为稀疏.其中 ...

  2. GNN 相关资料记录;GCN 与 graph embedding 相关调研;社区发现算法相关;异构信息网络相关;

    最近做了一些和gnn相关的工作,经常听到GCN 和 embedding 相关技术,感觉很是困惑,所以写下此博客,对相关知识进行索引和记录: 参考链接: https://www.toutiao.com/ ...

  3. 社区发现算法问题&&NetworkX&&Gephi

    在做东西的时候用到了社区发现,因此了解了一下有关社区发现的一些问题 1,社区发现算法 (1)SCAN:一种基于密度的社团发现算法 Paper: <SCAN: A Structural Clust ...

  4. SLAP(Speaker-Listener Label Propagation Algorithm)社区发现算法

    其中部分转载的社区发现SLPA算法文章 一.概念 社区(community)定义:同一社区内的节点与节点之间关系紧密,而社区与社区之间的关系稀疏. 设图G=G(V,E),所谓社区发现是指在图G中确定n ...

  5. Top Leaders社区发现算法(top leaders community detection approach in information networks)

    一.概念 复杂网络:现实生活中各种系统都可以看做成复杂网络,复杂网络构成包括节点和边,节点是网络中的基本组成单元,节点之间的联系或者关系是网络中的边.例如 电力网络:基站代表节点,基站之间是否互通表示 ...

  6. 并行Louvain社区检测算法

    因为在我最近的科研中需要用到分布式的社区检测(也称为图聚类(graph clustering))算法,专门去查找了相关文献对其进行了学习.下面我们就以这篇论文IPDPS2018的文章[1]为例介绍并行 ...

  7. LabelRank非重叠社区发现算法介绍及代码实现(A Stabilized Label Propagation Algorithm for Community Detection in Networks)

    最近在研究基于标签传播的社区分类,LabelRank算法基于标签传播和马尔科夫随机游走思路上改装的算法,引用率较高,打算将代码实现,便于加深理解. 这个算法和Label Propagation 算法不 ...

  8. 社区发现的3个评估指标:标准化互信息NMI,ARI指标,以及模块度(modularity)

    转载请注明出处:http://www.cnblogs.com/bethansy/p/6890972.html 一.已知真实社区划分结果 1.NMI指数,互信息和标准化互信息 具体公式和matlab代码 ...

  9. 社区发现(Community Detection)算法 [转]

    作者: peghoty 出处: http://blog.csdn.net/peghoty/article/details/9286905 社区发现(Community Detection)算法用来发现 ...

随机推荐

  1. 常用的JAVA集合讲解

    java.util包中包含了一系列重要的集合类,而对于集合类,主要需要掌握的就是它的内部结构,以及遍历集合的迭代模式. 接口:Collection Collection是最基本的集合接口,一个Coll ...

  2. linux的“自动化”

    h2:first-child, body>h1:first-child, body>h1:first-child+h2, body>h3:first-child, body>h ...

  3. Session Sticky About Nginx

    Nginx以前对session 保持支持不太好,主要采用ip_hash把同一来源的客户(同一C段的IP)固定指向后端的同一台机器,ip_hash有个缺点是不能实现很好的负载均衡:直到nginx的扩展模 ...

  4. 如何生成可变表头的excel

    1.实现功能: 传入一个表头和数据,将数据导入到excel中. 为了便于项目的扩展,数据传入通过泛型集合传入,获取数据时,通过反射的方式获取,这样无论你的表头是多少项,我都能很方便的生成.另外为了便于 ...

  5. C++学习笔记【转载】

    转载自:http://www.cnblogs.com/maowang1991/p/3290321.html 1.struct成员默认访问方式是public,而 class默认访问方式是private! ...

  6. [译] OpenStack Liberty 版本中的53个新变化

    一个新的秋季,一个新的OpenStack 版本.OpenStack 的第12个版本,Liberty,在10月15日如期交付,而且目前发行版本已经备好了.那么我们期望能从过去六个月时间的开发中获得些什么 ...

  7. JustWeEngine - 轻量级游戏框架

    JustWeEngine - 轻量级游戏框架 An easy open source Android game engine. Github地址 引擎核心类流程图 使用方法 引入Engine作为Lib ...

  8. 单调队列优化DP,多重背包

    单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...

  9. 网页下载Google Play 的App

    前言 当你想在google play上下载某个应用,而无奈手机的系统并没有安装google servicess,此刻是否有些捉急? 本文分享的是一个网站,它可以无需手机而直接通过网页下载Google ...

  10. JMeter学习(四)参数化

    JMeter也有像LR中的参数化,本篇就来介绍下JMeter的参数化如何去实现. 参数化:录制脚本中有登录操作,需要输入用户名和密码,假如系统不允许相同的用户名和密码同时登录,或者想更好的模拟多个用户 ...