-
Remove for loop to get 20x speedup (compute computationally costly common terms depending on nu, mu and sigma only once)
-
Generate x_rand in generated quantities for small extra speedup
-
Don't use uniform().
- It's not needed for rho, which has implicit uniform prior on constrained range.
- Don't use uniform to constrain parameters, so for sigma it's better to use, e.g. half-normal.
-
nu below 1 is unlikely to be sensible, as then the distribution has no finite moments (except 0th moment) so I would use constraint <lower=1>
-
Exponential(1/30) gives a lot of mass for very large values of nu. I prefer gamma(2,0.1);
proposed and anlysed by Juárez and Steel (2010). See also discussion in https://github.com/stan-dev/stan/wiki/Prior-Choice-Recommendations.
-
Traces are too crowded and it's not really possible to see the convergence from those. It would be nice if you would also print(cor.clean) to show n_eff's and Rhat's (they look good)
-
It would be usually better to not initialize all the chains with same inits, as it makes the adaptation in warm-up and convergence diagnostic less reliable. For this specific model it may work, but it would be good to mention that in general it's not recommended. It's better to use overdispersed inits for the chains.
-
I think you are running way too long warmup for this easy problem.
-
I think you are running way too long chains, it seems n_eff about 2000 would give you at least 2 digit accuracy for rho, which is probably sufficient. The relative efficiency seems to be around 0.5, so no more than 4000 post-warmup draws combined from different chains would be sufficient.
-
It would be better to run 4 chains, instead of 2 or 1. With the faster Stan code below, there should not be excuse for running 4 chains :)
data {
int<lower=1> N; // number of observations
vector[2] x[N]; // input data: rows are observations, columns are the two variables
}
parameters {
vector[2] mu; // locations of the marginal t distributions
real<lower=0> sigma[2]; // scales of the marginal t distributions
real<lower=1> nu; // degrees of freedom of the marginal t distributions
real<lower=-1, upper=1> rho; // correlation coefficient
}
transformed parameters {
// Covariance matrix
cov_matrix[2] cov = [[ sigma[1] ^ 2 , sigma[1] * sigma[2] * rho],
[sigma[1] * sigma[2] * rho, sigma[2] ^ 2 ]];
}
model {
// Likelihood
// Bivariate Student's t-distribution instead of normal for robustness
x ~ multi_student_t(nu, mu, cov);
// Uninformative priors on all parameters
sigma ~ normal(0,100);
mu ~ normal(0, 100);
nu ~ gamma(2, 0.1);
}
generated quantities {
vector[2] x_rand; // random samples from the bivariate t distribution
// Draw samples from the estimated bivariate t-distribution (for assessment of fit)
x_rand = multi_student_t_rng(nu, mu, cov);
}
Hi,
Nice blog post. Since the blog post didn't include contact info, I'll make an issue and I hopefully you find some of my comments useful.
Remove for loop to get 20x speedup (compute computationally costly common terms depending on nu, mu and sigma only once)
Generate x_rand in generated quantities for small extra speedup
Don't use uniform().
nu below 1 is unlikely to be sensible, as then the distribution has no finite moments (except 0th moment) so I would use constraint <lower=1>
Exponential(1/30) gives a lot of mass for very large values of nu. I prefer gamma(2,0.1);
proposed and anlysed by Juárez and Steel (2010). See also discussion in https://github.com/stan-dev/stan/wiki/Prior-Choice-Recommendations.
Traces are too crowded and it's not really possible to see the convergence from those. It would be nice if you would also print(cor.clean) to show n_eff's and Rhat's (they look good)
It would be usually better to not initialize all the chains with same inits, as it makes the adaptation in warm-up and convergence diagnostic less reliable. For this specific model it may work, but it would be good to mention that in general it's not recommended. It's better to use overdispersed inits for the chains.
I think you are running way too long warmup for this easy problem.
I think you are running way too long chains, it seems n_eff about 2000 would give you at least 2 digit accuracy for rho, which is probably sufficient. The relative efficiency seems to be around 0.5, so no more than 4000 post-warmup draws combined from different chains would be sufficient.
It would be better to run 4 chains, instead of 2 or 1. With the faster Stan code below, there should not be excuse for running 4 chains :)
Modified Stan code