以列表作为参数的 ODE 的灵敏度分析 - 结果给出标准偏差为 0

Sensitivity analysis for ODE with list as parameters - result gives standard deviation of 0

注意:最初的问题是“使用包含列表的参数对 ODE 进行灵敏度分析”,因为 sensRange 函数由于参数中传递的列表而出错。问题随着列表参数的固定而演变,但出现了一个不同的问题,其中灵敏度分析显示奇怪的结果,所有运行的标准偏差为 0。

我有一个模型,使用 deSolve 包在 R 中模拟化学物质随时间的浓度。我使用的参数是化学特性(分布容积、半衰期等)以及随时间变化的重量。权重在列表中给出,由于权重随时间增加,该列表迭代 ODE 中的每个时间步长,并且化学性质以数字形式给出。

我想对这个模型进行敏感性分析,只测试化学性质。我之前没有做过敏感性分析,但我正在尝试使用 sensRange() 来遵循示例。但是,似乎 sensRange() 函数不允许将其中一个参数作为列表给出。我收到错误:

Error in yRef[, ivar] : invalid subscript type 'list'

我的模型和全局敏感性分析代码是这样设置的:

library(FME)
library(deSolve)

c.weight <- c(3.5,  4,  5,  5,  6, 7,  7,  7,  8,  8,  8,  9,  9,  9,  9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 20, 20, 20, 21, 21, 21, 22, 22, 22, 23, 23, 23, 24, 24, 24, 25, 25, 25, 26, 26, 26, 27, 27, 27, 27, 28, 28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31, 32, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 35, 36, 36, 36, 37, 37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 42, 43, 43, 43, 44, 44, 44, 45, 45, 45, 46, 46, 46, 47, 47, 47, 48, 48, 48, 49, 49, 49, 50, 50, 50, 51, 51, 52, 54, 55)

params.sens <- c(vd = 0.2,
                 pm = 0.05,
                 halflife = 5,
                 dose = 0.001,
                 c.weight = c.weight)

solve.sens <- function(pars) {
  sens.model <- function(times, state, parameters) {
    with(as.list(c(state, parameters)), {
      
      if (times <= 5) {
        volume <- (((0.2 * times) * c.weight[times+1]) * 30)
        transferred <- pm * volume
      } else if (times > 5 & times <= 14) {
        volume <- ((0.1 * c.weight[times+1]) * 30)
        transferred <- pm * volume
      } else {
        transferred <- 0
      }
      
      intake.c <- (dose * c.weight[times+1])
      elimination.c <- concentration * vd * c.weight[times+1] * log(2) / (halflife * 12)
      
      #total
      concentration <- (intake.c + transferred - elimination.c) / (vd * c.weight[times+1])
      
      list(c(concentration))
      
    })
  }
  
  state <- c(concentration = 0.5)
  months <- seq(0, 144, 1)
  return(as.data.frame(ode(y = state, times = months, func = sens.model, parms = params.sens)))
  
}

out <- solve.sens(params.sens)

parRanges <- data.frame(min = c(0.02, 0.1, 2.1), max = c(0.09, 0.2, 5.5))
rownames(parRanges) <- c("pm", "vd", "halflife")

sens <- sensRange(func = solve.sens, parms = params.sens, dist = "latin", sensvar = "concentration", parRange = parRanges, num = 50)

head(summary(sens))
summ.sens <- summary(sens)
plot(summ.sens, xlab = "months", ylab = "concentration")

我不知道如何前进,有没有人有任何提示或看到我的错误在哪里??

编辑: 遵循 Soetart 和 Herman,2009 年的细菌生长模型,纠正我的 =/<- 错误,并将评论中的参数值添加到模型中。现在它运行没有错误,但是摘要显示了所有相同的值(平均值、最小值、最大值和所有分位数)所以我假设它不是 运行 正确

               x      Mean Sd       Min       Max       q05       q25       q50       q75       q95
concentration0 0  0.500000  0  0.500000  0.500000  0.500000  0.500000  0.500000  0.500000  0.500000
concentration1 1  1.246348  0  1.246348  1.246348  1.246348  1.246348  1.246348  1.246348  1.246348
concentration2 2  3.475493  0  3.475493  3.475493  3.475493  3.475493  3.475493  3.475493  3.475493
concentration3 3  7.170403  0  7.170403  7.170403  7.170403  7.170403  7.170403  7.170403  7.170403
concentration4 4 12.314242  0 12.314242 12.314242 12.314242 12.314242 12.314242 12.314242 12.314242
concentration5 5 18.890365  0 18.890365 18.890365 18.890365 18.890365 18.890365 18.890365 18.890365

原来post混淆了=<-来创建命名vector,所以推荐如下代码片段:

params.sens <- c(vd = p.vd,
              pm = p.pm,
              halflife = p.hl,
              dose = concentrations$dose,
              c.weight = variables$c.weight)

经过原 poster 的编辑,此答案大部分已过时并被删除。然而,在 中发现 <-(赋值)和 =(参数匹配;此处创建命名向量)之间的区别尚未完全清楚。

这是一个显示差异的示例。为避免混淆,运行 它在新的 R 会话中或删除工作 space 之前:

#rm(list=ls()) # uncomment this to clear the work space
x <- c(a <- 2, b <- 3)
y <- c(d = 2, e = 3)

x
y
ls()

我们看到 y 是一个命名向量,而 x 没有命名元素。相反,ab 是在用户工作 space:

中作为变量“即时”创建的
> x
[1] 2 3
> y
d e 
2 3 
> ls()
[1] "a" "b" "x" "y"

由于修复了分配错误,脚本现在可以正常运行并且可以重现行为。

现在我们可以看到传递给 solve.sens 的参数没有传递给 ode 函数。

解决方法是将 ode 调用中的 parms.sens 替换为 pars,并传递给调用函数:

return(as.data.frame(ode(y = state, times = months, func = sens.model, parms = pars)))

然后

plot(summ.sens, xlab = "months", ylab = "concentration")

结果: