原论文Fast unfolding of communities in large networks
2008年的
虽然本文是原始用于检测社区的,但其实可以作为层次聚类的一种形式。
层次聚类这个问题我研究不深,但是常见的层次聚类例如HAC,其实并不能够给定有效的层级结构。一般都是在某个distance阈值了,选取此时还保留的几个cluster。
但是低的hierarchy层级以及有效的hierarchy结构。其实并没有获取到。i.e. 其实没有层级的cluster。
举个例子,层级聚类,我们想要的不仅是这个方法给出的最顶层层级。我们也想要他的下属层级,并且想要自动化的获取。这总不能我们设定好有几个阈值,然后分别的cut吧,因为有的时候层级比较多,有的时候层级比较少,不能自动化。
提出一种简单在大型网络下抽取社区结构的方法,基于模块度优化的启发式方法
1 在计算时间上优于其他所有已知的社区检测方法。
2 检测的社区质量很好(通过模块度度量)
一些当今的社交网络等等,有非常多的结点和连线。都是数以百万计。因此有效的方法包括压缩网络变成子单元,这些子单元中都是高度内部连接的结点。
笔者:在Louvain中的思想就是把社区变成小node,再进行高层的社区聚类
识别这些子单元或者社区非常重要,可以发现一些例如社区网络中的“话题”等等。可以用来可视化社区结构等扽
笔者:也就是讲述发现community是很有意义的
社区检测问题需要网络的一部分变成一个高度内部连接的社区,不同社区之间的结点可能仅仅是稀疏连接笔者:这很合理
准确的公式化这个优化问题是非常棘手的,很多算法都被提了出来,此外由于社交网络的影响力和数据集公布等等,这个研究方向也吸引很多人。
算法可以被分为:
区分的质量通常被模块度来进行一个评估。
模块度介于 [ − 1 , 1 ] [-1, 1] [−1,1]去描述社区内连线的密度与社区间连接的密度。 在加权网络中,模块度定义为:
Q = 1 2 m ∑ i , j [ A i j − k i k j 2 m ] δ ( c i , c j ) , Q=\frac{1}{2 m} \sum_{i, j}\left[A_{i j}-\frac{k_{i} k_{j}}{2 m}\right] \delta\left(c_{i}, c_{j}\right), Q=2m1i,j∑[Aij−2mkikj]δ(ci,cj),
其中
- A i j A_{ij} Aij代表结点 i i i与结点 j j j之间的边的权重
- k i = ∑ j A i j k_i = \sum_{j} A_{ij} ki=∑jAij是结点 j j j的所有边的连接权重之和。同理 k j = ∑ i A i j k_{j}= \sum_{i} A_{ij} kj=∑iAij
- c i c_i ci, c j c_j cj分别是结点 i i i和 j j j所属的社区
- δ ( u , v ) \delta(u, v) δ(u,v)是一个函数,如果 u = v u=v u=v则值为1,如果 u ≠ v u \neq v u=v则值为0
- $ m = \frac{1}{2}\sum_{ij}A_{ij}$,也就是所有连接权重总和的1/2.
慢慢解析这个模块度公式,毕竟这个是全文的核心了(虽然这个模块度也不是louvain提出来的hhh)
这边尝试化整一下公式,先将 δ \delta δ公式取出来(假设所有的点全部存在于1个社区内),把上部分m公式带入
1 2 m [ ∑ i , j A i j ∑ i j A i j − k i k j 2 m ] = 1 4 m 2 ∑ i , j [ A i , j ∗ ∑ i , j A i , j − k i k j ] = 1 4 m 2 [ ∑ i , j A i , j ∗ ∑ i , j A i , j − ∑ i , j k i k j ] \begin{aligned} &\frac{1}{2m}[\sum_{i,j}\frac{A_{ij}\sum_{ij}A_{ij}- k_ik_j}{2m}]\\ &=\frac{1}{4m^2}\sum_{i,j}[A_{i,j}*\sum_{i,j}A_{i,j}-k_ik_j]\\ &=\frac{1}{4m^2}[\sum_{i,j}A_{i,j}*\sum_{i,j}A_{i,j}-\sum_{i,j}k_ik_j] \end{aligned} 2m1[i,j∑2mAij∑ijAij−kikj]=4m21i,j∑[Ai,j∗i,j∑Ai,j−kikj]=4m21[i,j∑Ai,j∗i,j∑Ai,j−i,j∑kikj]
重点强调一下其中的 m = 1 2 ∑ i j A i j m = \frac{1}{2}\sum_{ij}A_{ij} m=21∑ijAij 由于 ∑ i j A i j \sum_{ij}A_{ij} ∑ijAij是一个定值,我们可以在这里设置为值为 W a W_a Wa
然后上述公式为
1 4 m 2 [ ∑ i , j A i , j ∗ ∑ i , j A i , j − ∑ i , j k i k j ] = W a 2 − ∑ i , j k i k j W a 2 = 1 − ∑ i , j k i k j ∑ i , j A i , j ∗ ∑ i , j A i , j \begin{aligned} &\frac{1}{4m^2}[\sum_{i,j}A_{i,j}*\sum_{i,j}A_{i,j}-\sum_{i,j}k_ik_j]\\ &=\frac{W_a^2-\sum_{i,j}k_ik_j}{W_a^2}\\ &=1 - \frac{\sum_{i,j}k_ik_j}{\sum_{i,j}A_{i,j}*\sum_{i,j}A_{i,j}} \end{aligned} 4m21[i,j∑Ai,j∗i,j∑Ai,j−i,j∑kikj]=Wa2Wa2−∑i,jkikj=1−∑i,jAi,j∗∑i,jAi,j∑i,jkikj
最后我还是把 m m m带回了原公式,可以看到模块度最大的上限为1。
最后也没能发现 k i k_i ki和 k j k_j kj存在什么特殊之处,我觉得应该就是想把两个点的一些特征带进去罢了。
出现-1的情况,想了一下应该是对于某个社区来说,如果特别差劲,内部连接全部没有,所有的连接全都在外面,就会出现-1的情况。
模块度被用于比较分块的质量,也是一个优化的目标函数。但是计算和优化都非常困难呢。贪心算法的效果也不太行。
文中提出的方法可以在短时间内寻找到高模块度并且可以展开称为一个完整的层级社区结构。因此可以去解决多种社区检测问题。
比较其他方法,该方法主要的问题是存储空间的大小而不是计算时间的问题。118个百万结点仅需要152分钟。Louvain NB
Louvain图例子
原图是点皆为灰色的情况,然后通过模块度优化(具体的优化过程后面再讲),得到了一群community。
然后将这群community化整称为一个新的node,做第二阶段的community的检测。就这样达到hierarchy的效果。
算法主要包括两个步骤,并且迭代的执行。
假设我们拥有 N N N个结点的加权网络,首先将每个node视作一个单独的community。
随后对每一个node i i i,考虑加入邻居结点 j j j所在的社区(对初始情况来说也就是加入自己,也就是1个结点的社区变为2个结点的社区)
考虑加入 i i i之后的 j j j社区模块度收益,如果收益高,就加入,如果不高就换个邻居。
文中提到的是使用最大的增益的一个结点增加进入。并且仅有增加的情况会加入。如果都是负的,就不改变了。
上述步骤对所有的结点执行,直到没有任何的结点可以进行加入了repeatly and sequentially,笔者:有些算法解析会说一开始随机选择,但原论文并非如此,结果是稳定的。但是这肯定并非是最优解,因为算法依赖于结点计算的顺序,但是文中又又说了对性能影响不大,会影响计算时间。。这就是图1中Modularity Optimization结束的那个标颜色的结点图。
由于考虑邻居,某一个点可能会被重复的考虑,因此文中也指出,结点会被经常性的重复计算和考虑。
当达到最大的local模块度时笔者:我的理解是,对于任何的一个子community,都无法再添加结点进入使其增加模块度了,此时就是最大的local modularity
计算模块度增益的公式如下
Δ Q = [ ∑ i n + k i , i n 2 m − ( ∑ t o t + k i 2 m ) 2 ] − [ ∑ i n 2 m − ( ∑ t o t 2 m ) 2 − ( k i 2 m ) 2 ] \Delta Q=\left[\frac{\sum_{i n}+k_{i, i n}}{2 m}-\left(\frac{\sum_{t o t}+k_{i}}{2 m}\right)^{2}\right]-\left[\frac{\sum_{i n}}{2 m}-\left(\frac{\sum_{t o t}}{2 m}\right)^{2}-\left(\frac{k_{i}}{2 m}\right)^{2}\right] ΔQ=[2m∑in+ki,in−(2m∑tot+ki)2]−[2m∑in−(2m∑tot)2−(2mki)2]
其中:
1 i i i是node, C C C是 j j j所在的community
2 ∑ i n \sum_{in} ∑in是 C C C之中所有的连接权重之和
3 ∑ t o t \sum_{tot} ∑tot是所有与 C C C内结点有连接的连接权之和
4 k i , i n k_{i, in} ki,in是从 i i i到 C C C中的内部结点之和
5 m m m是整个网络中的连接权重之和
分析这个公式。
前部分是 i i i加入 C C C对社区 C C C带来的增益,后半部分是社区 C C C的未加 i i i结点的情况。
1 ∑ i n + k i , i n 2 m \frac{\sum_{i n}+k_{i, i n}}{2 m} 2m∑in+ki,in是原本内部的连接权重,加上新增的 i i i与内部的连接权重
2 ( ∑ t o t + k i 2 m ) 2 \left(\frac{\sum_{t o t}+k_{i}}{2 m}\right)^{2} (2m∑tot+ki)2部分是新增了 i i i后 C C C社区增加需要减去的项。对应到原始模块度计算公式中,就是考虑了 δ \delta δ函数的 ∑ i j A i j \sum_{ij}A_{ij} ∑ijAij
3 后面部分对应上述为加 i i i的模块度算法解析
4 最后的 ( k i 2 m ) 2 (\frac{k_i}{2m})^{2} (2mki)2代表的是 i i i结点单独成为一个社区的模块度影响。
来一手化神奇为腐朽把
Δ Q = [ ∑ i n + k i , i n 2 m − ( ∑ t o t + k i 2 m ) 2 ] − [ ∑ i n 2 m − ( ∑ t o t 2 m ) 2 − ( k i 2 m ) 2 ] = ∑ i n + k i , i n 2 m − ( ∑ t o t 2 m ) 2 − ( k i 2 m ) 2 − ( 2 ∑ t o t ∗ k i 2 m ) − ∑ i n 2 m + ( ∑ t o t 2 m ) 2 + ( k i 2 m ) 2 = ∑ i n + k i , i n 2 m − ( 2 ∑ t o t ∗ k i 2 m ) − ∑ i n 2 m \begin{aligned} &\Delta Q=\left[\frac{\sum_{i n}+k_{i, i n}}{2 m}-\left(\frac{\sum_{t o t}+k_{i}}{2 m}\right)^{2}\right]-\left[\frac{\sum_{i n}}{2 m}-\left(\frac{\sum_{t o t}}{2 m}\right)^{2}-\left(\frac{k_{i}}{2 m}\right)^{2}\right]\\ &=\frac{\sum_{i n}+k_{i, i n}}{2 m}-(\frac{\sum_{t o t}}{2 m})^{2} - (\frac{k_{i}}{2 m})^{2}-(\frac{2\sum_{t o t} * k_{i}}{2 m})-\frac{\sum_{i n}}{2 m} + (\frac{\sum_{t o t}}{2 m})^{2} + (\frac{k_{i}}{2 m})^{2}\\ &= \frac{\sum_{i n}+k_{i, i n}}{2 m}-(\frac{2\sum_{t o t} * k_{i}}{2 m})-\frac{\sum_{i n}}{2 m} \end{aligned} ΔQ=[2m∑in+ki,in−(2m∑tot+ki)2]−[2m∑in−(2m∑tot)2−(2mki)2]=2m∑in+ki,in−(2m∑tot)2−(2mki)2−(2m2∑tot∗ki)−2m∑in+(2m∑tot)2+(2mki)2=2m∑in+ki,in−(2m2∑tot∗ki)−2m∑in
上述项一为加入后模块度的主要增加,二为增加后社区内部想剪去的item,对应就是考虑了 δ \delta δ函数的 − k i k j -k_ik_j −kikj。三为原始社区的模块度非重复项考虑了 δ \delta δ函数的 ∑ i j A i j \sum_{ij}A_{ij} ∑ijAij。
该公式计算的是社区加入 i i i,增加的模块度 △ Q \triangle Q △Q
当然也可以通过计算移除社区内的结点,来计算 △ Q \triangle Q △Q
此时第一步骤已经完结了,第二个阶段会将所有的community转换成新的node,具体:
1 同一个社区下,之间结点的link会变成自连接
2 不同社区的link 会根据其内node间的权重合并
算法有特别多的好处,容易实现,直觉的,无监督,非常非常的快速。
后面实验这边就不看了,主要是探究Louvain的前世今身
总结下来有一些特点吧:
原本node变为自连接,这个需要再去看看代码
邻居的选取是顺序的
模块度的优化和计算需要再细一些。