Skip to content

Instantly share code, notes, and snippets.

@Lewuathe
Created March 18, 2020 11:50
Show Gist options
  • Save Lewuathe/259bcb3c61e0363bdfd867d790e56e95 to your computer and use it in GitHub Desktop.
Save Lewuathe/259bcb3c61e0363bdfd867d790e56e95 to your computer and use it in GitHub Desktop.
covid-19-SIR.py
import numpy as np
import pandas as pd
from scipy.integrate import solve_ivp
from scipy.optimize import minimize
import matplotlib.pyplot as plt
from datetime import timedelta, datetime
S_0 = 15000
I_0 = 2
R_0 = 0
START_DATE = {
'Japan': '1/22/20',
'Italy': '1/31/20',
'Republic of Korea': '1/22/20',
'Iran (Islamic Republic of)': '2/19/20'
}
class Learner(object):
def __init__(self, country, loss):
self.country = country
self.loss = loss
def load_confirmed(self, country):
df = pd.read_csv('data/time_series_19-covid-Confirmed.csv')
country_df = df[df['Country/Region'] == country]
return country_df.iloc[0].loc[START_DATE[country]:]
def load_recovered(self, country):
df = pd.read_csv('data/time_series_19-covid-Recovered.csv')
country_df = df[df['Country/Region'] == country]
return country_df.iloc[0].loc[START_DATE[country]:]
def extend_index(self, index, new_size):
values = index.values
current = datetime.strptime(index[-1], '%m/%d/%y')
while len(values) < new_size:
current = current + timedelta(days=1)
values = np.append(values, datetime.strftime(current, '%m/%d/%y'))
return values
def predict(self, beta, gamma, data, recovered, country):
predict_range = 150
new_index = self.extend_index(data.index, predict_range)
size = len(new_index)
def SIR(t, y):
S = y[0]
I = y[1]
R = y[2]
return [-beta*S*I, beta*S*I-gamma*I, gamma*I]
extended_actual = np.concatenate((data.values, [None] * (size - len(data.values))))
extended_recovered = np.concatenate((recovered.values, [None] * (size - len(recovered.values))))
return new_index, extended_actual, extended_recovered, solve_ivp(SIR, [0, size], [S_0,I_0,R_0], t_eval=np.arange(0, size, 1))
def train(self):
data = self.load_confirmed(self.country)
recovered = self.load_recovered(self.country)
optimal = minimize(loss, [0.001, 0.001], args=(data, recovered), method='L-BFGS-B', bounds=[(0.00000001, 0.4), (0.00000001, 0.4)])
print(optimal)
beta, gamma = optimal.x
new_index, extended_actual, extended_recovered, prediction = self.predict(beta, gamma, data, recovered, self.country)
df = pd.DataFrame({'Confirmed': extended_actual, 'Recovered': extended_recovered, 'S': prediction.y[0], 'I': prediction.y[1], 'R': prediction.y[2]}, index=new_index)
fig, ax = plt.subplots(figsize=(15, 10))
ax.set_title(self.country)
df.plot(ax=ax)
print(f"country={self.country}, beta={beta:.8f}, gamma={gamma:.8f}, r_0:{(beta/gamma):.8f}")
fig.savefig(f"{self.country}.png")
def loss(point, data, recovered):
size = len(data)
beta, gamma = point
def SIR(t, y):
S = y[0]
I = y[1]
R = y[2]
return [-beta*S*I, beta*S*I-gamma*I, gamma*I]
solution = solve_ivp(SIR, [0, size], [S_0,I_0,R_0], t_eval=np.arange(0, size, 1), vectorized=True)
l1 = np.sqrt(np.mean((solution.y[1] - data)**2))
l2 = np.sqrt(np.mean((solution.y[2] - recovered)**2))
alpha = 0.1
return alpha * l1 + (1 - alpha) * l2
learner = Learner('Japan', loss)
learner.train()
learner = Learner('Republic of Korea', loss)
learner.train()
learner = Learner('Italy', loss)
learner.train()
learner = Learner('Iran (Islamic Republic of)', loss)
learner.train()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment