├── images └── 1.png ├── .idea ├── .gitignore ├── vcs.xml ├── inspectionProfiles │ └── profiles_settings.xml ├── misc.xml └── COVID-19-SEIR-LSTM.iml ├── NCP_cum_pred.png ├── SEIR_basic.png ├── real_data.xlsx ├── NCP_new_predict.png ├── NCP_active_predict.png ├── SEIR_20200123_Intervention.png ├── SEIR_20200202_Intervention.png ├── README.md ├── NCP_cum_pred.py ├── SEIR_basic.py ├── NCP_active_predict.py ├── NCP_new_predict.py ├── SEIR_20200202_Intervention.py └── SEIR_20200123_Intervention.py /images/1.png: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | /modules.xml 5 | -------------------------------------------------------------------------------- /NCP_cum_pred.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AndyYue1893/COVID-19-SEIR-LSTM/HEAD/NCP_cum_pred.png -------------------------------------------------------------------------------- /SEIR_basic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AndyYue1893/COVID-19-SEIR-LSTM/HEAD/SEIR_basic.png -------------------------------------------------------------------------------- /real_data.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AndyYue1893/COVID-19-SEIR-LSTM/HEAD/real_data.xlsx -------------------------------------------------------------------------------- /NCP_new_predict.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AndyYue1893/COVID-19-SEIR-LSTM/HEAD/NCP_new_predict.png -------------------------------------------------------------------------------- /NCP_active_predict.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AndyYue1893/COVID-19-SEIR-LSTM/HEAD/NCP_active_predict.png -------------------------------------------------------------------------------- /SEIR_20200123_Intervention.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AndyYue1893/COVID-19-SEIR-LSTM/HEAD/SEIR_20200123_Intervention.png -------------------------------------------------------------------------------- /SEIR_20200202_Intervention.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AndyYue1893/COVID-19-SEIR-LSTM/HEAD/SEIR_20200202_Intervention.png -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/COVID-19-SEIR-LSTM.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # COVID-19-SEIR-LSTM 2 | 本项目实现2019新型冠状病毒肺炎(COVID-19)预测,采用经典传染病动力学模型SEIR,通过控制接触率来改变干预程度,体现防控的意义。 3 | 4 | 另外,采用LSTM神经网络实现一定程度的预测,输入前三天的数据,预测第四天的数据。下一步要增加干预值作为输入,优化输入输出的序列长度,更好地实现预测。 5 | 6 | SEIR and LSTM prediction of the epidemics trend of COVID-19. 7 | 8 | 先上图 9 | ![image](https://github.com/AndyYue1893/Novel-Coronavirus-Pneumonia-SEIR-LSTM/blob/master/SEIR_basic.png) 10 | ![image](https://github.com/AndyYue1893/Novel-Coronavirus-Pneumonia-SEIR-LSTM/blob/master/SEIR_20200123_Intervention.png)![image](https://github.com/AndyYue1893/Novel-Coronavirus-Pneumonia-SEIR-LSTM/blob/master/SEIR_20200202_Intervention.png) 11 | ![image](https://github.com/AndyYue1893/Novel-Coronavirus-Pneumonia-SEIR-LSTM/blob/master/NCP_active_predict.png)![image](https://github.com/AndyYue1893/Novel-Coronavirus-Pneumonia-SEIR-LSTM/blob/master/NCP_new_predict.png)![image](https://github.com/AndyYue1893/Novel-Coronavirus-Pneumonia-SEIR-LSTM/blob/master/NCP_cum_pred.png) 12 | -------------------------------------------------------------------------------- /NCP_cum_pred.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | import numpy as np 4 | import matplotlib.pyplot as plt 5 | 6 | # 数据预处理 7 | import pandas as pd 8 | df = pd.read_excel('real_data.xlsx') 9 | value = df['全国累计确诊'].values[10:67] 10 | print(len(value)) 11 | x = [] 12 | y = [] 13 | seq = 3 14 | for i in range(len(value)-seq-1): 15 | x.append(value[i:i+seq]) 16 | y.append(value[i+seq]) 17 | #print(x, '\n', y) 18 | 19 | train_x = (torch.tensor(x[0:40]).float()/100000.).reshape(-1, seq, 1) 20 | train_y = (torch.tensor(y[0:40]).float()/100000.).reshape(-1, 1) 21 | test_x = (torch.tensor(x[40:57]).float()/100000.).reshape(-1, seq, 1) 22 | test_y = (torch.tensor(y[40:57]).float()/100000.).reshape(-1, 1) 23 | print(test_y) 24 | # 模型训练 25 | class LSTM(nn.Module): 26 | def __init__(self): 27 | super(LSTM, self).__init__() 28 | self.lstm = nn.LSTM(input_size=1, hidden_size=16, num_layers=1, batch_first=True) 29 | self.linear = nn.Linear(16 * seq, 1) 30 | def forward(self, x): 31 | x, (h, c) = self.lstm(x) 32 | x = x.reshape(-1, 16 * seq) 33 | x = self.linear(x) 34 | return x 35 | 36 | # 模型训练 37 | model = LSTM() 38 | optimzer = torch.optim.Adam(model.parameters(), lr=0.005) 39 | loss_func = nn.MSELoss() 40 | model.train() 41 | 42 | for epoch in range(400): 43 | output = model(train_x) 44 | loss = loss_func(output, train_y) 45 | optimzer.zero_grad() 46 | loss.backward() 47 | optimzer.step() 48 | if epoch % 20 == 0: 49 | tess_loss = loss_func(model(test_x), test_y) 50 | print("epoch:{}, train_loss:{}, test_loss:{}".format(epoch, loss, tess_loss)) 51 | 52 | # 模型预测、画图 53 | model.eval() 54 | prediction = list((model(train_x).data.reshape(-1))*100000) + list((model(test_x).data.reshape(-1))*100000) 55 | plt.plot(value[3:], label='True Value') 56 | plt.plot(prediction[:41], label='LSTM fit') 57 | plt.plot(np.arange(40, 53, 1), prediction[40:], label='LSTM pred') 58 | print(len(value[3:])) 59 | print(len(prediction[40:])) 60 | plt.legend(loc='best') 61 | plt.title('Cumulative infections prediction(mainland China)') 62 | plt.xlabel('Day') 63 | plt.ylabel('Cumulative Cases') 64 | plt.show() 65 | -------------------------------------------------------------------------------- /SEIR_basic.py: -------------------------------------------------------------------------------- 1 | # SEIR传染病模型仿真 2 | "View more, visit my github repository: https://github.com/AndyYue1893/Novel-Coronavirus-Pneumonia-SEIR-LSTM" 3 | '没有解析解,ode求解数值解' 4 | '重点是动力学模型的准确性(SEIR还是SEIRS、SIQR、SIQS模型,以及媒体宣传和随机因素的影响),难点是beta,gamma,sigma/Te的取值' 5 | '模型忽略迁入率和迁出率,死亡率,参数设置参考钟院士等文章http://dx.doi.org/10.21037/jtd.2020.02.64' 6 | ###################################### 7 | # N: 区域内总人口 # 8 | # S: 易感者 # 9 | # E: 潜伏者 # 10 | # I: 感染者 # 11 | # R: 康复者 # 12 | # r: 每天接触的人数 # 13 | # r2: 潜伏者每天接触的人数 # 14 | # beta1: 感染者传染给易感者的概率, I——>S # 15 | # beta2: 潜伏者感染易感者的概率, E——>S # 16 | # sigma: 潜伏者转化为感染者的概率, E——>I # 17 | # gama: 康复概率, I——>R # 18 | # T: 传播时间 # 19 | ####################################### 20 | 21 | import numpy as np 22 | import matplotlib.pyplot as plt 23 | import scipy.integrate as spi 24 | N = 100000 # 湖北省为6000 0000 25 | E_0 = 0 26 | I_0 = 1 27 | R_0 = 0 28 | S_0 = N - E_0 - I_0 - R_0 29 | beta1 = 0.78735 # 真实数据拟合得出 30 | beta2 = 0.15747 31 | # r2 * beta2 = 2 32 | sigma = 0.1 # 1/14, 潜伏期的倒数 33 | gamma = 0.1 # 1/7, 感染期的倒数 34 | r = 1 # 政府干预措施决定 35 | T = 150 36 | 37 | #ode求解 38 | INI = [S_0, E_0, I_0, R_0] 39 | def SEIR(inivalue, _): 40 | X = inivalue 41 | Y = np.zeros(4) 42 | # S数量 43 | Y[0] = - (r * beta1 * X[0] * X[2]) / N - (r * beta2 * X[0] * X[1]) / N 44 | # E数量 45 | Y[1] = (r * beta1 * X[0] * X[2]) / N + (r * beta2 * X[0] * X[1]) / N - sigma * X[1] 46 | # I数量 47 | Y[2] = sigma * X[1] - gamma * X[2] 48 | # R数量 49 | Y[3] = gamma * X[2] 50 | return Y 51 | 52 | T_range = np.arange(0, T+1) 53 | Res = spi.odeint(SEIR, INI, T_range) 54 | S_t = Res[:, 0] 55 | E_t = Res[:, 1] 56 | I_t = Res[:, 2] 57 | R_t = Res[:, 3] 58 | 59 | plt.plot(S_t, color='blue', label='Susceptibles')#, marker='.') 60 | plt.plot(E_t, color='grey', label='Exposed') 61 | plt.plot(I_t, color='red', label='Infected') 62 | plt.plot(R_t, color='green', label='Removed') 63 | plt.xlabel('Day') 64 | plt.ylabel('Number') 65 | plt.title('SEIR Model') 66 | plt.legend() 67 | plt.show() -------------------------------------------------------------------------------- /NCP_active_predict.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | import numpy as np 4 | import matplotlib.pyplot as plt 5 | 6 | # 数据预处理 7 | import pandas as pd 8 | df = pd.read_excel('real_data.xlsx') # 这个会直接默认读取到这个Excel的第一个表单 9 | value = df['湖北现有确诊'].values[0:67] 10 | #value = df['全国累计确诊'].values[10:50] 11 | print(len(value)) 12 | x = [] 13 | y = [] 14 | seq = 3 15 | for i in range(len(value)-seq): 16 | x.append(value[i:i+seq]) 17 | y.append(value[i+seq]) 18 | #print(x, '\n', y) 19 | print(len(x)) # 67 20 | 21 | train_x = (torch.tensor(x[:50]).float()/100000.).reshape(-1, seq, 1) 22 | train_y = (torch.tensor(y[:50]).float()/100000.).reshape(-1, 1) 23 | test_x = (torch.tensor(x[50:]).float()/100000.).reshape(-1, seq, 1) 24 | test_y = (torch.tensor(y[50:]).float()/100000.).reshape(-1, 1) 25 | print(len(train_x)) 26 | print(len(test_x)) 27 | 28 | # 模型训练 29 | class LSTM(nn.Module): 30 | def __init__(self): 31 | super(LSTM, self).__init__() 32 | self.lstm = nn.LSTM(input_size=1, hidden_size=16, num_layers=1, batch_first=True) 33 | self.linear = nn.Linear(16 * seq, 1) 34 | def forward(self, x): 35 | x, (h, c) = self.lstm(x) 36 | x = x.reshape(-1, 16 * seq) 37 | x = self.linear(x) 38 | return x 39 | 40 | # 模型训练 41 | model = LSTM() 42 | optimzer = torch.optim.Adam(model.parameters(), lr=0.005) 43 | loss_func = nn.MSELoss() 44 | model.train() 45 | 46 | for epoch in range(400): 47 | output = model(train_x) 48 | loss = loss_func(output, train_y) 49 | optimzer.zero_grad() 50 | loss.backward() 51 | optimzer.step() 52 | if epoch % 20 == 0: 53 | tess_loss = loss_func(model(test_x), test_y) 54 | print("epoch:{}, train_loss:{}, test_loss:{}".format(epoch, loss, tess_loss)) 55 | 56 | # 模型预测、画图 57 | model.eval() 58 | prediction = list((model(train_x).data.reshape(-1))*100000) + list((model(test_x).data.reshape(-1))*100000) 59 | plt.plot(value[3:], label='True Value') 60 | plt.plot(prediction[:51], label='LSTM fit') 61 | plt.plot(np.arange(50, 64, 1), prediction[50:64], label='LSTM pred') 62 | print(len(value[3:])) 63 | print(len(prediction)) 64 | plt.legend(loc='best') 65 | plt.title('Active infections prediction(Hubei province)') 66 | plt.xlabel('Day') 67 | plt.ylabel('Active Cases') 68 | plt.show() 69 | -------------------------------------------------------------------------------- /NCP_new_predict.py: -------------------------------------------------------------------------------- 1 | # 基于AI数据模型的疫情预测 2 | '考虑到传染病动力学建模的复杂性和参数确定的复杂度,采用LSTM神经网络对湖北省新增病例数预测,并对比体现防控的意义' 3 | 4 | import torch 5 | from torch import nn 6 | import numpy as np 7 | import matplotlib.pyplot as plt 8 | ''' 9 | # 数据预处理 10 | with open("data.txt", "r", encoding="utf-8") as f: 11 | data = f.read() 12 | print([data]) 13 | data = [row.split(',') for row in data.split("\n")] 14 | value = [int(each[1]) for each in data] 15 | print(data, '\n', value) 16 | # 异常点处理 17 | ''' 18 | import pandas as pd 19 | df = pd.read_excel('real_data.xlsx')#这个会直接默认读取到这个Excel的第一个表单 20 | value = df['湖北新增确诊'].values[0:67] 21 | #value = df['全国累计确诊'].values[10:50] 22 | print(len(value)) 23 | 24 | 25 | x = [] 26 | y = [] 27 | seq = 3 28 | for i in range(len(value)-seq-1): 29 | x.append(value[i:i+seq]) 30 | y.append(value[i+seq]) 31 | #print(x, '\n', y) 32 | 33 | train_x = (torch.tensor(x[:50]).float()/1000.).reshape(-1, seq, 1) 34 | train_y = (torch.tensor(y[:50]).float()/1000.).reshape(-1, 1) 35 | test_x = (torch.tensor(x[50:]).float()/1000.).reshape(-1, seq, 1) 36 | test_y = (torch.tensor(y[50:]).float()/1000.).reshape(-1, 1) 37 | #print(train_x, '\n', train_y) 38 | # 模型训练 39 | class LSTM(nn.Module): 40 | def __init__(self): 41 | super(LSTM, self).__init__() 42 | self.lstm = nn.LSTM(input_size=1, hidden_size=16, num_layers=1, batch_first=True) 43 | self.linear = nn.Linear(16 * seq, 1) 44 | def forward(self, x): 45 | x, (h, c) = self.lstm(x) 46 | x = x.reshape(-1, 16 * seq) 47 | x = self.linear(x) 48 | return x 49 | 50 | # 模型训练 51 | model = LSTM() 52 | optimzer = torch.optim.Adam(model.parameters(), lr=0.005) 53 | loss_func = nn.MSELoss() 54 | model.train() 55 | l = [] 56 | for epoch in range(600): 57 | output = model(train_x) 58 | loss = loss_func(output, train_y) 59 | l.append(loss) 60 | optimzer.zero_grad() 61 | loss.backward() 62 | optimzer.step() 63 | if epoch % 20 == 0: 64 | tess_loss = loss_func(model(test_x), test_y) 65 | print("epoch:{}, train_loss:{}, test_loss:{}".format(epoch, loss, tess_loss)) 66 | 67 | # 模型预测、画图 68 | model.eval() 69 | prediction = list((model(train_x).data.reshape(-1))*1000) + list((model(test_x).data.reshape(-1))*1000) 70 | print(len(value[3:]), len(prediction), len(np.arange(50, 64, 1)), len(prediction[50:64])) 71 | #print('train_x', train_x*1000, '\n', 'train_y', train_y*1000, '\n', 'test_x', test_x*1000, '\n', 'test_y', len(test_y), test_y*1000) 72 | plt.figure(1) 73 | plt.plot(value[3:], label='True Value') 74 | plt.plot(prediction[:51], label='LSTM fit') 75 | plt.plot(np.arange(50, 63, 1), prediction[50:64], label='LSTM pred') 76 | plt.legend(loc='best') 77 | plt.title('New daily infections prediction(Hubei province)') 78 | plt.xlabel('Day') 79 | plt.ylabel('New Confirmed Cases') 80 | #plt.figure(2) 81 | #plt.plot(l) 82 | plt.show() -------------------------------------------------------------------------------- /SEIR_20200202_Intervention.py: -------------------------------------------------------------------------------- 1 | # SEIR传染病模型仿真 2 | "View more, visit my github repository: https://github.com/AndyYue1893/Novel-Coronavirus-Pneumonia-SEIR-LSTM" 3 | '没有解析解,ode求解数值解' 4 | '重点是动力学模型的准确性(SEIR还是SEIRS、SIQR、SIQS模型,以及媒体宣传和随机因素的影响),难点是beta,gamma,sigma/Te的取值' 5 | '模型忽略迁入率和迁出率,潜伏者传染率beta2,参数设置参考钟院士等文章http://dx.doi.org/10.21037/jtd.2020.02.64' 6 | ###################################### 7 | # N: 区域内总人口 # 8 | # S: 易感者 # 9 | # E: 潜伏者 # 10 | # I: 感染者 # 11 | # R: 康复者 # 12 | # r: 每天接触的人数 # 13 | # r2: 潜伏者每天接触的人数 # 14 | # beta1: 感染者传染给易感者的概率, I——>S # 15 | # beta2: 潜伏者感染易感者的概率, E——>S # 16 | # sigma: 潜伏者转化为感染者的概率, E——>I # 17 | # gama: 康复概率, I——>R # 18 | # T: 传播时间 # 19 | ####################################### 20 | 21 | import numpy as np 22 | import matplotlib.pyplot as plt 23 | import scipy.integrate as spi 24 | 25 | # 阶段一,11.24 - 1.23 1.11 26 | N = 60000000 # 湖北省为6000万,武汉900万 27 | E_0 = 0 28 | I_0 = 1 29 | R_0 = 0 30 | S_0 = N - E_0 - I_0 - R_0 31 | b1 = 0.02 # 真实数据拟合得出 32 | b2 = 0.021/3#0.007 33 | # r2 * beta2 = 2 34 | sigma = 1/14 # 1/14, 潜伏期的倒数 35 | gamma = 1/7 # 1/7, 感染期的倒数 36 | r = 18 # 政府干预措施决定 37 | T = 84 38 | 39 | #ode求解 40 | INI = [S_0, E_0, I_0, R_0] 41 | def SEIR(inivalue, _): 42 | X = inivalue 43 | Y = np.zeros(4) 44 | # S数量 45 | Y[0] = - (r * b1 * X[0] * X[2]) / N - (r * b2 * X[0] * X[1]) / N 46 | # E数量 47 | Y[1] = (r * b1 * X[0] * X[2]) / N + (r * b2 * X[0] * X[1]) / N - sigma * X[1] 48 | # I数量 49 | Y[2] = sigma * X[1] - gamma * X[2] 50 | # R数量 51 | Y[3] = gamma * X[2] 52 | return Y 53 | 54 | T_range = np.arange(0, T+1) 55 | Res = spi.odeint(SEIR, INI, T_range) 56 | S_t = Res[:, 0] 57 | E_t = Res[:, 1] 58 | I_t = Res[:, 2] 59 | R_t = Res[:, 3] 60 | #print(I_t[60], type(I_t)) # 549 61 | #print(E_t[57]) 62 | 63 | 64 | # 阶段二,1.23后 65 | S_2 = S_t[T] 66 | E_2 = E_t[T] 67 | I_2 = I_t[T] 68 | R_2 = R_t[T] 69 | 70 | beta1 = 0.02#0.15747 # 真实数据拟合得出 71 | beta2 = 0.021/3#0.78735 72 | # r2 * beta2 = 2 73 | sigma2 = 1/4 # 1/14, 潜伏期的倒数 74 | #gamma = 1/6.736 # 1/7, 感染期的倒数 75 | r2 = 0.1 # 政府干预措施决定 76 | T2 = 150-T 77 | 78 | #ode求解 79 | INI = [S_2, E_2, I_2, R_2] 80 | def SEIR(inivalue, _): 81 | X = inivalue 82 | Y = np.zeros(4) 83 | # S数量 84 | Y[0] = - (r2 * beta1 * X[0] * X[2]) / N - (r2 * beta2 * X[0] * X[1]) / N 85 | # E数量 86 | Y[1] = (r2 * beta1 * X[0] * X[2]) / N + (r2 * beta2 * X[0] * X[1]) / N - sigma2 * X[1] 87 | # I数量 88 | Y[2] = sigma2 * X[1] - gamma * X[2] 89 | # R数量 90 | Y[3] = gamma * X[2] 91 | return Y 92 | 93 | T_range = np.arange(0, T2+1) 94 | Res = spi.odeint(SEIR, INI, T_range) 95 | S_t2 = Res[:, 0] 96 | E_t2 = Res[:, 1] 97 | I_t2 = Res[:, 2] 98 | R_t2 = Res[:, 3] 99 | 100 | plt.figure(figsize=(10, 6)) 101 | #显示日期 102 | import pandas as pd 103 | xs = pd.date_range(start='20191124', periods=T+1, freq='1D')#生成2020-02-11类型的日期数组() 104 | #print(xs) 105 | xs2 = pd.date_range(start='20200216', periods=T2+1, freq='1D') 106 | 107 | #plt.plot(S_t, color='blue', label='Susceptibles')#, marker='.') 108 | plt.plot(xs, E_t, color='grey', label='Exposed', marker='.') 109 | plt.plot(xs2, E_t2, color='grey', label='Exposed Prediction') 110 | plt.plot(xs, I_t, color='red', label='Infected', marker='.') 111 | plt.plot(xs2, I_t2, color='red', label='Infected Prediction') 112 | plt.plot(xs, I_t + R_t, color='green', label='Infected + Removed', marker='.') 113 | plt.plot(xs2, I_t2 + R_t2, color='green', label='Cumulative Infections Prediction') 114 | #plt.plot(np.arange(0, T+1, 1), I_t + R_t, color='green', label='Removed') 115 | #plt.plot(np.arange(T, T+T2+1, 1), I_t2 + R_t2, color='green', label='Infected2') 116 | #plt.xlabel('Date') 117 | plt.ylabel('Number') 118 | plt.title('SEIR Prediction(Hubei province, 10 days later intervention)') 119 | plt.legend() 120 | 121 | xs3 = pd.date_range(start='20200202', periods=1, freq='1D') 122 | #plt.plot(xs3, np.arange(1000, 2000, 1000)) 123 | plt.annotate(r'$2.2-Intervention$', xy=(xs3, 200), xycoords='data', xytext=(-44, -60), textcoords='offset points', 124 | fontsize=10, arrowprops=dict(arrowstyle='->', connectionstyle='arc3, rad=0')) 125 | #print(I_t2) 126 | xs4 = pd.date_range(start='20200220', periods=1, freq='1D') 127 | plt.annotate(r'$2.20-Peak$', xy=(xs4, 103911), xycoords='data', xytext=(-25, -130), textcoords='offset points', 128 | fontsize=10, arrowprops=dict(arrowstyle='->', connectionstyle='arc3, rad=0')) 129 | #print(R_t2) 130 | xs5 = pd.date_range(start='20200420', periods=1, freq='1D') 131 | plt.annotate(r'4.20-Epidemic-Scale:261963', xy=(xs5, 261963), xycoords='data', xytext=(-70, -60), textcoords='offset points', 132 | fontsize=10, arrowprops=dict(arrowstyle='->', connectionstyle='arc3, rad=0')) 133 | #plt.text(30, 10, r'$This\ is\ the\ some\ text.\ \mu_j\ \sigma_i\ \alpha_t$') 134 | plt.show() -------------------------------------------------------------------------------- /SEIR_20200123_Intervention.py: -------------------------------------------------------------------------------- 1 | # SEIR传染病模型仿真 2 | "View more, visit my github repository: https://github.com/AndyYue1893/Novel-Coronavirus-Pneumonia-SEIR-LSTM" 3 | '没有解析解,ode求解数值解' 4 | '重点是动力学模型的准确性(SEIR还是SEIRS、SIQR、SIQS模型,以及媒体宣传和随机因素的影响),难点是beta,gamma,sigma/Te的取值' 5 | '模型忽略迁入率和迁出率,死亡率,参数设置参考钟院士等文章http://dx.doi.org/10.21037/jtd.2020.02.64' 6 | ###################################### 7 | # N: 区域内总人口 # 8 | # S: 易感者 # 9 | # E: 潜伏者 # 10 | # I: 感染者 # 11 | # R: 康复者 # 12 | # r: 每天接触的人数 # 13 | # r2: 潜伏者每天接触的人数 # 14 | # beta1: 感染者传染给易感者的概率, I——>S # 15 | # beta2: 潜伏者感染易感者的概率, E——>S # 16 | # sigma: 潜伏者转化为感染者的概率, E——>I # 17 | # gama: 康复概率, I——>R # 18 | # T: 传播时间 # 19 | ####################################### 20 | 21 | import numpy as np 22 | import matplotlib.pyplot as plt 23 | import scipy.integrate as spi 24 | import pytest # test git commit, 20240427 25 | 26 | # 阶段一,11.24 - 1.23 1.11 27 | N = 60000000 # 湖北省为6000万,武汉900万 28 | E_0 = 0 29 | I_0 = 1 30 | R_0 = 0 31 | S_0 = N - E_0 - I_0 - R_0 32 | beta1 = 0.02 # 真实数据拟合得出 33 | beta2 = 0.021/3 #0.007 34 | # r2 * beta2 = 2 35 | sigma = 1/14 # 1/14, 潜伏期的倒数 36 | gamma = 1/7 # 1/7, 感染期的倒数 37 | r = 18 # 政府干预措施决定 38 | T = 74 39 | 40 | #ode求解 41 | INI = [S_0, E_0, I_0, R_0] 42 | def SEIR(inivalue, _): 43 | X = inivalue 44 | Y = np.zeros(4) 45 | # S数量 46 | Y[0] = - (r * beta1 * X[0] * X[2]) / N - (r * beta2 * X[0] * X[1]) / N 47 | # E数量 48 | Y[1] = (r * beta1 * X[0] * X[2]) / N + (r * beta2 * X[0] * X[1]) / N - sigma * X[1] 49 | # I数量 50 | Y[2] = sigma * X[1] - gamma * X[2] 51 | # R数量 52 | Y[3] = gamma * X[2] 53 | return Y 54 | 55 | T_range = np.arange(0, T+1) 56 | Res = spi.odeint(SEIR, INI, T_range) 57 | S_t = Res[:, 0] 58 | E_t = Res[:, 1] 59 | I_t = Res[:, 2] 60 | R_t = Res[:, 3] 61 | 62 | 63 | # 阶段二,1.23后 64 | S_2 = S_t[T] 65 | E_2 = E_t[T] 66 | I_2 = I_t[T] 67 | R_2 = R_t[T] 68 | 69 | beta1 = 0.02#0.15747 # 真实数据拟合得出 70 | beta2 = 0.021/3 # 0.78735 71 | # r2 * beta2 = 2 72 | sigma2 = 1/4 # 1/14, 潜伏期的倒数 73 | #gamma = 1/6.736 # 1/7, 感染期的倒数 74 | r2 = 0.1 # 政府干预措施决定 75 | T2 = 150-T 76 | 77 | #ode求解 78 | INI = [S_2, E_2, I_2, R_2] 79 | def SEIR(inivalue, _): 80 | X = inivalue 81 | Y = np.zeros(4) 82 | # S数量 83 | Y[0] = - (r2 * beta1 * X[0] * X[2]) / N - (r2 * beta2 * X[0] * X[1]) / N 84 | # E数量 85 | Y[1] = (r2 * beta1 * X[0] * X[2]) / N + (r2 * beta2 * X[0] * X[1]) / N - sigma2 * X[1] 86 | # I数量 87 | Y[2] = sigma2 * X[1] - gamma * X[2] 88 | # R数量 89 | Y[3] = gamma * X[2] 90 | return Y 91 | 92 | T_range = np.arange(0, T2+1) 93 | Res = spi.odeint(SEIR, INI, T_range) 94 | S_t2 = Res[:, 0] 95 | E_t2 = Res[:, 1] 96 | I_t2 = Res[:, 2] 97 | R_t2 = Res[:, 3] 98 | 99 | #显示日期 100 | plt.figure(figsize=(10, 6)) 101 | import pandas as pd 102 | xs = pd.date_range(start='20191124', periods=T+1, freq='1D') # 生成2020-02-11类型的日期数组() 103 | #print(xs) 104 | xs2 = pd.date_range(start='20200206', periods=T2+1, freq='1D') 105 | 106 | #plt.plot(S_t, color='blue', label='Susceptibles')#, marker='.') 107 | plt.plot(xs, E_t, color='grey', label='Exposed', marker='.') 108 | plt.plot(xs2, E_t2, color='grey', label='Exposed Prediction') 109 | plt.plot(xs, I_t, color='red', label='Infected', marker='.') 110 | plt.plot(xs2, I_t2, color='red', label='Infected Prediction') 111 | plt.plot(xs, I_t + R_t, color='green', label='Infected + Removed', marker='.') 112 | plt.plot(xs2, I_t2 + R_t2, color='green', label='Cumulative Infections Prediction') 113 | #plt.plot(np.arange(0, T+1, 1), I_t + R_t, color='green', label='Removed') 114 | #plt.plot(np.arange(T, T+T2+1, 1), I_t2 + R_t2, color='green', label='Infected2') 115 | #plt.xlabel('Date') 116 | plt.ylabel('Number') 117 | plt.title('SEIR Prediction(Hubei Province, 1.23 Intervention)') 118 | plt.legend() 119 | 120 | xs3 = pd.date_range(start='20200123', periods=1, freq='1D') 121 | #plt.plot(xs3, np.arange(1000, 2000, 1000)) 122 | plt.annotate(r'$1.23-Intervention$', xy=(xs3, -3000), xycoords='data', xytext=(-47, -30), textcoords='offset points', 123 | fontsize=10, arrowprops=dict(arrowstyle='->', connectionstyle='arc3, rad=0')) 124 | 125 | xs4 = pd.date_range(start='20200210', periods=1, freq='1D') 126 | plt.annotate(r'$2.10-Peak$', xy=(xs4, 24700), xycoords='data', xytext=(-25, -130), textcoords='offset points', 127 | fontsize=10, arrowprops=dict(arrowstyle='->', connectionstyle='arc3, rad=0')) 128 | 129 | xs5 = pd.date_range(start='20200401', periods=1, freq='1D') 130 | plt.annotate(r'$4.1-Epidemic-Scale:62188$', xy=(xs5, 62188), xycoords='data', xytext=(-75, -60), textcoords='offset points', 131 | fontsize=10, arrowprops=dict(arrowstyle='->', connectionstyle='arc3, rad=0')) 132 | 133 | xs6 = pd.date_range(start='20200123', periods=1, freq='1D') 134 | plt.annotate(r'$1.23-Exposed:5257$', xy=(xs6, 5257), xycoords='data', xytext=(-180, -3), textcoords='offset points', 135 | fontsize=10, arrowprops=dict(arrowstyle='->', connectionstyle='arc3, rad=0')) 136 | 137 | xs7 = pd.date_range(start='20191124', periods=1, freq='1D') 138 | plt.annotate(r'$2019.11.24-0-Case$', xy=(xs7, -3000), xycoords='data', xytext=(-56, -30), textcoords='offset points', 139 | fontsize=10, arrowprops=dict(arrowstyle='->', connectionstyle='arc3, rad=0')) 140 | 141 | xs8 = pd.date_range(start='20200206', periods=1, freq='1D') 142 | plt.annotate(r'$14days-Delay$', xy=(xs8, 41000), xycoords='data', xytext=(-130, -3), textcoords='offset points', 143 | fontsize=10, arrowprops=dict(arrowstyle='<->', connectionstyle='arc3, rad=0')) 144 | #plt.text(30, 10, r'$This\ is\ the\ some\ text.\ \mu_j\ \sigma_i\ \alpha_t$') 145 | plt.show() 146 | 147 | 148 | # 写数据到excel 149 | import xlsxwriter 150 | workbook = xlsxwriter.Workbook('result_data.xlsx') #创建一个Excel文件 151 | worksheet = workbook.add_worksheet() 152 | for i in range(1, 151): 153 | #print(i) 154 | num = str(i) 155 | row = 'A' + num 156 | if i < 75: 157 | data = [S_t[i], E_t[i], I_t[i], R_t[i], I_t[i]+R_t[i]] 158 | else: 159 | data = [S_t2[i - 75], E_t2[i - 75], I_t2[i - 75], R_t2[i - 75], I_t2[i-75]+R_t2[i-75]] 160 | worksheet.write_row(row, data) 161 | i += 1 162 | 163 | workbook.close() 164 | --------------------------------------------------------------------------------