Prior predictive check multivariate model

I’m fitting a multivariate model in brms and I wanted to do a prior predictive check. But, I’m running into issues with setting priors.

Here is a toy example:

library(brms)

data("BTdata", package = "MCMCglmm")

fit0 <- brm(
    mvbind(tarsus, back) ~ sex + hatchdate + (1|p|fosternest) + (1|q|dam),
    data = BTdata, chains = 2, cores = 2,  sample_prior = "only"
)
Setting 'rescor' to TRUE by default for this model
Error: Sampling from priors is not possible as some parameters have no proper priors. Error occured for parameter 'b_tarsus'

Ok so I put sample_prior to “no” and fit a model and then do prior_summary(fit0) to get:

> prior_summary(fit0)
                  prior     class      coef      group   resp dpar nlpar bound
1                               b                        back                 
2                               b hatchdate              back                 
3                               b   sexMale              back                 
4                               b    sexUNK              back                 
5                               b                      tarsus                 
6                               b hatchdate            tarsus                 
7                               b   sexMale            tarsus                 
8                               b    sexUNK            tarsus                 
9   student_t(3, 0, 10) Intercept                        back                 
10  student_t(3, 0, 10) Intercept                      tarsus                 
11 lkj_corr_cholesky(1)         L                                             
12                              L                  dam                        
13                              L           fosternest                        
14 lkj_corr_cholesky(1)   Lrescor                                             
15  student_t(3, 0, 10)        sd                        back                 
16  student_t(3, 0, 10)        sd                      tarsus                 
17                             sd                  dam   back                 
18                             sd Intercept        dam   back                 
19                             sd                  dam tarsus                 
20                             sd Intercept        dam tarsus                 
21                             sd           fosternest   back                 
22                             sd Intercept fosternest   back                 
23                             sd           fosternest tarsus                 
24                             sd Intercept fosternest tarsus                 
25  student_t(3, 0, 10)     sigma                        back                 
26  student_t(3, 0, 10)     sigma                      tarsus    

Ok so the b terms don’t have priors so I attempt to set them:

fit1 <- brm(
    mvbind(tarsus, back) ~ sex + hatchdate + (1|p|fosternest) + (1|q|dam),
    data = BTdata, chains = 2, cores = 2, ,
    prior = set_prior("normal(0, 5)", class = "b", coef = "",
                      resp = c("tarsus", "back")), sample_prior = "no")
prior_summary(fit1)

However now I’m still getting the error and when I check priors this time:

> prior_summary(fit1)
                  prior     class      coef      group   resp dpar nlpar bound
1          normal(0, 5)         b                        back                 
2                               b hatchdate              back                 
3                               b   sexMale              back                 
4                               b    sexUNK              back                 
5          normal(0, 5)         b                      tarsus                 
6                               b hatchdate            tarsus                 
7                               b   sexMale            tarsus                 
8                               b    sexUNK            tarsus                 
9                       Intercept                        back                 
10                      Intercept                      tarsus                 
11 lkj_corr_cholesky(1)         L                                             
12                              L                  dam                        
13                              L           fosternest                        
14 lkj_corr_cholesky(1)   Lrescor                                             
15  student_t(3, 0, 10)        sd                        back                 
16  student_t(3, 0, 10)        sd                      tarsus                 
17                             sd                  dam   back                 
18                             sd Intercept        dam   back                 
19                             sd                  dam tarsus                 
20                             sd Intercept        dam tarsus                 
21                             sd           fosternest   back                 
22                             sd Intercept fosternest   back                 
23                             sd           fosternest tarsus                 
24                             sd Intercept fosternest tarsus                 
25  student_t(3, 0, 10)     sigma                        back                 
26  student_t(3, 0, 10)     sigma                      tarsus

I see it has not set priors for all the coefficients for the outcomes. I tried to do this but can’t figure it out. Also, now for some reason the priors for the Intercepts have dissappeared.

Where am I going wrong here?

So I eventually got this to work by specifying many of the priors manually as follows:

fit1 <- brm(
    mvbind(tarsus, back) ~ sex + hatchdate + (1|p|fosternest) + (1|q|dam),
    data = BTdata, chains = 2, cores = 2, ,
    prior = c(
              set_prior("normal(0, 5)", class = "b", resp = c("tarsus", "back"),
                        coef = "sexMale"),
              set_prior("normal(0, 5)", class = "b", resp = c("tarsus", "back"),
                        coef = "sexUNK"),
              set_prior("normal(0, 5)", class = "b", resp = c("tarsus", "back"),
                        coef = "hatchdate"),
              set_prior("normal(0, 5)", class = "Intercept", resp = c("tarsus", "back"),
                                                      coef = "")),
    sample_prior = "only")

pp_check(fit1, resp = "tarsus")

In my real data I have more outcomes and so the priors to set will grow - it gets clunky. @paul.buerkner - am I missing a neater way to set the priors for multiple coefficients in multivariate models ?

Drop the coef argument and only specify the prior once.

Ok thanks. I think I am confused by the prior_summary() output.

i.e. when it looked like this:

… I thought there were no priors on the hatchdate, sexMale and sexUNK covars. I take it thats wrong? Does this instead mean the prior applies to all the covars ?

Yes. See ?set_prior

1 Like

@paul.buerkner I have one more follow on question here. I’m trying to make my priors more informative - however changing that priors for b or intercept doens’t really make much difference.

My real data model is:

fit1 <- brm(
    mvbind(out_fvc, out_svc, out_snip, out_peak) ~ cohort + days_from_baseline +
        (days_from_baseline | uin),
    data = df2, chains = 4, cores = 4,
    prior = c(set_prior("normal(0, 1)", class = "b", resp = c("outfvc", "outsvc", "outsnip", "outpeak")),
              set_prior("normal(0, 1)", class = "Intercept",
                        resp = c("outfvc", "outsvc", "outsnip", "outpeak") )),
    sample_prior = "yes" )

My prior predictive check looks like this:

Current priors are:

> prior_summary(fit1)
                    prior     class               coef group    resp dpar nlpar bound
1            normal(0, 1)         b                           outfvc                 
2                                 b          cohortLON        outfvc                 
3                                 b          cohortLVN        outfvc                 
4                                 b          cohortSHD        outfvc                 
5                                 b          cohortTUR        outfvc                 
6                                 b          cohortUTR        outfvc                 
7                                 b days_from_baseline        outfvc                 
8            normal(0, 1)         b                          outpeak                 
9                                 b          cohortLON       outpeak                 
10                                b          cohortLVN       outpeak                 
11                                b          cohortSHD       outpeak                 
12                                b          cohortTUR       outpeak                 
13                                b          cohortUTR       outpeak                 
14                                b days_from_baseline       outpeak                 
15           normal(0, 1)         b                          outsnip                 
16                                b          cohortLON       outsnip                 
17                                b          cohortLVN       outsnip                 
18                                b          cohortSHD       outsnip                 
19                                b          cohortTUR       outsnip                 
20                                b          cohortUTR       outsnip                 
21                                b days_from_baseline       outsnip                 
22           normal(0, 1)         b                           outsvc                 
23                                b          cohortLON        outsvc                 
24                                b          cohortLVN        outsvc                 
25                                b          cohortSHD        outsvc                 
26                                b          cohortTUR        outsvc                 
27                                b          cohortUTR        outsvc                 
28                                b days_from_baseline        outsvc                 
29           normal(0, 1) Intercept                           outfvc                 
30           normal(0, 1) Intercept                          outpeak                 
31           normal(0, 1) Intercept                          outsnip                 
32           normal(0, 1) Intercept                           outsvc                 
33   lkj_corr_cholesky(1)         L                                                  
34                                L                      uin                         
35   lkj_corr_cholesky(1)   Lrescor                                                  
36   student_t(3, 0, 2.5)        sd                           outfvc                 
37 student_t(3, 0, 148.3)        sd                          outpeak                 
38  student_t(3, 0, 31.1)        sd                          outsnip                 
39   student_t(3, 0, 2.5)        sd                           outsvc                 
40                               sd                      uin  outfvc                 
41                               sd days_from_baseline   uin  outfvc                 
42                               sd          Intercept   uin  outfvc                 
43                               sd                      uin outpeak                 
44                               sd days_from_baseline   uin outpeak                 
45                               sd          Intercept   uin outpeak                 
46                               sd                      uin outsnip                 
47                               sd days_from_baseline   uin outsnip                 
48                               sd          Intercept   uin outsnip                 
49                               sd                      uin  outsvc                 
50                               sd days_from_baseline   uin  outsvc                 
51                               sd          Intercept   uin  outsvc                 
52   student_t(3, 0, 2.5)     sigma                           outfvc                 
53 student_t(3, 0, 148.3)     sigma                          outpeak                 
54  student_t(3, 0, 31.1)     sigma                          outsnip                 
55   student_t(3, 0, 2.5)     sigma                           outsvc      

Now I know that Y can never be negative and will never be higher than about 400 in value, so I’ like to constrain y to about the 0 to 2000 range or so (or I guess -1000 to 1000 range). Do I need to change the sd and sigma priors for each outcome and if so - both sd and sigma or just one?

Zooming in on the pp_checks above I see this:

Is there anyway to set a different prior on the intercept for each outcome? I tried this but it gives an error:

> fit1 <- brm(
+     mvbind(out_fvc, out_svc, out_snip, out_peak) ~ cohort + days_from_baseline +
+         (days_from_baseline | uin),
+     data = df2, chains = 4, cores = 4,
+     prior = c(set_prior("normal(0, 1)", class = "b", resp = c("outfvc", "outsvc", "outsnip", "outpeak")),
+               set_prior("normal(0, 1)", class = "Intercept", resp = c("outfvc"),
+                         "normal(0, 1)", class = "Intercept", resp = c("outsvc"),
+                         "normal(50, 10)", class = "Intercept", resp = c("outsnip"),
+                         "normal(250, 50)", class = "Intercept", resp = c("outpeak") )
+               ),
+     sample_prior = "only" )
Setting 'rescor' to TRUE by default for this model
In the future, 'rescor' will be set to FALSE by default for all models. It is thus recommended to explicitely set 'rescor' via 'set_recor' instead of using the default.Error in set_prior("normal(0, 1)", class = "Intercept", resp = c("outfvc"),  : 
  formal argument "class" matched by multiple actual arguments

OK that error seems to have been caused by c( ) around the resp argument in set_prior. Without it it works perfectly:

fit1 <- brm(
    mvbind(out_fvc, out_svc, out_snip, out_peak) ~ cohort + days_from_baseline +
        (days_from_baseline | uin),
    data = df2, chains = 4, cores = 4,
    prior = c(set_prior("normal(0, 1)", class = "b", resp = c("outfvc", "outsvc", "outsnip", "outpeak")),
              set_prior("normal(2.5, 1)", class = "Intercept", resp = "outfvc" ),
              set_prior("normal(2.5, 1)", class = "Intercept", resp = "outsvc" ),
              set_prior("normal(50, 10)", class = "Intercept", resp = "outsnip" ),
              set_prior("normal(250, 50)", class = "Intercept", resp = "outpeak" )
              ),
    sample_prior = "only" )