I am puzzled by a simple question in R JAGS. I have for example, 10 parameters: d[1], d[2], ..., d[10]. It is intuitive from the data that they should be increasing. So I want to put a constraint on them.
Here is what I tried to do but it give error messages saying "Node inconsistent with parents":
model{
...
for (j in 1:10){
d.star[j]~dnorm(0,0.0001)
}
d=sort(d.star)
}
Then I tried this:
d[1]~dnorm(0,0.0001)
for (j in 2:10){
d[j]~dnorm(0,0.0001)I(d[j-1],)
}
This worked, but I don't know if this is the correct way to do it. Could you share your thoughts?
Thanks!
If you are ever uncertain about something like this, it is best to just simulate some data to determine if the model structure you suggest works (spoiler alert: it does).
Here is the model that I used:
cat('model{
d[1] ~ dnorm(0, 0.0001) # intercept
d[2] ~ dnorm(0, 0.0001)
for(j in 3:11){
d[j] ~ dnorm(0, 0.0001) I(d[j-1],)
}
for(i in 1:200){
y[i] ~ dnorm(mu[i], tau)
mu[i] <- inprod(d, x[i,])
}
tau ~ dgamma(0.01,0.01)
}',
file = "model_example.R")```
And here are the data I simulated to use with this model.
library(run.jags)
library(mcmcplots)
# intercept with sorted betas
set.seed(161)
betas <- c(1,sort(runif(10, -5,5)))
# make covariates, 1 for intercept
x <- cbind(1,matrix(rnorm(2000), nrow = 200, ncol = 10))
# deterministic part of model
y_det <- x %*% betas
# add noise
y <- rnorm(length(y_det), y_det, 1)
data_list <- list(y = as.numeric(y), x = x)
# fit the model
mout <- run.jags('model_example.R',monitor = c("d", "tau"), data = data_list)
Following this, we can plot out the estimates and overlay the true parameter values
caterplot(mout, "d", reorder = FALSE)
points(rev(c(1:11)) ~ betas, pch = 18,cex = 0.9)
The black points are the true parameter values, the blue points and lines are the estimates. Looks like this set up does fine so long as there are enough data to estimate all of those parameters.
It looks like there is an syntax error in the first implementation. Just try:
model{
...
for (j in 1:10){
d.star[j]~dnorm(0,0.0001)
}
d[1:10] <- sort(d.star) # notice d is indexed.
}
and compare the results with those of the second implementation. According to the documentation, these are both correct, but it is advised to use the function sort.
Related
I'm a beginner with OpenBUGS which I use through the R2OpenBUGS R package. I try to set state space model for identifying a lognormal signal in very noisy data. After many trials and errors, I managed to get this code but I still get the following error message: "empty slot not allowed in variable name error pos 664" which I don't understand. Can anyone knows what is wrong with the code ?
Disclaimer:
alt = measured altitude
true_alt = what I try to assess
nbird = number of individuals
nobs = number of observations (this number is not the same for every bird)
nstate = 'flight state', which is the way the birds behave (nstate = 3 because there are 3 different behaviours)
I try to determine the lognormal distribution of true_alt for each state.
model <- function(){
## MODEL SPECIFICATION
for(j in 1:nbird){
for(i in 1:nobs[j]){
alt[i,j] ~ dnorm(true_alt[i,j], tau.obs)
log(true_alt[i,j]) <- log_true_alt[i,j]
log_true_alt[i,j] ~ dnorm(mean.alt[i,j], tau[state[i,j]])
mean.alt[i,j] <- alt1[state[i,j]] + ind.re[j]
}
}
for(i in 1:nstate){ tau[i] <- 1/(sig[i]) }
# Random Effects:
tau.re <- 1/sig.re
for(j in 1:nbird) { ind.re[j] ~ dnorm(0, tau.re) }
## PRIORS
for(i in 1:nstate) {
alt1[i] ~ dnorm(0, 0.01)
sig[i] ~ dunif(0, 200)
}
sig.re ~ dunif(0, 200)
state ~ dunif(1,3)
## POSTERIOR PREDICTIVE DISTRIBUTIONS FOR EACH STATE
for(s in 1:nstate){
log_alt_pred[s] ~ dnorm(alt1[s], tau[s])
log(alt_pred[s]) <- log_alt_pred[s]
}
}
Thank you!!!
It could be because in your priors you're trying to set a distribution for "alt1[i]" but in your model you've used "alt[i,j]".
I have fitted following simple linear regression Bayesian model using rjags.
I was able to run the model by specifying all the predictors separately(like for a lm object). Now I want to learn how to specify the predictors by introducing them as a matrix instead of specifying them separately.
So I ran the following code, but it gave some errors.
I used tobbaco data set in rrr package to provide a reproducible example.
library(rrr)
require(dplyr)
library(rjags)
tobacco <- as_data_frame(tobacco)
N1 = length(tobacco$Y1.BurnRate)
x1 = model.matrix(Y1.BurnRate~X2.PercentChlorine+X3.PercentPotassium ,data = tobacco)
bayes_model_mul1=
"model {
for(i in 1:N1){
Y1.BurnRate[i]~dnorm(mu1[i],tau1)
for(j in 1:3){
mu1[i]=beta1[j]*x1[i,j]
}
}
for (l in 1:3) { beta1[l] ~dnorm(0, 0.001) }
tau1 ~ dgamma(.01,.01)
sigma_tau1 = 1/tau1
}"
model3 <- jags.model(textConnection(bayes_model_mul1),
data = list(Y1.BurnRate=tobacco$Y1.BurnRate, x1=x1, N1=N1),
n.chains=1)
After I run model3 , I got following error.
Error in jags.model(textConnection(bayes_model_mul1), data = list(Y1.BurnRate = tobacco$Y1.BurnRate, :
RUNTIME ERROR:
Compilation error on line 6.
Attempt to redefine node mu1[1]
Can anyone help me figure this out ?
Does this due to introducing predictors as a matrix ?
There are a few ways to do this, here are two:
Use matrix multiplication outside of the likelihood loop
m1 =
"model {
mu1 = x1 %*% beta1 # ---> this
for(i in 1:N1){
Y1.BurnRate[i] ~ dnorm(mu1[i], tau1)
}
for (l in 1:3) { beta1[l] ~ dnorm(0, 0.001) }
tau1 ~ dgamma(.01,.01)
sigma_tau1 = 1/tau1
}"
Use inprod to multiply the parameters with the design matrix
m2 =
"model {
for(i in 1:N1){
mu1[i] = inprod(beta1, x1[i,]) #----> this
Y1.BurnRate[i] ~ dnorm(mu1[i], tau1)
}
for (l in 1:3) { beta1[l] ~ dnorm(0, 0.001) }
tau1 ~ dgamma(.01,.01)
sigma_tau1 = 1/tau1
}"
You received an error with for(j in 1:3){ mu1[i] = beta1[j]* x1[i,j] } as every time you loop though the parameter index j you overwrite mu1[i]. It also doesn't sum up the individual terms. You may be able to index mu1 with j as well and then sum but untested ...
I'm given the data that contains 1000 numbers from uniform distribution ~[a,b]
and I need to use jags in r to find it/
I tried this code
library(arm)
library('rjags')
library(coda)
library(readr)
x <- read.csv(file='C:/Users/Amir/Desktop/אבנר/data analysis/תרגילים/תרגיל
3/Unif.csv', header=FALSE)
N<-length(x)
y <- x[1:1000,1]
dat<- list("y" = y, "N" = N)
jags.inits <- function() {list (a = -3, b = 30)}
parameters<- c("a", "b")
reg.jags <- jags.model(file='1.txt', data=dat, n.chains = 4, n.adapt = 1000)
update(jags, n.iter=1000)
regression.sim<-coda.samples(reg.jags, variable.names=parameters,
n.iter=15000)
summary(regression.sim)
and the model is
model {
for (i in 1:N) {
y[i] ~ dunif(a, b)
}
a ~ dnorm(-5, .0001)
b ~ dnorm(15, .0001)
}
but the result are very bad, instead of around [-3,23] I get around [-42,65]
any help?
I can't replicate your findings as your code is not reproducible: we don't have access to your data. But using simulated data with an essentially identical model gives results that seem to be very sensible:
library('runjags')
m <- 'model{
for(i in 1:N){
Obs[i] ~ dunif(a, b)
}
a ~ dnorm(0, 10^-6)
b ~ dnorm(0, 10^-6)
#data# N, Obs
#monitor# a, b
#inits# a, b
}'
N <- 1000
Obs <- runif(N, 1, 7)
a <- 0
b <- 10
results <- run.jags(m)
plot(results)
results
range(Obs)
The upper and lower 95% confidence intervals for a and b respectively are very close to the range of Obs, with mode estimates that are closer to the respective upper and lower 95% CI (the maximum likelihood solution would be exactly at the range of the data), and varying the size of N gives narrower/wider 95% CI. So all as expected.
My best guess at your problem is that your y are somehow all (or nearly all) missing. If that does not help solve your problem I think you will need to post your dataset.
I am trying to fit a logistic regression model in JAGS, but I have data in the form of (# success y, # attempts n), rather than a binary variable. In R, one can fit a model to data such as these by using glm(y/n ~ ) with the "weights" argument, but I am not sure how to fit this in JAGS.
Here is a simple example that I hope addresses what I am trying to ask. Note that I am using the rjags package. Thanks for any help!
y <- rbinom(10, 500, 0.2)
n <- sample(500:600, 10)
p <- y/n
x <- sample(0:100, 10) # some covariate
data <- data.frame(y, n, p, x)
model <- "model{
# Specify likelihood
for(i in 1:10){
y[i] ~ dbin(p[i], n[i])
logit(p[i]) <- b0 + b1*x
}
# Specify priors
b0 ~ dnorm(0, 0.0001)
b1 ~ dnorm(0, 0.0001)
}"
You don't need to compute p in your data set at all. Just let it be a logical node in your model. I prefer the R2jags interface, which allows you to specify a BUGS model in the form of an R function ...
jagsdata <- data.frame(y=rbinom(10, 500, 0.2),
n=sample(500:600, 10),
x=sample(0:100, 10))
model <- function() {
## Specify likelihood
for(i in 1:10){
y[i] ~ dbin(p[i], n[i])
logit(p[i]) <- b0 + b1*x[i]
}
## Specify priors
b0 ~ dnorm(0, 0.0001)
b1 ~ dnorm(0, 0.0001)
}
Now run it:
library("R2jags")
jags(model.file=model,data=jagsdata,
parameters.to.save=c("b0","b1"))
I've just switched from R2jags from R2OpenBUGS, and have noticed something I don't understand. After running the simulation using jags() and converting the output using as.mcmc(), the first sample always has very high deviance, and is typically very far from the converged parameter estimate. Running the same data with bugs() this sample does not appear. It's almost like the first sample is the actual first sample from the burn-in phase.
Reproducible code, including a bad initial estimate to show the bad parameter in the first sample of the jags() but not bugs() output.
require(R2jags); require(R2OpenBUGS); require(mcmcplots)
set.seed(1)
x <- rnorm(100)
y <- 2*x + rnorm(100)
jags.model <- function()
{
# likelihood
for( i in 1:n ){
mu[i] <- alpha + beta * x[i]
y[i] ~ dnorm( mu[i], tau )
}
# priors
alpha ~ dnorm(0,0.001)
beta ~ dnorm(1,0.001)
tau ~ dgamma(1,1)
sigma <- 1/sqrt(tau)
}
n <- length(x)
inits <- function() list( "alpha"=5,"beta"=5,"tau"=5 ) # very far initial estimate
dat <- list("x","y","n")
out.jags <- jags( dat,
inits=inits, model=jags.model,
n.iter=1000, n.thin=1, n.chains=2,
DIC=TRUE,
parameters.to.save=c("alpha","beta") )
codaout.jags <- as.mcmc(out.jags)
out.bugs <- bugs( dat,
inits=inits, model=jags.model,
n.iter=1000, n.thin=1, n.chains=2,
DIC=TRUE,
parameters.to.save=c("alpha","beta") )
codaout.bugs <- as.mcmc.bugs(out.bugs)
plot(codaout.jags)
x11(); plot(codaout.bugs)
For posterity, the problem is that R2jags does not always handle the burn in period properly, as discussed here.