I received some help getting the sampler_RJ_indicator function to work for a problem where I wanted to select among both categorical and continuous variables and have the algorithm sample the categorical variable as one variable (although it is represented by multiple indicator variables in the model).
This seemed to work fine in the last version of nimble that I have on my PC, but when I updated the version and tried to run it on my Mac it fails to compile and reports the error that is related to a modified version of the sampler_RJ_indicator that I created with some help (thanks Sally!).
I'm not sure why the code would run fine in a previous version and now it is throwing this error. The inner workings of nimble are a bit over my head, so I was hoping this would be more obvious to someone involved with the development.
## example MCMC rj
# my_sampler_RJ_indicator #######################################
my_sampler_RJ_indicator <- nimbleFunction(
name = 'my_sampler_RJ_indicator',
contains = sampler_BASE,
setup = function(model, mvSaved, target, control) {
## note: target is the indicator variable,
## control$targetNode is the variable conditionally in the model
## control list extraction
coefNode <- model$expandNodeNames(control$targetNode, returnScalarComponents = TRUE)
coefNodes <- control$targetNode
proposalScale <- control$scale
proposalMean <- control$mean
## node list generation
calcNodes <- model$getDependencies(c(coefNode, target))
calcNodesReduced <- model$getDependencies(target)
},
run = function() {
currentIndicator <- model[[target]]
if(currentIndicator == 0) { ## propose addition of coefNode
currentLogProb <- model$getLogProb(calcNodesReduced)
proposalCoef <- numeric(length(coefNode))
logProbForwardProposal <- 0
for(l in 1:length(coefNode)){
proposalCoef[l] <- rnorm(1, proposalMean, proposalScale)
logProbForwardProposal <- logProbForwardProposal + dnorm(proposalCoef[l], proposalMean, proposalScale, log = TRUE)
}
model[[coefNodes]] <<- proposalCoef
model[[target]] <<- 1
proposalLogProb <- model$calculate(calcNodes)
logAcceptanceProb <- proposalLogProb - currentLogProb - logProbForwardProposal
} else { ## propose removal of coefNode
currentLogProb <- model$getLogProb(calcNodes)
currentCoef <- model[[coefNodes]]
logProbReverseProposal<- 0
for(l in 1:length(coefNode)){
logProbReverseProposal <- logProbReverseProposal + dnorm(currentCoef[l], proposalMean, proposalScale, log = TRUE)
}
model[[coefNodes]] <<- 0
model[[target]] <<- 0
model$calculate(calcNodes)
logAcceptanceProb <- model$getLogProb(calcNodesReduced) - currentLogProb + logProbReverseProposal
}
accept <- decide(logAcceptanceProb)
if(accept) { copy(from = model, to = mvSaved, row = 1, nodes = calcNodes, logProb = TRUE)
} else { copy(from = mvSaved, to = model, row = 1, nodes = calcNodes, logProb = TRUE) }
},
methods = list(
reset = function() { }
)
)
code <- nimbleCode({
beta0 ~ dnorm(0, sd = 100)
beta[1] ~ dnorm(0, sd = 100)
beta[2] ~ dnorm(0, sd = 100)
beta[3] ~ dnorm(0, sd = 100)
sigma ~ dunif(0, 100)
for(i in 1:2){
z[i] ~ dbern(psi)
}
#z1 ~ dbern(psi) ## indicator variable associated with beta1
#z2 ~ dbern(psi) ## indicator variable associated with beta2
psi ~ dbeta(1, 1) ## hyperprior on inclusion probability
for(i in 1:N) {
Ypred[i] <- beta0 + z[1]*beta[1] * x1[i] + z[1] *beta[2] * x2[i] + beta[3] * x3[i] * z[2]
Y[i] ~ dnorm(Ypred[i], sd = sigma)
}
})
## simulate some data
set.seed(1)
N <- 100
x1 <- rbinom(N, 1, 0.5)
x2 <- rbinom(N, 1, 0.5) #
x3 = std2(runif(N, -10, 10))
Y <- rnorm(N, 1.5 + 2 * x1 + 0.4 * x2 + 0.8 * x3, sd = 1)
## build the model and configure default MCMC
RJexampleModel <- nimbleModel(code, constants = list(N = N),
data = list(Y = Y, x1 = x1, x2 = x2, x3=x3),
inits = list(beta0 = 0, beta=c(0,0,0),
sigma = sd(Y), z = rbinom(2,1,0.5), psi = 0.5))
cRJexampleModel <- compileNimble(RJexampleModel)
RJexampleConf <- configureMCMC(RJexampleModel)
configureRJ(conf = RJexampleConf,
targetNodes = c("beta[3]"),
indicatorNodes = c('z[2]'),
control = list(mean = c(0), scale = 2))
nodeControl = list(mean = 0, scale = 1)
nodeControl$targetNode <- c("beta[1:2]")
RJexampleConf$removeSamplers("z[1]")
RJexampleConf$addSampler(type = my_sampler_RJ_indicator,
target = "z[1]",
control = nodeControl)
currentConf <- RJexampleConf$getSamplers("beta[1]")
RJexampleConf$removeSampler("beta[1]")
RJexampleConf$addSampler(type = sampler_RJ_toggled,
target = "beta[1]",
control = list(samplerType = currentConf[[1]]))
currentConf <- RJexampleConf$getSamplers("beta[2]")
RJexampleConf$removeSampler("beta[2]")
RJexampleConf$addSampler(type = sampler_RJ_toggled,
target = "beta[2]",
control = list(samplerType = currentConf[[1]]))
mpleConf$printSamplers()
RJexampleConf$addMonitors(c('z'))
mcmc = buildMCMC(RJexampleConf)
cmcmc5 = compileNimble(mcmc, project = RJexampleModel, resetFunctions = TRUE, showCompilerOutput = TRUE)
#tic()
results_samplerRJind <- runMCMC(cmcmc4, niter = 20000, nburnin=5000,thin=1,nchains=1, setSeed = 500)