Multi-dimensional prior distribution

I kindly request your help with specifying a certain prior distribution using set_prior function in the brms package.

The parameter ˮlogbˮ is 16-dimensional and depends on the covariate ˮcompoundˮ (categorical covariate with 16-levels). I need to set a prior for it, which could be - for instance – a 16-dimensional normal distribution with null covariance.

I fail to write the right R code for such a multidimensional prior and its covariance. Could you please help me?

In case of 1-dimensional prior I used:

set_prior(“normal(log(2.5), 0.5)”, nlpar = “logb”)

and it worked.

Thanks!

can you show us your call to brm so we see the formula for the model being fit?

Sure.

dr.fun.m6 <- logy ~ loga + log(exp(logc))*(1 - exp(-(x/exp(logb))^exp(logd)))
# variable comp is categorical, with 16 levels

prior_m6 <- c(set_prior("normal(2.3025, 0.22)",  nlpar = "loga"),
             set_prior("normal(log(0.85), 0.7891595)", nlpar = "logb"), # logb depends on "comp"
             set_prior("normal(log(2.5), 0.5)", nlpar = "logc"),
             set_prior("normal(0, 0.1732051)", nlpar = "logd"),
             set_prior("cauchy(0, 1)", class = "sd", group = "comp", coef="Intercept", nlpar="loga"),
             set_prior("cauchy(0, 1)", class = "sd", group = "comp", coef="Intercept", nlpar="logd"))

form.m6 = bf(dr.fun.m6, nl = TRUE) + list(logc~1,logb~comp, loga~(1||comp), logd~(1||comp))

n_m6 <- brm(form.m6, data = data.ind.m15, prior = prior_m6, control = list(adapt_delta = 0.90, max_treedepth = 11))

edited by @jsocolar for syntax highlighting

Just want to check here. in dr.fun.m6 you have log(exp(logc)) which is just logc. And then you have a triple-exponential of logd. Is this the formula you intend?

I think your question might have an easy answer, but then there’s a subtlety that may or may not matter to you. The easy answer is that you 16-dimensional prior with null covariance is what you achieve by putting normal priors on all of the margins, which in turn is what you achieve by assigning some prior to the coefficients for nlpar = "logb". So maybe that already solves your question?

However, now the subtlety: the categorical covariate will get dummy coded with a reference level and 15 non-reference levels, meaning that by setting independent marginal priors on the intercept and then on the 15 coefficients, the 15 non-reference levels will necessarily have higher marginal prior variance than the reference level. One way to avoid this is to code comp not as a 16-level factor but as 15 binary covariates coded -1/1 instead of 0/1. Then, if independent, symmetrical, zero-centered priors are assigned to all 15 of those covariates, you will end up with prior symmetry across all of the levels of comp. The intercept will no longer correspond to a reference level, but rather to some hypothetical construct that sits directly “in between” belonging to and not belonging to each category.

Thank you for the answer. Yes, I confirm that the model formula is correct as it is.

The inconvenience of the first solution is that I can only specify one single prior for all margins of logb, which is not in line with my real data. “Comp” exhibits different effects on different logb’s and this is what I want to have it reflected in the priors.

The second solution is also inconvenient because I lose the interpretation of the effects, to which I attach importance.

Finally, I did not receive answer to my question: is this not possible to specify a multi-dimensional prior as argument in set_prior?

Thanks.

Brms has no problem specifying some multidimensional priors, and substantial problem specifying others.

When you call

this is already a multidimensional prior on the levels of logb, it’s just that the covariance is null 15 of the margins are the same, and are all higher variance than the margin of the reference category.

If you want to specify the 16 margins independently, but are still ok with null covariance, you can explicitly unpack the factor covariate to it’s 15 columns in the design matrix as part of your input data, and then pass the desired priors on the coefficients via the coef argument in set_prior. However, unless you are willing to encode these columns using something other than dummy coding, you will still be restricted to priors in which the prior variance is higher for 15 levels than for the reference level.

As far as I know, it is not possible to specify multivariate priors with non-null covariance except by getting really hack-y at the level of the generated Stan code. If you’d like to get hack-y, you can specify whatever prior you want by using stanvars to inject arbitrary Stan code into your model block.

To add on what @jsocolar already described, if you want to put a different prior on each level of comp, you can change

to

logb ~ 0 + comp

which supresses the intercept and will estimate an effect for each level of comp, instead of 1 reference level and 15 differences. Then you can set your priors:

set_prior('whateverprior1', class='b', coef='name_of_level1', nlpar='logb') +
set_prior('whateverprior2', class='b', coef='name_of_level2', nlpar='logb') +
...
set_prior('whateverprior16', class='b', coef='name_of_level16', nlpar='logb') 
1 Like

Thank you very much Ven_Popov, this is exactly what I was looking for! Now it works as I wanted!

1 Like

Thank you for the explanations!