使用Tidymodels获取Lasso回归系数遇错求助
解决tidymodels中Lasso回归网格搜索的系数提取问题
问题描述
使用tidymodels进行Lasso回归网格搜索时,执行show_notes(.Last.tune.result)出现两个错误:
- 没有适用于
c('elnet', 'glmnet')类对象的tidy方法 - 相关性计算因
estimate为常量、标准差为0导致除零错误,返回NA
解决方案
1. 修复tidy方法缺失问题
tidy()方法由broom包提供,尽管tidymodels依赖broom,但在自定义提取函数中显式调用broom::tidy()可避免方法匹配问题,同时需确保加载broom包:
修改包加载代码
pacman::p_load(tidyverse, schrute, tidymodels, vip, broom)
修正自定义系数提取函数
get_glmnet_coefs <- function(x) { x %>% extract_fit_engine() %>% broom::tidy(return_zeros = TRUE) %>% rename(penalty = lambda) }
2. 解决除零错误问题
该错误通常因过大的penalty值导致Lasso将所有特征系数压缩为0,预测值变为常量(仅截距),进而触发相关性计算时的除零。
调整penalty搜索范围
缩小penalty的取值范围,避免极端大值:
lambda_grid <- grid_regular(penalty(range = c(1e-4, 1)), levels = 50)
增强数据预处理
确保在bootstrap抽样的每个样本中先过滤零方差特征,再执行标准化(已在recipe中设置,确认顺序即可):
office_rec <- recipe(imdb_rating ~ ., data = office_train) %>% update_role(episode_name, new_role = "ID") %>% step_zv(all_numeric(), -all_outcomes()) %>% # 先过滤零方差特征 step_normalize(all_numeric(), -all_outcomes()) # 再标准化
完整修正后的关键代码片段
# 加载必要包 pacman::p_load(tidyverse, schrute, tidymodels, vip, broom) # ... 数据预处理部分保持不变 ... # 修正后的系数提取函数 get_glmnet_coefs <- function(x) { x %>% extract_fit_engine() %>% broom::tidy(return_zeros = TRUE) %>% rename(penalty = lambda) } # 调整penalty范围 lambda_grid <- grid_regular(penalty(range = c(1e-4, 1)), levels = 50) parsnip_ctrl <- control_grid(extract = get_glmnet_coefs) set.seed(2020) lasso_grid <- tune_grid( wf %>% add_model(tune_spec), resamples = office_boot, grid = lambda_grid, control = parsnip_ctrl )
验证
运行修正后的代码后,执行show_notes(.Last.tune.result)应不再出现错误,且可通过以下代码提取系数并可视化:
lasso_coefs <- lasso_grid %>% collect_extracts() %>% filter(term != "(Intercept)") lasso_coefs %>% ggplot(aes(penalty, estimate, group = term)) + geom_line(alpha = 0.7) + scale_x_log10() + labs(x = "Penalty (log scale)", y = "Coefficient Estimate")
内容的提问来源于stack exchange,提问作者TheGoat
相关产品推荐
相关产品推荐

