SEIAR模型

使用Python实现SEIAR模型,模拟流行病传播过程


日期

SEIAR模型

1 概述

SEIAR模型通常适用于预测一些急性传染病的流行趋势,这类疾病具有传染性强,传播途径简单直接,存在隐性感染者,潜伏期短,感染后一段时间具有传染性,病程短,考虑治愈的过程,无免疫保护等特点。 S为易感者,E为暴露者,I为显性感染者,A为隐性感染者,R为康复者。S仓室以单位时间betaS(I+κA)的速率向E仓室流入,E仓室以单位时间betaS(I+κA)的速率向E仓室流入

1.1 模型假设

在一起暴发疫情中,不考虑人口流动和空间分布的影响,疾病传播仅考虑人传人,感染率在疾病流行过程中保持不变,康复者获得暂时性免疫,再次感染者与初始易感者具有相同感染风险等假设的前提下,建立SEIARS模型。

1.2 模型描述

SEIARS模型考虑了无症状感染者(A)和免疫力衰退(Rs)的特点,特别适合模拟以下几类疾病:新型冠状病毒(COVID-19);流感病毒(Influenza);诺如病毒(Norovirus);呼吸道合胞病毒(RSV)。

1.3 模型仓室及参数含义

S为易感者,E为暴露者,I为显性感染者, A为隐性感染者,R为恢复者。

参数 含义
( S ) 易感者人数:未感染但可能被感染的人群
( E ) 暴露者人数:已被感染但尚未具有传染性的人群
( I ) 感染者人数:具有传染性并能传播疾病的人群
( A ) 无症状感染者人数:无症状但具有一定传染性的人群
( R ) 康复者人数:感染者经过病程后康复的人群
( N ) 总人口数( N = S + E + I + A ),假设人口总数不变
( $\beta$ ) 传播率:每个感染者或无症状感染者在单位时间内感染易感者的概率
( $\omega$ ) 暴露者转化速率:暴露者 ( E ) 转化为感染者的速率
( $\omega$') 暴露者转化速率:暴露者 ( E ) 转化为无症状感染者的速率
( p ) 发病概率:暴露者 ( E ) 转化为感染者 ( I ) 的概率
( 1-p ) 无症状概率:暴露者 ( E ) 转化为无症状感染者 ( A ) 的概率
( $\kappa$ ) 隐形感染者相对患者的传染力的倍数
( $\gamma$ ) 显性感染者变为恢复者的速率,病程倒数
( $\gamma$') 隐性感染者变为恢复者的速率
( $\epsilon$) 恢复者失去免疫力的速率

2 模型流程图及方程

SEIAR流程图 $$ \begin{cases} dS/dt = -\beta * S * (I + \kappa * A) / N + \epsilon * R \\
dE/dt = \beta * S * (I + \kappa * A) / N - ( p*\omega+ (1-p)*\omega') * E \\
dI/dt = (1-p)*\omega * E - \gamma * I \\
dA/dt = p*\omega * E - \gamma' * A\\
dR/dt = \gamma * I + \gamma' * A - \epsilon * R \end{cases} $$

3 适用疾病流行条件

疾病同时存在显性感染者和无症状感染者,康复者获得暂时性免疫,但存在免疫力衰退的情况

4 代码(R /Python)

import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt

def seiar_model(y, t, N, beta, kappa, p, omega1 , omega2, gamma1, gamma2, epsilon):
    """
    SEIAR model with waning immunity
    S: Susceptible
    E: Exposed
    I: Infectious (symptomatic)
    A: Asymptomatic
    R: Recovered
    """
    S, E, I, A, R = y
    
    # Model equations
    dSdt = -beta * S * (I + kappa * A) / N + epsilon * R
    dEdt = beta * S * (I + kappa * A) / N - ( p*omega1 + (1-p)*omega2) * E
    dIdt = (1-p)*omega1 * E - gamma1 * I
    dAdt = p*omega2 * E - gamma2 * A
    dRdt = gamma1 * I + gamma2 * A - epsilon * R
    
    return [dSdt, dEdt, dIdt, dAdt, dRdt]

# Model parameters
params = {
    'beta': 0.001,     # transmission rate
    'kappa': 0.5,    # relative infectivity of asymptomatic cases
    'p': 0.15,        # proportion of asymptomatic cases
    'omega1': 0.50,   # rate of becoming symptomatic
    'omega2': 0.80,  # rate of becoming asymptomatic
    'gamma1': 0.20,   # recovery rate for symptomatic
    'gamma2': 0.25,  # recovery rate for asymptomatic
    'epsilon': 0.0027  # immunity waning rate
}

# Simulation settings
N = 10000  # total population
I0 = 10   # initial infectious cases
days = 50  # simulation period

# Calculate initial conditions
E0 = I0 * 2  # initial exposed (assume twice the number of infectious)
A0 = I0 * params['p'] / (1 - params['p'])  # initial asymptomatic based on p
R0 = 0  # initial recovered
S0 = N - E0 - I0 - A0 - R0  # initial susceptible

# Initial conditions vector
y0 = [S0, E0, I0, A0, R0]

# Time points
t = np.linspace(0, days, days + 1)

# Solve the differential equations
solution = odeint(seiar_model, y0, t, args=(N, 
                                           params['beta'],
                                           params['kappa'],
                                           params['p'],
                                           params['omega1'],
                                           params['omega2'],
                                           params['gamma1'],
                                           params['gamma2'],
                                           params['epsilon']))

# Plot results
plt.figure(figsize=(12, 8))
categories = ['Exposed (E)', 'Infectious (I)', 'Asymptomatic (A)', 'Recovered (R)']
colors = ['#FFC107', '#DC3545', '#28A745', '#17A2B8']  # Harmonious color scheme

for i, (cat, col) in enumerate(zip(categories, colors), start=1):
    plt.plot(t, solution[:, i], 
             label=cat, 
             color=col,
             linewidth=2)

plt.xlabel('Time (days)', fontsize=12)
plt.ylabel('Population', fontsize=12)
plt.title('SEIAR Model Simulation', fontsize=14)
plt.legend(bbox_to_anchor=(1.05, 1), 
          loc='upper left', 
          borderaxespad=0.,
          fontsize=10)
plt.grid(True, linestyle='--', alpha=0.7)
plt.tight_layout()
plt.show()

# Print peak values and their timing
for i, cat in enumerate(categories, start=1):
    peak_value = max(solution[:, i])
    peak_day = t[np.argmax(solution[:, i])]
    print(f"\n{cat}:")
    print(f"Peak value: {peak_value:.0f}")
    print(f"Peak day: {peak_day:.1f}")
    
# Calculate and print final sizes
print("\nFinal sizes:")
for i, cat in enumerate(categories, start=1):
    final_size = solution[-1, i]
    percentage = (final_size / N) * 100
    print(f"{cat}: {final_size:.0f} ({percentage:.1f}%)")


#### 4.2  结果

png


​ Exposed (E): ​ Peak value: 20 ​ Peak day: 0.0 ​
​ Infectious (I): ​ Peak value: 14 ​ Peak day: 2.0 ​
​ Asymptomatic (A): ​ Peak value: 3 ​ Peak day: 2.0 ​
Recovered (R): Peak value: 25 Peak day: 22.0

Final sizes:
Exposed (E): 0 (0.0%)
Infectious (I): 0 (0.0%)
Asymptomatic (A): 0 (0.0%)
Recovered (R): 23 (0.2%)

模拟为,在总人口数为1万的小区或学校中流感疫情的发生发展,初始感染人口为10人。随着感染的进行,到第3天时,新增感染人数达到顶峰,到第30天时新增感染人数趋于0。

5 扩展(保证仓室不变)

例:传播过程中加入干预措施、改变仓室流向…

注:保证上述描述不变情况下可自行扩展说明书。

谢昉
闽南北混血儿、马兆海鸥守护者