Hello,
As it cannot be said often enough:
Thanks to the Stan-team for the time and effort
they invest to make this a great list!!
Now to my problem:
I am implementing fully conditional imputation of amongst
others ordinal variables. I validated the model (code
below) with simulated data, but now it turns out that
fitting is very slow when using HMC for real data.
When using a subset of my data -2500 cases, 4 variables,
two of which are ordinal, with 4 and 6 levels, respectively-
fewer than 100 iterations are done after 12h (with
adapt_delta=.8, on a PC with a 3.4 ghz processor and 8gb RAM).
The same data and model can be fit in around a minute
using variational Bayes, but then vb is “experimental”.
My questions:
1) Does anybody see a way to speed up the model?
I assume the speed-bottle neck is marginalizing out multiple
(here 2) ordinal variables.
2) Is there a reasonable approach to determine that vb
results can be trusted?
I am thinking of (a) simulating data with the same
characteristics as my real data and validate vb by
comparing true and imputed data and/or (b) taking multiple
(very) small subsets of my real data and checking that
for those hmc and vb give the same results.
Thanks in advance for your help!
Guido
/*
fully conditional imputation model for mixed normal & ordinal data.
model assumes two columns of ordinal and two of normal data
*/
data {
int N; // number cases (rows)
int K; // number variables (columns)
int missings[N,K]; // indicator and index of missing variables
int Nmiss[K]; // number missing variables
int nD; // number of discrete variables
int DCs[nD]; // number of unique values per column (discrete vars)
matrix[N,K-nD] x; // matrix with continuous variables
int Dx[N,nD]; // matrix with discrete variables
}
transformed data {
int nC; // number continuous variables
int idvs1[N]; // number of possible values for 1st categorical variable
int idvs2[N]; // number of possible values for 2nd categorical variable
int n_lps[N]; // number of combinations of imputed categorical values over which to marginalize
nC = K-nD;
for (n in 1:N) {
idvs1[n] = missings[n,1] == 0 ? 1 : DCs[1];
idvs2[n] = missings[n,2] == 0 ? 1 : DCs[2];
n_lps[n] = idvs1[n]*idvs2[n];
}
}
parameters{
matrix[K,K-1] betas; // regression weights for imputation
vector[K] alpha; // intercepts for imputation
vector<lower=0>[nC] sigmas; // error variance for imputation
ordered[DCs[1]-1] cp1; // cutpoints first discret variable
ordered[DCs[2]-1] cp2;
real m1[Nmiss[1]]; // missing values
real m2[Nmiss[2]];
real m3[Nmiss[3]];
real m4[Nmiss[4]];
}
model{
matrix[N,nC] xi; // matrix with observed and imputed continuous values
to_vector(betas) ~ normal(0,2);
alpha ~ normal(0,2);
sigmas ~ cauchy(0,2);
m1 ~ normal(0,2); // model won't converge without priors
m2 ~ normal(0,2); // on imputed discrete values
// fill in missing continuous values
for (n in 1:N) {
xi[n,1] = (missings[n,3] == 0 ? x[n,1] : m3[missings[n,3]]);
xi[n,2] = (missings[n,4] == 0 ? x[n,2] : m4[missings[n,4]]);
}
for (n in 1:N) {
int iDx1[n_lps[n]]; // instantiations of of imputed discrete variables
int iDx2[n_lps[n]];
real lp_dv[n_lps[n]]; // log-probabilies for combinations of imputed discrete variables
int m;
m = 0;
for (idv1 in 1:idvs1[n]) {
for (idv2 in 1:idvs2[n]) {
m = m+1;
iDx1[m] = missings[n,1] == 0 ? Dx[n,1] : idv1;
iDx2[m] = missings[n,2] == 0 ? Dx[n,2] : idv2;
lp_dv[m] = (missings[n,1] == 0 ? 0 : ordered_logistic_lpmf(idv1 | m1[missings[n,1]], cp1)) +
(missings[n,2] == 0 ? 0 : ordered_logistic_lpmf(idv2 | m2[missings[n,2]], cp2));
}
}
for (k in 1:K) {
real lps[n_lps[n]];
// marginalize out imputed discrete values
for (j in 1:n_lps[n]) {
real eta;
if (k == 1) {
eta = alpha[k] + iDx2[j]*betas[k,1] + xi[n,1]*betas[k,2] + xi[n,2]*betas[k,3];
lps[j] = lp_dv[j] + ordered_logistic_lpmf(iDx1[j] | eta, cp1);
} else if (k == 2) {
eta = alpha[k] + iDx1[j]*betas[k,1] + xi[n,1]*betas[k,2] + xi[n,2]*betas[k,3];
lps[j] = lp_dv[j] + ordered_logistic_lpmf(iDx2[j] | eta, cp2);
} else if (k == 3) {
eta = alpha[k] + iDx1[j]*betas[k,1] + iDx2[j]*betas[k,2] + xi[n,2]*betas[k,3];
lps[j] = lp_dv[j] + normal_lpdf(xi[n,1] | eta, sigmas[1]);
} else if (k == 4) {
eta = alpha[k] + iDx1[j]*betas[k,1] + iDx2[j]*betas[k,2] + xi[n,1]*betas[k,3];
lps[j] = lp_dv[j] + normal_lpdf(xi[n,2] | eta, sigmas[2]);
}
}
target += log_sum_exp(lps);
}
}
}
generated quantities {
int i1[Nmiss[1]];
int i2[Nmiss[2]];
for (j in 1:Nmiss[1]) i1[j] = ordered_logistic_rng(m1[j], cp1);
for (j in 1:Nmiss[2]) i2[j] = ordered_logistic_rng(m2[j], cp2);
}
eta = alpha[k] + iDx1[j]*betas[k,1] + iDx2[j]*betas[k,2] + xi[n,2]*betas[k,3];
eta = alpha[k] + append_col(to_row_vector(iDx[,j]),xi[n,3]) * betas[,k];
for (j in 1:n_lps[n]) {
real eta;
...
eta = alpha[k] + append_col(to_row_vector(iDx[,j]),xi[n,3]) * betas[,k];
lps[j] = lp_dv[j] + normal_lpdf(xi[n,4] | eta, sigmas[2]);
}
real etas[n_lps[n]];
matrix[n_lps[n],K-1] tmp_x;tmp_x = append_col(append_col(iDx1,IDX2), rep_vector(xi[n,4],[n_lps[n])
etas = alpha[k] + tmp_x * betas[,k];
for (j in 1:n_lps[n]) {
....
lps[j] = lp_dv[j] + normal_lpdf(xi[n,4] | etas[j], sigmas[2]);
}--
You received this message because you are subscribed to the Google Groups "Stan users mailing list" group.
To unsubscribe from this group and stop receiving emails from it, send an email to stan-users+...@googlegroups.com.
To post to this group, send email to stan-...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
eta = x[1]*b[1] + x[2]*b[2] + x[3]*b[3];eta = x * b;Thank you Daniel,I had hoped for a shorter way to learn this,but let me see if I can take a short cut :-).
Figure 1 in the paper shows an expression graph.Is it correct to say that if I have column and rowvectors x and b of length 3, then if I write anywherein the model (or transformed parameters) blockthis results in 11 automatic differentiation variables,eta = x[1]*b[1] + x[2]*b[2] + x[3]*b[3];and an expression tree with 3 levels, whereaseta = x * b;results in only 3 automatic differentiation variablesand an expression tree of 2 levels?
To unsubscribe from this group and stop receiving emails from it, send an email to stan-users+unsubscribe@googlegroups.com.
Thanks Daniel,this helps (not as in "now I fully understand" but moreas in "now I know a bit better what I don't know").Given my limited math and programming background,its probably wise I stick to the "follow best paractice" option.
[about what eta, x and b are: eta and b are parameters, andx is a mix of parameters (used to imputed missing data) anddata.]
To unsubscribe from this group and stop receiving emails from it, send an email to stan-users+unsubscribe@googlegroups.com.
You received this message because you are subscribed to a topic in the Google Groups "Stan users mailing list" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/stan-users/zoelNcwfFYk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to stan-users+...@googlegroups.com.
You received this message because you are subscribed to a topic in the Google Groups "Stan users mailing list" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/stan-users/zoelNcwfFYk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to stan-users+...@googlegroups.com.
just to make sure that I understand what your are saying:lets say we have a design matrix for a regression model x_imputed, which consists mostly of observed data, but some entries of which are parameters (i.e. imputed).If we now focus on one row of x and want multiplicate x_imputed[n,] with regressions weights beta, are you saying that then it would be fastest to do straight forward matrix multiplication for the rows that consist only of data, and to separate data from parameters in a rows of x_imputed that contains parameters before multiplying each predictor with its weight beta?
guido
To unsubscribe from this group and stop receiving emails from it, send an email to stan-users+unsubscribe@googlegroups.com.
--
To post to this group, send email to stan-...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
You received this message because you are subscribed to a topic in the Google Groups "Stan users mailing list" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/stan-users/zoelNcwfFYk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to stan-users+unsubscribe@googlegroups.com.
To post to this group, send email to stan-...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "Stan users mailing list" group.
To unsubscribe from this group and stop receiving emails from it, send an email to stan-users+unsubscribe@googlegroups.com.
After more experimentation I came to the conclusion that this approach (marginalization over multiple imputeted ordered variables) is to slow for my data set.
An alternative approach that seems to work is to rescale the original data to lie between 0 and 1, apply a logit transform to the rescaled data, and to impute data using a multivariate normal distribution (for the rescaled and logit-transformed data). This approach is reasonably faithful to the (my) data and orders of magnitude faster than the original approach.
just to make sure that I understand what your are saying:lets say we have a design matrix for a regression model x_imputed, which consists mostly of observed data, but some entries of which are parameters (i.e. imputed).If we now focus on one row of x and want multiplicate x_imputed[n,] with regressions weights beta, are you saying that then it would be fastest to do straight forward matrix multiplication for the rows that consist only of data, and to separate data from parameters in a rows of x_imputed that contains parameters before multiplying each predictor with its weight beta?guido
On Wed, Dec 14, 2016 at 5:20 PM Daniel Lee wrote:
Hi Guido,
To unsubscribe from this group and stop receiving emails from it, send an email to stan-users+unsubscribe@googlegroups.com.
--
To post to this group, send email to stan-...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
You received this message because you are subscribed to a topic in the Google Groups "Stan users mailing list" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/stan-users/zoelNcwfFYk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to stan-users+unsubscribe@googlegroups.com.