Lesson 8 of 8

Bayesian Regression and GLMs End to End

Every model in this course so far had exactly one unknown: a conversion rate, a demand level, a single number that the prior and the data fought over. Real questions have moving parts. Asha does not just want to know how many terrarium kits she sells; she wants to know whether the money she spends on ads actually moves that number, and by how much.

The moment a predictor enters, the unknown stops being a point and becomes a whole line. This capstone runs the entire pipeline you have built, once, start to finish, on that line.

By the end of this lesson you will be able to:

  • Explain how a predictor turns a one-parameter model into a posterior over a line, and why that beats a single least-squares fit
  • Write a Bayesian generalized linear model for counts (a Poisson likelihood, a log link, and priors on the coefficients), with every symbol defined
  • Fit it in R by extending Lesson 1's grid to two coefficients, then check it, compare it, and report it
  • Turn the posterior into a decision: a credible interval for the effect, a multiplier a stakeholder can act on, and a forecast for a new day, and know what that number does not license

Prerequisites: Lessons 1 to 7 of this course, especially the prior-times-likelihood update on a grid (Lesson 1), the Gamma-Poisson count model and posterior predictive checks (Lesson 6), and WAIC with its elpd difference and standard error (Lesson 7).

Where we are

One unknown becomes a line

Look at the widget on the last slide: a scatter of points and one straight line you can drag. Ordinary regression asks "which single line fits best?" This whole course has trained you to distrust single answers. In Lesson 1 a point estimate became a curve of belief; here a single line becomes a distribution over lines.

Asha's new question needs data with two columns. Each lesson runs in a fresh interactive R session, so we build her log right here. We simulate it from a known truth, a slope of 0.35, so that at the very end we can check whether the fit recovered it (Asha, of course, does not get to peek at that number; we do, so we can grade ourselves):

RInteractive R
set.seed(1) n <- 90 spend <- round(runif(n, 0, 40)) # ad spend each day, in dollars z <- (spend - 20) / 10 # centered at a $20 day, in $10 units kits <- rpois(n, exp(0.4 + 0.35 * z)) # orders that day: a whole-number count head(data.frame(spend, kits, z), 6) #> spend kits z #> 1 11 0 -0.9 #> 2 15 0 -0.5 #> 3 23 2 0.3 #> 4 36 5 1.6 #> 5 8 2 -1.2 #> 6 36 4 1.6

  

Two quick numbers frame the whole lesson: how many kits over the ninety days, and whether the busy ad days really do outsell the quiet ones.

RInteractive R
c(days = n, total = sum(kits), zero_days = sum(kits == 0), biggest = max(kits)) #> days total zero_days biggest #> 90 146 21 6 round(tapply(kits, spend > 20, mean), 2) # mean orders on quiet vs busy ad days #> FALSE TRUE #> 1.12 2.19

  

On the days Asha spent under twenty dollars she sold about 1.1 kits; over twenty, about 2.2, roughly double. That gap could be a real effect of the ads, or it could be the ordinary jitter of small counts. Telling those apart, with honest uncertainty, is the entire job.