Prediction and Model Selection

Dr. Lucy D’Agostino McGowan

Why Prediction Matters

In regression analysis, we often care about:

  1. Prediction accuracy - how well does our model predict new observations?
  2. Model selection - which predictors should we include?
  3. Generalization - will our model work on future data?

Prediction with OLS

The Prediction Problem

We fit a model on our data and get \(\hat{\beta}\)

Question: How well will this model predict a new observation \(y_{\text{new}}\) at \(x_{\text{new}}\)?

Two Types of Predictions

Fitted values: Predictions for observations in our dataset

\[\hat{y}_i = x_i^T\hat{\beta}\]

Two Types of Predictions

Out-of-sample predictions: Predictions for new observations

\[\hat{y}_{\text{new}} = x_{\text{new}}^T\hat{\beta}\]

Prediction Error

Goal: Minimize prediction error on new data, not just training data!

Cross-Validation

The Problem with Training Error

Training error (in-sample): \[\text{MSE}_{\text{train}} = \frac{1}{n}\sum_{i=1}^n (y_i - \hat{y}_i)^2\]

Problem: Always decreases when we add predictors, even useless ones!

Solution: Estimate error on data the model hasn’t seen

Leave-One-Out Cross-Validation (LOOCV)

Idea: For each observation \(i\):

  1. Remove observation \(i\) from the dataset
  2. Fit model on remaining \(n-1\) observations
  3. Predict the removed observation
  4. Calculate prediction error

Leave-One-Out Cross-Validation (LOOCV)

\[\text{CV} = \frac{1}{n}\sum_{i=1}^n (y_i - \hat{y}_{-i})^2\]

where \(\hat{y}_{-i}\) is the prediction for \(y_i\) using all data except observation \(i\)

LOOCV: Visual Intuition

LOOCV Seems Expensive!

Problem: LOOCV requires fitting the model \(n\) times

For \(n = 1000\) observations, we need to fit 1000 models!

Good news: There’s a shortcut using the hat matrix!

The Hat Matrix

Remember that fitted values are: \[\hat{y} = X\hat{\beta} = X(X^TX)^{-1}X^Ty = Hy\]

\[H = X(X^TX)^{-1}X^T\]

is called the hat matrix because it puts a “hat” on \(y\)

Leverage: The Diagonal of \(H\)

The diagonal elements \(h_{ii}\) are called leverages

\[\hat{y}_i = \sum_{j=1}^n h_{ij}y_j = h_{ii}y_i + \sum_{j \neq i}h_{ij}y_j\]

Interpretation: \(h_{ii}\) measures how much \(y_i\) influences its own prediction

The LOOCV Shortcut

Fun fact: We don’t need to refit the model \(n\) times!

\[\text{CV} = \frac{1}{n}\sum_{i=1}^n \left(\frac{y_i - \hat{y}_i}{1 - h_{ii}}\right)^2\]

This is exact LOOCV computed from a single model fit!

Intuition: The term \(\frac{1}{1-h_{ii}}\) inflates residuals for high-leverage points

LOOCV Formula Derivation

When we remove observation \(i\), the prediction error is:

\[y_i - \hat{y}_{-i} = \frac{y_i - \hat{y}_i}{1 - h_{ii}}\]

Why? The fitted value \(\hat{y}_i\) uses \(y_i\) with weight \(h_{ii}\)

When we remove \(y_i\), we need to account for its influence

Computing LOOCV in R

set.seed(1)
n <- 50
x <- runif(n, 0, 10)
y <- x + rnorm(n)

model <- lm(y ~ x)

# Get hat values (leverages)
h <- hatvalues(model)

# Get residuals
resid <- residuals(model)

# LOOCV using the shortcut formula
cv_error <- mean((resid / (1 - h))^2)

cv_error
[1] 0.8909796

LOOCV for Model Selection

I generated data with a quadratic relationship and then fit increasingly flexible models.

Information Criteria

Akaike Information Criterion (AIC)

Idea: Penalize model complexity

\[\text{AIC} = n\log(\text{MSE}) + 2p+\underbrace{n+n\log(2\pi)}_{C}\]

where \(p\) is the number of parameters (including intercept)

Akaike Information Criterion (AIC)

Interpretation:

  • First term: fit to the data (want small MSE)
  • Second term: penalty for complexity (want small \(p\))

Lower AIC is better

Connection Between AIC and LOOCV

Fun fact: AIC is asymptotically equivalent to LOOCV!

Implication: Choosing the model with smallest AIC is approximately the same as choosing the model with smallest LOOCV error

Computing AIC in R

# Using quadratic data from before
model1 <- lm(y ~ x)
model2 <- lm(y ~ poly(x, 2))
model3 <- lm(y ~ poly(x, 3))

aic_values <- c(AIC(model1), AIC(model2), AIC(model3))

data.frame(
  model = c("Linear", "Quadratic", "Cubic"),
  AIC = round(aic_values, 2)
)
      model    AIC
1    Linear 358.23
2 Quadratic 325.19
3     Cubic 327.11

AIC for Model Selection

Notice: AIC and LOOCV select the same model (degree 2)!

Other Model Selection Criteria

Adjusted R²

Problem with \(R^2\): Always increases when we add predictors

\[R^2 = 1 - \frac{\text{SSE}}{\text{TSS}}\]

Adjusted R²

Solution: Penalize for number of predictors

\[R^2_{\text{adj}} = 1 - \frac{\text{SSE}/(n-p)}{\text{TSS}/(n-1)}\]

Higher is better (unlike AIC where lower is better)

Adjusted R²: Intuition

Adjusted R² uses unbiased estimates of variance:

  • \(\text{SSE}/(n-p)\) is unbiased for \(\sigma^2\)
  • \(\text{TSS}/(n-1)\) is unbiased for variance of \(y\)

Adjusted R²: Intuition

Adding a useless predictor:

  • Decreases SSE slightly
  • Increases \(p\) by 1
  • Denominator \(n-p\) gets smaller
  • Net effect can decrease \(R^2_{\text{adj}}\)

Comparing Criteria

             AIC Adj_R2 LOOCV
Degree 1 358.228  0.570 5.098
Degree 2 325.187  0.719 3.403
Degree 3 327.106  0.715 3.573
Degree 5 330.560  0.710 4.067

Mallows’ \(C_p\)

Another criterion for model selection:

\[C_p = \frac{\text{SSE}}{\hat{\sigma}^2} - n + 2p\]

where \(\hat{\sigma}^2\) is estimated from the largest model considered

Interpretation: Estimates prediction error, similar to AIC

All Criteria Together

Prediction Intervals

Point Predictions vs Intervals

So far: point prediction \(\hat{y}_{\text{new}} = x_{\text{new}}^T\hat{\beta}\)

Problem: This gives no sense of uncertainty!

Solution: Construct an interval that contains \(y_{\text{new}}\) with probability \(1-\alpha\)

Two Types of Intervals

Confidence interval for \(E[y_{\text{new}}]\):

  • Uncertainty in estimating the mean response
  • What is the average \(y\) at this \(x\)?

Two Types of Intervals

Prediction interval for \(y_{\text{new}}\):

  • Uncertainty in predicting a single new observation
  • What will the next \(y\) be at this \(x\)?

Prediction intervals are always wider!

Sources of Uncertainty

For confidence intervals: \[\text{Var}(\hat{y}_{\text{new}}) = \sigma^2 x_{\text{new}}^T(X^TX)^{-1}x_{\text{new}}\]

Sources of Uncertainty

For prediction intervals: \[\text{Var}(y_{\text{new}} - \hat{y}_{\text{new}}) = \sigma^2\left(1 + x_{\text{new}}^T(X^TX)^{-1}x_{\text{new}}\right)\]

The “+1” accounts for the inherent randomness of \(y_{\text{new}}\)

Prediction Interval Formula

\[\hat{y}_{\text{new}} \pm t_{\alpha/2, n-p} \cdot \hat{\sigma}\sqrt{1 + x_{\text{new}}^T(X^TX)^{-1}x_{\text{new}}}\]

where:

  • \(t_{\alpha/2, n-p}\) is the t-distribution critical value
  • \(\hat{\sigma}\) is the estimated standard deviation of residuals

Visualization: Confidence vs Prediction

Computing Intervals in R

# Fit model
model <- lm(y ~ x)

# New x value
x_new <- data.frame(x = 5)

# Confidence interval for mean
conf_int <- predict(model, newdata = x_new, 
                    interval = "confidence", level = 0.95)

# Prediction interval for new observation
pred_int <- predict(model, newdata = x_new, 
                    interval = "prediction", level = 0.95)

# Compare
rbind(
  Confidence = conf_int,
  Prediction = pred_int
)
       fit       lwr      upr
1 17.48305 16.151581 18.81453
1 17.48305  8.041862 26.92425

Ridge Regression

The Problem: Multicollinearity

What happens when predictors are highly correlated?

  • OLS estimates \(\hat{\beta}\) become unstable
  • Small changes in data → large changes in coefficients
  • Variance of \(\hat{\beta}\) is large
  • Predictions can be unreliable

Visualizing Multicollinearity

The Variance Inflation Factor

Quantifies multicollinearity:

\[\text{VIF}_j = \frac{1}{1 - R^2_j}\]

where \(R^2_j\) is from regressing \(x_j\) on all other predictors

Ridge Regression: The Idea

Trade bias for reduced variance

Instead of minimizing SSE: \(\min_{\beta} \sum_{i=1}^n (y_i - x_i^T\beta)^2\)

Ridge regression adds a penalty: \(\min_{\beta} \sum_{i=1}^n (y_i - x_i^T\beta)^2 + \lambda\sum_{j=1}^p \beta_j^2\)

Ridge Regression: The Idea

\(\lambda \geq 0\) is the tuning parameter:

  • \(\lambda = 0\): ordinary least squares
  • \(\lambda > 0\): shrinks coefficients toward zero
  • \(\lambda \to \infty\): all coefficients → 0

Why Penalize the Coefficients?

Large coefficients indicate:

  • Model is fitting noise
  • Overly sensitive to small changes
  • High variance in predictions

Why Penalize the Coefficients?

Penalizing \(\sum \beta_j^2\) encourages:

  • Smaller, more stable coefficients
  • Reduced variance
  • Better prediction (despite bias)

Ridge Solution

The ridge estimator has a closed form: \(\hat{\beta}_{\text{ridge}} = (X^TX + \lambda I)^{-1}X^Ty\)

Compare to OLS: \(\hat{\beta}_{\text{OLS}} = (X^TX)^{-1}X^Ty\)

Key difference: Adding \(\lambda I\) to \(X^TX\) ensures the matrix is invertible even when \(X^TX\) is singular!

Standardization is Critical

Problem: Penalty depends on scale of predictors

If \(x_1\) is in dollars and \(x_2\) is in thousands of dollars, their coefficients are penalized differently

Solution: Standardize predictors before applying ridge regression \(\tilde{x}_{ij} = \frac{x_{ij} - \bar{x}_j}{s_j}\)

Note: Usually don’t penalize the intercept

Bias-Variance Tradeoff

Choosing Lambda: Cross-Validation

How do we choose \(\lambda\)?

Use cross-validation to find \(\lambda\) that minimizes prediction error!

LOOCV is a standard approach for selecting \(\lambda\)

Ridge Regression with CV

library(glmnet)

# Use previous data
# alpha = 0 means ridge (alpha = 1 would be lasso)
ridge_cv <- cv.glmnet(X_scaled, y, alpha = 0)

# Plot CV error
plot(ridge_cv, main = "Cross-Validation for Ridge Regression")

LOOCV Shortcut for Ridge

Good news: The hat matrix trick works for ridge too!

For ridge regression with penalty \(\lambda\), the hat matrix is:

\(H_{\lambda} = X(X^TX + \lambda I)^{-1}X^T\)

LOOCV formula:

\(\text{CV}(\lambda) = \frac{1}{n}\sum_{i=1}^n \left(\frac{y_i - \hat{y}_i(\lambda)}{1 - h_{ii}(\lambda)}\right)^2\)

where \(h_{ii}(\lambda)\) is the \(i\)-th diagonal of \(H_{\lambda}\)

Just like OLS, but now everything depends on \(\lambda\)!

Computing LOOCV for Ridge

# Compute LOOCV manually for a grid of lambdas
lambdas <- 10^seq(2, -2, length.out = 50)
loocv_errors <- numeric(length(lambdas))

for (i in seq_along(lambdas)) {
  lambda <- lambdas[i]
  
  # Ridge hat matrix
  H_lambda <- X_scaled %*% solve(t(X_scaled) %*% X_scaled + lambda * diag(p)) %*% t(X_scaled)
  
  # Ridge predictions
  y_hat <- H_lambda %*% y
  
  # LOOCV using shortcut formula
  h_diag <- diag(H_lambda)
  loocv_errors[i] <- mean(((y - y_hat) / (1 - h_diag))^2)
}

# Plot
ggplot(data.frame(lambda = lambdas, loocv = loocv_errors),
       aes(x = log10(lambda), y = loocv)) +
  geom_line(color = "#d5008f", linewidth = 1) +
  geom_point(color = "#d5008f", size = 2) +
  geom_vline(xintercept = log10(lambdas[which.min(loocv_errors)]),
             linetype = "dashed", color = "blue") +
  labs(title = "LOOCV Error vs Ridge Penalty",
       subtitle = paste("Optimal log₁₀(λ) =", 
                       round(log10(lambdas[which.min(loocv_errors)]), 2)),
       x = expression(log[10](λ)),
       y = "LOOCV Error") +
  theme_minimal()

LOOCV vs K-Fold CV for Ridge

LOOCV advantages: - Exact formula using hat matrix - No randomness in the split - Maximum use of training data

K-fold CV (what cv.glmnet uses): - Computationally faster for large \(n\) - Can be more stable (less variance) - Default is 10-fold

In practice: Both work well, k-fold is more common

Ridge vs OLS Coefficients

# OLS coefficients
beta_ols <- coef(lm(y ~ X_scaled))[-1]  # Remove intercept

# Ridge coefficients at optimal lambda
beta_ridge <- as.vector(coef(ridge_cv, s = "lambda.min"))[-1]

# Compare first 8 coefficients
comparison <- data.frame(
  Predictor = paste("x", 1:8, sep = ""),
  True = beta_true[1:8],
  OLS = round(beta_ols[1:8], 3),
  Ridge = round(beta_ridge[1:8], 3)
)

comparison
          Predictor True    OLS  Ridge
X_scaled1        x1  3.0  2.488  2.164
X_scaled2        x2 -2.0 -1.558 -1.044
X_scaled3        x3  1.5  1.889  1.352
X_scaled4        x4 -1.0 -0.991 -0.564
X_scaled5        x5  0.5  0.571  0.426
X_scaled6        x6  0.0  0.070  0.077
X_scaled7        x7  0.0  0.410  0.324
X_scaled8        x8  0.0 -0.621 -0.491

When Does Ridge Help?

Ridge regression is most useful when:

  1. Predictors are highly correlated
  2. Number of predictors is large relative to sample size
  3. You care more about prediction than interpretation
  4. OLS estimates are unstable

Prediction Performance Comparison

Effective Degrees of Freedom

Question: How many parameters does ridge regression use?

Naïve answer: Still \(p\) predictors… but they’re shrunk!

Correct answer: Effective degrees of freedom

\(\text{df}(\lambda) = \text{tr}(H_{\lambda})\)

where \(H_{\lambda} = X(X^TX + \lambda I)^{-1}X^T\) is the ridge hat matrix

Properties:

  • \(\lambda = 0\): \(\text{df} = p\) (OLS)
  • \(\lambda \to \infty\): \(\text{df} \to 0\) (no predictors).
  • Larger \(\lambda\) → fewer effective parameters

The Ridge Constraint Region

Ridge solution: Point where SSE contour touches the constraint circle