社区发现算法 louvain

背景

· 由node和egde形成的网络图中,关系紧密的可以形成一个社区,其内部紧密,与外部连接稀疏。社区发现算法就是要检测网络结构中紧密的社区团。
· 用什么可以描述社团的紧密程度:模块度(modularity), louvain算法的核心思想就是最大化模块度。

模块度

· 以无权重无向图为例(无权重可以看成边权重都是1)
Q = 1 2 m ∑ i , j [ A i , j − k i k j 2 m ] δ ( c i , c j ) Q = \frac{1}{2m}\sum_{i,j}[A_{i,j} - \frac{k_ik_j}{2m}]\delta (c_i,c_j) Q=2m1i,j[Ai,j2mkikj]δ(ci,cj)
其中, A i , j A_{i,j} Ai,j是指示函数,表示i,j之间是否有边; δ ( c i , c j ) \delta (c_i,c_j) δ(ci,cj)也是指示函数,表示i和j是否在一个社群; k k k表示节点的度,也就是和几个node相连; k i k j 2 m \frac{k_ik_j}{2m} 2mkikj表示在随机状态下,i和j相连的概率;
在这里插入图片描述

· Q的公式的化简过程:
Q = 1 2 m ∑ i , j [ A i , j − k i k j 2 m ] δ ( c i , c j ) Q = \frac{1}{2m}\sum_{i,j}[A_{i,j} - \frac{k_ik_j}{2m}]\delta (c_i,c_j) Q=2m1i,j[Ai,j2mkikj]δ(ci,cj)
= 1 2 m [ ∑ i , j A i , j − ∑ k i ∑ k j 2 m ] δ ( c i , c j ) =\frac{1}{2m}[\sum_{i,j}A_{i,j} - \frac{\sum k_i\sum k_j}{2m}]\delta (c_i,c_j) =2m1[i,jAi,j2mkikj]δ(ci,cj)
= 1 2 m ∑ c [ ∑ i n − ( ∑ t o t ) 2 2 m ] =\frac{1}{2m}\sum_{c}[\sum in - \frac{(\sum tot)^2}{2m}] =2m1c[in2m(tot)2]
= ∑ c [ ∑ i n 2 m − ( ∑ t o t 2 m ) 2 ] =\sum_{c}[\frac{\sum in}{2m} - (\frac{\sum tot}{2m})^2] =c[2min(2mtot)2]
其中in表示社团c内部的连接,tot表示社团的节点的所有连接;

louvain算法

1)将图中的每个节点看成一个独立的社区
2)对每个节点 i i i ,依次尝试把节点 i i i 分配到其每个邻居节点所在的社区,计算分配前与分配后的模块度变化 Δ ,并记录 Δ 最大的那个邻居节点,如果 Δ > 0,则把节点 i i i 分配 Δ 最大的那个邻居节点所在的社区,否则保持不变
3)重复2)直到所有节点的所属社区不再变化
4)将所有在同一个社区的节点压缩成一个新节点,社区内节点之间的边的权重转化为新节点的环的权重,社区间的边权重转化为新节点间的边权重
5)重复1)直到整个图的模块度不再发生变化

Δ Q \Delta Q ΔQ = 把i并入c的模块度 - (之前c的模块度 + i作为单独社区的模块度)
所以,
Δ Q = ∑ c [ ∑ i n + k i , i n 2 m − ( ∑ t o t + k i 2 m ) 2 ] − ∑ c [ ∑ i n 2 m − ( ∑ t o t 2 m ) 2 − ( k i 2 m ) 2 ] \Delta Q =\sum_{c}[\frac{\sum in+k_{i,in}}{2m} - (\frac{\sum tot + k_i}{2m})^2] - \sum_{c}[\frac{\sum in}{2m} - (\frac{\sum tot}{2m})^2 - (\frac{k_i}{2m})^2] ΔQ=c[2min+ki,in(2mtot+ki)2]c[2min(2mtot)2(2mki)2]

疑问:如果c有指向自己的边是不是 ∑ i n \sum in in那项不能约掉
全部展开化简后(已手推):
Δ Q = ∑ c [ k i , i n 2 m − ∑ t o t + k i 2 m 2 ] \Delta Q =\sum_{c}[\frac{k_{i,in}}{2m} - \frac{\sum tot + k_i}{2m^2}] ΔQ=c[2mki,in2m2tot+ki]

调包:networkx

pip install python-louvain

#Louvain算法 
import matplotlib.pyplot as plt
import networkx as nx
from community import community_louvain

# 空手道俱乐部
G   = nx.karate_club_graph()

com = community_louvain.best_partition(G)

#节点大小设置,与度关联
node_size = [G.degree(i)**1*20 for i in G.nodes()]


#格式整理
df_com = pd.DataFrame({'Group_id':com.values(),
                       'object_id':com.keys()}
                    )
# 统计每个团伙人数 并降序
df_com.groupby('Group_id').count().sort_values(by='object_id', ascending=False) 


# 颜色设置
colors = ['DeepPink','orange','DarkCyan','#A0CBE2','#3CB371','b','orange','y','c','#838B8B','purple','olive','#A0CBE2','#4EEE94']*500
colors = [colors[i] for i in com.values()]



#使用 kamada_kawai_layout spring_layout 布局
plt.figure(figsize=(4,3),dpi=500)
nx.draw_networkx(G,

                 pos = nx.spring_layout(G),
                 node_color = colors,
                 edge_color = '#2E8B57',
                 font_color = 'black',
                 node_size = node_size,
                 font_size = 5,
                 alpha = 0.9,
                 width = 0.1,
                 font_weight=0.9
                 )
plt.axis('off')  
plt.show()

参考:https://zhuanlan.zhihu.com/p/556291759

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值