第 15 章 正则化、高维统计与稀疏计算

在传统回归课程中,我们通常假设样本量 \(n\) 明显大于变量个数 \(p\)。但在现代经济统计中,变量数量可能非常多:宏观预测中有大量指标,企业风险评估中有财务、交易和行为变量,问卷调查中也可能包含大量题项。当 \(p\) 较大或变量高度相关时,普通最小二乘估计可能方差很大,甚至无法唯一估计。

正则化的基本思想是在拟合误差之外加入惩罚项,用一点偏差换取更低方差和更稳定预测。本章介绍 Ridge回归和 Lasso 回归,并强调它们的计算实现。

15.1 Ridge 回归

Ridge 回归在最小二乘目标函数中加入二范数惩罚:

\[ \hat{\boldsymbol\beta}_{\text{ridge}} = \arg\min_{\boldsymbol\beta} \left\{ \sum_{i=1}^n(y_i-\mathbf x_i^\top\boldsymbol\beta)^2 +\lambda\sum_{j=1}^p\beta_j^2 \right\}. \]

其中 \(\lambda\geq 0\) 是调节参数。\(\lambda=0\) 时就是普通最小二乘;\(\lambda\) 越大,系数被压缩得越接近 0。若自变量已经中心化,Ridge 解为

\[ \hat{\boldsymbol\beta}_{\text{ridge}} = (\mathbf X^\top\mathbf X+\lambda\mathbf I)^{-1} \mathbf X^\top\mathbf y. \]

这里 \(\mathbf I\) 是单位矩阵。与普通最小二乘相比,\(\lambda\mathbf I\) 改善了矩阵条件,从计算上也提高了稳定性。

ridge_fit <- function(X, y, lambda) {
  Xs <- scale(X)
  yc <- y - mean(y)
  center <- attr(Xs, "scaled:center")
  scale_x <- attr(Xs, "scaled:scale")

  beta_scaled <- solve(crossprod(Xs) + lambda * diag(ncol(Xs)),
                       crossprod(Xs, yc))
  beta <- as.vector(beta_scaled) / scale_x
  intercept <- mean(y) - sum(center * beta)

  list(intercept = intercept, beta = beta)
}

注意,正则化前通常要标准化变量。否则,惩罚项会受到变量量纲影响,尺度大的变量和尺度小的变量被惩罚的程度不可比。

15.2 Lasso 回归

Lasso 回归使用一范数惩罚:

\[ \hat{\boldsymbol\beta}_{\text{lasso}} = \arg\min_{\boldsymbol\beta} \left\{ \frac{1}{2n}\sum_{i=1}^n(y_i-\mathbf x_i^\top\boldsymbol\beta)^2 +\lambda\sum_{j=1}^p|\beta_j| \right\}. \]

与 Ridge 不同,Lasso 可以把一些系数精确压缩到 0,因此具有变量选择效果。它适合用于高维预测和初步筛选变量,但不应把 Lasso 选出的变量机械解释为“真实因果变量”。

Lasso 的目标函数在 \(\beta_j=0\) 处不可导,因此不能直接套用普通 Newton 法。常用算法之一是坐标下降:每次固定其他系数,只更新一个系数。核心操作是软阈值函数

\[ S(z,\lambda) = \operatorname{sign}(z)(|z|-\lambda)_+, \]

其中 \((a)_+=\max(a,0)\)

soft_threshold <- function(z, lambda) {
  sign(z) * pmax(abs(z) - lambda, 0)
}

lasso_cd <- function(X, y, lambda, max_iter = 1000, tol = 1e-6) {
  Xs <- scale(X)
  yc <- y - mean(y)
  center <- attr(Xs, "scaled:center")
  scale_x <- attr(Xs, "scaled:scale")

  p <- ncol(Xs)
  beta <- rep(0, p)
  x2 <- colMeans(Xs^2)

  for (iter in seq_len(max_iter)) {
    beta_old <- beta
    for (j in seq_len(p)) {
      r_j <- yc - drop(Xs %*% beta) + Xs[, j] * beta[j]
      z_j <- mean(Xs[, j] * r_j)
      beta[j] <- soft_threshold(z_j, lambda) / x2[j]
    }
    if (max(abs(beta - beta_old)) < tol) break
  }

  beta_raw <- beta / scale_x
  intercept <- mean(y) - sum(center * beta_raw)

  list(intercept = intercept, beta = beta_raw, iter = iter)
}

这段代码用于教学,强调算法逻辑。实际项目中应优先使用经过充分测试的专业包,例如 glmnet。但理解坐标下降有助于看清 Lasso 为什么会产生稀疏解。

15.3 调节参数的选择

正则化强度 \(\lambda\) 控制偏差与方差之间的权衡。常用方法是交叉验证:在一组候选 \(\lambda\) 上分别拟合模型,选择验证误差最小的值。

下面构造一个模拟宏观预测数据集。变量数较多,但只有少数变量真正影响目标变量。

set.seed(2026)
n <- 140
p <- 30
factor_common <- rnorm(n)
X <- matrix(rnorm(n * p), n, p) + 0.4 * factor_common
beta_true <- c(1.2, -1.0, 0.8, rep(0, p - 3))
y <- drop(X %*% beta_true) + rnorm(n, sd = 1.5)

用 5 折交叉验证选择 Lasso 的 \(\lambda\)

set.seed(1)
lambda_grid <- exp(seq(log(0.02), log(1.5), length.out = 25))
K <- 5
fold <- sample(rep(seq_len(K), length.out = n))
cv_mse <- numeric(length(lambda_grid))

for (l in seq_along(lambda_grid)) {
  loss <- numeric(K)
  for (k in seq_len(K)) {
    train <- fold != k
    valid <- fold == k
    fit <- lasso_cd(X[train, ], y[train], lambda = lambda_grid[l])
    pred <- fit$intercept + X[valid, ] %*% fit$beta
    loss[k] <- mean((y[valid] - pred)^2)
  }
  cv_mse[l] <- mean(loss)
}

lambda_best <- lambda_grid[which.min(cv_mse)]
fit_lasso <- lasso_cd(X, y, lambda = lambda_best)

c(lambda_best = lambda_best,
  selected_variables = sum(abs(fit_lasso$beta) > 1e-8))
#>        lambda_best selected_variables 
#>             0.1732             4.0000
round(fit_lasso$beta[1:8], 3)
#> [1]  1.164 -0.762  0.773  0.000  0.000  0.000  0.000  0.000

由于数据是随机生成的,Lasso 不一定每次都完美选择前三个变量。但整体上,正则化会减少无关变量带来的方差,提高预测稳定性。

15.4 Ridge 与 Lasso 的比较

Ridge 和 Lasso 都会压缩系数,但方式不同:

  1. Ridge 适合处理许多相关变量共同产生预测信息的情形;
  2. Lasso 适合希望得到稀疏模型、做变量筛选的情形;
  3. Ridge 通常不会把系数压缩为 0;
  4. Lasso 在高度相关变量中可能只选择其中一个,选择结果可能不稳定;
  5. 两者都需要通过交叉验证或其他方法选择 \(\lambda\)

下面在同一数据上比较 Ridge 和 Lasso 的训练误差。这里只是演示,不代表泛化误差。

fit_ridge <- ridge_fit(X, y, lambda = 20)
pred_ridge <- fit_ridge$intercept + X %*% fit_ridge$beta
pred_lasso <- fit_lasso$intercept + X %*% fit_lasso$beta
pred_ols <- fitted(lm(y ~ X))

c(OLS = mean((y - pred_ols)^2),
  Ridge = mean((y - pred_ridge)^2),
  Lasso = mean((y - pred_lasso)^2))
#>   OLS Ridge Lasso 
#> 1.932 2.029 2.331

训练误差最小的往往是最灵活的模型,但这不等于预测最好。因此,本章应与第 14章的交叉验证一起理解。

15.5 稀疏计算简介

高维数据不仅带来统计问题,也带来计算问题。若一个矩阵大部分元素为 0,称为稀疏矩阵。许多经济和管理数据都可能具有稀疏性,例如用户–商品购买矩阵、地区–行业投入产出矩阵、企业–银行借贷网络。

稀疏矩阵不应按普通密集矩阵存储,否则会浪费大量内存。R 中常用 Matrix 包处理稀疏矩阵。虽然本书不展开稀疏矩阵算法,但要记住一个原则:数据结构会影响算法可行性。高维统计不是只多了几个变量,它会同时改变估计、存储和计算。

15.6 本章小结

正则化通过在目标函数中加入惩罚项,改善高维和共线性条件下的估计稳定性。Ridge 使用二范数惩罚,会连续压缩系数;Lasso 使用一范数惩罚,可以产生稀疏解。调节参数 \(\lambda\) 决定偏差和方差之间的权衡,通常通过交叉验证选择。实际经济统计应用中,正则化适合预测和变量筛选,但因果解释仍需依赖研究设计和经济理论。

15.7 练习

  1. 修改模拟数据中的相关性强度,比较 OLS、Ridge 和 Lasso 的表现。
  2. 改变 Lasso 的 lambda,观察被选择变量个数如何变化。
  3. 用交叉验证选择 Ridge 的 lambda,并与 Lasso 的验证误差比较。
  4. 思考为什么标准化变量是正则化前的必要步骤。