生物医学网络科学Biomedical Network Science
Example01 / 10

相关网络与偏相关网络

所属专题
症状网络与网络精神病学
下载
Notebook · .py

由相关矩阵求精度矩阵 K,偏相关 pcor_ij = -K_ij / sqrt(K_ii K_jj)。 分别统计 |r| > 0.1 与 |pcor| > 0.1 的边数,与真实网络的 10 条边比较。 输出解读:相关网络把间接关联也画成了边,边数明显多于真实边;偏相关网络更接近真实结构。 例如“睡眠问题–注意力差”只经由“疲乏”相关,相关系数不为 0,偏相关接近 0。

Output输出图

相关网络与偏相关网络:输出图 1

Output文字输出

真实边数: 10
相关网络 |r| > 0.1 的边数: 17
偏相关网络 |pcor| > 0.1 的边数: 10 ;其中真实边 10 条,虚假边 0 条
例:睡眠问题–注意力差  r = 0.23,pcor = 0.04(真实网络中无直接边)

Code代码

# 由相关矩阵求精度矩阵 K,偏相关 pcor_ij = -K_ij / sqrt(K_ii K_jj)。
# 分别统计 |r| > 0.1 与 |pcor| > 0.1 的边数,与真实网络的 10 条边比较。
# 输出解读:相关网络把间接关联也画成了边,边数明显多于真实边;偏相关网络更接近真实结构。
# 例如“睡眠问题–注意力差”只经由“疲乏”相关,相关系数不为 0,偏相关接近 0。
import numpy as np

names = ["兴趣减退", "情绪低落", "睡眠问题", "疲乏", "食欲改变",
         "自我评价低", "注意力差", "精神运动改变", "自杀意念"]
TRUE_EDGES = {(0, 1): .40, (1, 5): .30, (1, 8): .25, (5, 8): .25, (2, 3): .40,
              (3, 6): .30, (3, 7): .20, (3, 4): .20, (0, 3): .20, (6, 7): .20}

def simulate_symptoms(n, seed=0):
    """模拟数据,仅用于演示方法:从已知偏相关结构的多元正态分布抽样。"""
    K = np.eye(9)
    for (i, j), w in TRUE_EDGES.items():
        K[i, j] = K[j, i] = -w          # 精度矩阵负的非对角元 → 正偏相关
    rng = np.random.default_rng(seed)
    return rng.multivariate_normal(np.zeros(9), np.linalg.inv(K), size=n)

def pcor_from_corr(R):
    K = np.linalg.inv(R)
    d = np.sqrt(np.diag(K))
    P = -K / np.outer(d, d)
    np.fill_diagonal(P, 0)
    return P

X = simulate_symptoms(500)
R = np.corrcoef(X, rowvar=False)
P = pcor_from_corr(R)

iu = np.triu_indices(9, k=1)
true_set = set(TRUE_EDGES)
est = {(i, j) for i, j in zip(*iu) if abs(P[i, j]) > 0.1}
print("真实边数:", len(true_set))
print("相关网络 |r| > 0.1 的边数:", int(np.sum(np.abs(R[iu]) > 0.1)))
print("偏相关网络 |pcor| > 0.1 的边数:", len(est),
      ";其中真实边", len(est & true_set), "条,虚假边", len(est - true_set), "条")
print(f"例:睡眠问题–注意力差  r = {R[2, 6]:.2f},pcor = {P[2, 6]:.2f}(真实网络中无直接边)")

import networkx as nx
import matplotlib.pyplot as plt

def draw_signed(ax, M, labels, thr, title, node_color="#DDDDDD", node_size=180, pos=None):
    """边宽 ∝ |权重|,蓝色为正边、红色为负边。"""
    n = len(labels)
    pos = nx.circular_layout(range(n)) if pos is None else pos
    G = nx.Graph(); G.add_nodes_from(range(n))
    G.add_weighted_edges_from((i, j, M[i, j]) for i in range(n) for j in range(i + 1, n) if abs(M[i, j]) > thr)
    ws = [d["weight"] for _, _, d in G.edges(data=True)]
    nx.draw_networkx_edges(G, pos, ax=ax, width=[max(1.0, 8 * abs(w)) for w in ws],
                           edge_color=["#4477AA" if w > 0 else "#CC6677" for w in ws])
    nx.draw_networkx_nodes(G, pos, ax=ax, node_size=node_size, node_color=node_color, edgecolors="k")
    lab_pos = {k: (1.22 * np.asarray(v)) for k, v in pos.items()}
    nx.draw_networkx_labels(G, lab_pos, labels=dict(enumerate(labels)), ax=ax, font_size=9)
    ax.plot([], [], color="#4477AA", lw=2, label="positive")
    ax.plot([], [], color="#CC6677", lw=2, label="negative")
    ax.legend(loc="lower right", fontsize=7, frameon=False)
    ax.set_title(title, fontsize=10); ax.set_aspect("equal"); ax.axis("off")
    ax.set_xlim(-1.45, 1.45); ax.set_ylim(-1.45, 1.45)

abbr = ["Anh", "Sad", "Slp", "Fat", "App", "Gui", "Con", "Mot", "Sui"]   # PHQ-9 条目英文缩写
fig, axes = plt.subplots(1, 2, figsize=(10, 4.8))
draw_signed(axes[0], R - np.eye(9), abbr, 0.1, f"Correlation |r| > 0.1: {int(np.sum(np.abs(R[iu]) > 0.1))} edges")
draw_signed(axes[1], P, abbr, 0.1, f"Partial correlation |pcor| > 0.1: {len(est)} edges")
plt.tight_layout(); plt.show()

Run在浏览器中运行

首次加载 Python 环境约需 20–40 秒;可以修改参数后重新运行。

相关网络与偏相关网络