I have implemented ELBO for M&M model based on write up in this document. See Section 8 for derivation details; also Section B for an independent re-derivation from Yuxin Zou in checking my work.
(the analytic form are not identical due to different simplifications but I coded both up and checked they agree).
susieR implementation in univariate case¶Here I simulate one trait and run with susieR::susie as well as mvsusieR::susie to check if the elbo agree.
library(mvsusieR)
set.seed(2)
I pick L=5 and simulate a univariate trait,
L = 5
dat = mvsusie_sim1(r=1)
Then run SuSiE and get the ELBO,
res = susieR::susie(dat$X,dat$y,L=L,scaled_prior_variance=0.2,estimate_residual_variance=F,estimate_prior_variance=F)
res$elbo
res = susieR::susie(dat$X,dat$y,L=L,scaled_prior_variance=0.2,estimate_residual_variance=T,estimate_prior_variance=F)
res$elbo
res = susieR::susie(dat$X,dat$y,L=L,scaled_prior_variance=0.2,estimate_residual_variance=T,estimate_prior_variance=T)
res$elbo
mvsusieR's Bayesian multivariate regression module with SuSiE¶I have implemented the multiple regression in this class in mvsusieR package. On the mvsusieR interface this is triggered by setting prior V as a scalar and make input Y a one column matrix,
res = mvsusieR::mvsusie(dat$X,dat$y,L=L,prior_variance=0.2,compute_objective=T,estimate_residual_variance=F,estimate_prior_variance=F)
res$elbo
res = mvsusieR::mvsusie(dat$X,dat$y,L=L,prior_variance=0.2,compute_objective=T,estimate_residual_variance=T,estimate_prior_variance=F)
res$elbo
res = mvsusieR::mvsusie(dat$X,dat$y,L=L,prior_variance=0.2,compute_objective=T,estimate_residual_variance=T,estimate_prior_variance=T)
res$elbo
The output is identical to using susieR.
mvsusieR's MASH regression module with SuSiE¶Here I create a degenerated MASH regression module implemented in mvsusieR. "Degenerated" means it has only one phenotype, and the prior is also a trivial one-component 1 by 1 matrix of 0.2 * var(Y). Here we use EE model in MASH (alpha = 0).
The difference in code between this and previous section in computing ELBO can be found in this function for computing the L-th KL: compute_expected_loglik_partial() and this function: compute_objective() for finalizing the ELBO. The univariate and multivariate cases are distinguished by if ... else statement.
m_init = mvsusieR:::MashInitializer$new(list(matrix(0.2*var(dat$y))), 1, alpha=0)
m_init$mash_prior
res = mvsusieR::mvsusie(dat$X,dat$y,L=L,prior_variance=m_init,compute_objective=T, estimate_residual_variance=F,estimate_prior_variance=F)
res$elbo
The output is also the same as previous calculations.
Now using the same code, but more phenotypes, R = 5, and still using a very simple prior for the MASH part,
set.seed(2)
dat = mvsusie_sim1(r=5)
m_init = mvsusieR:::MashInitializer$new(list(dat$V), 1, alpha=0)
m_init$mash_prior
res = mvsusieR::mvsusie(dat$X,dat$y,L=L,prior_variance=m_init,compute_objective=T,estimate_residual_variance=F,estimate_prior_variance=F)
res$elbo
and with a different seed:
set.seed(1)
dat = mvsusie_sim1(r=5)
m_init = mvsusieR:::MashInitializer$new(list(dat$V), 1, alpha=0)
res = mvsusieR::mvsusie(dat$X,dat$y,L=L,prior_variance=m_init,compute_objective=T,estimate_residual_variance=F,estimate_prior_variance=F)
res$elbo