模块度Q——复杂网络社区划分评价标准

  对复杂网络进行社区划分,需要有一些评价指标,来评判算法对网络划分结果的好坏优劣。如果我们预先知道网络的真实划分结果,那么我们可以用NMI(归一化互信息)去衡量算法划分结果和真实结果的重合程度,这个会在以后的文章中具体介绍。大多数情况下,我们是不知道网络的真实划分的,尤其是对于大型网络来说更是如此,复杂网络的命名明确的说明了这种现实情况。但是我们依然有方法可以量化或评判我们的社区划分水平,也就是今天要介绍的模块度(Modularity)概念,也称Q值。
  从网上看到其他同学写的博客,首先对这方面介绍的不多,仅有的一些文章也是有好有坏,所以决定自己梳理一下,也是对其他人的分享。

资料

  这次,先贴链接:
  wiki:https://en.wikipedia.org/wiki/Modularity_(networks) 一定要搜英文的,中文版的并没有什么信息量。
  原定义作者论文:Finding and evaluating community structure in networks (1)
          Modularity and community structure in networks (2)
  一篇认为介绍的比较好的文章:Community Detection – Modularity的概念
  建议是:看一下那篇博客,再看一下wiki,然后看一下原作者论文定义。
  当然,也可以只看我的文章~O(∩_∩)O哈哈~。
  之所以选择那篇博客是因为该作者从历史演进角度介绍了模块度概念的由来及变化,从方法论上来说,认识历史可以更好的认识现在,这几乎可以套用在对任何事物的认识上面。。。扯远了
  

定义

  我这里大概以通俗的语言翻译一下,严格的定义还是要看论文的,
  定义一:
  最早由Newman在文章(1)中给出的模块度的概念:
   Consider a particular division of a network into k communities. Let us define a k ×k symmetric matrix e whose element eij is the fraction of all edges in the network that link vertices in community i to vertices in community j.
   假设网络被划分为 k 个社区,那么定义一个 k×k 的对称矩阵 e ,它的元素 eij 表示社区 i 和社区 j 之间的边的数量。
  
  The trace of this matrix Tre=ieii gives the fraction of edges in the network that connect vertices in the same community, and clearly a good division into communities should have a high value of this trace.
  矩阵的迹 Tre=ieii ,也就表示了在相同社区内节点之间的边集合。显然,社区划分的好,也就是社区内部节点之间联系密集,那么该值就越高,这与我们通常对社区的认识是一致的。
  作者也指出,仅通过矩阵的迹这个值不能完全反应社区结构,因为如果把网络仅划分成1个社区的话,那么会导致 Tre=1

  So we further define the row (or column) sums ai=jeij , which represent the fraction of edges that connect to vertices in community i
  因此又定义了一个值 ai=jeij,表示所有连接到社区 i 的边数量。
  于是,作者定义了第一版模块度的概念:
  

Q=i(eiia2i)=Tre||e2||

   ||x|| 表示矩阵 x 的所有元素的和。
  简单展开一下上面的公式会更清晰:
  
Q=i(eiia2i)=ieiiia2i=Tre||e2||(1)

  例如下面的网络,10个节点,12条边,被分成3个社区:
 这里写图片描述
  根据上述定义生成的社区矩阵为:
  这里写图片描述
  模块度 Q=3+3+412(72×12)2(72×12)2(102×12)2=0.49

  定义二:
  再来看第二版定义:
  Newman在论文(2)中更新了模块度Q的定义,增加了矩阵的表达,感觉更不直观了。
  个人感觉从wiki里的定义理解更清楚一些,下面是一些定义及推导:
  Modularity is the fraction of the edges that fall within the given groups minus the expected such fraction if edges were distributed at random.
  模块度 = (落在同一组内的边的比例) 减 (对这些边进行随机分配所得到的概率期望)
  为了说明上述公式,对定义如下内容:
  假设网络有 n 个节点,有m条边,节点 v 的度表示为kv
  将网络的邻接矩阵表示为 A Avw=0 表示节点 v w之间没有边, Avw=1 表示有边。
  定义变量 s svw=1表示 v w属于同一社区, svw=1 表示不在同一社区,那么可以用 δvw=12(svw+1) 量化表示 v w是否在同一社区,如果是则等于1,不是则等于0.
  那么上述模块度定义就可以表示为:
  

Q=12vwAvwmδvw

   vwAvwδvw/m 表示在同一社区内的边的数量占所有边数量的比例, 乘以 1/2 ,是因为对每条边计算过两次。
  
  以上这部分计算很清楚,下面主要看那个期望值如何计算。
  这里面用到了Configuration Models,大体意思就是,对网络的边进行随机分配,需要将每条边切断一分为二,切断的点我们称作末梢点(stub),这样 m 条边就会产生ln=2m=nv=1kv个末梢点,随机的将这 ln 个末梢点进行连接,包括同一节点拥有的末梢点的自连接。这样可以保持每个节点原有的度不变的条件下,可以得到一个完全随机网络。
  在该随机网络下,任意两点 vw 连接边数的期望值是: expvw=kvkwln=kvkw2m
  因此,节点 v w的实际边数与随机网络下边数期望之差为: Avwkvkw2m
  模块度最终可表示为:
Q=12mvw(Avwkvkw2m)δvw(2)

  定义 eij 表示连接社区 i j 的边的总数, eij=vwAvw2mδviδwj ai 表示连接 社区 i 的边的总数,ai=jeij=ki2m,那么模块度可以表示为:
Q=12mvwAvwδvw12mvwkvkw2mδvw=i=1c(eiia2i)

  
  可以看到,虽然初始含义不同,但经过推导,模块度的公式(1)和公式(2)具有一致的表现形式,而且最终的结果非常简单。
  应当注意,模块度的取值范围为: [1/2,1) ,有可能得到负值。
  

代码实现

  虽然推导过程非常复杂,但是最终形式非常简单,代码自然也清晰易懂。

#python2.7
#type(graph) = networkx.Graph
def Q(graph, cluster):
    e = 0.0
    a_2 = 0.0
    cluster_degree_table = {}
    for vtx, adj in graph.edge.iteritems():
        label = cluster[vtx]
        for neighbor in adj.keys():
            if label == cluster[neighbor]:
                e += 1
        if label not in cluster_degree_table:
            cluster_degree_table[label] =0
        cluster_degree_table[label] += len(adj)
    e /= 2 * graph.number_of_edges()

    for label, cnt in cluster_degree_table.iteritems():
        a = 0.5 * cnt / graph.number_of_edges()
        a_2 += a * a

    Q = e - a_2
    return Q
  • 75
    点赞
  • 254
    收藏
    觉得还不错? 一键收藏
  • 41
    评论
### 回答1: 你可以使用 NetworkX 库来实现网络模块计算。 NetworkX 是一个用于创建、操作、以及分析复杂网络的 Python 库。它提供了计算网络模块的函数,可以帮助您在 Python 中简单地计算网络模块。 以下是一个简单的示例代码: ```python import networkx as nx # 创建一个图 G = nx.karate_club_graph() # 计算模块 modularity = nx.algorithms.community.modularity_max.modularity_max(G, weight='weight') print("网络模块:", modularity) ``` 在这段代码中,我们首先导入了 NetworkX 库,然后创建了一个图,最后使用 `modularity_max` 函数计算了该图的模块。 希望这对您有所帮助! ### 回答2: 要基于Python实现网络社区模块计算代码,可以使用以下步骤进行实现: 1. 导入所需的库:导入networkx库用于构建和处理网络图。 2. 构建网络图:使用networkx库中的Graph对象构建网络图。可以通过增加节点和边来表示社区关系。 3. 计算社区模块社区模块是评估社区结构的指标,用于衡量节点在网络图中的聚类情况。可以使用以下方法来计算模块: - 定义计算模块的函数。 - 遍历网络图中的每个节点。 - 计算节点所属社区内的数和社区内边的权重之和。 - 计算节点的数和总边的权重之和。 - 计算模块。 以下是一个简单的基于Python的网络社区模块计算代码示例: ```python import networkx as nx def compute_modularity(graph): degree_dict = dict(graph.degree(weight='weight')) total_edge_weight = graph.size(weight='weight') modularity = 0 for community in nx.connected_components(graph): subgraph = graph.subgraph(community) internal_weight = subgraph.size(weight='weight') external_weight = degree_dict[subgraph.nodes] - internal_weight modularity += internal_weight / total_edge_weight - (external_weight / (2 * total_edge_weight)) ** 2 return modularity # 构建网络图 graph = nx.Graph() graph.add_nodes_from(["A", "B", "C", "D", "E"]) graph.add_edges_from([("A", "B"), ("B", "C"), ("C", "D"), ("D", "E"), ("E", "A")]) # 计算社区模块 modularity = compute_modularity(graph) print("Modularity:", modularity) ``` 这段代码演示了如何通过网络图计算社区模块。首先,构建了一个包含5个节点和5条边的网络图。然后,使用`compute_modularity`函数计算了该网络图的社区模块,并将结果打印输出。 请注意,这只是一个简单的示例,具体的实现可能需要根据实际应用情况进行调整和扩展。 ### 回答3: 基于Python的网络社区模块计算代码可以通过以下步骤实现: 1. 导入所需的库:首先,需要导入NetworkX库(用于创建和分析网络)和Community库(用于社区检测)。 2. 创建网络:使用NetworkX库创建一个无向图网络,这可以通过添加节点和边来完成。节点代表社区成员,边代表节点之间的连接关系。 3. 检测社区:使用Community库中的算法,如Louvain算法或GN算法,来检测网络中的社区结构。这些算法将网络分割为不同的社区。 4. 计算模块:定义一个函数来计算网络的模块模块是一种评估社区结构质量的指标,它衡量网络中社区之间的紧密程和节点在同一社区内联系的程。可以使用以下公式来计算模块: Modularity = 社区内连接数 / 总连接数 - (社区内节点数之和 / (2 * 总连接数)^2) 5. 打印结果:将计算得到的模块输出打印出来,以便进一步分析和比较。 下面是一个简单示例: ```python import networkx as nx import community # 创建网络 G = nx.Graph() G.add_edges_from([(1, 2), (1, 3), (2, 3), (3, 4), (4, 5), (4, 6), (5, 6)]) # 检测社区 partition = community.best_partition(G) # 计算模块 modularity = community.modularity(partition, G) # 打印结果 print("Modularity:", modularity) ``` 以上是基于Python的网络社区模块计算代码的简单示例。根据具体的网络数据和需求,你可以使用更复杂的数据集和算法来进行社区检测和模块计算。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 41
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值