基于岭回归公式实现的代码与glmnet结果不一致的技术咨询
岭回归手动实现与glmnet结果不一致的原因及解决办法
我猜你遇到的核心问题大概率是标准化处理差异和lambda尺度对齐,这也是手动实现岭回归和调用glmnet时最容易踩的坑。咱们一步步拆解解决:
1. 先搞懂glmnet的默认行为
glmnet执行岭回归时,默认会对除截距外的所有自变量做标准化(均值为0,方差为1),同时惩罚项是针对标准化后的系数计算的。如果你的手动实现直接用原始数据计算,结果自然会和glmnet不一致。
2. 修正手动实现,和glmnet对齐
基于你给出的代码片段,咱们调整手动实现的逻辑,让结果和glmnet匹配:
步骤1:对自变量(除截距)做标准化
set.seed(110) n = 5 p = 2 x=matrix(rnorm(n*p), nrow=n, ncol=p) y=as.matrix(rnorm(n)) # 按照glmnet默认逻辑标准化x:均值0,方差1 x_std = scale(x) # 添加截距项 int <- rep(1, length(y)) x_std_with_int <- cbind(int, x_std)
步骤2:手动计算岭回归系数
这里的lambda和glmnet的lambda尺度一致(因为都是针对标准化后的变量):
lambda=0.1 # 岭回归核心公式:(X^T X + λI)^-1 X^T y beta_manual = solve(t(x_std_with_int) %*% x_std_with_int + lambda * diag(ncol(x_std_with_int))) %*% t(x_std_with_int) %*% y beta_manual
步骤3:用glmnet验证结果
你可以两种方式调用glmnet,结果都会和手动计算匹配:
library(glmnet) # 方式1:用原始x,让glmnet自动标准化(默认行为) fit_glmnet = glmnet(x, y, alpha=0, lambda=lambda, intercept=TRUE) coef(fit_glmnet) # 方式2:用已经标准化的x_std,关闭glmnet的自动标准化 fit_glmnet_std = glmnet(x_std, y, alpha=0, lambda=lambda, intercept=TRUE, standardize=FALSE) coef(fit_glmnet_std)
此时你会看到,手动计算的beta_manual和coef(fit_glmnet_std)的结果几乎完全一致(仅存在微小浮点误差)。
3. 额外注意:截距的计算逻辑
glmnet的截距是基于原始数据的均值计算的:$\hat{\beta}0 = \bar{y} - \sum{j=1}^p \hat{\beta}_j \bar{x}_j$。当x被标准化后,$\bar{x}_j=0$,所以截距就是$\bar{y}$,这和手动实现的截距结果也是对齐的。
内容的提问来源于stack exchange,提问作者Ville
相关产品推荐
相关产品推荐

