in
I am following up with 2 points:
1) My belief that the reference manual describes
and incorrect optimized hurdle model is strengthened
2) Code for a faster zero inflated negative binomial model.
### 1) The reference manual describes an ###
### incorrect optimized hurdle model ###
Following up on my last message:
I checked and, as described in the manual,
poissonCDF(0 | lambda) = log(1-exp(-lambda)).
However, to calculate p(y[n] | lambda) for the hurdle model,
one has to divide (or subtract on the log scale) by the
complementary poisson CDF. poissonCCDF.
Instead, the code on page 115 of the
reference manual uses the poissonCDF.
So it should not be
increment_log_prob(-log1m_exp(-lambda))
but
increment_log_prob(-log1m_exp(log1m_exp(-lambda))).
[Alternatively, I am making a fool out of myself ...]
### 2) Code for a faster zero inflated ###
### negative binomial model. ###
Replacing the model section from page 114 in the
stan reference the following makes gradient evaluation
ca. 20% faster.
This code is for a hierarchical model involving multiple
groups, using following variables:
y: vector of length N with observed counts.
phi: vector with over dispersion parameters for groups
etas: vector of length N containing log(mu) for the negative binomial distribution
thetas: logit of p(y == 0)
sx: design matrix
sx0: design matrix for zero inflation
g_start: index of the first entry for a group in y, sx, or sx0
g_nzstart: index of the first nonzero entry for a group in y, sx, or sx0
g_end: index of the last entry for a group in y, sx, or sx0
betas: matrix with regression weights to obtain log(mu), by group
alphas: regressions weight for zero inflation part (same for all groups)
### begin model ###
...
thetas <- to_vector(sx0 * to_matrix(alpha));
for (gr in 1:M) {
log_phi <- log(phi[gr]);
etas[g_start[gr]:g_end[gr]] <- sx[g_start[gr]:g_end[gr],1:K] * beta[gr,1:K]';
// y > 0 cases
increment_log_prob(bernoulli_logit_log(0,thetas[g_nzstart[gr]:g_end[gr]])
+ neg_binomial_2_log_log(y[g_nzstart[gr]:g_end[gr]],
etas[g_nzstart[gr]:g_end[gr]],
phi[gr]));
// y == 0 cases
for (k in g_start[gr]:(g_nzstart[gr]-1)) {
increment_log_prob(log_sum_exp(bernoulli_logit_log(1,thetas[k]),
bernoulli_logit_log(0,thetas[k])
+ neg_binomial_2_log_log(0,etas[k],phi[gr])));
}
}
### end model ####
Following additional modifications did make the model
slightly faster (around 5%), but appeared to be less stable
(i.e. produced NaNs or infinite values where the above model did not):
bernoulli_logit_log(1,thetas[k]) can be obtained from log_inv_logit(thetas[k])
bernoulli_logit_log(0,thetas[k]) can be obtained from log1m__inv_logit(thetas[k])
neg_binomial_2_log_log(0,etas[k],phi[gr]) can be obtained from
(log1m_exp(etas[k] - log_sum_exp(etas[k],log_phi)))*phi[gr])).