资讯动态

gs-quant 流行病学 SEIR 模型解析:从仓室微分方程到数据校准与预测

发布时间:2026/9/15 19:51:26 来源:尧图企业网站定制
gs-quant 流行病学 SEIR 模型解析从仓室微分方程到数据校准与预测【免费下载链接】gs-quantPython toolkit for quantitative finance项目地址: https://gitcode.com/GitHub_Trending/gs/gs-quant导读SEIR是 Goldman Sachs 开源量化工具包 gs-quantPython toolkit for quantitative finance在流行病学建模方向上提供的基础仓室模型之一完整实现位于 gs_quant/models/epidemiology.py。本文以 SEIR 类文档 为核心骨架结合源码、底层拟合框架EpidemicModel与时间序列高层封装SEIRModel系统讲解 SEIR 模型的四个仓室动力学方程、calibrate与get_parameters两个核心类方法、基于 lmfit 与 SciPyodeint的参数拟合流程以及如何将模型接入 gs-quant 的时序分析管线。读完本文你将能够独立完成从定义初始条件、构造参数到拟合真实数据并输出各仓室预测曲线的完整闭环。SEIR 模型是什么四仓室动力学框架SEIRSusceptible–Exposed–Infectious–Removed是传染病传播的经典仓室模型。与三仓室的 SIR 模型相比SEIR 额外引入了暴露Exposed, E仓室用于刻画个体在感染病原体后、尚未具备传染力之前的潜伏阶段因此更贴近具有潜伏期特征的真实疫情过程。在 gs-quant 中SEIR 模型以SEIR类的形式提供其定义在 gs_quant/models/epidemiology.py状态向量xs [S]usceptible, [E]xposed, [I]nfected, [R]emoved即易感者、暴露者、感染者、移除者康复或死亡四个仓室的人数模型参数为beta传播速率易感 → 暴露、sigma暴露 → 感染速率、gamma恢复/移除速率感染 → 移除以及总人口N。从源码结构看SEIR继承自抽象基类CompartmentalModelepidemiology.py该基类通过classmethod与abstractmethod强制要求所有仓室模型实现两个接口calibrate返回各仓室关于时间的导数与get_parameters构造拟合所需的参数对象。这一抽象设计使得SIR、SEIR、SEIRCM、SEIRCMAgeStratified等模型可以共享同一套求解与拟合引擎。在 docs 中与SEIR同属 Epidemiology 模块并在 docs/models.rst 中并列导出的还有SIR与EpidemicModel对应的类文档为 SIR.rst 与 EpidemicModel.rst它们共同构成 gs-quant 的流行病学模型家族。SEIR 类核心方法一calibrate 与四仓室微分方程SEIR.calibrate(xs, t, parameters)返回 SEIR 模型在时刻t的四个仓室导数是模型微分方程的右侧函数源码classmethod def calibrate(cls, xs: tuple, t: float, parameters: Union[Parameters, tuple]) - tuple: s, e, i, r xs # 参数可从 lmfit.Parameters 或普通 tuple 中读取 if isinstance(parameters, Parameters): beta parameters[beta].value gamma parameters[gamma].value sigma parameters[sigma].value N parameters[N].value elif isinstance(parameters, tuple): beta, gamma, sigma, N parameters else: raise ValueError(Cannot recognize parameter input) dSdt -beta * s * i / N # 易感者被感染 dEdt beta * s * i / N - sigma * e # 暴露者转化为感染者 dIdt sigma * e - gamma * i # 感染者被移除 dRdt gamma * i return dSdt, dEdt, dIdt, dRdt对应的微分方程组为dS/dt -β·S·I/N dE/dt β·S·I/N − σ·E dI/dt σ·E − γ·I dR/dt γ·I四个方程背后的物理含义导数含义dSdt易感者因接触感染者而以速率 β 转化为暴露者人数减少dEdt易感者流入β·S·I/N与暴露者以速率 σ 进入感染仓室−σ·E的净值dIdt暴露者流入σ·E与感染者以速率 γ 被移除−γ·I的净值dRdt感染者恢复/移除的累计速率值得注意的细节时间参数t在该模型中是惰性的源码 docstring 明确标注t: time parameter, inactive for this model模型本身是自治autonomous系统t仅用于与scipy.integrate.odeint的接口对齐——这正是 CompartmentalModel.calibrate 抽象方法 docstring 中要求的形如callable(y, t, ...)的标准形式参数输入支持双形态既可以是 lmfit 的Parameters对象参数拟合时的形态也可以是普通tuple直接数值求解时的形态除此之外会抛出ValueError(Cannot recognize parameter input)N作为独立参数传入而不是由 SEIR 之和推算因此当传入的参数使各仓室人数之和不等于N时模型仍按给定的N归一化接触率。SEIR 类核心方法二get_parameters 与完整的拟合参数体系SEIR.get_parameters(...)负责把用户给定的初始条件、动力学参数及其上下界、是否固定等约束打包成 lmfit 的Parameters对象同时返回初始条件的变量名列表源码。完整的签名与默认值如下classmethod def get_parameters( cls, S0: float, # 初始易感人数 E0: float, # 初始暴露人数 I0: float, # 初始感染人数通常设为 1 R0: float, # 初始移除人数通常设为 0 N: float, # 总人口规模 beta: float 0.2, # 传播速率 gamma: float 0.1, # 恢复速率 sigma: float 0.2, # 暴露 → 感染速率 beta_max: float 10, gamma_max: float 1, sigma_max: float 1, beta_fixed: bool False, gamma_fixed: bool False, sigma_fixed: bool False, S0_fixed: bool True, S0_max: float 1e6, R0_fixed: bool True, R0_max: float 1e6, I0_fixed: bool True, I0_max: float 1e6, E0_fixed: bool True, E0_max: float 1e6, ) - tuple:其内部构造的Parameters变量与对应约束源码 L206-L215参数名初始值取值范围是否参与拟合varyNN[0, N]固定varyFalse总人口不做拟合S0S0[0, S0_max]not S0_fixed默认固定E0E0[0, E0_max]not E0_fixed默认固定I0I0[0, I0_max]not I0_fixed默认固定R0R0[0, R0_max]not R0_fixed默认固定betabeta[0, beta_max]not beta_fixed默认参与拟合gammagamma[0, gamma_max]not gamma_fixed默认参与拟合sigmasigma[0, sigma_max]not sigma_fixed默认参与拟合设计要点说明默认策略是动力学参数可拟合、初始条件固定beta、gamma、sigma三个速率参数默认_fixedFalse交给最小二乘优化器搜索而S0/E0/I0/R0与N默认固定为观测值避免参数空间过大导致拟合不稳定。若需要放宽某个初始条件将对应的*_fixedFalse并将*_max调大即可*_max参数作为拟合搜索的硬边界例如beta_max默认 10、gamma_max/sigma_max默认 1用于把速率参数约束在生物学合理的范围内防止优化器发散到无意义区域返回值为二元组(parameters, initial_conditions)initial_conditions [S0, E0, I0, R0]是初始条件变量名列表EpidemicModel拟合时据此从参数对象中提取各仓室的初始值N的上下界被设为min0, maxN且varyFalse即总人口在拟合中保持恒定这符合仓室模型的守恒假设不计出生与自然死亡时 SEIR ≡ N。配套的求解与拟合引擎EpidemicModelSEIR本身只定义微分方程与参数构造真正完成解方程、拟合参数的是EpidemicModelepidemiology.py。它以model: type[CompartmentalModel]作为第一个构造参数因此SIR、SEIR乃至带管控措施与死亡仓室的SEIRCM都可以无缝接入。构造参数EpidemicModel( model, # 仓室模型类如 SEIR parametersNone, # 参数默认取 model.get_parameters 的输出 dataNone, # 用于校准的观测数据 np.array initial_conditionsNone, fit_methodleastsq, # lmfit.minimize 支持的方法默认 Levenberg-Marquardt 最小二乘 errorNone, # 自定义残差函数 callable(solution, data, parameters) fit_periodNone, # 只拟合最近多少个时点默认使用全部数据 )三个核心方法solve(time_range, initial_conditions, parameters)调用 SciPy 的scipy.integrate.odeint对模型 ODE 做数值积分返回np.ndarray行对应每个时间点列对应各仓室SEIR 为 4 列。这是预测路径的入口time_range即np.arange(days_ahead)之类的时间网格。residual(parameters, time_range, data)先以当前参数与初始条件求出模型解再计算solution - data若传入自定义error函数则改用error(solution, data, parameters)计算残差若设置了fit_period则只取残差序列的最近fit_period段最后ravel()展平供优化器使用。fit(time_rangeNone, parametersNone, initial_conditionsNone, residualNone, verboseFalse, dataNone, fit_periodNone)以residual为目标函数调用lmfit.minimize(residual, parameters, args(time_range, data), methodself.fit_method)结果保存在self.result拟合后的参数字典保存在self.fitted_parameters即result.params.valuesdict()verboseTrue时输出report_fit(result)拟合报告。从源码结构可以清晰看到一条完整的调用链fit()→residual()→solve()→SEIR.calibrate()→odeint即用户只需准备数据与初始条件拟合与求解的编排由EpidemicModel统一完成。端到端实战从拟合到预测基于仓库测试的完整示例仓库测试 gs_quant/test/models/test_epidemiology.py 给出了 SEIR 的完整闭环示例先按已知参数生成观测数据再用被扰动的参数初值去拟合验证优化器能找回真实参数。下面将其整理为可直接运行的完整流程。第 1 步用真实参数生成模拟观测数据import numpy as np from gs_quant.models.epidemiology import SEIR, EpidemicModel # 初始条件S99, E1, I1, R0总人口 N100 # 真实动力学参数 beta, gamma, sigma 0.5, 0.25, 0.2 N, S0, E0, I0, R0 100, 99, 1, 1, 0 # 先构造参数对象可固定初始条件 parameters, initial_conditions SEIR.get_parameters( S0, E0, I0, R0, N, betabeta, gammagamma, sigmasigma, S0_fixedTrue, E0_fixedTrue, I0_fixedFalse, R0_fixedTrue, S0_max10e6, I0_max5e6, R0_max10e6, ) seir EpidemicModel(SEIR, parametersparameters, initial_conditionsinitial_conditions) # 未来 40 天的预测 days_ahead 40 T np.arange(days_ahead) forecast seir.solve(T, (S0, E0, I0, R0), (beta, gamma, sigma, N)) # 将预测曲线当作观测数据 data np.array([forecast[:, 0], forecast[:, 1], forecast[:, 2], forecast[:, 3]]).T # S, E, I, R 四列第 2 步用扰动参数拟合验证参数可辨识性# 用偏离真实值的初值beta0.4, gamma0.2, sigma0.1重新拟合 parameters, initial_conditions SEIR.get_parameters( S_data[0], E_data[0], I_data[0], R_data[0], N, betabeta 0.4, gammagamma 0.2, sigmasigma 0.1, S0_fixedTrue, E0_fixedTrue, I0_fixedTrue, R0_fixedTrue, S0_max10e6, I0_max5e6, R0_max10e6, ) seir EpidemicModel(SEIR, parametersparameters, datadata, initial_conditionsinitial_conditions) seir.fit() # 拟合结果应能恢复到真实参数 assert np.isclose(beta, seir.fitted_parameters[beta]) assert np.isclose(gamma, seir.fitted_parameters[gamma]) assert np.isclose(sigma, seir.fitted_parameters[sigma])第 3 步仅用最近一段时间的数据拟合EpidemicModel(..., fit_period10)或fit(fit_period10)会让残差只取最近 10 个时点residual中的residual residual[-self.fit_period:]适用于疫情早期观测数据稀疏、后期数据质量更高或关注近期动态的场景。仓库测试对fit_period10的情形同样验证了参数可恢复test_epidemiology.py。数据格式约定data为形状(n_timesteps, n_compartments)的np.ndarraySEIR 对应 4 列列顺序与calibrate的状态解包顺序一致S, E, I, Rtime_range默认为np.arange(data.shape[0])即默认以每个数据行代表一个单位时间步通常为一天若既未传入data也未在构造时提供self.datafit()会抛出ValueError(No data to fit the model on!)同理缺初始条件或缺参数都会得到明确的ValueError提示。时间序列层面的高层封装SEIRModel除了底层SEIR EpidemicModel的组合gs-quant 还在时序统计模块提供了开箱即用的高层封装SEIRModelgs_quant/timeseries/statistics.py与SIRModel同族可直接对接pd.Series形式的仓室人口序列。from gs_quant.timeseries.statistics import SEIRModel # s/e/i/r 可为 pd.Series按日期索引的各仓室人口序列n 为总人口 model SEIRModel(betaNone, gammaNone, sigmaNone, ss, ee, ii, rr, nn, fitTrue, fit_periodNone)核心行为对应源码 L1497-L1590未显式传入s/e/i/r时自动以sn、e1、i1、r0填充n缺省为 100若四个状态均为Nonefit自动置为Falsefit参数必须是布尔值否则抛出MqTypeError(expected a boolean value for fit)测试 test_statistics.py 专门验证了fit0会触发该异常beta/gamma/sigma未指定时取默认初值0.9 / 0.01 / 0.2且拟合期由各序列索引的起止日期结合DataContext决定内部实例化EpidemicModel(SEIR, ...)完成fit与solve并输出带日期索引的预测序列predict_s()、predict_e()、predict_i()、predict_r()以及拟合后的s0()/e0()/i0()/r0()/beta()/gamma()/sigma()参数取值方法这些取值方法均带plot_method装饰器可接入 gs-quant 的绘图体系直接可视化。时序侧测试 test_statistics.py 使用scipy.integrate.odeint手工生成 SEIR 曲线后喂给SEIRModel断言拟合参数与真实值误差小于 0.01、预测序列长度等于时间跨度并验证了fitFalse时模型直接使用用户给定参数不重估的行为。模型家族速览SEIR 在 gs-quant 流行病学模块中的定位SEIR 并非孤立类理解它在 gs_quant/models/epidemiology.py 中的定位有助于正确选型模型类仓室状态关键参数适用场景SIRS, I, Rbeta, gamma无潜伏期的快速传播过程SEIR本文主题S, E, I, Rbeta, gamma, sigma存在潜伏期Exposed的过程SEIRCMS, E, I, R, C, M上述 eta管控折减、epsilon病死率、T管控生效时间叠加累计确诊C与累计死亡M的观测建模可刻画隔离/封锁对传播率的时变影响SEIRCMAgeStratified每个年龄组一组 S/E/I/R/C/M按年龄组分组的 epsilon_k 等按年龄分层、各年龄组病死率不同的精细化建模其中SEIRCM与SEIRCMAgeStratified依赖工具函数switch(t, T, eta, xi, nu)epidemiology.py实现从时刻 T 开始传播速率以指数衰减形式从 1×β 降到 η×β的管控效应eta表示管控后的保留比例如隔离使传播率降低 60% 则eta0.4xi控制衰减斜率nu控制衰减峰值相对T的平移当T0时不启用该效应。若不需要管控效应设置eta1.0即可关闭。SEIRCM的基线来自 2020 年 3 月的 medRxiv 论文源码 docstring 中给出了原始出处读者可直接在 源码 中查看引用信息。使用注意事项与适用边界确定性 ODE 框架calibrate返回的是确定性导数solve使用odeint数值积分模型输出是确定性的仓室人数曲线不包含随机性也不适合描述个体异质性参数可辨识性依赖数据从仓库测试看在数据恰好由已知参数生成的理想条件下Levenberg-Marquardt 最小二乘可以精确恢复参数但对真实疫情数据观测通常只覆盖 I、R 等可观测仓室E 仓室难以直接观测拟合结果应结合fit_period、参数上下界与自定义error函数谨慎解读fit_period只影响残差截取它不改变求解区间仅决定优化器在多大时间窗口上评估拟合优度总人口 N 守恒SEIR 的N参数在拟合中固定不变模型隐含 SEIRN 的封闭系统假设适用于较短时间窗内的疫情演化版本与依赖本模块依赖numpy、scipyodeint与lmfitParameters、minimize、report_fit对应依赖声明见仓库 requirements.txt引入该模块前请确保依赖已安装。总结本文围绕 SEIR 类文档 的三个公开方法展开calibrate定义了四仓室微分方程与参数双形态读取逻辑get_parameters建立了动力学参数可拟合、初始条件默认固定的参数体系二者与EpidemicModel的solve/residual/fit引擎共同构成完整的拟合-预测管线时序模块的SEIRModel则提供了面向pd.Series的开箱即用封装。若需扩展到带管控措施、死亡统计或年龄分层的场景可继续研究同模块的SEIRCM与SEIRCMAgeStratified其文档与测试同样位于本仓库 docs/classes 与 gs_quant/test/models 目录下。【免费下载链接】gs-quantPython toolkit for quantitative finance项目地址: https://gitcode.com/GitHub_Trending/gs/gs-quant创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价