
STAT3530 Fall 2026

Centering and scaling, \(x_j \leftarrow (x_j - \bar{x}_j)/s_j\), makes coefficients comparable.
Estimate Std. Error t value Pr(>|t|)
(Intercept) 24.5333333 1.849605 13.2640910 4.413822e-13
scale(Acetic) 0.1871004 2.545979 0.0734886 9.419798e-01
scale(H2S) 8.3200133 2.655260 3.1334077 4.247081e-03
scale(Lactic) 5.9698141 2.618832 2.2795710 3.107948e-02
A one unit increase is now a one SD increase, so H2S is associated with a relatively larger change in mean taste than lactic acid.
Consider the question: is the H2S “effect” (remember, not causal) the largest?
This is actually about the ranking of coefficients; consider the estimand
\[ \theta(\beta) = \text{argmax}_{j>0}\; |\beta_j| \]
The estimate in the standardized cheddar taste model is \(\hat\theta = 2\)
The corresponding population hypothesis is the model constraint
\[ H_0: \theta(\beta) = 2 \qquad\Longleftrightarrow\qquad \{\beta: |\beta_2| \geq |\beta_k| \text{ for each } k > 0\} \]
But this defines a (nonconvex) cone, not a subspace, so you can’t do F tests.
Simulation based inference builds a sampling distribution empirically via computation.
The basic idea:
This is flexible and largely theory free, but it can be tricky to figure out how to simulate from an appropriate model.
One approach: fit a model (possibly under \(H_0\)), shuffle residuals to simulate new data.
Do this many (say \(B = 1000\)) times, then build a sampling distribution for any \(T(Y)\).
Recall the contrast \(H_0: \beta_2 = \beta_3\) in the cheddar model. Here’s a randomization test:
# constrained fit and the observed F statistic
fit.c <- lm(taste ~ Acetic + I(H2S + Lactic),
data = cs)
F.obs <- anova(fit.c, fit.s)$F[2]
# recompute the F stat from new data
sim.F <- function(y) {
m0 <- lm(y ~ Acetic + I(H2S + Lactic), data = cs)
m1 <- lm(y ~ Acetic + H2S + Lactic, data = cs)
anova(m0, m1)$F[2]
}
# shuffle residuals 2000 times
set.seed(1)
F.null <- replicate(2000, {
yb <- fitted(fit.c) + sample(resid(fit.c))
sim.F(yb)
})Here we’re just approximating the F distribution, so the tests are almost identical.
Another approach: draw new residuals from the fitted error model \(\tilde\epsilon_i \stackrel{iid}{\sim} N(0, \hat\sigma^2)\).
As before, set \(B\) large and build a sampling distribution for \(T(Y)\).
This is called a “parametric” bootstrap because we are drawing from an error model.
Testing the same contrast in the cheddar model:
[1] 0.607
We are again just approximating the theoretical sampling distribution.
However the bootstrap distribution is a bit closer to theory since it assumes normality.

Where model-based simulation really shines is for unusual estimands.
Let’s estimate how often the data ranks H2S as most important to taste: \[ P\left(\theta(\hat{\beta}) = 2\right) \qquad\text{where}\qquad \theta(\beta) = \text{argmax}_{j>0}\; |\beta_j| \]
# helper functions
refit <- function(y) lm(y ~ Acetic + H2S + Lactic, data = cs)
biggest <- function(f) names(which.max(abs(coef(f)[-1])))
# 2000 bootstrap samples
set.seed(1)
theta.boot <- replicate(2000, {
yb <- fitted(fit.s) + rnorm(30, 0, sigma(fit.s))
refit(yb) |> biggest()
})
# bootstrap distribution of theta
table(theta.boot) |> prop.table()theta.boot
Acetic H2S Lactic
0.0100 0.7005 0.2895
Bootstrapping works for any functional as long as you can simulate under the model.
Suppose you want a confidence interval for the “effect size” of H2S relative to lactic acid: \[ \theta(\beta) = \frac{\beta_2}{\beta_3} \]
Build a sampling distribution and take quantiles.
2.5% 97.5%
0.2990749 7.8234811
With 95% confidence, the “effect” of H2S on taste is estimated to be between 0.3 and 7.8 times larger than that of lactic acid.
Average SAT total, educational expenditure, and the share of test takers in 50 states.
\[ \text{SAT}_i = \beta_0 + \beta_1 \text{spending}_i + \beta_2 \log(\text{takers}_i) + \epsilon_i \]
Question: what level of spending reaches a target of 975 at 30% participation?
\[\hat{x} = \frac{975 - \hat\beta_0 - \hat\beta_2 \log(\text{takers})}{\hat\beta_1}\]
Note \(\hat{x}(\beta)\) is a nonlinear functional. So compute a bootstrap interval:
2.5% 97.5%
7.571457 11.308079
With 95% confidence, the level of state spending required (in 1994-1995) to achieve a mean SAT total of 975 is estimated to be between $7571 and $11,308.
The symmetry of the usual parametric confidence intervals comes from the normal sampling distribution.
In principle, one could substitute a bootstrap standard error:
This works pretty well in this case, but relies on symmetry of the bootstrap distribution.
The bootstrap distribution for the inverse prediction is heavily skewed.
A normal interval is not appropriate.

To enforce symmetry, take the interval half-width directly from the bootstrap:
\[ \hat\theta \pm c \quad \text{where } P\big(|\hat\theta^{(b)} - \hat\theta| \leq c\big) = 0.95 \]

Recall the tree girth data.
Girth is a circumference. By geometry: \[\text{volume} \propto \text{girth}^2\]
So simply add a quadratic term and fit \[ \text{volume}_i = \beta_0 + \beta_1\, \underbrace{\text{girth}_i}_{f_1(x_i)} + \beta_2\,\underbrace{\text{girth}_i^2}_{f_2(x_i)} + \epsilon_i \]


More broadly, we can fit a \(k^\text{th}\) order polynomial via \[ Y_i = \beta_0 + \beta_1\,x_i + \beta_2\,x_i^2 + \cdots + \beta_k\,x_i^k + \epsilon_i \]
For example, we could try a cubic model for the girth data.
Analysis of Variance Table
Model 1: Volume ~ Girth + I(Girth^2)
Model 2: Volume ~ poly(Girth, degree = 3)
Res.Df RSS Df Sum of Sq F Pr(>F)
1 28 311.38
2 27 302.18 1 9.2022 0.8222 0.3726
No evidence of a cubic relationship.
poly() in RThe poly() function generates polynomials.
By default, these are orthogonalized via Gram-Schmidt. Guesses as to why?
Notice the partial tests are not helpful because raw polynomials are correlated.
Estimate Std. Error Pr(>|t|)
(Intercept) -1.401833e+02 178.34785925 0.4389665
poly(Girth, degree = 4, raw = T)1 4.156852e+01 54.06757554 0.4489249
poly(Girth, degree = 4, raw = T)2 -4.306252e+00 5.96658281 0.4769025
poly(Girth, degree = 4, raw = T)3 2.042494e-01 0.28427175 0.4788565
poly(Girth, degree = 4, raw = T)4 -3.317801e-03 0.00494356 0.5080531
Orthogonalization fixes that.
Estimate Std. Error Pr(>|t|)
(Intercept) 30.170968 0.6070656 2.646861e-27
poly(Girth, degree = 4)1 87.073425 3.3799983 4.903516e-20
poly(Girth, degree = 4)2 14.591793 3.3799983 2.036754e-04
poly(Girth, degree = 4)3 3.033512 3.3799983 3.776938e-01
poly(Girth, degree = 4)4 -2.268438 3.3799983 5.080531e-01
Gram Schmidt orthogonalization gives \(X \to XT\) where \(T\) is an invertible upper-triangular matrix, so \(\text{col}(XT) = \text{col}(X)\) and the least squares projections are identical.


In other words, different coordinates, same column space.
Ozone concentration against temperature, 330 days in the Los Angeles basin.




The data seem to show a change point around 60\(^\circ\)F.
Could fit two models But better if continuous
A piecewise linear model \[ Y_i = \begin{cases} \beta_0 + \beta_1 x_i + \epsilon_i &\text{if } x_i \leq t \\ \alpha_0 + \alpha_1 x_i + \epsilon_i &\text{if } x_i > t \end{cases} \] with the usual assumptions on \(\epsilon_i\).
Cut the range at a knot \(t\) via indicator functions:
\[\begin{align*} I_1(x) &= \begin{cases} 1, &x \leq t \\ 0, &x > t \end{cases} \qquad I_2(x) = \begin{cases} 1, &x > t \\ 0, &x \leq t \end{cases} \end{align*}\]

Now write the piecewise model in terms of “new” predictors \[ Y_i = \beta_0 \underbrace{I_1(x_i)}_{\tilde x_{1i}} + \beta_1 \underbrace{x_i I_1(x_i)}_{\tilde x_{2i}} + \alpha_0 \underbrace{I_2(x_i)}_{\tilde x_{3i}} + \alpha_1 \underbrace{x_i I_2(x_i)}_{\tilde x_{4i}} + \epsilon_i \]
\[ Y_i = \beta_0 I_1(x_i) + \beta_1 x_i I_1(x_i) + \alpha_0 I_2(x_i) + \alpha_1 x_i I_2(x_i) + \epsilon_i \]
Estimate Std. Error t value Pr(>|t|)
x1 -1.6879648 2.41912947 -0.6977571 4.858265e-01
x2 0.1603439 0.04875170 3.2889914 1.115329e-03
x3 -27.0046348 3.00187958 -8.9959088 1.967514e-17
x4 0.5994737 0.04096317 14.6344551 1.248113e-37

So the estimates are \[ \hat\beta_0 = -1.69 \qquad \hat\beta_1 = 0.16 \qquad \hat\alpha_0 = -27.00 \qquad \hat\alpha_1 = 0.60 \]
Let’s add a constraint that the mean has to be continuous in \(x\)
\[ \underbrace{\beta_0 + \beta_1 t}_{\text{left piece at } t} \;=\; \underbrace{\alpha_0 + \alpha_1 t}_{\text{right piece at } t} \quad\Longleftrightarrow\quad \beta_0 + \beta_1 t - \alpha_0 - \alpha_1 t = 0 \]
This is a contrast! \[ c^T\left[\begin{array}{c} \beta \\ \alpha \end{array}\right] = 0 \quad\text{where}\quad c^T = [\,1\;\;t\;\;-1\;\;-t\,] \]
We can reparametrize under the contrast to obtain the “broken stick” model \[ Y_i = \gamma_0 + \gamma_1\,x_i + \gamma_2\, (x_i - t)_+ + \epsilon_i \quad\text{where}\quad (x_i - t)_+ = \max(x_i - t, 0) \]
A bit of algebra and you can show \[ \gamma_0 = \beta_0 \quad \gamma_1 = \beta_1 \quad \underbrace{\gamma_2 = \alpha_1 - \beta_1}_\text{change in slope at knot} \]
\[ Y_i = \gamma_0 + \gamma_1\,x_i + \gamma_2\, (x_i - t)_+ + \epsilon_i \]
(Intercept) temp pmax(temp - 60, 0)
-3.100 0.193 0.433

No evidence of a jump.
Consider now derived variables based on \(K\) knots
\[ 1, \quad x, \quad (x - t_1)_+, \quad \ldots, \quad (x - t_K)_+ \]
Each \((x - t_k)_+\) is flat to the left of its knot, so only changes the slope past \(t_k\).
Consider \(Y_i = f(x_i) + \epsilon_i\) where \(f\) is piecewise linear with knots at \(t_1, \dots, t_K\).
We parametrize via the linear model \(Y = X\gamma + \epsilon\) where \(X\) has rows \[ p(x_i)^T = \left[\begin{array}{ccccc} 1 &x_i &(x_i - t_1)_+ &\cdots &(x_i - t_K)_+ \end{array}\right] \]
Now let \(\eta_k = f(t_k)\) be the mean at the \(k\)th knot so that, adding boundary knots, \[ \eta = E\gamma \quad\text{where}\quad E = \left[\begin{array}{ccccc} p(t_0) &p(t_1) &\cdots &p(t_{K + 1}) \end{array}\right]^T \]
Now \(E\) is invertible so \(\gamma = E^{-1} \eta\) and the model becomes \[ Y = H\eta + \epsilon \] where \(H\) has rows \[ \left[\begin{array}{cccc} h_0(x_i) &h_1(x_i) &\cdots &h_{K + 1}(x_i)\end{array}\right] \quad\text{with}\quad h_k(z) = p(z)^TE^{-1} \]
The functions \(h_k(z) = p(z)^TE^{-1}\) define a local basis for piecewise linear functions.
For any piecewise linear \(f\) with knots at \(t_0, \dots, t_{K + 1}\) \[ f(x) = \sum_{k = 0}^{K + 1} c_k h_k(x) \] for some coefficients \(c_0, \dots, c_{K + 1}\).
So instead of using pmax(...), specify a piecewise linear basis:
Estimate Std. Error
bs(temp, knots = c(50, 60), degree = 1, intercept = TRUE)1 2.740269 1.5842119
bs(temp, knots = c(50, 60), degree = 1, intercept = TRUE)2 6.036252 0.6508552
bs(temp, knots = c(50, 60), degree = 1, intercept = TRUE)3 8.712008 0.5291268
bs(temp, knots = c(50, 60), degree = 1, intercept = TRUE)4 28.941656 0.8606079


Why not change the shape of \(h_k(x)\)’s? If we make them indicators, i.e.,
\[ h_k^{(0)}(x) = I(t_{k} < x \leq t_{k+1}) = \begin{cases} 1, &x\in (t_{k}, t_{k + 1}] \\ 0, &\text{otherwise} \end{cases} \]
we obtain a level shift model. Annual flow of the Nile, with one level change at 1898:
Estimate Std. Error
era[1871,1898] 1097.7500 24.12807
era(1898,1970] 849.9722 15.04649


We can recover the piecewise linear basis by linearly blending the indicator basis:
\[ h_k^{(1)}(x) = \underbrace{\frac{x - t_k}{t_{k + 1} - t_k}}_{\text{ramp up}} h_k^{(0)}(x) \;+\; \underbrace{\frac{t_{k + 2} - x}{t_{k + 2} - t_{k + 1}}}_{\text{ramp down}} h_{k + 1}^{(0)}(x) \]
Now iterate to obtain increasingly smooth bases:
\[ h_k^{(d)}(x) = \frac{x - t_k}{t_{k + d} - t_k}\, h_k^{(d - 1)}(x) \;+\; \frac{t_{k + d + 1} - x}{t_{k + d + 1} - t_{k + 1}}\, h_{k + 1}^{(d - 1)}(x) \]
Repeating boundary knots to “clamp” bases gives \(k = 0, \dots, K + d\).
Each iteration defines a b-spline basis of degree \(d\).

Consider a general nonlinear regression model in one predictor:
\[ Y_i = f(x_i) + \epsilon_i \]
Often one can approximate \(f\) by \[ f(x) \approx \sum_{k = 0}^{K + d} c_k h_k^{(d)}(x) \] where \(h_0^{(d)}, \dots, h_{K + d}^{(d)}\) is a b-spline basis.
bs() functionJust as poly() generates polynomial terms, bs() generates basis expansions.

1 2 3 4 5
[1,] 1.000 0.00000 0.0000000 0.00000000 0
[2,] 0.216 0.55744 0.2152659 0.01129412 0
[3,] 0.064 0.49536 0.4025224 0.03811765 0

Nonlinear relationships can be estimated using a linear model for the basis expansion: \[ Y_i = \beta_0 h_0^{(d)}(x_i) + \beta_1 h_1^{(d)}(x_i) + \cdots + \beta_K h_{K+d}^{(d)}(x_i) + \epsilon_i \]
Estimate Std. Error
H1 2.081659 3.811630
H2 4.746948 2.669437
H3 4.499714 1.465026
H4 10.220868 1.511883
H5 26.083061 1.953848
H6 26.157815 1.670010


Accelerometer readings from a motorcycle crash test. Four knots at degree 3:


Knots are placed where the function seems to bend.
An alternative is to place knots at data quantiles.
Models are nested, so one can compare with an F test.
Analysis of Variance Table
Model 1: accel ~ bs(times, df = 5)
Model 2: accel ~ bs(times, df = 8)
Model 3: accel ~ bs(times, df = 12)
Res.Df RSS Df Sum of Sq F Pr(>F)
1 127 134906
2 124 65319 3 69587 45.7593 < 2e-16 ***
3 120 60829 4 4490 2.2142 0.07145 .
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
