社交媒体网络分析,如识别兴趣小组或朋友圈 网络生物学研究,如在蛋白质相互作用网络中寻找功能模块、细胞聚类等 信息检索,用于在文档网络中找到主题聚类 甚至在网络路由优化、城市规划等领域也有潜在应用
一、算法摘要
二、官方资料汇总
Leidenalg的官方社区提供了丰富的资源,包括文档、教程和问题解答。如果你在使用过程中遇到问题,可以访问[Leidenalg的GitHub页面],https://github.com/vtraag/leidenalg-python),那里有一个问题跟踪器,你可以在那里提问或搜索已有的问题。
说明文档:https://readthedocs.org/projects/leidenalg/downloads/pdf/latest/
Github链接:https://github.com/vtraag/leidenalg
论文链接:https://arxiv.org/pdf/1810.08473
官方手册:https://leidenalg.readthedocs.io/en/stable/intro.html
官方文档:https://leidenalg.readthedocs.io/en/stable/advanced.html#fixed-nodes
三、对Louvain的优化
1、运行速度更快
2、改善不良连接
四、算法原理详解
a)每个节点单独作为一个社区
b)首先进行节点的移动以得到社区划分
c)接着进行Refine,得到细化的社区划分
d)然后基于细化划分创建聚合网络 ,并使用非细化划分创建聚合网络的初始划分,例如,b) 中的红色社区被细化为 c) 中的两个子社区,在聚合后成为它们变成了 d) 中的两个独立节点,这两个节点都属于同一个社区
e)进一步,Leiden 移动聚合网络中的各个节点 e)在上图的情况下,细化不改变社区划分 f)
1、局部移动节点
从队列最前端移除一个节点。 将该节点分配至能获得最大模块度增益(ΔQ)的不同社区;如果加入任何社区都不能获得大于 0 的增益,则保留该节点在原社区。 如果该节点被移动到另一个社区,将所有不属于该节点新社区且不在队列中的邻居节点添加到队列尾端(因为要访问所有变化了的邻居节点)。
2、社区优化(Refine步骤)
refine:精炼;改进;改善;提纯;使精练;去除杂质;
3、社区压缩
4、算法优缺点
高效性:Leiden算法在处理大规模图时表现出良好的效率,可以快速找到图中的社区结构。 可扩展性:该算法可以处理具有不同分辨率参数的图,并且能够适应不同类型的网络结构。 鲁棒性:Leiden算法对于噪声和局部连接的影响相对较小,能够在一定程度上保持稳健性。
分辨率参数选择:Leiden算法对于分辨率参数的选择比较敏感,不同的参数可能导致不同的社区结构,因此需要谨慎选择参数。 局部最优解:算法可能陷入局部最优解,特别是在处理具有多个重叠社区的复杂网络时,可能无法找到全局最优解。 对初始分区敏感:Leiden算法对初始分区的选择比较敏感,不同的初始分区可能导致不同的结果,因此需要对初始分区进行一定的处理和调整。
五、 算法的应用
1、算法安装
pip install cairocffi
pip install leidenalg
pip install python-igraph
initial_membership=None,
weights=None,
n_iterations=2,
max_comm_size=0,
seed=None,
**kwargs
)
graph (ig.Graph):需要进行社区发现的目标图数据结构,该参数类型应为 ig.Graph。 partition_type (type of :class:):用于优化的社区划分类型,例如 ModularityVertexPartition(模块度优化)或CPMVertexPartition (CPM 算法),MutableVertexPartition、SurpriseVertexPartition、RBERVertexPartition等 initial_membership (list of int):初始社区划分,以整数列表形式提供,列表长度应与图中节点数相同,每个元素代表对应节点所属的社区编号。如果为 None,则默认为每个节点各自形成一个独立社区。 weights (list of double, or edge attribute):边的权重。可以是一个浮点数列表,也可以是图对象的边属性名称。如果不指定,则默认所有边的权重为 1。 n_iterations (int):Leiden 算法的迭代次数。默认值为 2。如果设置为负数,则算法会一直运行,直到某次迭代不再改进社区结构为止。 max_comm_size (non-negative int):社区大小的最大限制,即一个社区最多允许包含的节点数量。默认为 0,表示对社区大小没有限制。 seed (int):随机数种子,用于确保算法结果的可重复性。默认情况下,如果不指定种子,则会使用随机种子。 kwargs:传递给 partition_type 构造函数的其他参数,例如 resolution_parameter(分辨率参数)。
leidenalg.find_partition_multiplex(graphs, partition_type,
layer_weights=None, n_iterations=2,
max_comm_size=0, seed=None, **kwargs)
leidenalg.find_partition_temporal(graphs, partition_type, interslice_weight=1,
slice_attr='slice',vertex_id_attr='id', edge_type_attr='type', weight_attr='weight',
n_iterations=2, max_comm_size=0, seed=None, **kwargs)
import numpy as np
import igraph as ig
import leidenalg as la
# 创建一个简单的网络
g = ig.Graph.Famous('Zachary')
# 计算社区分配
partition = la.find_partition(g, la.ModularityVertexPartition)
# 打印社区分配结果
print(partition)
Clustering with 34 elements and 4 clusters
[0] 8, 9, 14, 15, 18, 20, 22, 26, 29, 30, 32, 33
[1] 0, 1, 2, 3, 7, 11, 12, 13, 17, 19, 21
[2] 23, 24, 25, 27, 28, 31
[3] 4, 5, 6, 10, 16
# 简单的可视化
ig.plot(partition)
partition = la.find_partition(g,
la.CPMVertexPartition,
resolution_parameter = 0.05
)
ig.plot(partition)
3、分辨率调整
# 使用不同的分辨率参数
partition_high = find_partition(g, bin_method='infomap', resolution=0.3)
partition_low = find_partition(g, bin_method='infomap', resolution=1.0)
# 打印不同分辨率下的社区分配结果
print("High resolution partition:")
print(partition_high)
print("Low resolution partition:")
print(partition_low)
partition = la.find_partition(g,
la.CPMVertexPartition,
resolution_parameter = 0.05
)
ig.plot(partition)
resolution_parameter = 0.05
resolution_parameter = 0.2
resolution_parameter = 0.6
4、限制社区规模
# 限定最大子社区规模为10
partition = la.find_partition(G,
la.ModularityVertexPartition,
max_comm_size=10
)
5、提取子图
import leidenalg as la
import igraph as ig
# 创建一个示例图
g = ig.Graph.Famous("Zachary")
#print(g)
# 应用 Leiden 算法进行社区检测
partition = la.find_partition(g, la.ModularityVertexPartition)
# 打印每个节点所属的社区
print(partition.membership)
# 提取第一个社区作为子图
subgraph = g.subgraph(partition[0])
# 打印子图信息
print(subgraph.vcount()) # 节点数量
print(subgraph.ecount()) # 边数量
# 全图可视化
ig.plot(partition)
# 子图可视化
ig.plot(g.subgraph(partition[3]))
#假设你已经有了 leiden 分区的结果,并且 G 是一个 igraph.Graph 对象
modularity = partition.quality()
modularity
0.4197896120973044
6、增量更新
new_membership = list(range(G2.vcount()))
new_membership[:G.vcount()] = partition.membership
new_partition = la.CPMVertexPartition(G2,
new_membership,
resolution_parameter=partition.resolution_parameter
)
is_membership_fixed = [i < G.vcount() for i in range(G2.vcount())]
diff = optimiser.optimise_partition(partition,
is_membership_fixed=is_membership_fixed
)
六、Leiden算法实战
1、数据读取
#读取前两列
import networkx as nx
import pandas as pd
import numpy as np
import igraph as ig
import leidenalg as la
data = pd.read_csv('email.edgelist.txt',delimiter='\t',header=None)
data = data.iloc[1:,:2]
data.columns = ['src','dst']
data
2、数据构图
# 创建一个igraph的空图
g = ig.Graph()
da = data[['src','dst']].values
# 边构建
edges = []
for num in range(len(da)):
edges.append((da[num,0],da[num,1]))
# 节点构建
nodes = set(data['src'].astype('str').tolist()+data['dst'].astype('str').tolist())
for node in nodes:
g.add_vertex(node)
g.add_edges(edges)
3、社群检测
# 计算社区分配
partition = la.find_partition(g,
la.ModularityVertexPartition
)
# 创建一个新的DataFrame来存储节点Label及其模块化社区编号
com = pd.DataFrame({"group_id": g.vs['name'],
"Community": partition.membership
})
com.head()
com.groupby('GroupID').count().sort_values(by='User_ID', ascending=False) .head(120)
sub_g = partition.subgraph(112)
sub_g.vcount()
4、社群可视化
import igraph as ig
import matplotlib.pyplot as plt
sub_g = partition.subgraph(73)
ax = plt.subplots(figsize=(12, 12))
ig.plot(sub_g,
#bbox=(500, 500),
target = ax,
vertex_color="lightblue",
vertex_shape='circle',
vertex_frame_color='red',
vertex_frame_width=0.8,
vertex_label=range(sub_g.vcount()),
vertex_label_size = 8,
#edge_color='gray',
edge_width = 0.1,
layout_kamada_kawai='kk',
#margin=10,
vertex_size=18
)
plt.show()
往期精彩:
SynchroTrap-基于松散行为相似度的欺诈账户检测算法