Forcing Regression Coefficients in R - Part III Bayesian
Question:
I’m working on a regression model and I need to force the regression coefficients to be positive. How can I accomplish this in R?
Solution:
For linear model regression model with restricted coefficients you have 3 options: Linear with nls, Bayes with brms and Lasso. Here we will look at Linear Model with bayes regresison with the brms package
In this case bayes provides a convenient way to restrict coefficients regularizing the coefficients. Here’s how to accomplish the question using R
if (!require(brms)) install.packages("brms")
if (!require(tidyverse)) install.packages("tidyverse")
# Install kable to visualize tables
if (!require(knitr)) install.packages("knitr")
# Restrict all coefficients to be positive
prior <- c(set_prior("normal(0,10)", class = "b",lb = "0",ub = "10"),
set_prior("uniform(0,100)",class = "Intercept"))
# Now we have a 0 as lower bound for each variable in the model in the vector lb
# And we have a vector of 10 as upper bound for each variable in the model under ub. We can't provide Inf as the upper boundary
# but any large number should be sufficient.
# Fit model using Bayes, attention this is slow
fit2 <- brm(formula = Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width,
data = iris,
family = "gaussian",
warmup = 1000,
iter = 2000,
chains = 4,
prior = prior)
##
## SAMPLING FOR MODEL '7eae0a011a2d1821e7ae3dccca1f5f9b' NOW (CHAIN 1).
## Chain 1:
## Chain 1: Gradient evaluation took 0 seconds
## Chain 1: 1000 transitions using 10 leapfrog steps per transition would take 0 seconds.
## Chain 1: Adjust your expectations accordingly!
## Chain 1:
## Chain 1:
## Chain 1: Iteration: 1 / 2000 [ 0%] (Warmup)
## Chain 1: Iteration: 200 / 2000 [ 10%] (Warmup)
## Chain 1: Iteration: 400 / 2000 [ 20%] (Warmup)
## Chain 1: Iteration: 600 / 2000 [ 30%] (Warmup)
## Chain 1: Iteration: 800 / 2000 [ 40%] (Warmup)
## Chain 1: Iteration: 1000 / 2000 [ 50%] (Warmup)
## Chain 1: Iteration: 1001 / 2000 [ 50%] (Sampling)
## Chain 1: Iteration: 1200 / 2000 [ 60%] (Sampling)
## Chain 1: Iteration: 1400 / 2000 [ 70%] (Sampling)
## Chain 1: Iteration: 1600 / 2000 [ 80%] (Sampling)
## Chain 1: Iteration: 1800 / 2000 [ 90%] (Sampling)
## Chain 1: Iteration: 2000 / 2000 [100%] (Sampling)
## Chain 1:
## Chain 1: Elapsed Time: 0.089 seconds (Warm-up)
## Chain 1: 0.055 seconds (Sampling)
## Chain 1: 0.144 seconds (Total)
## Chain 1:
##
## SAMPLING FOR MODEL '7eae0a011a2d1821e7ae3dccca1f5f9b' NOW (CHAIN 2).
## Chain 2: Rejecting initial value:
## Chain 2: Log probability evaluates to log(0), i.e. negative infinity.
## Chain 2: Stan can't start sampling from this initial value.
## Chain 2:
## Chain 2: Gradient evaluation took 0 seconds
## Chain 2: 1000 transitions using 10 leapfrog steps per transition would take 0 seconds.
## Chain 2: Adjust your expectations accordingly!
## Chain 2:
## Chain 2:
## Chain 2: Iteration: 1 / 2000 [ 0%] (Warmup)
## Chain 2: Iteration: 200 / 2000 [ 10%] (Warmup)
## Chain 2: Iteration: 400 / 2000 [ 20%] (Warmup)
## Chain 2: Iteration: 600 / 2000 [ 30%] (Warmup)
## Chain 2: Iteration: 800 / 2000 [ 40%] (Warmup)
## Chain 2: Iteration: 1000 / 2000 [ 50%] (Warmup)
## Chain 2: Iteration: 1001 / 2000 [ 50%] (Sampling)
## Chain 2: Iteration: 1200 / 2000 [ 60%] (Sampling)
## Chain 2: Iteration: 1400 / 2000 [ 70%] (Sampling)
## Chain 2: Iteration: 1600 / 2000 [ 80%] (Sampling)
## Chain 2: Iteration: 1800 / 2000 [ 90%] (Sampling)
## Chain 2: Iteration: 2000 / 2000 [100%] (Sampling)
## Chain 2:
## Chain 2: Elapsed Time: 0.061 seconds (Warm-up)
## Chain 2: 0.046 seconds (Sampling)
## Chain 2: 0.107 seconds (Total)
## Chain 2:
##
## SAMPLING FOR MODEL '7eae0a011a2d1821e7ae3dccca1f5f9b' NOW (CHAIN 3).
## Chain 3:
## Chain 3: Gradient evaluation took 0 seconds
## Chain 3: 1000 transitions using 10 leapfrog steps per transition would take 0 seconds.
## Chain 3: Adjust your expectations accordingly!
## Chain 3:
## Chain 3:
## Chain 3: Iteration: 1 / 2000 [ 0%] (Warmup)
## Chain 3: Iteration: 200 / 2000 [ 10%] (Warmup)
## Chain 3: Iteration: 400 / 2000 [ 20%] (Warmup)
## Chain 3: Iteration: 600 / 2000 [ 30%] (Warmup)
## Chain 3: Iteration: 800 / 2000 [ 40%] (Warmup)
## Chain 3: Iteration: 1000 / 2000 [ 50%] (Warmup)
## Chain 3: Iteration: 1001 / 2000 [ 50%] (Sampling)
## Chain 3: Iteration: 1200 / 2000 [ 60%] (Sampling)
## Chain 3: Iteration: 1400 / 2000 [ 70%] (Sampling)
## Chain 3: Iteration: 1600 / 2000 [ 80%] (Sampling)
## Chain 3: Iteration: 1800 / 2000 [ 90%] (Sampling)
## Chain 3: Iteration: 2000 / 2000 [100%] (Sampling)
## Chain 3:
## Chain 3: Elapsed Time: 0.06 seconds (Warm-up)
## Chain 3: 0.054 seconds (Sampling)
## Chain 3: 0.114 seconds (Total)
## Chain 3:
##
## SAMPLING FOR MODEL '7eae0a011a2d1821e7ae3dccca1f5f9b' NOW (CHAIN 4).
## Chain 4: Rejecting initial value:
## Chain 4: Log probability evaluates to log(0), i.e. negative infinity.
## Chain 4: Stan can't start sampling from this initial value.
## Chain 4: Rejecting initial value:
## Chain 4: Log probability evaluates to log(0), i.e. negative infinity.
## Chain 4: Stan can't start sampling from this initial value.
## Chain 4: Rejecting initial value:
## Chain 4: Log probability evaluates to log(0), i.e. negative infinity.
## Chain 4: Stan can't start sampling from this initial value.
## Chain 4:
## Chain 4: Gradient evaluation took 0 seconds
## Chain 4: 1000 transitions using 10 leapfrog steps per transition would take 0 seconds.
## Chain 4: Adjust your expectations accordingly!
## Chain 4:
## Chain 4:
## Chain 4: Iteration: 1 / 2000 [ 0%] (Warmup)
## Chain 4: Iteration: 200 / 2000 [ 10%] (Warmup)
## Chain 4: Iteration: 400 / 2000 [ 20%] (Warmup)
## Chain 4: Iteration: 600 / 2000 [ 30%] (Warmup)
## Chain 4: Iteration: 800 / 2000 [ 40%] (Warmup)
## Chain 4: Iteration: 1000 / 2000 [ 50%] (Warmup)
## Chain 4: Iteration: 1001 / 2000 [ 50%] (Sampling)
## Chain 4: Iteration: 1200 / 2000 [ 60%] (Sampling)
## Chain 4: Iteration: 1400 / 2000 [ 70%] (Sampling)
## Chain 4: Iteration: 1600 / 2000 [ 80%] (Sampling)
## Chain 4: Iteration: 1800 / 2000 [ 90%] (Sampling)
## Chain 4: Iteration: 2000 / 2000 [100%] (Sampling)
## Chain 4:
## Chain 4: Elapsed Time: 0.054 seconds (Warm-up)
## Chain 4: 0.044 seconds (Sampling)
## Chain 4: 0.098 seconds (Total)
## Chain 4:
# Extract Coefficients, now all coefficients are positive (except Intercept)
fixef(fit2)[,1:2] -> fits
# See in a neat table
knitr::kable(fits, caption = "Forced Positive Coefficients")
Estimate | Est.Error | |
---|---|---|
Intercept | 2.2725140 | 0.2592316 |
Sepal.Width | 0.5913650 | 0.0717306 |
Petal.Length | 0.4591361 | 0.0230698 |
Petal.Width | 0.0307185 | 0.0310286 |
# Plot Betas
plot(fit2)