模塊度與Louvain社區發現算法


  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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM