Brms - set priors correctly for group effects

I’m trying to understand how is the best way to set priors for group effects taking into account the variation between them, because I’m a bit confused about the class = “sd”. I have the following case where I want to estimate Units sold using Price which varies by Region (North, South, East, West), using the following :

"Units ~ 1 + Price + (0 + Price | Region)"

Let’s assume that I have knowledge and want the estimates for each region to be around those values :

  • North : 0.6
  • South : 1.1
  • East : 2.1
  • West : 0.05

What would be the best way to define the model priors in order to define the variation among groups since in I can’t specify seperate priors for each beta coefficient of every Region? Would it best captured by something like :

set_prior(normal(Region_avg, Region_sd), class = "b", coef = "Price")

or also I need to add a prior for the sd class where I also account for the variation?

set_prior(student_t(3, 0,  Region_sd)), class = "sd", coef = "Price", group = "Region") 

What would be the best way to define the model priors in order to define the variation among groups since in I can’t specify seperate priors for each beta coefficient of every Region?

Specifying a hierarchical model is setting a prior on the group-level betas. Specifically, it is setting them all to come from a normal distribution with mean zero and a variance to be estimated. Therefore, the prior on that variance is what will determine the extent to which you allow those coefficients to get away from zero. Small sd = all of them will stay close to zero, large sd = it will close to what you would get by running separate models on each subset of data.

By the way, I would be careful about removing the group level intercept. Doing so means that the price coefficient will be forced to absorb any variation across regions, even if it is not actually related to price.

Is there a way to implement regional priors? I attempted the following method, but it did not yield the desired results and get the errors
[R1/R1- regions, and F2F/Event etc. are independent variables.]

prior3 ← c(set_prior(“normal(0,.5)”, class = “b”, coef = “F2F”, group= ‘R1’,lb=0),
set_prior(“normal(1,.5)”, class = “b”, coef = “F2F”, group= ‘R2’,lb=0),
set_prior(“normal(2,25)”, class = “b”, coef = “Event_Attendee”, group= ‘R1’,lb=0),
set_prior(“normal(2.5,25)”, class = “b”, coef = “Event_Attendee”, group= ‘R2’,lb=0),
set_prior(“normal(3.5,25)”, class = “b”, coef = “Virtual_calls”, group= ‘R1’,lb=0)
set_prior(“normal(4.5,25)”, class = “b”, coef = “Virtual_calls”, group= ‘R2’,lb=0)
)
prior3

set.seed(7662345)
model3= brms::brm(Sales_Unit ~ F2F + Event_Attendee + Virtual_calls + (1 + F2F + Event_Attendee + Virtual_calls |Region), data = model_data_Trelegy, prior= prior3)

No, given the structure of your model, I am not aware of any way to set Region-specific priors.

1 Like

@paul.buerkner could you please guide me in that matter as it seems unlikely using brms.

Can you explain what you mean by regional priors?

1 Like

@paul.buerkner
thank you for your response I tried many ways but not worked.

My case study involves analyzing sales and advertising data across multiple states. Each state exhibits unique characteristics, leading to variations in sales and advertising performance. Consequently, it is not feasible to apply a uniform prior across all states, instead, I must assign distinct priors tailored to each state’s specific sales and advertising context and the output beta always should be positive.

Month State Sales Advertisement1 Advertisement2 Advertisement3
Jan-21 Berlin 87,441,004 470 408 211
Feb-21 Berlin 81,858,691 436 430 477
Mar-21 Berlin 50,054,560 361 359 317
Jan-21 Saarland 29,147,001 515 496 447
Feb-21 Saarland 27,286,230 528 265 572
Mar-21 Saarland 16,684,853 559 332 476

I am applying like below
prior3 ← c(set_prior(“normal(2,0.50)”, class = “b”, lb=0, coef = “Advertisement1”, State= ‘Berlin’),
set_prior(“normal(2.5,75)”, class = “b”, lb=0, coef = “Advertisement2”, State= ‘Berlin’),
set_prior(“normal(2.5,60)”, class = “b”, lb=0, coef = “Advertisement3”, State= ‘Berlin’),
set_prior(“normal(1,0.1)”, class = “b”, lb=0, coef = “Advertisement1”, State= ‘Saarland’),
set_prior(“normal(2,25)”, class = “b”, lb=0, coef = “Advertisement2”, State= ‘Saarland’),
set_prior(“normal(2,20)”, class = “b”, lb=0, coef = “Advertisement3”, State= ‘Saarland’)
)
prior3

library(brms)
set.seed(7662345)
model3= brms::brm(Sales~ “Advertisement1”, + “Advertisement2”, + “Advertisement3”, + (1 + “Advertisement1”, + “Advertisement2”, + “Advertisement3” | State), data = StateLevelData, prior= prior3)

that did not work for me.

It’s pannel data set I explained it again with a state level data

I am confused how you specify your formula. It should not use quotes or commas. I.e. use

Sales ~ Ad1 + Ad2 + ... + (Ad1 + Ad2 + ... | State)

That said, you want to specify State specific priors, you cannot use the random effects terms (. | State). Rather, you have to use fixed effects, I assume that something like

Sales ~ (Ad1 + Ad2 + ...) * State

will get you closer to what you want.

Yes, the comma was a typographical error. It does not function for me to provide state-level priors, whether used both model random or fixed.

To specify priors for the individual interactions between the Advertisement variables and State values (which, as other commenters have noted, is only possible for fixed effects), you need to use the names that brms is using internally for those coefficients. Below is an example with the penguins data.

Given a model formula and a data frame, the get_prior() function returns the coefficients in the model. The coef column contains the names brms is using for these coefficients, which will guide you in specifying priors.

library(palmerpenguins)
library(brms)

form = bill_length_mm ~ species*sex

get_prior(formula=form, data=penguins)
#>                  prior     class                     coef group resp dpar nlpar
#>                 (flat)         b                                               
#>                 (flat)         b                  sexmale                      
#>                 (flat)         b         speciesChinstrap                      
#>                 (flat)         b speciesChinstrap:sexmale                      
#>                 (flat)         b            speciesGentoo                      
#>                 (flat)         b    speciesGentoo:sexmale                      
#>  student_t(3, 44.5, 7) Intercept                                               
#>     student_t(3, 0, 7)     sigma                                               
#>  lb ub       source
#>             default
#>        (vectorized)
#>        (vectorized)
#>        (vectorized)
#>        (vectorized)
#>        (vectorized)
#>             default
#>   0         default

No we can set priors for the interactions. The code below sets a global fixed effects prior of normal(0, 1) that will be applied to all fixed effects that don’t have a specific prior, and then sets specific priors for the interactions.

priors = c(prior(normal(0, 1), class="b"),
           prior(normal(0, 0.5), class="b", coef="speciesChinstrap:sexmale"),
           prior(normal(0, 2), class="b", coef="speciesGentoo:sexmale"))

Then, the model fitting code would be:

m = brm(formula=form, prior=priors, data=penguins)

So, in your case, run get_prior() on your model formula and data, then use the coef names to target the specific coefficients (in this case, the interactions between the Advertisement variables and State) for which you want to set individual priors.

In cases where you have lots of priors to set, there are also ways to reduce the amount of typing necessary to set individual priors. For example, in the code below we set a global prior of normal(0, 1) for the fixed effects, which will be applied to all fixed effects coefficients without an explicit prior, and then set specific priors for each of the interaction coefficients.

library(tidyverse)

# Filter priors to target the global fixed effect prior and the interaction priors
priors = get_prior(formula=form, data=penguins) %>% 
  filter(class=="b", grepl(":", coef) | coef=="") 

priors
#>   prior class                     coef group resp dpar nlpar lb ub       source
#>  (flat)     b                                                           default
#>  (flat)     b speciesChinstrap:sexmale                             (vectorized)
#>  (flat)     b    speciesGentoo:sexmale                             (vectorized)

# Set each prior to our desired values
priors = priors %>% 
  mutate(prior = paste0("normal(0, ", c(1, 0.5, 2), ")"))

priors
#>           prior class                     coef group resp dpar nlpar lb ub
#>    normal(0, 1)     b                                                     
#>  normal(0, 0.5)     b speciesChinstrap:sexmale                            
#>    normal(0, 2)     b    speciesGentoo:sexmale                            
#>   source
#>  default
#>  default
#>  default

# Fit the model with the chosen priors
m = brm(formula=form, prior=priors, data=penguins)
1 Like