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

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 秒;可以修改参数后重新运行。