[changed subject so people can find it in the future]
Thanks for the nice example and writeup.
I have one piece of advice: always work on the log scale
when you can. Things like binomial coefficients and gamma are prone
to overflow when taken off the log scale, so exp() is always a red flag.
Here's the program excerpt:
> data {
...
> matrix[n, length_u] u_mat; // matrix of indicators to facilitate summation
> }
> parameters {
> vector<lower=0>[3] theta; // expected values for component responses
> }
> transformed parameters {
...
> vector[length_u] u_terms;
>
> for (i in 1:length_u){
> u_terms[i] <- exp(binomial_coefficient_log(Y[1, which_n[i]], u[i]) +
> binomial_coefficient_log(Y[2, which_n[i]], u[i]) +
> lgamma(u[i] + 1) +
> u[i] * (log_theta[3] - log_theta[1] - log_theta[2]));
> }
> u_sum <- u_mat * u_terms;
> }
>
>
> model {
...
> log(u_sum[i]);
> }
Formatting wise, the "+" signs can go on the next line following standard
math notation --- unlike R, Stan can handle run-on expressions like this because
we have the ";" for a line-termination marker.
The robust way to write this is with the log_sum_exp operation. So
just leave u_terms on the log scale, defining a variable:
> for (i in 1:length_u)
> log_u_terms[i] <- binomial_coefficient_log(Y[1, which_n[i]], u[i])
> + binomial_coefficient_log(Y[2, which_n[i]], u[i])
> + lgamma(u[i] + 1) +
> + u[i] * (log_theta[3] - log_theta[1] - log_theta[2]));
And then noting that
u_sum[i] = u_mat[i] * u_terms,
so that
log(u_sum[i]) = log(u_mat[i] * u_terms)
and noting that u_mat[i] is a row vector and u_terms a vector, you get
log(u_sum[i]) = log(SUM_k u_mat[i,k] * u_terms[k])
= log(SUM_k exp(log(u_mat[i,k] * u_terms[k])))
= log(SUM_k exp(log(u_mat[i,k]) + log(u_terms[k])))
= log_sum_exp(log(u_mat[i]) + log_u_terms)
which should all execute without overflow anywhere. You'll want to recompute
u_mat on the log scale as transformed data and create an array of vectors,
as in:
transformed data {
vector[length_u] log_u_mat[N];
for (n in ...)
for (m in ...)
log_u_mat[n,m] <- log(u_mat[n,m]);
to do this most efficiently (there's a chapter on arrays vs. matrices
and efficiency in the manual).
You'll want to recompute u_mat on the log scale rather than literally
taking the log of it each time.
You should get the same answer, though!
- Bob
> On Jan 11, 2015, at 12:05 AM, Maxwell Joseph <
maxwell...@gmail.com> wrote:
>
> Here's a start - recovers the true parameters well, but could probably be more efficiently constructed. This specification lacks covariates, so there are only three parameters: theta_1, theta_2, and theta_3. This is a general case of a bivariate Poisson, rather than the specific parameterization for N-mixture model equivalence given by Dennis et al. 2014. The bivariate Poisson corresponds to an N-mixture model with two repeated surveys. With R repeated surveys, you'd need an R-dimensional multivariate Poisson. I'm going to see if I can implement that case with covariates, but this might be useful for people interested in the bivariate Poisson, but not interested in N-mixture models. Here's a gist of the same script. The parameterization below corresponds to the likelihood:
>
>
>
>
>
>