Hi all,
I'm running a complex model that seems to be taking ages to run, even if I were to run it without data to perform a prior predictive check. Right now the model runs about 1 iteration per minute, which is agonizing.
I suspect the problem is in the way I'm dealing with some latent multinomials in the model, but I can't figure out a way to speed it up so I'm reaching out for help.
Essentially, there are 105 pixels and 12 life stages that an individual can be in. Individuals can move and they can age (change stages). The problem is that none of this is observed, so to get the likelihood, I combined two large multinomials into a single multinomial draw. This turns the problem into a 105*12 vector of probabilities. I think something in this process is making the model go very very slowly.
Here's what my custom function looks like:
dmmm_psi_move_two <- nimbleFunction(
run = function(x = double(2),
nn = double(2), #n_survivors[1:nState, t, 1:nPix]
psi = double(3), #psi[1:nState,1:nState,t,1:nPix]
nState = double(0), #12 states
nPix = double(0),
pixcount = double(1),
pixopts = double(2),
not0_psi = double(2),#binary indicating impossible transitions
probs_norm = double(3), #movement probabilities
log = integer(0, default = 0)) {
returnType(double(0))
newsize <- sum(nn[1:nState, 1:nPix])
if(newsize < 1)
return(0) #unlikely but saves time if the pop dies out!
x_size <- sum(x[1:nState,1:nPix])
if(x_size != newsize)
return(-Inf)
all_prob = matrix(0, nr = nState*nPix, nc = nState*nPix)
all_prob_norm = matrix(0, nr = nState*nPix, nc = nState*nPix)
#Combine transitions and movement:
for(q in 1:nPix){
for(es in 1:nState){
for(ss in 1:nState){
if(not0_psi[ss,es] >0){ #skip all the known impossible transitions
for(pp in 1:pixcount[q]){
all_prob[ss+nState*(q-1), es+nState*(pixopts[q, pp]-1)] <- probs_norm[q, pixopts[q, pp], es]*psi[ss,es,q]
} #end pp
} #end if statement
} #end ss
} #end es
} #end q
for(i in 1:(nState*nPix)){
if(sum(all_prob[i,]) > 0){
all_prob_norm[i,] <- all_prob[i,]/sum(all_prob[i,])
}
}
#eww, this will go very slowly
#we want to do one multinomial, based on the outcomes of the size-weighted probabilities in each columns
#but first we need to count up how many are in each state right now:
colsizes = c(nn)#just rearranging nn; now goes Stage1pix1, Stage2pix1.... Stage12pix1, stage1pix2..... stage12pixN
#nn <- n_survivors[1:nState, t, 1:nPix] 12*25
newpsis = array(0, dim = nState*nPix)
for(i in 1:(nState*nPix)){ #weight each psi value by size
newpsis[i] = sum(all_prob_norm[1:(nState*nPix), i]*colsizes/newsize)
}
x2 <- c(x) #rearrange n vector from n[1:nState, t, 1:nPix] to a single vector
#x = n[1:nState, t, 1:nPix], two dimensional argument. Hmm.
loglike = dmulti(x2, size = newsize, prob = newpsis, log = TRUE)
if(log) return(loglike)
else return(exp(loglike))
}
)
I realize it's a long shot, but I was hoping someone had some suggestions for how to increase the speed of this beast. I've attached an example that attempts to simplify most everything else in the model *except* for the slow down part.
Best,
Heather