Brms doesn't appear to account for priors on `sigma` when using `sample_prior = "only"`?

When I try to get prior predictive samples for a simple gaussian intercept model with brms, it appears to ignore priors on sigma. Is this intended? Is there a way to somehow override this behavior? Any insight is appreciated!

This is what I expect from a manual simulation:

library(tidyverse)

  tibble(
    mu = rnorm(1e3, 0, 10),
    sigma1 = rexp(1e3, 1),
    sigma5 = rexp(1e3, 5)
  ) |>
  mutate(
    `exp(1)` = rnorm(mu, sigma1),
    `exp(5)` = rnorm(mu, sigma5)
  ) |>
  pivot_longer(starts_with("exp"), names_to = "prior", values_to = "y") |>  
  ggplot(aes(y, color = prior)) + geom_density()

But here’s what I get from brms:

library(brms)
options(brms.backend = 'cmdstanr')

m1 <- brm(
  y ~ 0 + Intercept,
  data = tibble(y = 1),
  family = gaussian(),
  prior = c(
    prior(normal(0, 10), class = "b"),
    prior(exponential(1), class = "sigma")
  ),
  sample_prior = "only",
  chains = 4,
  cores = 4
)

m2 <- brm(
  y ~ 0 + Intercept,
  data = tibble(y = 1),
  family = gaussian(),
  prior = c(
    prior(normal(0, 10), class = "b"),
    prior(exponential(5), class = "sigma")
  ),
  sample_prior = "only",
  chains = 4,
  cores = 4
)

bind_rows(
  posterior_predict(m1, newdata = tibble(y = 1)) |>
    as.vector() |>
    enframe(value = "y") |>
    mutate(prior = "exp(1)"),
  posterior_predict(m2, newdata = tibble(y = 1)) |>
    as.vector() |>
    enframe(value = "y") |>
    mutate(prior = "exp(5)")
) |>
  ggplot(aes(y, color = prior)) + geom_density()

which appears to just be sampling from the normal(0, 10) prior.

I’m running brms 2.18.0, using the cmdstanr 0.5.3 backend on R 4.2.1

Hi and welcome! Your simulation code has a problem. Try instead:

library(tidyverse)

tibble(
  mu = rnorm(1e3, 0, 10),
  sigma1 = rexp(1e3, 1),
  sigma5 = rexp(1e3, 5)
) |>
  mutate(
    `exp(1)` = rnorm(1e3, mu, sigma1),
    `exp(5)` = rnorm(1e3, mu, sigma5)
  ) |>
  pivot_longer(starts_with("exp"), names_to = "prior", values_to = "y") |>  
  ggplot(aes(y, color = prior)) + geom_density()

Hello and thank you! Indeed that was the case, fell victim to not having strong enough expectations of what the predictive distributions should look like. Here’s a better illustrative example using the corrected manual simulation, brms is working as expected.

N <- 1e3

manual_with_sd <- rnorm(
  N,
  mean = rnorm(N, 0, 10),
  sd = rexp(N, 0.05)
)

manual_without_sd <- rnorm(N, 0, 10)

m1 <- brm(
  y ~ 0 + Intercept,
  data = tibble(y = 1),
  family = gaussian(),
  prior = c(
    prior(normal(0, 10), class = "b"),
    prior(exponential(0.05), class = "sigma")
  ),
  sample_prior = "only",
  chains = 4,
  cores = 4
)

brms_preds <- posterior_predict(m1, newdata = tibble(y = 1), ndraws = N) |>
  as.vector()

tibble(manual_with_sd, manual_without_sd, brms_preds) |>
  pivot_longer(everything(), names_to = "simulation", values_to = "y") |>
  ggplot(aes(y, color = simulation)) + geom_density()