Python小白的数学建模课-B5. 新冠疫情 SEIR模型
Posted YouCans
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python小白的数学建模课-B5. 新冠疫情 SEIR模型相关的知识,希望对你有一定的参考价值。
传染病的数学模型是数学建模中的典型问题,常见的传染病模型有 SI、SIR、SIRS、SEIR 模型。
考虑存在易感者、暴露者、患病者和康复者四类人群,适用于具有潜伏期、治愈后获得终身免疫的传染病。
本文详细给出了 SEIR 模型微分方程的建模、例程、结果和分析,让小白都能懂。
『Python小白的数学建模课 @ Youcans』带你从数模小白成为国赛达人。
欢迎关注『Python小白的数学建模课 @ Youcans』系列,每周持续更新
Python小白的数学建模课-B2. 新冠疫情 SI模型
Python小白的数学建模课-B3. 新冠疫情 SIS模型
Python小白的数学建模课-B4. 新冠疫情 SIR模型
Python小白的数学建模课-B5. 新冠疫情 SEIR模型
Python小白的数学建模课-B6. 新冠疫情 SEIR改进模型
Python小白的数学建模课-09.微分方程模型
Python小白的数学建模课-10.微分方程边值问题
1. SEIR 模型
1.1 SEIR 模型的提出
建立传染病的数学模型来描述传染病的传播过程,要根据传染病的发病机理和传播规律, 结合疫情数据进行拟合分析,可以认识传染病的发展趋势,预测疫情持续时间和规模,分析和模拟各种防控措施对疫情发展的影响程度, 为传染病防控工作提供决策指导,具有重要的理论意义和现实意义。
SI 模型是最简单的传染病传播模型,把人群分为易感者(S 类)和患病者(I 类)两类,通过 SI 模型可以预测传染病高潮的到来;提高卫生水平、强化防控手段,降低病人的日接触率,可以推迟传染病高潮的到来。在 SI 模型基础上发展的 SIS 模型考虑患病者可以治愈而变成易感者,SIS 模型表面传染期接触数 σ \\sigma σ 是传染病传播和防控的关键指标,决定了疫情终将清零或演变为地方病长期存在。在 SI 模型基础上考虑病愈免疫的康复者(R 类)就得到 SIR 模型,通过 SIR 模型也揭示传染期接触数 σ \\sigma σ 是传染病传播的阈值,满足 s 0 > 1 / σ s_0>1/\\sigma s0>1/σ 才会发生传染病蔓延,由此可以分析各种防控措施,如:提高卫生水平来降低日接触率 λ \\lambda λ、提高医疗水平来提高日治愈率 μ \\mu μ,通过预防接种达到群体免疫来降低 s 0 s_0 s0 等。
传染病大多具有潜伏期(incubation period),也叫隐蔽期,是指从被病原体侵入肌体到最早临床症状出现的一段时间。在潜伏期的后期一般具有传染性。不同的传染病的潜伏期长短不同,从短至数小时到长达数年,但同一种传染病有固定的(平均)潜伏期。例如,流感的潜伏期为 1~3天,冠状病毒感染的潜伏期为4~7天,新型冠状病毒肺炎传染病(COVID-19)的潜伏期为1-14天(* 来自:新型冠状病毒肺炎诊疗方案试行第八版,潜伏时间 1~14天,多为3~7天,在潜伏期具有传染性),肺结核的潜伏期从数周到数十年。
SEIR 模型考虑存在易感者(Susceptible)、暴露者(Exposed)、患病者(Infectious)和康复者(Recovered)四类人群,适用于具有潜伏期、治愈后获得终身免疫的传染病。易感者(S 类)被感染后成为潜伏者(E类),随后发病成为患病者(I 类),治愈后成为康复者(R类)。这种情况更为复杂,也更为接近实际情况。
SEIR 模型的仓室结构示意图如下:
1.2 SEIR 模型假设
-
考察地区的总人数 N 不变,即不考虑生死或迁移;
-
人群分为易感者(S 类)、暴露者(E 类)、患病者(I 类)和康复者(R 类)四类;
-
易感者(S 类)与患病者(I 类)有效接触即变为暴露者(E 类),暴露者(E 类)经过平均潜伏期后成为患病者(I 类);患病者(I 类)可被治愈,治愈后变为康复者(R 类);康复者(R类)获得终身免疫不再易感;
-
将第 t 天时 S 类、E 类、I 类、R 类人群的占比记为 s ( t ) s(t) s(t)、 e ( t ) e(t) e(t)、 i ( t ) i(t) i(t)、 r ( t ) r(t) r(t),数量分别为 S ( t ) S(t) S(t)、 E ( t ) E(t) E(t)、 I ( t ) I(t) I(t)、 R ( t ) R(t) R(t);初始日期 t = 0 t=0 t=0 时,各类人群占比的初值为 s 0 s_0 s0、 e 0 e_0 e0、 i 0 i_0 i0、 r 0 r_0 r0;
-
日接触数 λ \\lambda λ,每个患病者每天有效接触的易感者的平均人数;
-
日发病率 δ \\delta δ,每天发病成为患病者的暴露者占暴露者总数的比例;
-
日治愈率 μ \\mu μ,每天被治愈的患病者人数占患病者总数的比例,即平均治愈天数为 1 / μ 1/\\mu 1/μ;
-
传染期接触数 σ = λ / μ \\sigma = \\lambda / \\mu σ=λ/μ,即每个患病者在整个传染期内有效接触的易感者人数。
1.3 SEIR 模型的微分方程
由
N
d
s
d
t
=
−
N
λ
s
i
N
d
e
d
t
=
N
λ
s
i
−
N
δ
e
N
d
i
d
t
=
N
δ
e
−
N
μ
i
N
d
r
d
t
=
N
μ
i
\\begincases N \\fracdsdt = - N \\lambda s i\\\\ N \\fracdedt = N \\lambda s i - N \\delta e\\\\ N \\fracdidt = N \\delta e - N \\mu i\\\\ N \\fracdrdt = N \\mu i\\\\ \\endcases
⎩⎪⎪⎪⎨⎪⎪⎪⎧Ndtds=−NλsiNdtde=Nλsi−NδeNdtdi=Nδe−NμiNdtdr=Nμi
得:
d
s
d
t
=
−
λ
s
i
,
s
(
0
)
=
s
0
d
e
d
t
=
λ
s
i
−
δ
e
,
e
(
0
)
=
e
0
d
i
d
t
=
δ
e
−
μ
i
,
i
(
0
)
=
i
0
\\begincases \\fracdsdt = -\\lambda s i, &s(0)=s_0\\\\ \\fracdedt = \\lambda s i - \\delta e, &e(0)=e_0\\\\ \\fracdidt = \\delta e - \\mu i, &i(0)=i_0 \\endcases
⎩⎪⎨⎪⎧dtds=−λsi,dtde=λsi−δe,dtdi=δe−μi,s(0)=s0e(0)=e0i(0)=i0
SEIR 模型不能求出解析解,可以通过数值计算方法求解。
2. SEIR 模型的 Python 编程
2.1 Scipy 工具包求解微分方程组
SIS 模型是常微分方程初值问题,可以使用 Scipy 工具包的 scipy.integrate.odeint() 函数求数值解。
scipy.integrate.odeint(func, y0, t, args=())
**scipy.integrate.odeint() **是求解微分方程的具体方法,通过数值积分来求解常微分方程组。
odeint() 的主要参数:
- func: callable(y, t, …) 导数函数 f ( y , t ) f(y,t) f(y,t) ,即 y 在 t 处的导数,以函数的形式表示
- y0: array: 初始条件 y 0 y_0 y0,注意 SEIR模型是二元常微分方程组, 初始条件为数组向量 y 0 = [ i 0 , s 0 ] y_0=[i_0, s_0] y0=[i0,s0]
- t: array: 求解函数值对应的时间点的序列。序列的第一个元素是与初始条件 y 0 y_0 y0 对应的初始时间 t 0 t_0 t0;时间序列必须是单调递增或单调递减的,允许重复值。
- args: 向导数函数 func 传递参数。当导数函数 f ( y , t , p 1 , p 2 , . . ) f(y,t,p1,p2,..) f(y,t,p1,p2,..) 包括可变参数 p1,p2… 时,通过 args =(p1,p2,…) 可以将参数p1,p2… 传递给导数函数 func。
odeint() 的返回值:
- y: array 数组,形状为 (len(t),len(y0),给出时间序列 t 中每个时刻的 y 值。
2.2 odeint() 求解 SEIR 模型的编程步骤
- 导入 scipy、numpy、matplotlib 包。
- 定义导数函数 f ( y , t ) f(y,t) f(y,t)。注意对于常微分方程(例如 SI模型)和常微分方程组(SEIR模型),y 分别表示标量和向量,函数定义略有不同,以下给出两种情况的例程以供对比。
常微分方程的导数定义(SIS模型)
def dySIS(y, t, lamda, mu): # SIS 模型,导数函数
dy_dt = lamda*y*(1-y) - mu*y # di/dt = lamda*i*(1-i)-mu*i
return dy_dt
常微分方程组的导数定义(SEIR模型)
def dySEIR(y, t, lamda, delta, mu): # SEIR 模型,导数函数
s, e, i = y
ds_dt = - lamda*s*i # ds/dt = -lamda*s*i
de_dt = lamda*s*i - delta*e # de/dt = lamda*s*i - delta*e
di_dt = delta*e - mu*i # di/dt = delta*e - mu*i
return np.array([ds_dt,de_dt,di_dt])
Python 可以直接对向量、向量函数进行定义和赋值,使程序更为简洁。但考虑读者主要是 Python 小白,又涉及到看着就心烦的微分方程组,所以我们宁愿把程序写得累赘一些,便于读者将程序与前面的微分方程组逐项对应。
- 定义初值
y
0
y_0
y0 和
y
y
y 的定义区间
[
t
0
,
t
]
[t_0,
以上是关于Python小白的数学建模课-B5. 新冠疫情 SEIR模型的主要内容,如果未能解决你的问题,请参考以下文章
Python小白的数学建模课-A3. 12个新冠疫情数模竞赛赛题与点评