如何将cv.glmnet()输出的lambda值转换为selectiveInference包可用格式
正确的lambda转换方式
参数化差异说明
glmnet和selectiveInference两个包的Lasso目标函数参数化规则不同,是转换的核心依据:
- glmnet默认线性回归场景(
family = "gaussian")的目标函数为:(1/(2n)) * 残差平方和 + λ_glmnet * 系数绝对值和
其中n为样本量 - selectiveInference包
fixedLassoInf方法对应的目标函数为:(1/2) * 残差平方和 + λ_si * 系数绝对值和
转换公式
将两个目标函数做等价变换后,可得通用转换规则:
si_lambda <- glmnet_lambda * n
你之前的猜测方向是正确的,出现lambda数值过大、运行警告的问题,是因为示例代码中选取了lambda.1se作为交叉验证输出的lambda:该规则会选择比交叉验证误差最小点大1倍标准差的lambda,本身就是为了得到更稀疏的模型,在你的模拟场景中很可能将所有非零系数都压缩为0,没有变量被选入模型自然会触发警告。你可以换成lambda.min(交叉验证误差最小对应的lambda)验证转换的正确性。
修改后的示例代码
library(glmnet) library(selectiveInference) library(tidyverse) set.seed(1839) n <- 1000 # 样本量 B <- c(0, 1, 0) # 截距为0,beta1 = 1,beta2 = 0 eps_sd <- 1 # 误差项标准差 # 生成模拟数据 X <- cbind(1, replicate(length(B) - 1, rnorm(n, 0, 1))) y <- X %*% B + rnorm(n, 0, eps_sd) dat <- as.data.frame(X[, -1]) dat <- as_tibble(cbind(dat, y)) # 交叉验证获取lambda,这里用lambda.min替代lambda.1se避免过度压缩 glmnet_lambda <- cv.glmnet( x = as.matrix(select(dat, -y)), y = dat$y ) %>% getElement("lambda.min") # 用交叉验证得到的lambda拟合lasso模型 m1 <- glmnet( x = as.matrix(select(dat, -y)), y = dat$y, lambda = glmnet_lambda ) # 提取系数,按文档要求去掉截距项 m1_coefs <- coef(m1)[-1] # lambda转换:乘以样本量n si_lambda <- glmnet_lambda * n # 执行后选择推断,无参数错误警告 m2 <- fixedLassoInf( x = as.matrix(select(dat, -y)), y = dat$y, beta = m1_coefs, lambda = si_lambda )
补充说明
如果你的glmnet拟合时手动设置了standardize = FALSE,上述转换公式依然有效:glmnet的标准化操作在拟合内部完成,输出的lambda已经适配原始变量尺度,不需要额外调整。
内容的提问来源于stack exchange,提问作者Mark White
相关产品推荐
相关产品推荐

