Imagine you have a belief about something (a coin’s fairness, a regression coefficient, whatever). Then you observe data. Bayes’ theorem tells you exactly how to update your belief given that new evidence.
\[ \text{Posterior} \;\propto\; \text{Likelihood} \times \text{Prior} \]
Formally:
\[ P(\theta \mid \text{data}) = \frac{P(\text{data} \mid \theta) \, P(\theta)}{P(\text{data})} \]
Analogy: A doctor thinks you have a 1% chance of a rare disease (prior). You test positive on a test that’s 90% accurate (likelihood). Bayes’ theorem combines those two things to tell you your actual updated probability of having the disease (posterior) — which is often much lower than 90%, because the prior matters a lot.
| OLS (Frequentist) | Bayesian | |
|---|---|---|
| Parameters | Fixed, unknown constants | Random variables with a probability distribution |
| Goal | Find the single point estimate minimizing squared residuals | Compute a full posterior distribution over parameters |
| Prior info | Not used (unless you add penalties like ridge/lasso) | Explicitly incorporated via a prior |
| Output | Point estimate + confidence interval | Full posterior + credible interval |
| Interval interpretation | “95% of intervals built this way would contain the true value” | “There’s a 95% probability the true value is in this interval” |
| With a flat/vague prior | — | Posterior mean \(\approx\) OLS estimate (they converge!) |
| With an informative prior | — | Estimates shrink toward the prior (regularization effect, like ridge regression) |
Key insight: OLS is basically a special case of Bayesian inference — the case where you use a completely flat (uninformative) prior. Bayesian analysis generalizes it by letting you add real prior knowledge, and gives you a full distribution of plausible parameter values instead of a single number.
## [1] 0.7083333
## [1] 0.75
Notice the Bayesian estimate is pulled slightly toward the prior belief of 0.5, compared to the raw frequentist estimate. That “pull toward the prior” is the entire philosophical difference from OLS.
This example shows mathematically how a Bayesian posterior mean converges to the OLS estimate as the prior becomes vague, and diverges (shrinks) when the prior is informative. It uses only base R matrix algebra — no extra packages required.
## [,1]
## 1.687471
## x 3.027159
## (Intercept) x
## 1.687471 3.027159
We assume a prior \(\beta \sim \text{Normal}(0, \tau^2 I)\) and treat \(\sigma^2\) as known for simplicity. The posterior is then also Normal, with a closed-form mean:
## [,1]
## 1.687470
## x 3.027159
## [,1]
## 1.270270
## x 3.089465
What this shows:
| Method | Intercept | Slope |
|---|---|---|
| OLS | 1.687 | 3.027 |
| Bayes (vague prior) | 1.687 | 3.027 |
| Bayes (strong prior) | 1.270 | 3.089 |
rstanarm)In practice you rarely do the matrix algebra by hand — you use a
package that runs MCMC sampling to get the full posterior distribution,
which also works for non-conjugate models. This chunk is set to
eval = FALSE by default since it requires installing
rstanarm (which depends on Stan and can take a while to
install).
##
## SAMPLING FOR MODEL 'continuous' NOW (CHAIN 1).
## Chain 1:
## Chain 1: Gradient evaluation took 7.4e-05 seconds
## Chain 1: 1000 transitions using 10 leapfrog steps per transition would take 0.74 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.062 seconds (Warm-up)
## Chain 1: 0.048 seconds (Sampling)
## Chain 1: 0.11 seconds (Total)
## Chain 1:
##
## SAMPLING FOR MODEL 'continuous' NOW (CHAIN 2).
## Chain 2:
## Chain 2: Gradient evaluation took 1.8e-05 seconds
## Chain 2: 1000 transitions using 10 leapfrog steps per transition would take 0.18 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.04 seconds (Warm-up)
## Chain 2: 0.054 seconds (Sampling)
## Chain 2: 0.094 seconds (Total)
## Chain 2:
##
## SAMPLING FOR MODEL 'continuous' NOW (CHAIN 3).
## Chain 3:
## Chain 3: Gradient evaluation took 1.6e-05 seconds
## Chain 3: 1000 transitions using 10 leapfrog steps per transition would take 0.16 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.042 seconds (Warm-up)
## Chain 3: 0.045 seconds (Sampling)
## Chain 3: 0.087 seconds (Total)
## Chain 3:
##
## SAMPLING FOR MODEL 'continuous' NOW (CHAIN 4).
## Chain 4:
## Chain 4: Gradient evaluation took 1.5e-05 seconds
## Chain 4: 1000 transitions using 10 leapfrog steps per transition would take 0.15 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.037 seconds (Warm-up)
## Chain 4: 0.042 seconds (Sampling)
## Chain 4: 0.079 seconds (Total)
## Chain 4:
## stan_glm
## family: gaussian [identity]
## formula: y ~ x
## observations: 100
## predictors: 2
## ------
## Median MAD_SD
## (Intercept) 1.7 0.5
## x 3.0 0.1
##
## Auxiliary parameter(s):
## Median MAD_SD
## sigma 1.8 0.1
##
## ------
## * For help interpreting the printed output see ?print.stanreg
## * For info on the priors used see ?prior_summary.stanreg
## 2.5% 97.5%
## (Intercept) 0.7448792 2.637528
## x 2.8529457 3.204966
## sigma 1.6022757 2.115897
##
## Call:
## lm(formula = y ~ x, data = df)
##
## Residuals:
## Min 1Q Median 3Q Max
## -3.7768 -1.0133 0.0245 1.0821 5.7248
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.68747 0.47975 3.517 0.000662 ***
## x 3.02716 0.08767 34.531 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1.817 on 98 degrees of freedom
## Multiple R-squared: 0.9241, Adjusted R-squared: 0.9233
## F-statistic: 1192 on 1 and 98 DF, p-value: < 2.2e-16
stan_glm() gives you the full posterior
distribution for each coefficient (so you can plot it, compute
any probability statement you want, e.g. “P(slope > 2.5)”), whereas
lm() only gives you a point estimate and a confidence
interval based on repeated-sampling theory.