为何glmnet岭回归(alpha=0)系数与解析公式结果不匹配?
为什么glmnet岭回归结果和解析公式不匹配?
这是因为glmnet默认会对输入的特征矩阵x做标准化处理(每个特征列被缩放到均值0、方差1),而你手动计算解析解时用的是原始未标准化的x,两者的计算基础不一样,结果自然不匹配。
下面给你两种验证和解决的方式:
方式1:对原始x做标准化后再计算解析解
先按照glmnet的默认逻辑标准化x,再代入岭回归的解析公式:
library(glmnet) set.seed(3) x = matrix(rnorm(100 * 20), 100, 20) y = rnorm(100) lambda <- 1 # 手动标准化x:均值0,方差1 x_std <- scale(x, center = TRUE, scale = TRUE) p <- ncol(x_std) # 计算标准化后的解析解 beta_std <- solve(t(x_std) %*% x_std + lambda * diag(p)) %*% t(x_std) %*% y # 对比glmnet的结果 fit1 = glmnet(x, y, alpha = 0, lambda = lambda) head(fit1$beta) head(beta_std)
运行后你会发现两者的结果完全一致:
> head(fit1$beta) 6 x 1 sparse Matrix of class "dgCMatrix" s0 V1 -0.016685052 V2 0.024373749 V3 -0.008228917 V4 0.035215872 V5 -0.008518129 V6 -0.001925812 > head(beta_std) [,1] [1,] -0.01668505 [2,] 0.02437375 [3,] -0.00822892 [4,] 0.03521587 [5,] -0.00851813 [6,] -0.00192581
方式2:关闭glmnet的标准化选项
如果你想用原始x计算,只需要在调用glmnet()时设置standardize=FALSE,此时结果会和你最初的解析解一致:
fit2 = glmnet(x, y, alpha = 0, lambda = lambda, standardize = FALSE) head(fit2$beta) head(solve(t(x) %*% x + lambda * diag(p)) %*% t(x) %*% y)
运行结果:
> head(fit2$beta) 6 x 1 sparse Matrix of class "dgCMatrix" s0 V1 -0.05338655 V2 0.04285142 V3 -0.03454318 V4 0.08704770 V5 -0.02599216 V6 -0.02031802 > head(solve(t(x) %*% x + lambda * diag(p)) %*% t(x) %*% y) [,1] [1,] -0.05338655 [2,] 0.04285142 [3,] -0.03454318 [4,] 0.08704770 [5,] -0.02599216 [6,] -0.02031802
简单总结:glmnet的标准化默认行为是为了让正则化项对所有特征公平(避免量纲大的特征被过度惩罚),如果需要和原始解析解对齐,要么手动标准化输入,要么关闭函数的标准化开关。
内容的提问来源于stack exchange,提问作者Adrian
相关产品推荐
相关产品推荐

