尧图精选

Python实现BA与ER网络SIR传播模拟:源码解析与参数调优

🕒 发布时间:2026/10/2 3:24:00 📁 来源:尧图网络
简介这份资源是面向复杂网络与流行病学建模学习者的Python实践项目围绕SIR传染病模型在BA无标度网络与ER随机图上的传播对比展开适合具备Python基础、希望理解网络拓扑如何影响疾病扩散的读者。压缩包共21个文件约217KB以10张png结果图、4个py源码脚本为主辅以README说明、LICENSE授权文件及缓存文件源码分别对应BA网络、ER网络与SIR模型的实现图片则用于呈现不同网络结构下的模拟曲线与传播趋势。目前已有875人学习下载。通过运行与阅读代码读者可掌握易感—感染—康复三状态转换的建模思路观察高连接度节点在BA网络中引发的集中爆发以及ER网络中相对均匀但规模有限的传播特征并借助Matplotlib等工具完成数据分析与可视化为网络动力学与流行病学仿真提供可复用的实践案例。1. 从一份 BA/ER 网络 SIR 模拟包说起它到底能跑出什么如果你正在做网络传播动力学、传染病建模或者复杂网络课程设计大概率绕不开一个经典问题同样的 SIR 规则放在 BA 无标度网络和 ER 随机图上结果会差多少。这份BA_ER_SIR_python-master就是冲着这个问题来的。它用 Python 把 SIR 模型分别跑在 BA 网络和 ER 网络上输出感染曲线和对比图目录里已经带了Figure_1.png到Figure_10.png十张结果图说明作者是把模拟跑通、图也出过一遍的。适合三类人想快速复现网络传播实验的学生、需要对比不同拓扑影响的科研入门者、以及想拿一份能改的 Python 源码练手的数据分析从业者。它不教你 Python 语法但把「网络生成 → 状态演化 → 结果可视化」这条链路完整摆出来了。2. 先看懂代码骨架main.py、BA_wjc.py、ER_wjc.py、SIR_wjc.py 各管什么拿到一个源码包我习惯先看文件命名和调用关系而不是急着python main.py。这个包的模块划分很直白四个.py文件各司其职__pycache__里还有cpython-37的字节码说明作者本地用的是 Python 3.7 环境。下面把每个文件的职责和它们之间的依赖讲清楚你改代码时才知道该动哪一层。2.1 四个核心模块的职责边界从文件名就能推断出设计意图BA_wjc.py负责生成 Barabási-Albert 无标度网络ER_wjc.py负责生成 Erdős-Rényi 随机图SIR_wjc.py封装 SIR 传播过程main.py是入口把网络和传播模型串起来并画图。这种「网络生成」和「传播规则」分离的写法是常见做法好处是你可以只换网络、不动传播逻辑或者只改传播参数、复用同一张网络。BA_wjc.py里通常包含优先连接preferential attachment的实现初始若干节点之后每加入一个新节点按已有节点的度数比例连边。ER_wjc.py则是以概率 p 在每对节点间独立连边或者用固定边数 G(n, m) 的变体。SIR_wjc.py里会定义状态数组、感染概率 β、康复概率 γ以及按时间步迭代的循环。main.py一般会设置节点数 N、平均度、β、γ、模拟轮数然后调用前三个模块。提示先别改参数先把四个文件从头到尾读一遍确认每个函数的输入输出。很多「跑出来图不对」的问题根源是没搞清哪个变量控制网络规模、哪个控制传播强度。2.2 一次完整模拟的调用链下面这段伪代码还原了main.py里最可能的调用顺序你可以对照自己的文件确认。它不是原文照抄而是把典型结构写出来方便你定位。# main.py 典型结构对照你的实际文件 from BA_wjc import generate_BA_network from ER_wjc import generate_ER_network from SIR_wjc import run_SIR N 1000 # 节点数 m 3 # BA 网络每个新节点的连边数 p 0.006 # ER 网络连边概率约等于平均度/N beta 0.05 # 感染概率 gamma 0.1 # 康复概率 steps 100 # 时间步 # 生成两种网络 ba_adj generate_BA_network(N, m) er_adj generate_ER_network(N, p) # 分别跑 SIR ba_curve run_SIR(ba_adj, beta, gamma, steps) er_curve run_SIR(er_adj, beta, gamma, steps) # 画对比图 plot_compare(ba_curve, er_curve)逻辑说明先分别构造两种网络的邻接关系再把同一套 SIR 参数喂进去最后对比感染人数随时间的变化。参数说明N决定规模m和p决定网络密度beta/gamma决定传播烈度steps决定模拟时长。这里最关键的是让 BA 和 ER 的平均度接近否则你看到的差异可能只是密度不同造成的而不是拓扑结构造成的。常见做法是令 ER 的p m / (N - 1)左右让两者平均度大致相等。2.3 环境准备与首次运行这个包依赖 NumPy、NetworkX、Matplotlib 这三个库。__pycache__显示 Python 3.7但 3.8 到 3.11 一般也能跑NetworkX 版本差异是主要变量。建议用虚拟环境避免和系统里的包打架。# 创建并激活虚拟环境 python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate # 安装依赖 pip install numpy networkx matplotlib # 运行入口 python main.py逻辑说明先隔离环境再装三个核心库最后跑main.py。参数说明如果你机器上python指向 Python 2改用python3。运行后如果弹出十张图或生成新的Figure_*.png说明链路通了。如果报ModuleNotFoundError逐个补装如果报 NetworkX API 相关错误多半是版本问题见第 4 章的排查。3. 把 SIR 参数调明白β、γ、初始感染比例与网络平均度代码能跑只是第一步真正决定你能不能得到有意义结论的是参数怎么设。这一章把 SIR 模型里几个关键参数和网络参数的关系讲透并给出可复现的调参步骤。很多人跑出来「BA 和 ER 差不多」八成是参数落在了一个不敏感的区间里。3.1 SIR 三状态与传播阈值SIR 模型里每个节点处于 S易感、I感染、R康复三态之一。每个时间步感染节点以概率 β 感染其易感邻居同时自身以概率 γ 康复。传播能否爆发取决于基本再生数 R0在均匀网络里近似为 R0 β·⟨k⟩ / γ其中 ⟨k⟩ 是平均度。当 R0 1 时感染规模会显著扩散R0 1 则很快熄灭。在 BA 无标度网络里由于度分布是幂律的、存在少量高连接「超级节点」有效传播阈值会趋近于零也就是说即使 β 很小疾病也可能通过 hub 节点扩散开来。ER 网络度分布集中在平均度附近阈值行为更接近均匀网络的经典结论。这就是为什么同样的 β、γ在两种网络上可能给出完全不同的曲线形态。注意如果你把 β 设得远大于阈值两种网络都会「全境感染」差异被淹没如果 β 远小于阈值两者都熄火。想看出拓扑差异β 要落在阈值附近。3.2 让 BA 与 ER 可比平均度对齐这是最容易翻车的地方。BA 网络用参数m控制平均度约为2mER 网络用概率p控制平均度约为p·(N-1)。如果不对齐你比较的其实是「稠密网络 vs 稀疏网络」不是「无标度 vs 随机」。# 对齐平均度的常见做法 N 1000 m 3 avg_degree_target 2 * m # BA 平均度约 6 p avg_degree_target / (N - 1) # ER 用同样平均度反推 p print(BA 平均度约:, 2 * m) print(ER 平均度约:, p * (N - 1))逻辑说明先由 BA 的m算出目标平均度再用它反推 ER 的p。参数说明m3对应平均度约 6p≈0.006。实际生成的网络平均度会有随机波动建议在代码里打印真实平均度做校验。我一般会跑 10 次取平均确认两者差距在 5% 以内再开始对比传播结果。3.3 初始感染设置与多轮平均初始感染节点的数量和位置对早期传播影响很大。只放一个随机初始感染者单次模拟的随机性极强曲线抖动会掩盖拓扑差异。常见做法是固定初始感染比例比如 1%并且对每个配置重复模拟几十次取平均。import numpy as np def run_multi(adj, beta, gamma, steps, init_ratio0.01, repeats50): N adj.shape[0] init_num max(1, int(N * init_ratio)) curves [] for _ in range(repeats): # 随机选初始感染者 init_nodes np.random.choice(N, init_num, replaceFalse) curve run_SIR(adj, beta, gamma, steps, init_nodes) curves.append(curve) return np.mean(curves, axis0)逻辑说明把单次模拟包一层重复循环对感染曲线按时间步求平均。参数说明init_ratio控制初始感染比例repeats控制重复次数50 次通常够平滑。注意run_SIR的签名要支持传入初始节点如果你的版本不支持需要小改一下SIR_wjc.py把初始感染集合作为参数传进去。3.4 结果怎么看峰值、达峰时间与最终规模跑完图别只看「像不像」要提取三个量化指标感染峰值峰值高度、达峰时间峰值出现的时间步、最终感染比例R 态占比。BA 网络通常表现为早期快速上升、峰值高、达峰早因为 hub 节点加速了扩散ER 网络上升相对平缓、峰值低、拖尾长。把这两个网络的三个指标列成表比贴两张图更有说服力。指标BA 网络预期ER 网络预期感染峰值较高较低达峰时间较早较晚最终感染比例较高较低曲线形态陡升陡降平缓拖尾提示这张表是定性预期具体数值取决于你的 β、γ 和平均度。如果实测和预期相反先检查平均度是否对齐、重复次数是否够、初始感染是否固定。4. 避坑与排查跑不通、图不对、结果反直觉的五个血泪经验这一章是我自己复现这类网络传播代码时踩过的坑按「现象 → 原因 → 解决」写。你如果卡在某一步大概率能在这里找到对应条目。现象一python main.py报ModuleNotFoundError: No module named networkx。原因依赖没装或者装到了另一个 Python 环境里。解决确认当前python和pip指向同一环境用pip install networkx重装必要时python -m pip install networkx强制走当前解释器。现象二NetworkX 报AttributeError比如找不到某个图生成函数。原因NetworkX 2.x 和 3.x 的 API 有变动老代码里的函数名或参数在新版本被改了。解决先pip show networkx看版本最稳的是降到 2.x 系列比如pip install networkx3再跑一遍。如果不想降级就按报错信息把对应调用改成新 API。现象三BA 和 ER 的感染曲线几乎重合看不出差异。原因要么平均度没对齐要么 β 远离传播阈值两种网络都进入「全感染」或「全熄灭」区间。解决先打印两种网络的实际平均度对齐到 5% 以内再把 β 调到阈值附近反复扫几个值找到曲线开始分叉的区间。现象四每次运行结果都不一样图抖得没法看。原因单次模拟随机性太大初始感染节点随机、传播过程随机。解决固定随机种子np.random.seed(42)同时把重复次数提到 50 次以上取平均。固定种子保证可复现多次平均保证曲线平滑。现象五图能出但保存的Figure_*.png是空白或只有坐标轴。原因Matplotlib 后端问题或者plt.show()和plt.savefig()顺序不对保存发生在绘图之前。解决在savefig之前确认已经plot并且用非交互后端在文件开头加import matplotlib; matplotlib.use(Agg)再plt.savefig(...)。5. 进阶玩法从单层网络到多层耦合与参数扫描把基础版本跑通之后这个包还能往两个方向扩展一是把单层网络变成多层耦合网络二是做参数扫描找出传播阈值。这两个方向都能让一份课程设计或小论文的含金量明显提升。5.1 多层网络耦合的改法现实中的传播往往发生在多层网络上比如物理接触层和社交信息层同时存在。改法不复杂分别生成两张网络让每个节点在两层各有一个副本传播时感染状态可以在同一节点的两层之间按一定概率同步。def run_SIR_multiplex(adj1, adj2, beta, gamma, steps, coupling0.1): N adj1.shape[0] # 两层各自的状态 state1 np.zeros(N, dtypeint) state2 np.zeros(N, dtypeint) # 初始感染 state1[0] 1 state2[0] 1 for t in range(steps): # 层内传播 层间耦合 # coupling 控制同一节点两层状态同步的概率 pass return state1, state2逻辑说明核心是维护两套状态数组层内按各自邻接矩阵传播层间按coupling概率把感染状态同步过去。参数说明coupling越大两层越同步设为 0 就退化成两个独立网络。这个扩展需要你自己补全传播循环但骨架和单层版本一致。5.2 参数扫描找传播阈值想找出 BA 和 ER 各自的传播阈值就对 β 做扫描看最终感染比例随 β 的变化曲线在哪里突然抬升。import numpy as np betas np.linspace(0.01, 0.3, 20) final_sizes_ba [] final_sizes_er [] for b in betas: ba_curve run_multi(ba_adj, b, gamma, steps) er_curve run_multi(er_adj, b, gamma, steps) final_sizes_ba.append(ba_curve[-1]) final_sizes_er.append(er_curve[-1]) # 画 final_size vs beta找抬升点逻辑说明对每个 β 跑多次平均取最终时间步的感染比例作为该 β 下的稳态规模。参数说明betas的扫描范围要覆盖阈值附近步长太粗会错过抬升点。你会看到 BA 的抬升点比 ER 更靠左这正是无标度网络阈值趋零的体现。5.3 一个我常用的验证习惯每次改完参数或扩展功能我不会直接看新图而是先跑一个「已知答案」的小规模用例N200、m2、β 设得很大确认最终几乎全感染再把 β 设得极小确认几乎全熄灭。这两个极端能过中间区间的结果才可信。从那以后我每次动传播逻辑都强制先走一遍这两个极端用例省得在错误的基础上调半天参数。希望这份拆解帮到你把这份 BA/ER 网络 SIR 模拟包真正跑出自己的结论。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联 返回资讯列表 →