vdorie / blme

Bayesian Linear Mixed Effect Models
40 stars 8 forks source link

Passing prior parameters as variables instead of lists #9

Closed brianhuey closed 5 years ago

brianhuey commented 5 years ago

First off, thanks so much for writing this package - it's become indispensable in my work.

Both blmer() and bglmer() allow a list to be passed to cov.prior, i.e. bglmer(...,cov.prior=list(fc.nm ~ dist1, fc.nm ~ dist2)), but if we were to set the list as a variable:

cov.prior <-  list(fc.nm ~ dist1, fc.nm ~ dist2)
bglmer(...,cov.prior=cov.prior)

An error is thrown. Some cursory debugging indicates that when a variable that references a list is passed, it gets wrapped in a list twice, which causes problems in evaluateCovPriors(). I was able to hack together a solution but I wanted to raise the issue since there might need to be a more general solution.

vdorie commented 5 years ago

Thanks for bringing this to my attention. I've pushed a commit (ed7f51ba9911be8aa8575eead7833e02c5f043df) that I hope will fix the issue. Let me know if you encounter any problems.

brianhuey commented 5 years ago

It's working for me, thanks so much!

randel commented 5 years ago

Hi Vincent, thanks for the nice package! blmer() works if running in a single instance, but I still got an error if running blmer() in parallel like in the environment of foreach(). Do you have any idea how to fix this? Thanks!

library(blme)
data("sleepstudy", package = "lme4")

scale0 = diag(0.5, 2)

fm4 <- blmer(Reaction ~ Days + (1 + Days|Subject), sleepstudy,
              cov.prior = invwishart(df = 5, scale = scale0))

library(doParallel)
cl <- makeCluster(1)
registerDoParallel(cl)

res = foreach(i = 1) %dopar% {library(blme); blmer(Reaction ~ Days + (1 + Days|Subject), sleepstudy,
                                   cov.prior = invwishart(df = 5, scale = scale0))}
Error in { : task 1 failed - "object 'scale0' not found"
randel commented 5 years ago

It seems that the error can be somehow avoided using the snow package for parallel computing.

library(snow)
clus <- makeCluster(1)

clusterExport(clus, "scale0")
aa <- parSapply(clus, 1, function(x) {
  library(blme); blmer(Reaction ~ Days + (1 + Days|Subject), sleepstudy,
                       cov.prior = invwishart(df = 5, scale = scale0))
})

clusterExport() loads the variable to .GlobalEnv by default, so this may be still an enviromental issue.

vdorie commented 5 years ago

Yeah, I think it has to do with variable scoping. It works with doParallel and foreach with

res <- foreach(i = 1) %dopar% {
  library(blme)
  blmer(Reaction ~ Days + (1 + Days|Subject), sleepstudy,
        cov.prior = invwishart(df = 5, scale = diag(0.5, 2)))
}
randel commented 5 years ago

Yes, the issue is that an "outside" variable cannot be passed to the prior. clusterExport() also cannot work when each run needs its own prior that is saved as variables.