How to set prior for hyper-parameter

You can do this in brms by passing Stan code to brm() via two arguments: prior and stanvars (which adds tau as a parameter). Effectively this is exactly what @Jean_Billie recommends, but leans on brms to create as much of the Stan code as possible.

bpriors <- prior(normal(0, 2), class = "Intercept") +
  prior(normal(0, 4), class = "b", coef = "x1") +
  prior(normal(0, tau), class = "b", coef = "x2")+  # here is where we add tau as a hyperparameter for the standard deviation of x2
  prior("target += exponential_lpdf(tau | 1)", check = FALSE) +  # here is where we define the prior for tau; I picked exponential(1)
  prior(exponential(1), class = "sigma")

stanvars <- stanvar(scode = "  real<lower=0> tau;",  # here is where we add the parameter for tau
                    block = "parameters")

bmod <- brm(y ~ 1 + x1 + x2, family = gaussian(),
            data = dat, chains = 2,
            prior = bpriors, stanvars = stanvars)  # this line passes the prior & modified parameter blocks into brm()

summary(bmod)

(ht: @paul.buerkner for posting a similar example https://github.com/paul-buerkner/brms/issues/459#issuecomment-399041581)

If your actual model is more complicated than the example you provided, you may find it easier to use the rethinking package. Its syntax is very similar to how you wrote your question. rethinking::ulam is the workhorse function, and within that alist wraps the model (<-) & priors (~)

rmod <- ulam(
  alist(
    y ~ dnorm(mu, sig),
    mu <- a + b*x1 + c*x2,
    a ~ dnorm(0, 2),
    b ~ dnorm(0, 4),
    c ~ dnorm(0, tau),
    tau ~ dexp(1),
    sig ~ dexp(1)
  ),
  data = dat, chains = 2
)
precis(rmod)

Finally, this code wouldn’t be complete without the data needed to make it reproducible. Here’s one way to generate a dummy dataset:

b0 <- 2
b1 <- 0.5
b2 <- 0.75
sigma <- 1

n <- 50
x1 <- runif(n)
x2 <- runif(n)

lp <- b0 + b1 * x1 + b2 * x2
y <- rnorm(n, lp, sigma)

dat <- data.frame(x1, x2, y)
2 Likes