# Setting lower bound for intercept parameter in brms?

**URL:** <https://discourse.mc-stan.org/t/setting-lower-bound-for-intercept-parameter-in-brms/16343>\
**Category:** brms\
**Created:** [July 2, 2020, 9:24am UTC](https://discourse.mc-stan.org/t/setting-lower-bound-for-intercept-parameter-in-brms/16343 "2020-07-02T09:24:31Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Guido\_Biele](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.mc-stan.org/guido_biele/32/3414_2.png) [@Guido\_Biele](https://discourse.mc-stan.org/u/Guido_Biele)\
**Post date:** [July 2, 2020, 9:24am UTC](https://discourse.mc-stan.org/t/setting-lower-bound-for-intercept-parameter-in-brms/16343/1 "2020-07-02T09:24:31Z")

</div>

With `set_prior`, brms allows to set lower bounds for regression weights `b` but not for the `Intercept` parameter.

Is there a different way to set a lower bound for a parameter?

One use case is regression models with a likelihood function that is constrained to positive values (e.g. `Gamma`) in combination with an identity link (default e.g. for `Gamma`).

PS:  
I am aware of following workaround:

1. Fit an initial model without bounds
2. Modify model code to implement bound
3. Generate new stanfit-object with updated model code
4. Replace stanfit object in original brmsfit object with the new stanfit object
5. Update the now modified brmsfit model to obtain samples from the updated model (with `compile = F`).

This is what I am currently doing. It works, but it is kind of hacky.

---

<div class="post-metadata">

**Author:** ![Guido\_Biele](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.mc-stan.org/guido_biele/32/3414_2.png) [@Guido\_Biele](https://discourse.mc-stan.org/u/Guido_Biele)\
**Post date:** [July 3, 2020, 12:36pm UTC](https://discourse.mc-stan.org/t/setting-lower-bound-for-intercept-parameter-in-brms/16343/2 "2020-07-03T12:36:52Z")

</div>

Here is a simpler way to use a custom Stan model to implement lower bounds (using rstan as the backend):

1. Create brmsfit object without stanfit object by using the `empty` option  
`bfit = brms(my_formula, my_data, my_family, empty = T)`

2. Update the Stan model, e.g.  
`bfit$model = gsub("real Intercept;","real<lower=0> Intercept;",bfit$model)`

3. Fit the model  
`my_standata = make_standata(my_formula, my_data, my_family)`  
`bfit$fit = stan(model_code = bfit$model, data = my_standata `

[ht](https://github.com/paul-buerkner/brms/issues/945) @paul.buerkner

---

<div class="post-metadata">

**Author:** ![jonah](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.mc-stan.org/jonah/32/200_2.png) [@jonah](https://discourse.mc-stan.org/u/jonah)\
**Post date:** [July 3, 2020, 4:43pm UTC](https://discourse.mc-stan.org/t/setting-lower-bound-for-intercept-parameter-in-brms/16343/3 "2020-07-03T16:43:16Z")

</div>

> [@Guido\_Biele](#):
>
> using rstan as the backend

FWIW I think it would probably also work with cmdstanr as the backend if you change step 3 to something like this:

```no-highlight
mod = cmdstan_model(stan_file = write_stan_tempfile(bfit$model))
fit = mod$sample(data = my_standata)
bfit$fit = rstan::read_stan_csv(fit$output_files())

```

---

<div class="post-metadata">

**Author:** ![Guido\_Biele](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.mc-stan.org/guido_biele/32/3414_2.png) [@Guido\_Biele](https://discourse.mc-stan.org/u/Guido_Biele)\
**Post date:** [July 3, 2020, 7:22pm UTC](https://discourse.mc-stan.org/t/setting-lower-bound-for-intercept-parameter-in-brms/16343/4 "2020-07-03T19:22:55Z")

</div>

Agreed, I didn’t want to imply to imply that it doesn’t work with cmdstanr. I just didn’t have the time to write it down then and wanted to avoid that somebody tries using the code without being aware that this example works with ratan.

---

<div class="post-metadata">

**Author:** ![Solomon](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.mc-stan.org/solomon/32/2495_2.png) [@Solomon](https://discourse.mc-stan.org/u/Solomon)\
**Post date:** [July 4, 2020, 8:56pm UTC](https://discourse.mc-stan.org/t/setting-lower-bound-for-intercept-parameter-in-brms/16343/5 "2020-07-04T20:56:17Z")

</div>

Another solution is to use the `formula = y ~ 0 + intercept + …` syntax where the `intercept` parameter is of `class = b`.

---

<div class="post-metadata">

**Author:** ![Guido\_Biele](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.mc-stan.org/guido_biele/32/3414_2.png) [@Guido\_Biele](https://discourse.mc-stan.org/u/Guido_Biele)\
**Post date:** [July 5, 2020, 11:12am UTC](https://discourse.mc-stan.org/t/setting-lower-bound-for-intercept-parameter-in-brms/16343/6 "2020-07-05T11:12:40Z")

</div>

I thought of this solution (should have mentioned it) and rejected it for the following reasons:

- I want to give the intercept a lower bound, but not the other regression weights
- There are often good reasons that the prior for the intercept is wider than the prior for regression weights

These two points are of course only correct if one sets only one prior for all regression weights. I never checked if brms allows to set different priors for different regression weights like this:

```no-highlight
my_prior = 
  set_prior(normal(0,10), class = "b", coef = "my_intercept", lb = 0) + 
  set_prior(normal(0,2), class = "b", coef = "x1")

```

If this is possible, the solution to with `y ~ 0 + ...` is clearly more elegant.

Edit: OK, I checked, and @Solomon’s solution does not work (except one thinks it’s OK giving intercept and regression weights the same prior and boundaries), because

> Argument ‘coef’ may not be specified when using boundaries.

What does work is to use different priors, and not to specify boundaries i.e. :

```no-highlight
my_prior = 
  set_prior(normal(0,10), class = "b", coef = "my_intercept") + 
  set_prior(normal(0,2), class = "b", coef = "x1")

```

However, this means that Stan can use negative values for `my_intercept` during initialisation, which is problematic for the data set I was am currently working with. More generally, it is my understanding that it is good practice that the one should add the correct boundaries when specifying model parameters.

In sum, the solution @Solomon proposes gets one half the way. If one wants correct specification of prior distribution and parameter boundaries, as of now one has to work with modified stan\_code as described above.

---

<div class="post-metadata">

**Author:** ![Solomon](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.mc-stan.org/solomon/32/2495_2.png) [@Solomon](https://discourse.mc-stan.org/u/Solomon)\
**Post date:** [July 5, 2020, 1:43pm UTC](https://discourse.mc-stan.org/t/setting-lower-bound-for-intercept-parameter-in-brms/16343/7 "2020-07-05T13:43:56Z")

</div>

Interesting. I was not aware that `Argument ‘coef’ may not be specified when using boundaries`. Good to know.

---

<div class="post-metadata">

**Author:** ![IvanUkhov](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.mc-stan.org/ivanukhov/32/6888_2.png) [@IvanUkhov](https://discourse.mc-stan.org/u/IvanUkhov)\
**Post date:** [August 30, 2020, 4:09pm UTC](https://discourse.mc-stan.org/t/setting-lower-bound-for-intercept-parameter-in-brms/16343/8 "2020-08-30T16:09:06Z")

</div>

I am thinking there has to be a reason this limitation exists. Is it simply because it has not been implemented yet, or is it because it would make things much more complicated for the sampler?

---

<div class="post-metadata">

**Author:** ![Guido\_Biele](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.mc-stan.org/guido_biele/32/3414_2.png) [@Guido\_Biele](https://discourse.mc-stan.org/u/Guido_Biele)\
**Post date:** [August 31, 2020, 7:13am UTC](https://discourse.mc-stan.org/t/setting-lower-bound-for-intercept-parameter-in-brms/16343/9 "2020-08-31T07:13:45Z")

</div>

It’s not a problem for the sampler.

---

<div class="post-metadata">

**Author:** ![paul.buerkner](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.mc-stan.org/paul.buerkner/32/3303_2.png) [@paul.buerkner](https://discourse.mc-stan.org/u/paul.buerkner)\
**Post date:** [August 31, 2020, 8:45am UTC](https://discourse.mc-stan.org/t/setting-lower-bound-for-intercept-parameter-in-brms/16343/10 "2020-08-31T08:45:22Z")

</div>

It is simply not implemented yet. The bound features of `set_prior` and not really far developed and will get a complete overhaul at some point to support boundaries more generally rather than just for a few specific parameter classes.

---

<div class="post-metadata">

**Author:** ![cour10eygrace](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.mc-stan.org/cour10eygrace/32/15604_2.png) [@cour10eygrace](https://discourse.mc-stan.org/u/cour10eygrace)\
**Post date:** [March 26, 2024, 10:34pm UTC](https://discourse.mc-stan.org/t/setting-lower-bound-for-intercept-parameter-in-brms/16343/12 "2024-03-26T22:34:21Z")

</div>

would love to see the lb = option implemented for other classes including sd
