对复杂网络进行社区划分,需要有一些评价指标,来评判算法对网络划分结果的好坏优劣。如果我们预先知道网络的真实划分结果,那么我们可以用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 的边数量。
于是,作者定义了第一版模块度的概念:
例如下面的网络,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.
那么上述模块度定义就可以表示为:
虽然推导过程非常复杂,但是最终形式非常简单,代码自然也清晰易懂。
#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