13.4 Setting priors

Bayesian models require priors for all parameters. The function brms::prior_summary shows which priors a model fitted with brms has (implicitly) assumed.

prior_summary(fit_temperature)
##                   prior     class coef group resp dpar nlpar lb ub       source
##                  (flat)         b                                       default
##                  (flat)         b year                             (vectorized)
##  student_t(3, 8.3, 2.5) Intercept                                       default
##    student_t(3, 0, 2.5)     sigma                             0         default

This output tells us that brms used a Student’s \(t\) distribution for the intercept and the standard deviation.62 It also shows us that all slope coefficients (abbreviated here as “b”) have a flat (non-informative) prior.

If we want to change the prior for any model parameter, or family of model parameters, we can use the prior argument in the brm function, which requires a special type of input using brmsprior() function. The syntax for distributions inside the prior() follows that of Stan, as documented in the Stan function reference. The example below sets the prior for the slope coefficient to a very narrow Student’s \(t\) distribution with mean -0.01 and standard deviation 0.001.

fit_temperature_skeptical <- brm(
  # specify what to explain in terms of what
  #  using the formula syntax
  formula = avg_temp ~ year,
  # which data to use
  data = aida::data_WorldTemp,
  # hand-craft priors for slope
  prior = prior(student_t(1, -0.01, 0.001), coef = year)
)

This prior is a skeptical prior in the sense that it assumes a negative slope to be more likely, that is, the world has been getting colder over the years. Comparing the summary statistics for the original fit:

map_dfr(post_samples_temperature, aida::summarize_sample_vector) %>% 
  mutate(Parameter = colnames(post_samples_temperature[1:3]))
## # A tibble: 3 × 4
##   Parameter     `|95%`     mean   `95%|`
##   <chr>          <dbl>    <dbl>    <dbl>
## 1 b_Intercept -4.69    -3.51    -2.32   
## 2 b_year       0.00563  0.00627  0.00689
## 3 sigma        0.373    0.405    0.440

against those of the new fit using skeptical priors:

post_samples_temperature_skeptical <- brms::posterior_samples(fit_temperature_skeptical) %>% 
  select(-lp__,-lprior)
map_dfr(post_samples_temperature_skeptical,
        aida::summarize_sample_vector) %>% 
  mutate(Parameter = colnames(post_samples_temperature_skeptical[1:3]))
## # A tibble: 3 × 4
##   Parameter     `|95%`     mean   `95%|`
##   <chr>          <dbl>    <dbl>    <dbl>
## 1 b_Intercept -4.65    -3.49    -2.21   
## 2 b_year       0.00559  0.00626  0.00688
## 3 sigma        0.372    0.406    0.439

we see that the data has overturned the initial skeptical prior, suggesting that the evidence provided in the data for the belief that the slope coefficient is positive is stronger than the original (maybe hypothetical) assumption to the contrary.

Exercise 13.1

What do you expect to happen to the estimate of the intercept when using a very strong prior on the slope coefficient for year, e.g., a normal distribution with a mean of 5 and a standard deviation of .01?

We should expect the posterior of the slope for year to be much higher than the original estimate, much closer to 5. The reason is that the normal distribution is much less “willing” to allow outliers and so constraints the fit much stronger towards the mean of the prior than the Student’s \(t\) distribution. Notice that with slope values close to 5, the estimates for the intercept and standard deviation also change (in ridiculous ways).

fit_temperature_ridiculous <- brm(
  # specify what to explain in terms of what
  #  using the formula syntax
  formula = avg_temp ~ year,
  # which data to use
  data = aida::data_WorldTemp,
  # hand-craft priors for slope
  prior = prior(normal(5, 0.01), coef = year)
)
post_samples_temperature_ridiculous <- brms::posterior_samples(fit_temperature_ridiculous) %>% 
  select(-lp__,-lprior)
map_dfr(post_samples_temperature_ridiculous,
        aida::summarize_sample_vector) %>% 
  mutate(Parameter = colnames(post_samples_temperature_ridiculous[1:3]))
## # A tibble: 3 × 4
##   Parameter     `|95%`     mean   `95%|`
##   <chr>          <dbl>    <dbl>    <dbl>
## 1 b_Intercept -9446.   -9407.   -9369.  
## 2 b_year          4.97     4.99     5.01
## 3 sigma         355.     386.     422.

  1. Actually, the prior on the standard deviation is a truncated Student’s \(t\) distribution, as negative values are impossible for a standard deviation.↩︎