数学建模传染病模型全解析:从SIR到SEIR的建模、拟合与实战

数学建模传染病模型全解析:从SIR到SEIR的建模、拟合与实战 要说数学建模竞赛里哪个模型最“常青”传染病模型绝对是头一号。从早年非典建模到这几年的流感、登革热、新冠疫情相关题目几乎每届国赛、华为杯里都能看到它的影子。很多队伍拿到这类题第一反应是“套个SIR”但真正上了赛场才发现光是参数拟合就能卡住半支队伍更别提模型改进和论文里的深度分析了。这篇内容我就围绕“数学建模之传染病模型”这个主题从模型原理、微分方程推导、Python代码实现到参数辨识、论文写作、AI工具辅助完整拆一遍。不管你是在备赛2026年国赛还是学校课程设计要交一份传染病建模论文这篇都值得收藏。我会把实际建模过程中踩过的坑、验证过的思路、写作时容易被评委挑刺的点全部讲透。1. 项目整体拆解传染病模型到底在考什么1.1 从一类典型题目看核心需求传染病模型类的竞赛题目通常不会直接告诉你“请使用SIR模型”而是给你一张或者几张疫情数据表再配一段新闻式的背景描述。题目要求往往可以归纳成三个层次第一建立合理的传染病传播模型解释数据变化趋势第二基于真实数据估计模型参数对后续疫情走势做出预测第三评估隔离、疫苗、口罩等干预措施的效果或者给出资源调配建议。拆开看这就是数学建模标准流水线机理建模、参数辨识、模型应用。难点不在第一层大多数队伍都能写出一个SIR方程组真正的分水岭在第二层和第三层——你能不能把模型参数拟合得让评委信服能不能在模型基础上做有洞察力的延伸分析。很多优秀论文和普通论文的差距说到底就差在“参数是怎么来的”和“模型结论有没有落到实际问题上”这两件事上。1.2 传染病的数学表达思路传染病传播的数学化核心思想就是“仓室模型”。你可以把整个人群想象成几个大池子易感者、感染者、康复者或者再加上潜伏者。池子之间有人流动流动速度由传染率、康复率等参数控制。这套思路最早可以追溯到1927年Kermack与McKendrick提出的SIR模型至今快一百年了依然是传染病建模的基石。为什么仓室模型生命力这么强因为它抓住了传染病传播的两个核心机制一是人与人接触导致易感者变成感染者这是“非线性项”的来源二是感染者会康复或死亡退出传播链这是“线性项”的来源。两条机制叠加就能解释疫情爆发、达峰、消退的全过程。理解这一点你就明白为什么SIR模型的方程里一定有“βSI”这种乘积项了——它代表的不是抽象数学符号而是“易感者和感染者碰面了”。1.3 模型家族与场景匹配传染病模型不是只有一个SIR而是一个完整的家族。选错了模型后面所有工作都是白费。我的经验是先看题目给了什么数据、疾病有什么特点再决定用哪个模型。模型状态结构适用场景特点SIS → I感染后终身不康复如HIV最简单但实用性有限SISS → I → S康复后无免疫力如细菌性痢疾会出现地方病平衡点SIRS → I → R感染后获得终身免疫如水痘、麻疹竞赛主力最常用SEIRS → E → I → R存在潜伏期如新冠、流感比SIR多一个潜伏仓室SEIRSS → E → I → R → S免疫力随时间消退适合长期传播研究竞赛中遇到最多的情况是题目给了一个“有潜伏期”的呼吸道传染病数据。这时候直接套SIR参数拟合出来形状对不上因为你把潜伏期的人也算进了感染人群。我见过太多队伍在这个地方翻车拟合出的曲线怎么调都不对最后才发现该用SEIR。2. 传染病模型家族从SI到SEIR的原理与适用边界2.1 SI模型最简单的增长描述SI模型只有两个仓室易感者S和感染者I。它的方程组是S(t) -βSI/N I(t) βSI/N其中N是总人口β是有效接触率。这个模型的逻辑是一个感染者每天接触β个人其中有一定比例是易感者于是产生新的感染。SI模型的解是一条S形曲线感染人数最终会逼近总人口因为模型假设没有康复、没有死亡。实际竞赛里直接用SI模型的情况很少但它有一个很重要的教学意义帮你建立“乘积项”的直觉。很多新手问为什么传染项是S乘以I而不是简单的常数增长因为新增感染人数既取决于“有多少感染者去传播”也取决于“有多少易感者可以被感染”。两者都多新感染才多。这个乘法逻辑贯穿所有仓室模型。另外SI模型也是后面所有模型的构建基础理解了它再往里面加康复项、潜伏项就顺理成章了。2.2 SIS模型康复后再次易感SIS模型引入了康复但假设康复者会重新变成易感者。方程组是S(t) -βSI/N γI I(t) βSI/N - γI这里γ是康复率1/γ就是平均感染期。SIS模型有一个非常漂亮的数学性质当基本再生数R0 β/γ 1时感染人数会收敛到一个正的平衡点地方病平衡点而不是归零当R0 ≤ 1时疫情会自然消退。这个阈值行为在公共卫生上有重要含义——如果人群无法获得持久免疫力你要做的不是等疫情自己消失而是把R0压到1以下。竞赛中SIS模型通常出现在细菌性、重复感染的场景或者题目明确说“康复后不产生抗体”。从建模角度看SIS模型让你学会分析平衡点的稳定性这在论文里是一个很好的理论支撑点。我记得有一年的题目涉及校园流感反复暴发用SIS加上季节参数效果就比SIR好很多。2.3 SIR模型竞赛中的绝对主力SIR模型在SI基础上增加了康复者仓室R完整方程组是S(t) -βSI/N I(t) βSI/N - γI R(t) γI满足S(t) I(t) R(t) N总人口守恒。模型假设感染者康复后获得终身免疫不再参与传播。参数β是有效接触率γ是康复率。平均感染期是1/γ。SIR模型最经典的分析是相平面分析。把前两个方程相除可以得到dI/dS的表达式进一步推出最终感染规模和R0 β/γ的关系。当R0 1时疫情会先上升后下降形成单峰曲线当R0 1时感染人数单调下降疫情不会暴发。这个结论直接解释了我们常说的“R0大于1才会人传人”的说法到底是怎么来的。竞赛中SIR模型的使用频率最高因为它参数少、解释性强、也最容易做扩展。无论是加隔离仓室、疫苗仓室还是做成时变参数模型都是在SIR骨架上做文章。把SIR模型吃透等于你拿到了传染病建模大题的及格分。2.4 SEIR与SEIRS必须考虑的潜伏期SEIR模型在SIR的基础上加入了暴露者E潜伏者。方程组是S(t) -βSI/N E(t) βSI/N - σE I(t) σE - γI R(t) γIσ是潜伏者转为感染者的速率1/σ是平均潜伏期。为什么要加E因为很多传染病在潜伏期没有症状却可能具备传染性或者至少不会因为“发热”被发现、隔离。如果题目给的数据有明显的“延迟”特征——比如接触者要过好几天才出现在确诊数据里——那就必须用SEIR。SEIRS模型则在SEIR的基础上让康复者重新回到易感者适用于免疫力随时间消退、可能重复感染的疾病。竞赛中SEIRS用的相对少但一旦用了通常是题目里明确出现了“二次感染”的描述。从SIR到SEIR再到SEIRS本质上是从“简单假设”往“现实复杂”逐步靠近每加一个仓室都要付出参数估计算法复杂度上升的代价所以模型不是越复杂越好够用就好。2.5 关键指标R0的推导与解读基本再生数R0是整个传染病模型里最有价值的输出量之一。它的定义是在一个完全易感的人群中一个感染者平均能传染给多少人。R0 1疫情指数增长R0 1疫情逐渐消失R0 1是临界值。这个阈值判断就是论文里要重点讨论的核心结论。以SIR模型为例R0 β/γ推导过程用无病平衡点的稳定性分析。令I 0S N疫情初期易感者近似等于总人口此时新增感染率为βN·I/N βI康复率为γI所以净增长率为(β - γ)I。当β γ时感染人数增加反之减少于是定义R0 β/γ。这个推导简洁有力是论文里用来体现数学功底的经典段落。在竞赛里解读R0要注意两点第一R0是早期无干预时的指标一旦隔离、口罩等干预措施介入有效再生数Rt是随时间变化的第二R0不能直接写“病毒的R0是3”你要结合你的数据、模型假设说明白你的R0是在什么参数组合下算出来的。很多评委喜欢追问这个问题你提前在论文里说清楚能少很多麻烦。3. 参数辨识与模型拟合怎么让模型贴近真实数据3.1 数据预处理是第一步也是最容易被忽略的一步拿到疫情数据先别急着画图和拟合。你需要先搞清楚数据的“口径”是每日新增病例还是累计病例是确诊病例还是包括无症状感染者不同口径对应模型里的不同状态量。如果用“每日新增确诊”拟合SIR模型里的I(t)严格来说是不严谨的因为每日新增更接近“新进入I仓室的人数”对应的是βSI/N或者σE而不是I(t)本身。实际操作中大家经常混用但你要在论文里说明你是如何处理的。我常用的做法是如果模型里需要的是I(t)但没有直接的活跃感染人数数据可以用“累计确诊数”减去“累计康复/死亡数”来近似。如果数据噪声大比如节假日不检测、检测能力不足导致数据大幅波动我会先做7天滑动平均再进入拟合。这个预处理看似不起眼实际上对参数辨识稳定性的影响非常大。直接用原始噪声数据拟合参数可能完全偏离真实值甚至导致优化不收敛。3.2 最小二乘拟合的数学逻辑参数辨识的数学本质是给定模型结构找到一组参数使得模型输出与真实数据之间的误差平方和最小。目标函数写作min Σ (y_data(t) - y_model(t, θ))²其中θ是要估计的参数向量在SIR里就是β、γ、I0甚至S0。这个最优化问题没有解析解通常用数值优化算法求解。竞赛中用的最多的工具是Python里scipy.optimize模块的curve_fit或者least_squares底层是Levenberg-Marquardt算法或信赖域算法对于SIR这种光滑参数空间收敛效果是很稳的。不过这里有一个容易翻车的地方最小二乘对初值敏感。你给β、γ、I0设定的初值如果离真实值太远优化器可能收敛到局部最优拟合出的曲线肉眼看上去也对不太上。我的建议是先用肉眼估计I0大约是多少再按疫情数据的时间尺度估算β、γ的大致范围然后设置多组初值做拟合取误差最小的一组。比赛时间充足的话还可以用scipy.optimize.differential_evolution做一次全局搜索能显著降低局部最优的风险。3.3 Python实现SIR模型拟合的完整流程下面给出一个完整的SIR模型拟合示例数据用合成的模拟数据代替真实数据方便你直接运行和理解。import numpy as np import matplotlib.pyplot as plt from scipy.integrate import odeint from scipy.optimize import curve_fit # 1. 定义SIR微分方程组 def sir_model(y, t, beta, gamma, N): S, I, R y dSdt -beta * S * I / N dIdt beta * S * I / N - gamma * I dRdt gamma * I return [dSdt, dIdt, dRdt] # 2. 生成模拟数据假设总人口10万初始感染者10人 N 100000.0 I0 10.0 R0_init 0.0 S0 N - I0 - R0_init y0 [S0, I0, R0_init] t np.linspace(0, 100, 101) true_beta 0.35 true_gamma 0.1 sol odeint(sir_model, y0, t, args(true_beta, true_gamma, N)) I_true sol[:, 1] # 感染人数 # 给模拟数据加噪声模拟真实上报数据 np.random.seed(42) I_obs I_true np.random.normal(0, 25, sizelen(I_true)) I_obs np.maximum(I_obs, 0) # 3. 用curve_fit拟合参数 # 注意需要把I0也作为参数或者固定为已知的初始感染数 def fit_func(t, beta, gamma, I0): S0 N - I0 y0 [S0, I0, 0.0] sol odeint(sir_model, y0, t, args(beta, gamma, N)) return sol[:, 1] # 初值设置在合理范围内 p0 [0.5, 0.2, 20.0] bounds ([0.0, 0.0, 0.0], [2.0, 2.0, N/10]) popt, pcov curve_fit(fit_func, t, I_obs, p0p0, boundsbounds, maxfev10000) beta_est, gamma_est, I0_est popt print(f拟合结果: beta{beta_est:.3f}, gamma{gamma_est:.3f}, I0{I0_est:.1f}) print(fR0 beta/gamma {beta_est/gamma_est:.2f}) # 4. 用拟合结果重新求解模型并与数据对比 y0_est [N - I0_est, I0_est, 0.0] sol_fit odeint(sir_model, y0_est, t, args(beta_est, gamma_est, N)) I_fit sol_fit[:, 1] plt.figure(figsize(10, 6)) plt.scatter(t, I_obs, s8, alpha0.6, label观测数据(带噪声)) plt.plot(t, I_true, g--, linewidth2, label真实曲线) plt.plot(t, I_fit, r-, linewidth2, label拟合曲线) plt.xlabel(时间/天) plt.ylabel(感染人数) plt.title(SIR模型拟合结果) plt.legend() plt.grid(alpha0.3) plt.show()这段代码跑完会输出β、γ、I0三个参数的估计值以及R0的计算结果。我在代码里特意把“模拟真实曲线”也画出来你可以直观看到拟合曲线和真实曲线的偏差。实际比赛中你只需要把这套流程中的数据换成题目给的真实数据即可。要注意如果你拟合的是“每日新增”而不是“在院感染人数”需要把fit_func的输出改成对应的量。另外数据时间段的选择对拟合结果影响巨大前期数据拟合出的R0通常是最大的后期数据会因为干预措施导致β下降混合在一起拟合有时会得到“一个折中的、什么都不像”的参数。3.4 参数辨识的常见坑与经验参数辨识是传染病模型里翻车率最高的环节我梳理几个高频问题和对应的处理思路。第一参数辨识度不足。SIR模型里β和γ高度相关因为决定疫情形状的往往是β-γ的差值和β/γ的比值。你可能会发现多次拟合得到的β和γ不同但R0接近——这不是bug是模型结构本身决定的。解决办法是论文里重点报告R0和相关衍生量而不是单独讨论β和γ。第二数据太短导致信息不足。只有疫情早期上升段的数据任何模型都无法可靠估计峰值和后续走势此时应该明确在论文里指出模型的外推局限不要硬着头皮做长期预测。第三噪声会使曲线拟合失真。建议先做滑动平均或者使用带权重的最小二乘对数据质量好的时间段给予更高权重。这些细节在评审时都是加分项因为评委看的不是你写没写出来而是你写出来的东西是不是有血有肉的实践经验。4. 真实案例复盘用SIR模型拟合模拟疫情数据4.1 为什么要先用合成数据做验证很多人一上来就用真实数据拟合拟合结果乱成一团找不到问题在哪。我的习惯是先在合成数据上测试建模流程用已知参数的模型生成一组数据加上噪声再跑完整的拟合—预测—敏感性分析流程。如果这套流程在合成数据上都不能恢复真实参数说明模型或者代码有漏洞这时候去碰真实数据就是事倍功半。真实数据只是换了数据源分析流程是完全一样的。这种做法在竞赛中还有一个额外的好处逼你把思路提前理清。合成数据的“真实答案”就摆在那里你能清晰看到参数拟合的误差有多大预测的置信区间有多宽。面对真实数据时你就知道哪些结论是数据支撑得住的哪些是模型强推硬猜的论文写起来会严谨很多。4.2 拟合过程与结果解读回到上面那段代码的输出。假设拟合得到的参数是β0.361γ0.104I012.5。对应的R03.47平均感染期1/γ≈9.6天。这些数字说明什么在无干预情况下每个感染者平均传给3.47个人被感染后大约9.6天才康复或者说退出传播链。这便是评判干预措施强度的重要参考点——如果把有效接触率β降到0.1以下R0就能压到1以下疫情会走向收敛。实际做预测时你可以用拟合好的参数继续往后求解比如预测第150天的感染人数。但我要提醒你这种预测只在“系统不发生结构性变化”时才有效比如没有实施封控、没有特效药。只要有外部干预模型参数就会变。竞技场上好的队伍往往不是做“铁板一块”的单一预测而是做“情景分析”假设不干预R03.47假设中度干预R01.8假设强干预R00.8分别求峰值和峰值时间。这种方法才是评委眼里的加分项。4.3 模型局限性拟合好不等于预测准SIR模型的强大建立在三个核心假设上人群均匀混合、参数恒定、总人口不变。真实世界远非如此有人群聚集和地区差异有行为变化和季节性波动有输入性病例还有无症状感染者。模型拟合效果好只能说明模型在数据时间范围内能描述历史趋势不代表未来一定按这个趋势走。把这部分写进论文不要藏着掖着。一个模型有哪些假设、哪些局限本身就是考察建模者理解深度的地方。我见过不少队伍在结论里大吹预测准确率结果被评委一问就愣住了。反过来主动承认模型局限并尝试改进的队伍哪怕预测不是最准也更容易拿高分。因为数学建模考的不是算命而是你如何用数学语言理解和解释世界。4.4 敏感性分析与干预措施评估SIR模型的一个经典扩展是敏感性分析。目标参数通常是峰值高度、峰值时间、最终感染规模。做法是让某个模型参数在合理区间内变动观察目标参数的变化幅度。比如β从0.2变到0.5峰值时间从第120天提前到第30天最终感染规模从总人口的30%上升到85%——这种量化结论比“干预有效”四个字有说服力得多。在论文写作上我会画一个二维热力图横轴是β纵轴是γ颜色表示最终感染人数占比。这张图视觉冲击力强信息密度高而且是纯模型的确定性计算不容易被质疑。另一个常见做法是“干预时间点分析”分别模拟第10天、第20天、第30天开始施加隔离的效果画成多条曲线叠加直观说明“早干预早受益”。这部分内容做得好论文的“模型应用”章节就会显得非常饱满。5. 竞赛实战经验论文写作、符号说明与AI辅助5.1 论文结构从摘要到结论的篇幅分配很多队伍模型做得还行论文写得一塌糊涂最后分数不理想。数学建模论文是给评委看的“研究报告”不是实验记录叙事逻辑要清晰。通常一篇20页左右的论文我建议这样分配摘要1页问题重述与分析1-2页模型假设与符号说明2页模型建立5-6页模型求解与参数辨识4-5页模型检验与敏感性分析3-4页模型评价与改进2页参考文献与附录3页。摘要极其重要。评委先看摘要摘要不行后面再精彩也白搭。摘要里必须出现用了什么模型、关键参数值、核心结论、R0或等效指标的具体数值。公式不是不能写但要挑最关键的写。我见过很多队伍在摘要里堆了一堆公式读了半天不知道结论是什么这就属于典型的本末倒置。5.2 符号说明与参数辩识的表单化呈现规范的学生论文和优秀论文之间一个明显差距就是符号说明。SIR模型本身符号不多但一加上干预措施、多群体、多地区符号体系就开始乱了。我的建议是在论文第三页放一张大表把所有符号、含义、单位、初值来源全部列出来后面正文涉及任何符号都只用代号不再重复解释。这样既省篇幅又显得专业。参数辨识部分不要只写“用最小二乘拟合得到β0.36”至少要把这些内容补全目标函数的表达式、优化算法名称、初值设置和约束范围、拟合结果图、R0计算过程、拟合优度分析。很多队伍把参数辨识当成一个黑盒工具只给结果不给过程这在竞赛里是大忌。评委对数值结果不一定较真但一定会看你有没有把整个分析链条讲清楚。5.3 AI辅助建模的提示词思路这两年AI辅助数学建模已经是非常普遍的做法了Claude、ChatGPT这类工具确实能帮上大忙但关键是你会不会用。我的经验是把AI当“高年级队友”而不是“代笔枪手”。建模思路卡住时我会问它“我有一份每日新增病例数据疑似有潜伏期的传染病请帮我对比SIR和SEIR模型在这种场景下的优缺点并指出参数辨识时需要注意的问题。”这种开放式提问能快速打开思路。写代码时AI更擅长把一段错误代码扔给它让它指出bug让它实现一个改进版的带干预措施的SEIR模型让它把拟合代码改写成支持多组数据面板的形式。这些都是节省大量时间的高效用法。但在两个环节我不建议依赖AI第一模型假设的合理性判断你需要深刻理解自己的题目背景AI给的是“通用答案”不一定贴合你的具体情境第二论文核心结论的措辞AI写出来的会议式、总结式语言在评委眼里往往带有明显的“模板感”你需要用自己的话重写。用AI时还有一条底线不要直接复制一整段AI生成论文提交现在竞赛主办方对AI生成率的审查越来越严格有些规则甚至直接明确了AI自查表。好东西要拿来用但学术诚信的底线不能碰。5.4 竞赛中的自查清单每次比赛提交前我都会按下面这份清单过一遍论文。第一摘要是否清楚回答了题目所有问题有没有出现具体数字结论。第二模型假设是否合理是否与题目背景信息矛盾比如题目说“该病存在潜伏期”你的模型里却没有E仓室这会被认为是硬伤。第三符号表是否完整单位是否清晰。第四所有图是否都有图题、坐标轴标签表是否有表题引用是否有出处。第五参数辨识部分是否展示了优化目标和数据来源。第六模型评价部分是否足够诚恳有没有认真讨论模型局限性。这份清单看起来琐碎但每次都能帮队伍捞回5到10分。6. 常见问题与排查技巧实录6.1 拟合不收敛或结果明显不合理症状是优化器报错或者拟合出的β、γ为负值、I0等于总人口这类荒谬结果。排查思路先检查微分方程求解是否正常画一下给定初值时模型的解长什么样再检查数据是否匹配模型状态量是不是把“累计确诊”当成“现有感染”来拟合最后检查优化初值是否离基本盘太远。建议每次拟合前手动把数据曲线和几条不同参数下的模型曲线画在一起感受一下参数量级再设置初值。我一直跟队友强调先人工粗调再交给机器精调不要一上来就盲目跑优化器。6.2 预测曲线出现负值或震荡SIR模型里I和R不会出现负值但数值积分在参数跨度极大或步长过大的情况下可能出现数值误差累积。解决方法是降低odeint的求解步长或者换用更稳定的scipy.integrate.solve_ivp并指定方法为LSODA或Radau。另一个常见原因是数据里有大量零值和负值预处理阶段要做平滑或者用指数加权移动平均把曲线抹平。预测时段也不要拉太长模型外推到几个月之后数值稳定不代表结论有意义这个要在论文里明说。6.3 R0计算与解读的常见误区R0β/γ是最常见的形式但很多人忽略了β的单位依赖于时间尺度。如果β是按“每小时接触率”算的γ却是按“每天康复率”算的算出来的R0完全错误。我见过不止一支队伍拟合的β用的是按天的时间单位γ用的是按小时的单位结果R0差了24倍还浑然不觉。建议统一按天计算并且论文里明确写出“本文所有参数均按天为单位”。另外一个误区是把R0当作固定常数。真实世界的R0随着人口密度、季节、防控措施在变化你算出来的只是“你这个模型、你这组数据下的R0”不是病毒本身的属性。6.4 从拿奖角度做的模型扩展方向如果基础SIR/SEIR已经做完时间和精力还允许可以考虑以下几个扩展方向。第一时变参数模型把β从常数改成随时间变化的函数比如分段常数用来模拟不同阶段的防控强度变化拟合效果通常显著优于恒定参数模型。第二加入隔离仓室Q或疫苗接种仓室V直接回答“如果提前N天隔离”“如果疫苗覆盖率达到多少”这类政策问题。第三分年龄/分地区的多群体模型适合题目给了年龄或地区维度数据的情况。第四和机器学习结合用LSTM或者随机森林对模型残差做修正这种“机理模型数据驱动”的组合往往能成为论文的创新点。但要记住扩展方向必须服务题目不要为了炫技而加模型复杂度否则很容易画蛇添足。最后再分享一个我在实际比赛中的体会传染病模型题拿高分的关键不是把模型建得多复杂而是把每个环节都踩实。参数怎么来的、为什么用这个模型、R0怎么解读、预测有哪些不确定、干预效果怎么量化这些问题你能在论文里扎扎实实地回答评委自然会给你高分。备赛阶段与其背一堆花哨模型不如亲手把SIR、SEIR的代码跑通把参数辨识的坑踩一遍。真上了赛场你会感谢自己当初多花的那几个小时。