Warning (non-fatal rejection): Error in function stan::prob::inv_wishart_log<i>(i): W is not positive definite (0)
Some Notes:I am using the -O3 flag.I have tried using the multinomial distribution (rather than lp__) that doesn't help speed things up.I have tried the multi_normal_cholesky (doesn't help speed)tried and found that softmax function is not available in current version (remove from documentation?)Looking forward to comments, ideas and suggestions.
etamu ~ multi_normal(mu_m_prior, mu_var_prior);
v <- t_L * (etamu - mu_m_prior);
lp__ <- lp__ - 0.5 * dot_product(v,v);
mu_m_prior is a zero vector, so you can just drop that.
In this line,
eta[h] ~ multi_normal(etamu,etavar);
etavar
is an unknown parameter, so using multi_normal() is okay. However,
multi_normal_cholesky() is faster if you parameterize the model in terms
of the elements of the Cholesky factor of the covariance matrix
(etavar). But, doing so presents a complication if you want to put an
inverse Wishart prior on the covariance matrix because you have to
handle the Jacobian yourself. Something like
parameters {
real subdiagonals[(H * (H -1)];
real<lower=0> diagonals[H];
// other parameters
}
model {
matrix[H,H] L_etavar;
int counter;
counter <- 1;
for(i in 1:H) {
for(j in i:(H - 1)) {
L_etavar[i,j] <- subdiagonals[counter];
counter <- counter + 1;
}
L_etavar[i,i] <- diagonals[i];
for(j in (i+1):H) {
L_etavar[i,j] <- 0.0;
}
}
for(h in 1:H) {
eta[h] ~ multi_normal_cholesky(etamu,L_etavar);
}
L_etavar * L_etavar' ~ inv_wishart((D+K-1), invR);
// change-of-variables see "Absolute Jacobian Determinant of the Covariance Matrix Inverse Transform" in Stan manual
for(h in 1:H) {
lp__ <- lp__ + (H - h + 2) * log(diagonals[h]);
}
// rest of model ...
}
At
the moment (this could change in the next version of Stan),
multi_normal() and multi_normal_cholesky() are not vectorized, which is
why you have to loop. This is regrettable because L_etavar gets inverted
H times when it only needs to be inverted once. For the time being, you
could get around this by parameterizing the model in terms of the
Cholesky factor of the precision matrix rather than the covariance
matrix. This resembles what we did above, except now you have to account
for the determinant part of the (log) multivariate normal
parameters {
real subdiagonals[(H * (H -1)];
real<lower=0> diagonals[H];
// other parameters
}
model {
vector[H] v;
matrix[H,H] L_etaprec;
int counter;
counter <- 1;
for(i in 1:H) {
for(j in i:(H - 1)) {
L_etaprec[i,j] <- subdiagonals[counter];
counter <- counter + 1;
}
L_etaprec[i,i] <- diagonals[i];
for(j in (i+1):H) {
L_etaprec[i,j] <- 0.0;
}
}
for(h in 1:H) {
v <- L_etaprec' * (eta - etamu);
lp__ <- lp__ - 0.5 * dot_product(v,v);
}
lp__ <- lp__ + H * sum(log(diagonals)); // log-determinant part
L_etaprec * L_etaprec' ~ wishart((D+K-1), R);
// change-of-variables see "Absolute Jacobian Determinant of the Covariance Matrix Inverse Transform" in Stan manual
for(h in 1:H) {
lp__ <- lp__ + (H - h + 2) * log(diagonals[h]);
}
// rest of model ...
}
Also, note that your prior over L_etaprec * L_etaprec' = etaprec is now Wishart, as opposed to having an inverse Wishart prior over L_etavar * L_etavar' = etavar.
Hopefully, that makes sense and hopefully, that will all be less cumbersome soon.
Ben
P.S. Double-check my Stan code for typos / thinkos.
Why does one have to perform the jacobian increment, manually, when placing LL' ~ inv_wishart() prior on for L, lower triangular? Does Stan recognize L as a cholesky factor and therefore not perform the jacobian adjustment to the unrestricted sampling form? this seem illogical. how would one have any intuition that they would need to handle the jacobian, themselves? in particular, for cov_matrix[D] fred; with fred = LL'; I would not have to perform the adjustment for fred ~ inv_wishart();
parameters{
cov_matrix[K] Sigma;
}
2) If the LHS of a ~ is declared in the transformed parameters block or is declared as a local variable in the model block, then the user DOES need to adjust lp__ with a log absolute Jacobian determinant. Similarly, if updating lp__ manually instead of using the ~ syntax, if the variable(s) that are contributing that that lp__ update are declared in the transformed parameters block or the model block, then the user DOES need to further adjust lp__ with a log absolute Jacobian determinant.
Thanks, Ben. I now understand the distinction *when* the user needs to include the (log absolute determinant) jacobian adjustment. that said, i don't understand why restricted parameters declared in the transformed parameters block if one specifies a distribution in the model block requires the adjustment. If the restricted parameters in the transformed parameters block are a function of parameters in the parameters block (in fashion that obeys previously declared restrictions) and I place a distribution on the transformed parameters in the model block, then the sampling focus shifts to the transformed parameters. I know one can't declare local parameters as restricted in the models block, but when may do so in the parameters block, right? i ask these questions b/c if I understand the outlines of how the stan dev team thinks then i may write smarter .stan scripts.
data {
int<lower=1> K;
}
parameters{
real<lower=0,upper=1> phi;
real<lower=0> sigma_squared;
}
transformed parameters {
cov_matrix[K] Sigma;
// loops to fill in Sigma as a function of phi and sigma_squared
}
model {
// informative prior on phi
phi ~ beta(1,2);
// informative prior on sigma_squared
sigma_squared ~ exp(1);
// should NOT have a prior on Sigma
// should NOT have a Jacobian adjustment
// some likelihood of the data as a function of Sigma
}
data {
int<lower=1> K;
int<lower=K+1> df;
matrix[K,K] scale;
}
parameters {
real<lower=0,upper=1> phi;
real<lower=0> sigma_squared;
}
transformed parameters {
cov_matrix[K] Sigma;
// loops to fill in Sigma as a function of phi and sigma_squared
}
model {
// prior on Sigma with Jacobian adjustment
Sigma ~ wishart(df,scale);
lp__ <- lp__ + SomeJacobianAdjustment;
// should NOT have a prior on phi or sigma_squared
// some likelihood of the data as a function of Sigma
}
g++ -arch x86_64 -dynamiclib -Wl,-headerpad_max_install_names -undefined dynamic_lookup -single_module -multiply_defined suppress -L/usr/local/lib -o file910317019b9b.so file910317019b9b.o /Users/sanjogmisra/Library/R/2.15/library/Rcpp/lib/x86_64/libRcpp.a /Users/sanjogmisra/Library/R/2.15/library/rstan/libstan/x86_64/libstan.a -F/Library/Frameworks/R.framework/.. -framework R -Wl,-framework -Wl,CoreFoundation
SAMPLING FOR MODEL 'hmnlcode' NOW (CHAIN 1).
*** caught segfault ***
address 0x0, cause 'unknown'
Traceback:
1: .External(list(name = "CppMethod__invoke_notvoid", address = <pointer: 0x11bff84d0>, dll = list(name = "Rcpp", path = "/Users/sanjogmisra/Library/R/2.15/library/Rcpp/libs/x86_64/Rcpp.so", dynamicLookup = TRUE, handle = <pointer: 0x115c15900>, info = <pointer: 0x10040adf0>), numParameters = -1L), <pointer: 0x1181408a0>, <pointer: 0x118178890>, .pointer, ...)
2: sampler$call_sampler(args_list[[i]])
3: .local(object, ...)
4: sampling(sm, data, pars, chains, iter, warmup, thin, seed, init, sample_file = sample_file, verbose = verbose, check_data = FALSE, ...)
5: sampling(sm, data, pars, chains, iter, warmup, thin, seed, init, sample_file = sample_file, verbose = verbose, check_data = FALSE, ...)
6: stan(model_code = hmnlcode, data = dat, iter = 2000, chains = 2, verbose = TRUE)
for (int h = 1; h <= H; ++h) {
assign(vk, multiply(transpose(L_etaprec),subtract(get_base1(eta,h,"eta",1),etamu)));
assign(lp__, (lp__ - (0.5 * dot_product(vk,vk))));
}
parameters {
real<lower=0> sigma;
...
}
transformed parameters {
real<lower=0> tau;
tau <- sqrt(sigma);
}
model {
...
tau ~ gamma(0.1, 0.1);
...
}
lp__ <- lp__ + log(0.5 * pow(sigma, -0.5));
Ben,Could you add your discussion of the rules of when the user needs to manually adjust lp__ to the manual? Unless I am missing something, the only discussion is in Ch 16.2 and it only talks about the case in which the LHS of ~ is an expression or lp__ is adjusted directly.And to make sure that I am understanding this correctly, for the following modelparameters {
real<lower=0> sigma;
...
}
transformed parameters {
real<lower=0> tau;
tau <- sqrt(sigma);
}
model {
...
tau ~ gamma(0.1, 0.1);
...
}requires an extra statement in the model block to adjust the log-posteriorlp__ <- lp__ + log(0.5 * pow(sigma, -0.5));
lp__ <- lp__ + log(2.0 * tau); // no abs() necessary because already positive
Also this may be a terrible idea, but I'll throw it out there anyways. Since accumulation seems to be used often in Stan, any chanceof adding the equivalent of =+ and =-? I guess that would be <-+ and <-- (the later being definitely suboptimal syntax).
Thanks for clearing that up; although now I'm feeling pretty stupid for calculating the wrong derivative. Chapter 26 covers the details of the transformations, but the manual doesn't explicitly mention that parameters defined in the transformed parameters block on the LHS of ~ need this adjustment to lp__. However, after writing this, I saw that the example basic_distributions/wishart2x2.stan is an example where the log Jacobian transform is added to lp__.
Thanks for clearing that up; although now I'm feeling pretty stupid for calculating the wrong derivative.
parameters {
real<lower=0> sigma;
...
}
transformed parameters {
real<lower=0> tau;
tau <- sqrt(sigma);
}
model {
...
tau ~ gamma(0.1, 0.1);
...
}requires an extra statement in the model block to adjust the log-posteriorlp__ <- lp__ + log(0.5 * pow(sigma, -0.5));
lp__ <- lp__ + log(0.5 * pow(sigma, -0.5));
Chapter 26 of 1.0.1 reference manual covers this in the most detail. If this were a real model that utilized both sigma and tau for some reason, I would declare tau as the parameter and sigma as the transformed parameter (or as a local parameter within the model block) if you wanted to place an informative prior on gamma.
On Sunday, September 23, 2012 11:02:08 PM UTC-4, Jeffrey Arnold wrote:Thanks for clearing that up; although now I'm feeling pretty stupid for calculating the wrong derivative.
Argh. You were right the first time; I was wrong. Sorry. Everyone vote down my response on Google Groups.
Do-over. You originally said:parameters {
real<lower=0> sigma;
...
}
transformed parameters {
real<lower=0> tau;
tau <- sqrt(sigma);
}
model {
...
tau ~ gamma(0.1, 0.1);
...
}requires an extra statement in the model block to adjust the log-posteriorlp__ <- lp__ + log(0.5 * pow(sigma, -0.5));
If you are going to use informative priors, Stan makes you apply them to things in the parameters block only. However, since
p(sigma | ...) \propto abs(det( J[sigma -> gamma] )) * p(gamma | ...)
a specification for p(gamma | ...) commits you to a specification for p(sigma | ...) but you have to adjust the log posterior yourself. In this case, the Jacobian is 1x1, so it is just the partial derivative of gamma with respect to sigma (which I totally messed up in my first attempt at a response).
On 9/23/12 8:58 PM, Ben Goodrich wrote:
> On Sunday, September 23, 2012 8:01:01 PM UTC-4, Jeffrey Arnold wrote:
>
> Ben,
>
> Could you add your discussion of the rules of when the user needs to manually adjust lp__ to the manual? Unless I am
> missing something, the only discussion is in Ch 16.2 and it only talks about the case in which the LHS of ~ is an
> expression or lp__ is adjusted directly.
We'll add a change of variables chapter to the
user's guide.
I want to try to make clear when you can transform
without a Jacobian and when's one necessary.
Which specific issue were you concerned about adding?
Just Ben's two-point post?
> And to make sure that I am understanding this correctly, for the following model
>
> parameters {
> real<lower=0> sigma;
> ...
> }
> transformed parameters {
> real<lower=0> tau;
> tau <- sqrt(sigma);
> }
> model {
> ...
> tau ~ gamma(0.1, 0.1);
> ...
> }
>
> requires an extra statement in the model block to adjust the log-posterior
>
> lp__ <- lp__ + log(0.5 * pow(sigma, -0.5));
I'd suggest putting it in the transformed parameters block.
And that is the derivative you need. I got SO confused
with the directionality of these in our first implementation
of Stan, that I can feel everyone's pain dealing with this
very acutely. The transform here (at least in the notation
of Gelman et al.'s BDA and our manual) is from tau to
sigma. The inverse transfrom is from sigma to tau,
and it's the log Jacobian of the inverse that needs to be added.
> Also this may be a terrible idea, but I'll throw it out there anyways. Since accumulation seems to be used often in
> Stan, any chance
> of adding the equivalent of =+ and =-? I guess that would be <-+ and <-- (the later being definitely suboptimal
> syntax).
Yes, that's on the to-do list. The usual syntax
in C, Java, etc. for compound assignment has the operator
first. The statement
a += b;
has the same effect on a as:
a = a + b;
Syntactically and semantically it's no issue to add,
but I'm uncertain what to call it given how ugly
"+<-" looks. But that's what it'll have to be.
An alternative would be:
lp_increment(x);
to stand in for:
lp <- lp + x;
Thoughts?
> I also wouldn't necessarily agree that accumulation needs to be used "often". It is just that we have been getting a lot
> of questions from people with big multivariate models, and Stan's implementations of the relevant densities work for
> everything but are optimal for nothing. So, for now, the fastest way to use multivariate normal / t or inverse / plain
> Wishart distributions is with hand-optimized accumulation, but it won't be that way forever.
I want to have this available for sums in loops, too.