One thing you can try is to use multi_normal_cholesky
I.E., add
transformed data {
matrix[N,N] A_chol;
A_chol <- cholesky_decompose(A);
}
then in the model
u ~ multi_normal_cholesky(0,sqrt(sigmasq_u)*A_chol);
Also, you should be able to use the vectorized version of the normal distribution. I.E., instead of the for loop over ys write
y ~ normal(beta0 + u, sqrt(sig2_e));
Cheers,
Marcus
One thing you can try is to use multi_normal_cholesky
I.E., add
transformed data {
matrix[N,N] A_chol;
A_chol <- cholesky_decompose(A);
}then in the model
u ~ multi_normal_cholesky(0,sqrt(sigmasq_u)*A_chol);
Also, you should be able to use the vectorized version of the normal distribution. I.E., instead of the for loop over ys write
y ~ normal(beta0 + u, sqrt(sig2_e));
transformed data {
matrix[N,N] A_inv; A_inv <- inverse(A);
t_LA_inv <- transpose(cholesky(A_inv));
}
model {
vector[N] v;
real sum_of_squares;
v <- t_LA_inv * u;
sum_of_squares <- 0.0; // or sum(pow(v, 2)) may / should work
for(i in 1:N) {
sum_of_squares <- sum_of_squares + pow(v[i], 2);
}
lp__ <- lp__ - 0.5 * N * log(sigmasq_u); // non-constant part of log(det(sigmasq_u * A)^-0.5)
lp__ <- lp__ - sum_of_squares / (2 * sigmasq_u); // log of kernel of multivariate normal
// rest of your likelihood and priors
}
r<T, std::allocator<_CharT> >&) [with T = double]':
chains.cpp:150: instantiated from here
../inst/include/stansrc/stan/prob/autocovariance.hpp:63: error:
return-statement with a value, in function returning 'void'
make: *** [chains.o] Error 1
ERROR: compilation failed for package 'rstan'
* removing '/home/domingue/R/x86_64-redhat-linux-gnu-library/2.15/rstan'
Warning in install.packages("rstan", type = "source") :
installation of package 'rstan' had non-zero exit status
## TRANSLATING MODEL 'anon_model' FROM Stan CODE TO C++ CODE NOW.## Error in stanc(file = file, model_code = model_code, model_name = model_name, :
## failed to parse Stan model 'anon_model' and error message provided as:
## LOCATION: file=input; line=11, column=40## t_LA_inv <- transpose(cholesky(A_inv));
## ^-- here## DIAGNOSTIC(S) FROM PARSER:
## no matches for function name="cholesky"
## arg 0 type=matrix
## expression is ill formed
## Parser expecting: <eps>
r<T, std::allocator<_CharT> >&) [with T = double]':
chains.cpp:150: instantiated from here
../inst/include/stansrc/stan/prob/autocovariance.hpp:63: error:
return-statement with a value, in function returning 'void'
make: *** [chains.o] Error 1
ERROR: compilation failed for package 'rstan'
* removing '/home/domingue/R/x86_64-redhat-linux-gnu-library/2.15/rstan'
Warning in install.packages("rstan", type = "source") :
installation of package 'rstan' had non-zero exit status
g++ --version
That does explain it. Just a note, but I'm finding a reference to
cholesky() on page 119 but no cholesky_decompose().
With that change, the solution using the Cholesky decomposition starts
producing the same error as the version produced by Frank's code
(which used just the inverse):
SAMPLING FOR MODEL 'anon_model' NOW (CHAIN 1).
Error in sampler$call_sampler(args_list[[i]]) :
No acceptably small step size could be found. Perhaps the posterior
is not continuous?
Howdy all,
I've wrapped the few examples I've been working with into the attached
monstrousity. To offer a little context, this paper is the jumping off
point:
http://www.gllamm.org/BIOMtwins_08.pdf
PS-While I'm writing, I have two add'l questions:
1. I'm wondering if there are plans to add the skew-normal
distribution to the distributions one can access.
2. This block of stan code:
vector[ni] vA;
real sum_of_squaresA;
vA <- t_LA_inv * uA;
#
sum_of_squaresA <- dot_product(vA,vA);
lp__ <- lp__ - 0.5 * ni * log(var_l2A); // non-constant part of log(det(var_l2A * A)^-0.5)
lp__ <- lp__ - sum_of_squaresA / (2 * var_l2A); // log of kernel of multivariate normal
magically leads to sampling of the uA random effects. I'd be really
interested in knowing more about how this happens.
u ~ multi_normal(mean_vector, var_l2A * A);
(var_l2A * A)^-1 = (1/var_l2A) * A^-1
sum_of_squares = u' * A_inv * u;
A_inv = L * L'
u' * A_inv * u = u' (L * L') * u = v' * v
vA ~ normal(0, sqrt(var_l2A));
sum_of_squaresA = dot_product(vA,vA);
lp__ <- lp__ - 0.5 * ni * log(var_l2A); // non-constant part of log(det(var_l2A * A)^-0.5)
lp__ <- lp__ - sum_of_squaresA / (2 * var_l2A); // log of kernel of multivariate normal
- sum_of_squaresA / (2 * var_l2A) = - 0.5 * u' * (var_l2A * A)^-1 * u
// some priors on alpha, xi, and omega
x ~ normal(xi, omega);
lp__ <- lp__ + log(normal_cdf(alpha * x, xi, omega));
// some prior on alpha
x ~ normal(0,1);
lp__ <- lp__ + log(Phi(alpha * x));
This is additional motivation for CDFs on the log scale
in addition to numerical stability of truncation.