【问题标题】:Translating WinBUGS model to JAGS (using R)将 WinBUGS 模型转换为 JAGS(使用 R)
【发布时间】:2017-04-08 04:29:37
【问题描述】:

我正在尝试在 JAGS 中实现为 WinBUGS 编写的以下模型:

model {
  for (i in 1:N) {                         
    wtp[i] ~ dweib(r[G[i]], mu[i])I(lower[i], upper[i])
    mu[i] <- exp(beta[G[i]])
    G[i] ~ dcat(P[])       
  }                                       
  P[1] ~ dunif(0.01, 0.99)
  P[2] <- 1 - P[1]
  r[1] ~ dunif(1, 10)
  r[2] ~ dunif(0.1, 10)
  beta[1] ~ dunif(0, 1000)      
  beta[2] ~ dunif(-1000, 0)                
  weibmed[1] <- pow(log(2) * exp(-beta[1]), 1 / r[1]) 
  weibmed[2] <- pow(log(2) * exp(-beta[2]), 1 / r[2])
  weibmed[3] <- pow(log(1 / (1 - 0.5 + P[1])) * exp(-beta[2]), 1 / r[2])
  weibmean[1] <- pow(exp(-beta[1]), 1 / r[1]) * exp(loggam((1 + r[1]) / r[1]))
  weibmean[2] <- pow(exp(-beta[2]), 1 / r[2]) * exp(loggam((1 + r[2]) / r[2]))
  weibmean[3] <- P[1] * weibmean[1] + P[2] * weibmean[2]
}

我认为在 JAGS 中使用它会很简单:

library(rjags)

txt <- 'model {
  for (i in 1:N) {                         
    wtp[i] ~ dweib(r[G[i]], mu[i])T(lower[i], upper[i])
    mu[i] <- exp(beta[G[i]])
    G[i] ~ dcat(P[])       
  }                                       
  P[1] ~ dunif(0.01, 0.99)
  P[2] <- 1 - P[1]
  r[1] ~ dunif(1, 10)
  r[2] ~ dunif(0.1, 10)
  beta[1] ~ dunif(0, 1000)      
  beta[2] ~ dunif(-1000, 0)                
  weibmed[1] <- pow(log(2) * exp(-beta[1]), 1 / r[1]) 
  weibmed[2] <- pow(log(2) * exp(-beta[2]), 1 / r[2])
  weibmed[3] <- pow(log(1 / (1 - 0.5 + P[1])) * exp(-beta[2]), 1 / r[2])
  weibmean[1] <- pow(exp(-beta[1]), 1 / r[1]) * exp(loggam((1 + r[1]) / r[1]))
  weibmean[2] <- pow(exp(-beta[2]), 1 / r[2]) * exp(loggam((1 + r[2]) / r[2]))
  weibmean[3] <- P[1] * weibmean[1] + P[2] * weibmean[2]
}'

set.seed(3.14159)
dat <- list(N = 1000, lower = rep(0, 1000), upper = runif(1000, 5, 200000))
ini <- list(P = c(0.4, NA), r = c(8.2, 1.2), beta = c(3.8, -6.5))

mod <- jags.model(
  file = textConnection(txt), 
  data = dat,
  inits = c(ini, .RNG.name = 'base::Mersenne-Twister', .RNG.seed = 314159),
  n.chains = 1,
  n.adapt  = 100
)

sam.jags <- coda.samples(
  model = mod,
  variable.names = c('P', 'r', 'beta', 'weibmed', 'weibmean'),
  n.iter = 400,
  n.thin = 1
)

只需将I() 替换为T()。这会产生coda.samples() 错误:

Error: Error in node weibmed[3]
Invalid parent values

如果我忽略对weibmedweibmean 的监控,那么coda.samples() 有效,但参数估计值:

                Mean          SD    Naive SE Time-series SE
P[1]       0.4840704   0.2769491  0.01384746     0.01384746
P[2]       0.5159296   0.2769491  0.01384746     0.01384746
beta[1]  509.3614647 295.0860473 14.75430237    14.75430237
beta[2] -487.5362940 285.4126899 14.27063449    14.27063449
r[1]       5.2054730   2.6330434  0.13165217     0.13165217
r[2]       5.0478143   2.9480476  0.14740238     0.14740238

无法与我使用 WinBUGS 时获得的相比:

library(R2WinBUGS)

sam.bugs <- bugs(
  model.file = 'model.bug',
  data = dat,
  inits = list(ini),
  parameters.to.save = c('P', 'r', 'beta'), #, 'weibmed', 'weibmean'),
  n.chains = 1,
  n.burnin = 100,
  n.iter = 500,
  n.thin = 1,
  debug = F,
  DIC = F,
  bugs.seed = 314159
)

 Inference for Bugs model at "3mixout2.bug", fit using WinBUGS,
 1 chains, each with 500 iterations (first 100 discarded)
 n.sims = 400 iterations saved
        mean  sd 2.5%  25%  50%  75% 97.5%
P[1]     0.4 0.0  0.3  0.4  0.4  0.4   0.4
P[2]     0.6 0.0  0.6  0.6  0.6  0.6   0.7
r[1]     7.2 0.8  6.2  6.6  6.9  7.7   9.3
r[2]     1.5 0.0  1.4  1.4  1.5  1.5   1.6
beta[1]  5.5 0.5  4.6  5.0  5.4  5.8   6.6
beta[2] -7.2 0.2 -7.5 -7.3 -7.2 -7.1  -6.9

有什么想法或建议吗?

【问题讨论】:

    标签: r jags winbugs r2winbugs


    【解决方案1】:

    JAGS 手册说;

    pow(x, z) ||幂函数 ||真实 ||如果 x

    0.5 &lt; P[1]log(1 / (1 - 0.5 + P[1])) * exp(-beta[2]) &lt; 0,所以weibmed[3]pow(negative, non_integer),变成NaN。据我所知,coda.samples() 不允许被监控变量占用NaN

    如果您通过更改名称(例如weibmed3 &lt;- pow(log(1 / (1 - 0.5 + P[1])) * exp(-beta[2]), 1 / r[2]))使用受监控变量列表中的P[1] ~ dunif(0.01, 0.5) 或除weibmed[3] 之外的weibmed3 &lt;- pow(log(1 / (1 - 0.5 + P[1])) * exp(-beta[2]), 1 / r[2]),您的代码将运行。

    【讨论】:

    • 感谢您指出这一点。除了监控变量列表中的weibmedweibmean,您知道为什么WinBUGS 和JAGS 会为Prbeta 产生如此不同的估计值吗?
    • @feats-by-jake;抱歉,我已经把旧 PC 的 BUGS 环境扔掉了。你能告诉我结果吗? (以及是否通过将weibmedweibmeanparameters.to.save 中排除而改变?)
    • 我在这两种情况下都排除了weibmedwebmean,并添加了coda.samples()bugs() 的输出。如果重新添加 weibmedwebmean,WinBUGS 输出不会改变。
    【解决方案2】:

    看来这是应该使用dinterval 而不是T() 的情况:

    txt2 <- '
    data {
      x <- rep(1, N)
    }
    model {
      for (i in 1:N) {     
        x[i] ~ dinterval(wtp[i], B[i, ])                 
        wtp[i] ~ dweib(r[G[i]], mu[i])
        mu[i] <- exp(beta[G[i]])
        G[i] ~ dcat(P[])
      }                                     
      P[1] ~ dunif(0, 1)
      P[2] <- 1 - P[1]
      r[1] ~ dunif(0, 10)
      r[2] ~ dunif(0, 10)
      beta[1] ~ dunif(1, 1000)      
      beta[2] ~ dunif(-1000, 0)                
      weibmed[1] <- pow(log(2) * exp(-beta[1]), 1 / r[1]) 
      weibmed[2] <- pow(log(2) * exp(-beta[2]), 1 / r[2])
      # weibmed[3] <- pow(log(1 / (1 - 0.5 + P[1])) * exp(-beta[2]), 1 / r[2])
      weibmean[1] <- pow(exp(-beta[1]), 1 / r[1]) * exp(loggam((1 + r[1]) / r[1]))
      weibmean[2] <- pow(exp(-beta[2]), 1 / r[2]) * exp(loggam((1 + r[2]) / r[2]))
      # weibmean[3] <- P[1] * weibmean[1] + P[2] * weibmean[2]
    }'
    
    mod <- jags.model(
      file = textConnection(txt2), 
      data = list(N = dat[[1]], B = cbind(dat$lower, dat$upper)),
      inits = c(ini, .RNG.name = 'base::Mersenne-Twister', .RNG.seed = 314159),
      n.chains = 1,
      n.adapt  = 100
    )
    

    【讨论】:

    • 很抱歉我的回复延迟了。此代码的估计与 JAGS 和 BUGS 所做的估计无法比较。例如,P[1] 大约为 0,P[2] 大约为 1,它们是否正确?
    • 你是对的!我认为这是因为我的可重现示例可能设计得不好。我一直在使用更仔细的模拟数据,JAGS 和 BUGS 产生了相似的结果。
    猜你喜欢
    • 2021-01-10
    • 2020-03-26
    • 2012-11-23
    • 2017-06-20
    • 1970-01-01
    • 2015-03-11
    • 2020-10-15
    • 2016-06-30
    • 2021-03-31
    相关资源
    最近更新 更多