节点同配性系数和相关性度量#

在本教程中,我们将探讨同配性 [1] 的理论及其度量。

我们将重点介绍 NetworkX 中提供的同配性度量,位于 algorithms/assortativity/correlation.py

  • 属性同配性

  • 数值同配性

  • 度同配性

以及与同配性度量密切相关的混合矩阵。

导入包#

import networkx as nx
import matplotlib.pyplot as plt
import pickle
import copy
import random
import warnings

%matplotlib inline

同配性#

网络中的同配性指的是节点倾向于连接其他“相似”节点而非“不相似”节点的趋势。

这里我们说两个节点在一个属性上“相似”,是指它们拥有相同的属性值。属性可以是任何结构属性,例如节点的度,也可以是其他属性,例如权重或容量。

基于这些属性,我们可以为网络提供不同的同配性度量。另一方面,我们也可以有异配性,在这种情况下,节点倾向于连接不相似的节点而不是相似的节点。

同配性系数#

假设我们有一个网络 \(N\)\(N = (V, E)\),其中 \(V\) 是网络中的节点集合,\(E\) 是网络中的边/有向边集合。此外,\(P(v)\) 表示每个节点 \(v\) 的一个属性。

混合矩阵#

设属性 \(P(v)\) 在网络中取 \(P[0],P[1],...P[k-1]\) 个不同的值,则**混合矩阵**是矩阵 \(M\),其中 \(M[i][j]\) 表示从属性为 \(P[i]\) 的节点到属性为 \(P[j]\) 的节点的边数。我们可以通过除以有序边的总数来归一化混合矩阵,即 \( e = \frac{M}{|E|}\)。

现在定义,

\(a[i]=\)\((u,v)\) 中满足 \(P(u)=P[i]\) 的比例

\[ a[i] = \sum\limits_{j}e[i][j] \]

\(b[i]=\)\((u,v)\) 中满足 \(P(v)=P[i]\) 的比例

\[ b[i] = \sum\limits_{j}e[j][i]\]

在 Python 代码中,它看起来像 a = e.sum(axis=0)b = e.sum(axis=1)

最后,让 \(\sigma_a\)\(\sigma_b\) 分别代表 \(\{\ P[i]\cdot a[i]\ |\ i \in 0...k-1\}\)\(\{ P[i]\cdot b[i]\ |\ i \in 0...k-1\}\) 的标准差。

然后我们可以根据皮尔逊相关系数定义该属性的同配性系数。

属性同配性系数#

这里属性 \(P(v)\) 是分配给每个名义节点的属性。如上所述,我们计算归一化混合矩阵 \(e\),并由此定义属性同配性系数 [2] 如下。

从现在开始,我们将使用下标表示法来表示索引,例如 \(P_i = P[i]\)\(e_{ij} = e[i][j]\)

\[ r = \frac{\sum\limits_{i}e_{ii} - \sum\limits_{i}a_{i}b_{i}}{1-\sum\limits_{i}a_{i}b_{i}} = \frac{Trace(e) - ||e^2||}{1-||e^2||}\]

它通过 attribute_assortativity_coefficient 实现。

数值同配性系数#

这里属性 \(P(v)\) 是分配给每个节点的数值属性,归一化混合矩阵 \(e\)\(\sigma_a\)\(\sigma_b\) 的定义与上文相同。由此我们定义数值同配性系数 [2] 如下。

\[ r = \frac{\sum\limits_{i,j}P_i P_j(e_{ij} -a_i b_j)}{\sigma_a\sigma_b} \]

它通过 numeric_assortativity_coefficient 实现。

度同配性系数#

对于有向网络的度同配性测量,与属性同配性相比,我们有更多选项,因为我们有两种类型的度,即入度和出度。基于这两种类型的度,我们可以测量 \(2 \times 2 =4\) 种不同类型的度同配性 [3]

  1. r(in,in):衡量存在有向边 (u,v) 且入度(u) = 入度(v) 的趋势。

  2. r(in,out):衡量存在有向边 (u,v) 且入度(u) = 出度(v) 的趋势。

  3. r(out,in):衡量存在有向边 (u,v) 且出度(u) = 入度(v) 的趋势。

  4. r(out,out):衡量存在有向边 (u,v) 且出度(u) = 出度(v) 的趋势。

注意:如果网络是无向的,则所有这 4 种类型的度同配性是相同的。

为了定义所有 4 种类型的度同配性系数,我们需要对 \(P[i]\)\(e\) 的定义进行微小修改,而 \(\sigma_a\)\(\sigma_b\) 的定义保持不变。

\(x,y \in \{in,out\}\)。属性 \(P(\cdot)\) 取自 \(x\)-度\((\cdot)\)\(y\)-度\((\cdot)\) 所取值的并集中的不同值,而 \(e_{i,j}\) 是有向边 \((u,v)\) 中满足 \(x\)-度\((u) = P_i\)\(y\)-度\((v) = P_j\) 的比例。

\[ r(x,y) = \frac{\sum\limits_{i,j}P_i P_j(e_{ij} -a_i b_j)}{\sigma_a\sigma_b} \]

它通过 degree_assortativity_coefficientdegree_pearson_correlation_coefficient 实现。后一个函数使用 scipy.stats.pearsonr 计算同配性系数,这可能使其更快。

同配性示例#

说明同配性值的变化方式

gname = "g2"
G = nx.read_graphml(f"data/{gname}.graphml")
with open(f"data/pos_{gname}", "rb") as fp:
    pos = pickle.load(fp)
fig, axes = plt.subplots(4, 2, figsize=(20, 20))

# assign colors and labels to nodes based on their 'cluster' and 'num_prop' property
node_colors = ["orange" if G.nodes[u]["cluster"] == "K5" else "cyan" for u in G.nodes]
node_labels = {u: G.nodes[u]["num_prop"] for u in G.nodes}

for i in range(8):
    g = nx.read_graphml(f"data/{gname}_{i}.graphml")

    # calculating the assortativity coefficients wrt different proeprties
    cr = nx.attribute_assortativity_coefficient(g, "cluster")
    r_in_out = nx.degree_assortativity_coefficient(g, x="in", y="out")
    nr = nx.numeric_assortativity_coefficient(g, "num_prop")

    # drawing the network
    nx.draw_networkx_nodes(
        g, pos=pos, node_size=300, ax=axes[i // 2][i % 2], node_color=node_colors
    )
    nx.draw_networkx_labels(g, pos=pos, labels=node_labels, ax=axes[i // 2][i % 2])
    nx.draw_networkx_edges(g, pos=pos, ax=axes[i // 2][i % 2], edge_color="0.7")
    axes[i // 2][i % 2].set_title(
        f"Attribute assortativity coefficient = {cr:.3}\nNumeric assortativity coefficient = {nr:.3}\nr(in,out) = {r_in_out:.3}",
        size=15,
    )

fig.tight_layout()
/home/circleci/repo/venv/lib/python3.12/site-packages/networkx/algorithms/assortativity/correlation.py:302: RuntimeWarning: invalid value encountered in scalar divide
  return float((xy * (M - ab)).sum() / np.sqrt(vara * varb))
../../../_images/3e6bd655aede16866e1ee4894fe5382987d400bca567b600288f44d9b7039d08.png

节点根据 cluster 属性着色,并根据 num_prop 属性标记。我们可以观察到,左侧的初始网络是完全同配的,而右侧的其补图是完全异配的。随着我们在同配(异配)网络中添加具有不同(相似)属性的节点之间的边,网络趋向于非同配网络,并且两个同配性系数的值都趋向于 \(0\)

attribute_assortativity_coefficientnumeric_assortativity_coefficient 中的参数 nodes 指定了哪些节点的边将被考虑用于计算混合矩阵。也就是说,如果 \((u,v)\) 是一条有向边,则当 \(u\)nodes 中时,边 \((u,v)\) 将被用于计算混合矩阵。对于无向情况,如果 \(u\)\(v\) 中至少有一个在 nodes 中,则考虑该边。

degree_assortativity_coefficientdegree_pearson_correlation_coefficient 中,nodes 参数的解释不同,它指定了构成一个子图的节点,这些子图的边将被考虑用于计算混合矩阵。

# list of nodes to consider for the i'th network in the example
# Note: passing 'None' means to consider all the nodes
nodes_list = [
    None,
    [str(i) for i in range(3)],
    [str(i) for i in range(4)],
    [str(i) for i in range(5)],
    [str(i) for i in range(4, 8)],
    [str(i) for i in range(5, 10)],
]
fig, axes = plt.subplots(3, 2, figsize=(20, 16))


def color_node(u, nodes):
    """Utility function to give the color of a node based on its attribute"""
    if u not in nodes:
        return "0.85"
    if G.nodes[u]["cluster"] == "K5":
        return "orange"
    else:
        return "cyan"


# adding a edge to show edge cases
G.add_edge("4", "5")

for nodes, ax in zip(nodes_list, axes.ravel()):
    # calculating the value of assortativity
    cr = nx.attribute_assortativity_coefficient(G, "cluster", nodes=nodes)
    nr = nx.numeric_assortativity_coefficient(G, "num_prop", nodes=nodes)

    # drawing network
    ax.set_title(
        f"Attribute assortativity coefficient: {cr:.3}\nNumeric assortativity coefficient: {nr:.3}\nNodes = {nodes}",
        size=15,
    )
    if nodes is None:
        nodes = [u for u in G.nodes()]
    node_colors = [color_node(u, nodes) for u in G.nodes]
    nx.draw_networkx_nodes(G, pos=pos, node_size=450, ax=ax, node_color=node_colors)
    nx.draw_networkx_labels(G, pos, labels={u: u for u in G.nodes}, font_size=15, ax=ax)
    nx.draw_networkx_edges(
        G,
        pos=pos,
        edgelist=[(u, v) for u, v in G.edges if u in nodes],
        ax=ax,
        edge_color="0.3",
    )
fig.tight_layout()
/home/circleci/repo/venv/lib/python3.12/site-packages/networkx/algorithms/assortativity/correlation.py:282: RuntimeWarning: invalid value encountered in scalar divide
  r = (t - s) / (1 - s)
../../../_images/d71dc4203d082bf161d150bf4fa5b5d6d22c4de457c1c9554cbc804f1cbec78a.png

在上述图中,只有被考虑的节点被着色,其余节点被灰显,并且只绘制了在同配性计算中被考虑的边。

参考文献#