并行Louvain社区检测算法
因为在我最近的科研中需要用到分布式的社区检测(也称为图聚类(graph clustering))算法,专门去查找了相关文献对其进行了学习。下面我们就以这篇论文IPDPS2018的文章[1]为例介绍并行社区检测算法。
关于基本的单机/串行社区检测算法,大家可以参考我的另一篇博客《图数据挖掘:社区检测算法(一)》(链接:https://www.cnblogs.com/orion-orion/p/15662253.html)。总而言之,目前对于图的簇/社团划分,目前最广泛的测量方法是使用模块性(modularity)。然而模块性的优化是NP完全问题,目前最有名的一种启发式求解方法是基于贪心准则的Louvain方法。由于其速度和对社区检测结果的高质量,Louvain方法在串行/单机社区检测中一直是最常用的方法之一。
目前有许多方式可以对Louvain方法进行并行化。目前最快的基于共享内存多线程的Louvain方法是Grappolo软件包[2]。该软件能够在812s内在20个核上处理现实世界中大型的网络(soc-friendER; 18亿条边)。
在本篇论文中,作者将这个方法扩展到了分布式内存领域(和前面基于共享内存的领域不同)。而设计一个分布式的Louvain算法的挑战在于执行高效的邻居节点扫描(为了捕捉邻居节点所属社区状态的变化),因为在图的分布式表示的情况下,通信开销会变得非常重要。另一个关键的挑战是我们对哪个社区的状态进行查询和更新。串行算法的好处在于每轮迭代之间有同步操作,然而在分布式的环境下维护与传播最新的信息是被禁止的。此外,在分布式环境下一条边跨几个进程的处理也是一个棘手的问题。
1. 串行Louvain方法
我们这里简要描述一下串行的Louvain方法(详细描述见另一篇博客)。Louvain方法是一个多轮的迭代过程,每轮迭代分几个步骤。第一步,将每个节点视为一个社区,然后遍历每个节点——其中对于节点\(v\),计算将\(v\)移入各邻居可能导致的模块性增益\(\Delta Q\),如果最大的增益为正,那么\(v\)就会从其现在的社区移入该社区;第二步,进行图重建,即将所有划分好的社区缩为超节点。这个迭代过程一直持续直到不再获得模块性的增益(可以人工给定一个阈值\(\tau\))。
该算法的伪代码描述如下(伪代码中省略了图重建的过程):
2. 并行Louvain方法
我们开始叙述并行算法部分。我们使用\(p\)表示进程的数量,编号\(i\)表示区间\([0, p-1]\)内的任意进程编号。
首先,我们将输入的节点及它们的边集列表(edge list)(我们采用邻接表进行存储)分摊到各进程上,使每个进程接收到的边数量大致相同(这里没有用高级的图划分算法)。每个进程除了它本身拥有的节点集合之外,还存储了虽然属于其他进程、但与本进程中节点相关联的其他节点的拷贝(后面我们统一把这类节点称为影子节点)。论文采用稀疏行(CSR)的方式存储点和边集列表。
类似地,每个进程也获得一个任意集合的社区(大致使每个进程获得的社区数量相同),同时也保存了和本进程的社区之间有关联边(incident edges,即“跨边”)的社区(我们称为影子社区)。
下面的伪代码给出了并行的Louvain算法的大致框架,它包含了LouvainIteration
过程(也就是前面的模块性增益最大化过程)和BuildNextPhaseGraph
(对应前面的图的重构)这两个过程。注意,LouvainIteration
过程的步骤我们还没有展开,其中包括了进程之间通信的过程。
接下来我们详细的看LouvainIteration
过程和BuildNextPhaseGraph
是怎么实现的。
(a)Louvain Iteration
下面的伪代码展示了LouvainIteration
过程:
在这个过程中,每个进程都拥有节点和社区的集合,而进程之间的通信主要交换的信息也是节点和社区之间的信息。对每个局部的节点,都会存储一个社区ID。对每个局部的社区,关联度(\(a_c\))也被局部地存储。因为节点和进程编号的映射关系没轮迭代都在变化,每个进程需要存储其影子节点的列表以及这些影子节点对应的进程。此外,因为在每轮迭代开始时每个节点都在其自身的社区,故初始化的影子社区信息能够由节点信息推导出来。
下面我们解释一下LouvainIteration
过程的主要步骤:
2行(即过程开始),因为节点到进程的映射在每轮迭代(这里的迭代是指
LouvainIteration
过程外的迭代,别搞混了)会改变(由于图的缩点重构),我们会调用ExchangeGhostVertices
操作执行一次通信操作来自交换影子的坐标信息。4-5行(相当于每轮迭代的开始),论文进行了每轮迭代一次的
send-receive
通信步骤来交换对应的影子节点信息(参照算法4),send
操作指将进程的局部节点信息发往以这些节点做为影子节点的其他进程;receive
操作指从其他进程获得影子节点的更新。7-9行,使用最新的节点信息来计算所有局部节点的社区分配。
10-11行(相当于每轮迭代的末尾),我们需要将影子社区已更新的信息送往它们所属的进程,并且使各进程的社区接受相关更新的社区。
12-13行,先新的社区状态计算当前进程子图的模块性,然后采用
AllReduce
操作规约得到全局模块性。如果网络的模块性增益(\(\Delta Q\))相对于前面的迭代低于需要的一个阈值下限,我们就终止迭代(否则继续迭代)。
其中,ExchangeGhost
函数的定义如下:
ExchangeGhost
函数中6-7行表示当\(u\)节点的所有者\(owner\)不是当前节点,就将\(u\)增加到列表 \(vmap[owner]\) 中(\(vmap\)做为一个局部缓冲区,后面在第10行将\(vmap\)发给进程\(j\),然后在第11行接受传到第\(j\)个进程的影子节点数据)。
(b)Graph reconstruction
下面我们来看图的重构过程。上一个社区划分过程中所划分的社团将在图的重构过程中被压缩为单个节点。在一个社区内部的边会形成自环,对于连接两个不同社区的“跨边”会形成连接两个节点的一条边(权重为所有"跨边"之和)。图的重建过程可以参考下图:
我们可以看到,模块性优化步骤最初始将节点\(\{0, 1, 3\}\)分配给社区\(0\),节点\(2\)分配给社区\(2\),节点\(4\)分配给社区\(4\)(节点\(2\)和\(4\)各自成为一个社区)。由于社区ID由节点ID产生,我们认为\(0-2\)号社区属于(存储在)进程\(0\),\(3-4\)号社区属于(存储在)进程\(1\)。注意,图例中[Array]
表示数组,<Map>
表示字典映射。<Vlocal, C>
字典中存储了节点编号和社区编号的映射关系;[Edges]
数组中存储了边的权重;<Vremote, C>
字典存储了影子节点编号与其所属社区的映射关系。
然后图的重建可分为7个步骤:
(1) 每个进程将其局部社区进行重编号。重编号使用一个关联原始社区ID和新社区ID的哈希表<Cold, Cnew>
来实现。
(2) 每个进程检查可能已分配给远程节点(但和局部节点已无任何联系)的局部社区的ID。
(3) 基于前\(N\)个进程中局部社区的数量,为第\(N+1\)个进程的局部社区进行全局编号(并行前缀和计算)。
(4) 将最新的局部社区ID和全局社区ID编号的映射关系(<C, Cnew>
) 以AllReduce的方式更新到各个进程上。
(5) 每个进程会检查其所拥有的节点并构建部分的新的边集列表。对进程所拥有的每个节点,进程会检查其邻居列表,其中和新的社区ID相关联的邻居会形成一个自环。
(6) 一旦新的“部分边集列表”生成,它们就会被重新分配到各进程,然后生成新的图划分并调整边的权重(每个进程会尽可能获得相同数量的节点)。
(7) 根据新的超节点的带权邻接列表<Cnew, <Cnew, weight>>
构建新的图。
参考文献
[1] Ghosh S, Halappanavar M, Tumeo A, et al. Distributed louvain algorithm for graph community detection[C]//2018 IEEE international parallel and distributed processing symposium (IPDPS). IEEE, 2018: 885-895.
[2] Lu H, Halappanavar M, Kalyanaraman A. Parallel heuristics for scalable community detection[J]. Parallel Computing, 2015, 47: 19-37.
并行Louvain社区检测算法的更多相关文章
- 模块度与Louvain社区发现算法
Louvain算法是基于模块度的社区发现算法,该算法在效率和效果上都表现较好,并且能够发现层次性的社区结构,其优化目标是最大化整个社区网络的模块度. 模块度(Modularity) 模块度是评估一个社 ...
- GNN 相关资料记录;GCN 与 graph embedding 相关调研;社区发现算法相关;异构信息网络相关;
最近做了一些和gnn相关的工作,经常听到GCN 和 embedding 相关技术,感觉很是困惑,所以写下此博客,对相关知识进行索引和记录: 参考链接: https://www.toutiao.com/ ...
- 机器学习:异常检测算法Seasonal Hybrid ESD及R语言实现
Twritters的异常检测算法(Anomaly Detection)做的比较好,Seasonal Hybrid ESD算法是先用STL把序列分解,考察残差项.假定这一项符合正态分布,然后就可以用Ge ...
- 海量数据挖掘MMDS week3:社交网络之社区检测:高级技巧
http://blog.csdn.net/pipisorry/article/details/49052255 海量数据挖掘Mining Massive Datasets(MMDs) -Jure Le ...
- 海量数据挖掘MMDS week3:社交网络之社区检测:基本技巧
http://blog.csdn.net/pipisorry/article/details/49052057 海量数据挖掘Mining Massive Datasets(MMDs) -Jure Le ...
- 社区发现算法 - Fast Unfolding(Louvian)算法初探
1. 社团划分 0x1:社区是什么 在社交网络中,用户相当于每一个点,用户之间通过互相的关注关系构成了整个网络的结构. 在这样的网络中,有的用户之间的连接较为紧密,有的用户之间的连接关系较为稀疏.其中 ...
- Python机器学习笔记 异常点检测算法——Isolation Forest
Isolation,意为孤立/隔离,是名词,其动词为isolate,forest是森林,合起来就是“孤立森林”了,也有叫“独异森林”,好像并没有统一的中文叫法.可能大家都习惯用其英文的名字isolat ...
- [转]Python机器学习笔记 异常点检测算法——Isolation Forest
Isolation,意为孤立/隔离,是名词,其动词为isolate,forest是森林,合起来就是“孤立森林”了,也有叫“独异森林”,好像并没有统一的中文叫法.可能大家都习惯用其英文的名字isolat ...
- FAIR开源Detectron:整合全部顶尖目标检测算法
昨天,Facebook AI 研究院(FAIR)开源了 Detectron,业内最佳水平的目标检测平台. 昨天,Facebook AI 研究院(FAIR)开源了 Detectron,业内最佳水平的目标 ...
随机推荐
- .Net Core微服务——Ocelot(3):超时、熔断、限流
基本概念 超时.熔断.限流听起来好像很远,但实际上用在方方面面.很多人可能还搞不懂熔断是做什么,其实可以把熔断理解为一种防护措施.做个假设,在微服务体系下,某个下游服务响应很慢,然后随着时间推移,会有 ...
- 基于EPPlus和NPOI实现的Excel导入导出
基于EPPlus和NPOI实现的Excel导入导出 CollapseNav.Net.Tool.Excel(NuGet地址) 太长不看 导入 excel 文件流将会转为 ExcelTestDto 类型的 ...
- LOTO示波器实测——光照强度传感器
loto最近推出了很多的周边传感器模块的实测案例,本文介绍和演示LOTO示波器实测光照强度传感器的使用. 下图就是主角感光模块,可以用来测量光照强度. 这个模块也很简单,只有3个引脚,一个电源,3.3 ...
- 力扣 - 剑指 Offer 12. 矩阵中的路径
题目 剑指 Offer 12. 矩阵中的路径 思路1(回溯.DFS) 这题可以使用回溯+递归来解决,思路如下: 将二维数组的每一个元素都作为起点进行回溯查找 每次查找的时候,都有四个方向,但是上一个方 ...
- [bzoj1032]祖码
先将连续的一段相同的点连起来,然后考虑对于一段区间,分两种情况:1.首尾两点再同时消掉,必然要先将去掉首尾的一段消掉后再消2.首尾两点再不同时刻消掉,那么必然存在一个断点k,使得k左右无关(题目中的错 ...
- Codeforces 1010F - Tree(分治 NTT+树剖)
Codeforces 题面传送门 & 洛谷题面传送门 神仙题. 首先我们考虑按照这题的套路,记 \(t_i\) 表示 \(i\) 上的果子数量减去其儿子果子数量之和,那么对于一个合法的放置果子 ...
- du命令之计算文件大小
在linux中,常用du命令来计算文件或目录的大小 名称: du - 计算每个文件的磁盘用量,目录则取总用量. 用法: du [选项]... [文件]... 常用选项 -a, --all 输出所有文件 ...
- Visual Studio Code常用操作整理
Live Server插件可以在保存html文件后实时地刷新页面 在html文件中键入"! +Tap"会生成一个html模板 保存文件:Ctrl+S 文件跳转:Ctrl+P 文件内 ...
- linux 常用查看命令
linux 常用查看命令 目录 linux 常用查看命令 linux 查看内存/进程-ps/top linux 查看磁盘存储-df linux 查看io读写-iotop linux 查看端口占用-ne ...
- 数仓:解读 NameNode 的 edits 和 fsimage 文件内容
一.edits 文件 一)文件组成 一个edits文件记录了一次写文件的过程,该过程被分解成多个部分进行记录:(每条记录在hdfs中有一个编号) 每一个部分为: '<RECORD>...& ...