Reputation: 25
I am trying to model the coronavirus infectious rate using SIR model in R. However, my beta (controls the transition between Susceptibles and Infected) and gamma (controls the transition between Infected and Recovered) values are not correct as you can see.
beta gamma
1.0000000 0.8407238
Here is my code:
library(deSolve)
Infected <- c(994, 307, 329, 553, 587, 843, 983, 1750, 2950, 4569, 5632, 4848, 9400, 10311, 11166, 13451, 17388, 18743, 19452, 20065, 20732,24914)
Day <- 1:(length(Infected))
N <- 331002651 # population of the us
This is the SIR function
SIR <- function(time, state, parameters) {
par <- as.list(c(state, parameters))
with(par, {
dS <- -beta/N * I * S
dI <- beta/N * I * S - gamma * I
dR <- gamma * I
list(c(dS, dI, dR))
})
}
Then I find the RSS
init <- c(S = N-Infected[1], I = Infected[1], R = 0)
RSS <- function(parameters) {
names(parameters) <- c("beta", "gamma")
out <- ode(y = init, times = Day, func = SIR, parms = parameters)
fit <- out[ , 3]
sum((Infected - fit)^2)
}
Opt <- optim(c(0.5, 0.5), RSS, method = "L-BFGS-B", lower = c(0, 0), upper = c(1, 1)) # optimize with some sensible conditions
Opt$message
Then I find beta and gamma
Opt_par <- setNames(Opt$par, c("beta", "gamma"))
Opt_par
## beta gamma
## 1.0000000 0.8407238
What went wrong with my code and how can I fix it? Thank you in advance!
Upvotes: 2
Views: 422
Reputation: 5813
Optimization is often tricky, there are several things that may be improved:
atol
) appropriate to the original scales.library(deSolve)
Infected <- c(994, 307, 329, 553, 587, 843, 983, 1750, 2950, 4569, 5632, 4848,
9400, 10311, 11166, 13451, 17388, 18743, 19452, 20065, 20732,24914)
Day <- 1:(length(Infected))
N <- 331002651 # population of the us
SIR <- function(time, state, parameters) {
par <- as.list(c(state, parameters))
with(par, {
dS <- -beta/N * I * S
dI <- beta/N * I * S - gamma * I
dR <- gamma * I
list(c(dS, dI, dR))
})
}
init <- c(S = N-Infected[1], I = Infected[1], R = 0)
RSS <- function(parameters) {
names(parameters) <- c("beta", "gamma")
out <- ode(y = init, times = Day, func = SIR, parms = parameters)
fit <- out[ , 3]
sum((Infected - fit)^2)
}
# optimize with some sensible conditions
Opt <- optim(c(0.5, 0.5), RSS, method = "L-BFGS-B",
lower = c(0, 0), upper = c(10, 10))
Opt$message
Opt_par <- setNames(Opt$par, c("beta", "gamma"))
Opt_par
# beta gamma
# 0.6512503 0.4920399
out <- ode(y = init, times = Day, func = SIR, parms = Opt_par)
plot(out)
plot(out, obs=data.frame(time=Day, I=Infected))
A basic SEIR model and additional links can be found here. Note however that not only the model is too simple, but also the data. The number of confirmed cases is not the number of infected, it depends on how it was tested and is probably much less than the number of infected.
Upvotes: 1