NetworkX 2.8.8 实战:Python 构建 ER/WS/BA 三大网络模型,5分钟生成可视化对比图

发布时间:2026/7/11 19:46:18
NetworkX 2.8.8 实战:Python 构建 ER/WS/BA 三大网络模型,5分钟生成可视化对比图 NetworkX 2.8.8 实战Python构建ER/WS/BA三大网络模型与可视化对比1. 复杂网络模型基础认知当我们观察社交网络中的好友关系、互联网中的网页链接或生物体内的蛋白质相互作用时这些系统都可以抽象为复杂网络——由大量节点通过边连接构成的图结构。在理论研究中有三种经典模型构成了复杂网络分析的基石ER随机网络Erdős-Rényi模型就像一场大型社交舞会组织者随机为参与者配对跳舞。假设有N个人参加每对人以概率p共舞。这种完全随机的连接方式会产生度分布近似泊松分布的网络大多数节点的连接数接近平均值。WS小世界网络Watts-Strogatz模型则模拟了真实社交的有趣特性你的大部分朋友彼此也认识高聚类但通过少数社交达人就能联系到远方的人短路径。从规则环状网络出发以概率p重新连接边在保持高聚类的同时显著缩短路径长度。BA无标度网络Barabási-Albert模型揭示了富者愈富现象。新加入网络的节点更倾向于连接已有高度连接的节点导致度分布服从幂律——少数枢纽节点拥有大量连接而大多数节点只有少量连接。import networkx as nx import matplotlib.pyplot as plt # 三大模型生成示例 er nx.erdos_renyi_graph(n30, p0.1) ws nx.watts_strogatz_graph(n30, k4, p0.3) ba nx.barabasi_albert_graph(n30, m2) fig, axes plt.subplots(1, 3, figsize(18, 5)) nx.draw(er, axaxes[0], node_size100); axes[0].set_title(ER随机网络) nx.draw(ws, axaxes[1], node_size100); axes[1].set_title(WS小世界网络) nx.draw(ba, axaxes[2], node_size100); axes[2].set_title(BA无标度网络) plt.show()2. 网络生成与参数配置实战2.1 ER随机网络构建ER模型的核心参数是连接概率p它直接影响网络的平均度〈k〉p(N-1)。当p大于临界值pc≈1/N时网络会出现巨连通分量。def generate_er_network(N, p): 生成ER随机网络 :param N: 节点数量 :param p: 连接概率 :return: NetworkX图对象 G nx.Graph() G.add_nodes_from(range(N)) for i in range(N): for j in range(i1, N): if np.random.random() p: G.add_edge(i, j) return G er_network generate_er_network(1000, 0.01) print(fER网络边数: {er_network.number_of_edges()})2.2 WS小世界网络构建WS模型有三个关键参数N节点数k初始每个节点的邻居数必须为偶数p边重连概率当p0时为规则网络p1时变为随机网络在0.001p0.1区间呈现小世界特性。def generate_ws_network(N, k, p): 生成WS小世界网络 :param N: 节点数 :param k: 初始邻节点数 :param p: 重连概率 :return: NetworkX图对象 if k N or k%2 ! 0: raise ValueError(k必须为偶数且小于N) G nx.Graph() G.add_nodes_from(range(N)) # 初始环形连接 for i in range(N): for j in range(1, k//2 1): G.add_edge(i, (ij)%N) # 边重连过程 for edge in list(G.edges()): if np.random.random() p: u, v edge G.remove_edge(u, v) new_v np.random.choice(list(set(range(N)) - set(G.neighbors(u)) - {u})) G.add_edge(u, new_v) return G ws_network generate_ws_network(1000, 10, 0.1)2.3 BA无标度网络构建BA模型通过优先连接机制生成增长网络初始有m0个节点每次新增一个带m条边的节点新边连接到现有节点i的概率与i的度数成正比def generate_ba_network(N, m): 生成BA无标度网络 :param N: 最终节点数 :param m: 每个新节点的边数 :return: NetworkX图对象 if m 1 or m N: raise ValueError(m必须在[1, N-1]区间) G nx.complete_graph(m) # 初始完全图 for new_node in range(m, N): # 计算现有节点的度分布 degrees dict(G.degree()) total_degree sum(degrees.values()) # 选择连接目标 targets [] while len(targets) m: r random.uniform(0, total_degree) cumulative 0 for node, degree in degrees.items(): cumulative degree if r cumulative and node not in targets: targets.append(node) break # 添加新节点和边 G.add_node(new_node) for target in targets: G.add_edge(new_node, target) return G ba_network generate_ba_network(1000, 3)3. 网络特性量化分析3.1 度分布可视化三大网络的度分布呈现显著差异网络类型度分布特征现实对应ER网络泊松分布峰值在平均度附近随机交友网络WS网络接近Delta函数存在少量长程连接社交关系网络BA网络幂律分布存在高度节点枢纽互联网链接、引文网络def plot_degree_distribution(G, title): degrees [d for n, d in G.degree()] plt.hist(degrees, binsrange(min(degrees), max(degrees)1), densityTrue) plt.title(f{title}度分布) plt.xlabel(度) plt.ylabel(频率) plt.figure(figsize(15,4)) plt.subplot(131); plot_degree_distribution(er_network, ER) plt.subplot(132); plot_degree_distribution(ws_network, WS) plt.subplot(133); plot_degree_distribution(ba_network, BA) plt.tight_layout()3.2 关键指标计算我们使用NetworkX内置函数计算三大核心指标def calculate_metrics(G, name): return { 网络类型: name, 平均路径长度: nx.average_shortest_path_length(G) if nx.is_connected(G) else float(inf), 集聚系数: nx.average_clustering(G), 度分布峰度: scipy.stats.kurtosis([d for n,d in G.degree()]) } metrics pd.DataFrame([ calculate_metrics(er_network, ER), calculate_metrics(ws_network, WS), calculate_metrics(ba_network, BA) ]) print(metrics)典型输出结果对比网络类型平均路径长度集聚系数度分布峰度ER4.20.009-0.05WS5.10.353.2BA3.80.0225.43.3 可视化对比仪表盘def create_network_dashboard(G, posNone, title): if pos is None: pos nx.spring_layout(G, seed42) plt.figure(figsize(12,5)) # 网络可视化 plt.subplot(121) nx.draw(G, pos, node_size20, width0.5) plt.title(f{title}拓扑结构) # 度分布直方图 plt.subplot(122) degrees [d for n, d in G.degree()] plt.hist(degrees, bins20, densityTrue) plt.title(f{title}度分布) plt.xlabel(度); plt.ylabel(频率) # 生成布局保持一致性 er_pos nx.spring_layout(er_network, seed42) ws_pos nx.spring_layout(ws_network, seed42) ba_pos nx.spring_layout(ba_network, seed42) create_network_dashboard(er_network, er_pos, ER随机网络) create_network_dashboard(ws_network, ws_pos, WS小世界网络) create_network_dashboard(ba_network, ba_pos, BA无标度网络)4. 进阶分析与优化技巧4.1 巨型组件分析对于大型稀疏ER网络当p (1ε)/N时几乎必然形成巨型组件def giant_component_analysis(): N 1000 p_values np.linspace(0.001, 0.01, 20) giant_sizes [] for p in p_values: sizes [] for _ in range(5): # 多次实验取平均 G nx.erdos_renyi_graph(N, p) giant max(nx.connected_components(G), keylen) sizes.append(len(giant)/N) giant_sizes.append(np.mean(sizes)) plt.plot(p_values, giant_sizes) plt.axvline(x1/N, colorr, linestyle--) plt.title(ER网络巨型组件相变) plt.xlabel(连接概率p); plt.ylabel(巨型组件比例) giant_component_analysis()4.2 小世界效应验证通过系统改变WS模型的重连概率p观察聚类系数和平均路径长度的变化def small_world_analysis(): N, k 500, 6 p_values np.logspace(-4, 0, 20) clustering [] path_lengths [] for p in p_values: ws nx.watts_strogatz_graph(N, k, p) clustering.append(nx.average_clustering(ws)) try: path_lengths.append(nx.average_shortest_path_length(ws)) except: path_lengths.append(float(nan)) fig, ax1 plt.subplots() ax1.plot(p_values, clustering, b-) ax1.set_xscale(log) ax1.set_xlabel(重连概率p) ax1.set_ylabel(聚类系数, colorb) ax2 ax1.twinx() ax2.plot(p_values, path_lengths, r-) ax2.set_ylabel(平均路径长度, colorr) plt.title(WS小世界网络特性演化) small_world_analysis()4.3 性能优化策略当处理超大规模网络时节点数1e6可采用以下优化# 稀疏矩阵存储 from scipy.sparse import csr_matrix def to_sparse_adjacency(G): n G.number_of_nodes() rows, cols zip(*G.edges()) data np.ones(len(rows)) return csr_matrix((data, (rows, cols)), shape(n,n)) # 并行计算聚类系数 from multiprocessing import Pool def parallel_clustering(G, workers4): nodes list(G.nodes()) with Pool(workers) as p: clustering p.map(lambda n: nx.clustering(G, n), nodes) return sum(clustering)/len(nodes)5. 实际应用场景扩展5.1 社交网络模拟def simulate_social_network(N, p_ws0.1, m_ba3): # 基础社交圈-小世界特性 base nx.watts_strogatz_graph(N, k10, pp_ws) # 添加意见领袖-无标度特性 influencers nx.barabasi_albert_graph(N, mm_ba) social_net nx.compose(base, influencers) # 随机弱连接-ER特性 for u,v in combinations(social_net.nodes(), 2): if not social_net.has_edge(u,v) and random.random() 0.01: social_net.add_edge(u,v) return social_net5.2 网络鲁棒性测试def robustness_test(G, attackrandom): nodes list(G.nodes()) if attack targeted: nodes.sort(keylambda x: -G.degree(x)) connected [] temp G.copy() for i in range(1, len(nodes)1): temp.remove_node(nodes[i-1]) connected.append(len(max(nx.connected_components(temp), keylen))/len(nodes)) plt.plot(np.arange(1,len(nodes)1)/len(nodes), connected) plt.title(f{attack.capitalize()}攻击下的网络鲁棒性) plt.xlabel(节点移除比例); plt.ylabel(最大连通分量比例) robustness_test(ba_network, random) robustness_test(ba_network, targeted)5.3 动态网络演化def dynamic_network_evolution(N100, steps50): G nx.complete_graph(5) # 初始核心 for t in range(steps): # 新增节点优先连接 new_node N t targets [] degrees dict(G.degree()) total_degree sum(degrees.values()) m min(3, len(G)) # 每个时间步新增3条边 while len(targets) m and total_degree 0: r random.uniform(0, total_degree) cumulative 0 for node, degree in degrees.items(): cumulative degree if r cumulative and node not in targets: targets.append(node) break G.add_node(new_node) for target in targets: G.add_edge(new_node, target) # 随机重连现有边 for edge in random.sample(list(G.edges()), min(10, len(G.edges()))): G.remove_edge(*edge) new_target random.choice(list(set(G.nodes()) - set(G.neighbors(edge[0])))) G.add_edge(edge[0], new_target) return G