Dear All:
I am still a bit fuzzy about arrays, vectors, and matrices in Stan. In particular, some of the issues relating to what final form results from an operation on any two of these basic types and also how Stan is structured to prefer one form over the other in terms of efficiency.
I am attaching an example that is working for me (extension of the 8.schools example) but I am not sure I have coded it in the most efficient manner possible, so here goes:
#####################################
require(rstan)
require(plyr)
require(doMC)
require(coda)
require(ggmcmc)
options(cores=4)
registerDoMC()
norm_code <- '
data {
int<lower=0> N;
int<lower=0> D;
row_vector[D] Y[N];
row_vector<lower=0>[D] S[N];
}
parameters {
real mu[D];
real<lower=0> tau[D];
row_vector[D] eta[N];
}
transformed parameters {
row_vector[D] theta[N];
for (n in 1:N) {
for (d in 1:D)
theta[n,d]<- mu[d] + tau[d] * eta[n,d];
}
}
model {
for (n in 1:N)
for (d in 1:D) {
eta[n,d] ~ normal(0, 1);
Y[n,d] ~ normal(theta[n,d], S[n,d]);
}
}
'
## Remove NAs from data and choose shelf
### which.ones <- !
is.na(info.param.p[,'age']) & info.param.p[,'shelf'] == 'AHM'
### Y <- data.matrix(info.param.p[which.ones,-c(1:3)])
### S <- data.matrix(info.se.p[which.ones,-c(1:3)])
Y <- read.csv('Y.csv')
S <- read.csv('S.csv')
N <- dim(Y)[1]
D <- dim(Y)[2]
norm_dat <- list(Y=Y,S=S,N=N,D=D)
initial_multi_lvl_fit <- stan(model_code = norm_code, data = norm_dat, iter = 1,
chains = 1)
num_chains <- 4
num_iter <- 5000
#prep for parallel case
fun <- function(){
fit <- stan(
fit = initial_multi_lvl_fit
, data = norm_dat
, iter = num_iter,
, chains = 1
, verbose = F
)
return(fit)
}
#parallel case
start <- proc.time()[3]
parallel_fit <- foreach(i = 1:num_chains) %dopar% fun()
do.plots <- FALSE
s.try <- extract(parallel_fit[[1]])
params.to.exclude <- -c((D*2 + 1):(D*2 + N*D),dim(s.try)[3])
s <- array(dim=c(dim(s.try)[1],num_chains,dim(s.try)[3]),
dimnames=list('iterations'=NULL,'chains'=paste('chain:',1:num_chains,sep=''),
'parameters'=dimnames(s.try)$parameters))
if (do.plots) {
for (i in 1:num_chains) {
s[,i,] <- extract(parallel_fit[[i]])
}
s.list <- do.call(mcmc.list,alply(s[,,params.to.exclude],2,mcmc))
S <- suppressWarnings(ggs(s.list))
ggmcmc(S, file = 'multi.lvl.V2.pdf')
}
theta.smp <- s.try[,,c(-(1:10),params.to.exclude)]
theta.df <- matrix(0,nrow=N,ncol=D)
j <- 1
for (i in 1:D) {
cat('j:j+N ',j,j+N - 1,'\n')
theta.df[,i] <- apply(theta.smp[,j:(j+N - 1)],2,median)
j <- j + N
}
rownames(theta.df) <- info.param.p[rownames(Y),'
pool.id']
colnames(theta.df) <- colnames(Y)
theta.df <- data.frame(
pool.id = rownames(theta.df),theta.df)
rownames(theta.df) <- NULL
elapsed.time <- proc.time()[3] - start
print(elapsed.time)
################ sessionInfo() ########
R version 2.15.0 (2012-03-30)
Platform: x86_64-pc-linux-gnu (64-bit)
locale:
[1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C LC_TIME=C LC_COLLATE=C LC_MONETARY=C LC_MESSAGES=C
[7] LC_PAPER=C LC_NAME=C LC_ADDRESS=C LC_TELEPHONE=C LC_MEASUREMENT=C LC_IDENTIFICATION=C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] ggmcmc_0.2 ggplot2_0.9.2.1 reshape_0.8.4 coda_0.14-7 doMC_1.2.5 multicore_0.1-7 foreach_1.3.5 codetools_0.2-8
[9] iterators_1.0.5 plyr_1.7.1 rstan_1.0.3 RcppEigen_0.3.1 Matrix_1.0-6 lattice_0.20-6 inline_0.3.10 Rcpp_0.9.10
loaded via a namespace (and not attached):
[1] MASS_7.3-18 RColorBrewer_1.0-5 colorspace_1.1-1 compiler_2.15.0 dichromat_1.2-4 digest_0.5.2 grid_2.15.0
[8] gtable_0.1.1 labeling_0.1 memoise_0.1 munsell_0.3 proto_0.3-9.2 reshape2_1.2.1 scales_0.2.2
[15] stringr_0.6 tools_2.15.0