优化ODE并重新计算R中的初始值

时间:2018-03-09 13:00:41

标签: r optimization ode

我想知道我是否可以在以下问题中输入一些内容:在使用modCost和modFit获取结果后,我尝试为我的函数返回一个最佳值。

所以基本上我尝试做的就是玩一个基本的预测,优化以获得良好的适应性(我认为有效)。但是我也想要' yi'参数作为参数包含在Modfit函数中。

我可以使用特定的功能或者解决方法吗?任何帮助/建议将不胜感激。

为编写得不好的代码,第一篇文章等道歉:)

library(deSolve) 
library(FME) 

## function derivs 
derivs <- function(time, y, pars) { 
   with (as.list(c(y, pars)), { 
     dy = a * y   
     return(list(c(dy))) 
   }) 
} 

## parameters 
pars <- c(a = 0.1) 

yi=6

## initial values 
y <- c(Y = yi) 

## time steps 
times <- c(seq(2005, 2017, 1)) 

## numerical solution of ODE 
out <- ode(y = y, parms = pars, times = times, func = derivs) 

## example observation data 
yobs <- data.frame( 
   time = 2005:2017, 
   Y = c(3,6,9,10,12,8,7,9,14,16,18,15,19) 
) 

## model cost function, see help file and vignette for details 
modelCost <- function(p) { 
   out <- ode(y = y, func = derivs, parms = p, times = yobs$time) 
   return(modCost(out, yobs)) 
} 

## start values for the parameters 
startpars <- c(a = 0.1) 

## fit the model; nprint = 1 shows intermediate results 
fit <- modFit(f = modelCost, p = startpars, control = list(nprint = 1)) 


summary(fit) 

## graphical result 
out2 <- ode(y = y, parms = startpars, times = times, func = derivs) 
out3 <- ode(y = y, parms = fit$par, times = times, func = derivs) 
plot(out, out2, out3, obs = yobs) 

legend("topleft", legend=c("original", "startpars", "fitted"), 
   col = 1:3, lty = 1:3)

1 个答案:

答案 0 :(得分:1)

只调整以下代码行似乎有效:

## model cost function, see help file and vignette for details 
modelCost <- function(p) { 
  out <- ode(y = p["Y"], func = derivs, parms = p["a"], times = yobs$time) 
  return(modCost(out, yobs)) 
} 

## start values for the parameters 
startpars <- c(Y = 6, a = 0.1) 

您会在解决方案中注意到初始条件和参数都已针对以下内容进行了优化:

#$par
#         Y          a 
#5.81276026 0.09872004 

请注意,微分方程有一个解析解:y = yi * exp(a * (time - time_0))。因此,更简单的方法是使用optim

将其直接拟合到数据中
# My cost function
ls_cost <- function(p){
  sum((p["Y"] * exp(p["a"] * (yobs$time - min(yobs$time))) - yobs$Y)^2)
}

# Optimise for initial condition and 'a'
optim(par = startpars, fn = ls_cost)

给出,

#$par
#         Y          a 
#5.81256899 0.09872287 

非常接近另一种方法。

现在,使用microbenchmark比较两者,我们得到以下结果:

Unit: milliseconds
                                 expr      min       lq     mean  median       uq      max neval
 modFit(f = modelCost, p = startpars) 36.22868 37.52432 40.68432 38.3405 40.02509 85.91644   100

Unit: milliseconds
                                 expr      min       lq     mean   median       uq      max neval
 optim(par = startpars, fn = ls_cost) 1.927786 1.980567 2.082507 2.010147 2.094988 5.522633   100

因此,后一种方法要快一个数量级。