ESS数据分类树建模遇运行过慢及报错问题求助
解决方案
一、先做变量预筛选,砍掉冗余计算量
632个变量是导致建模极慢的核心原因,先通过以下步骤缩小变量范围:
- 移除近零方差变量:去掉那些几乎无变异的变量(比如所有观测值一致的变量),可以用
step_nzv()集成到配方里。 - 移除高度相关变量:对数值变量计算相关系数,去掉相关系数>0.8的变量;分类变量可通过Cramer's V统计量筛选冗余变量。
- 单变量初步筛选:对每个自变量和
all_votes做卡方检验(分类变量)或t检验(数值变量),保留p值<0.1的变量,快速将变量数压缩到几十到一百个。
示例代码(tidymodels配方集成筛选):
library(tidymodels) vote_recipe <- recipe(all_votes ~ ., data = ess_data) %>% step_nzv(all_predictors(), freq_cut = 99/1, unique_cut = 10) %>% # 移除近零方差变量 step_corr(all_numeric_predictors(), threshold = 0.8) %>% # 移除高度相关数值变量 step_dummy(all_nominal_predictors(), one_hot = FALSE, other = "OTHER") %>% # 稀有因子水平归为OTHER step_impute_mode(all_nominal_predictors()) %>% # 填补分类变量NA step_impute_mean(all_numeric_predictors()) %>% # 填补数值变量NA step_filter(!is.na(all_votes)) # 移除因变量含NA的观测
二、解决tidymodels报错问题
1. "无法找到结果变量"
- 检查训练集数据:用
glimpse(training_data)确认all_votes存在,没有在数据拆分前误删。 - 核对配方拼写:确保
recipe(all_votes ~ ., data = ...)里的all_votes拼写、大小写和数据集完全一致。 - 排查预处理步骤:确认没有用
step_rm(all_votes)或step_select()误删因变量。
2. "因子存在新NA水平"
这个问题多是交叉验证的fold中出现了训练集没有的因子水平,或是缺失值未处理:
- 用
step_dummy(..., other = "OTHER")将训练集中的稀有因子水平统一归为"OTHER",避免fold里出现新水平。 - 强制填补所有缺失值:通过
step_impute_mode()(分类变量)和step_impute_mean()(数值变量)确保无NA进入建模。 - 检查
all_votes本身的NA:用table(is.na(ess_data$all_votes))确认,通过step_filter(!is.na(all_votes))移除异常观测。
三、优化分类树建模速度
1. tidymodels调优时缩小参数搜索范围
不要用默认的宽参数范围,限制树的复杂度:
# 定义分类树模型 tree_spec <- decision_tree( cost_complexity = tune(), tree_depth = tune(), min_n = tune() ) %>% set_engine("rpart") %>% set_mode("classification") # 缩小调优网格,减少计算量 tree_grid <- grid_regular( cost_complexity(range = c(0.001, 0.01)), # 不要用极小的cp,避免生成过复杂的树 tree_depth(range = c(3, 10)), min_n(range = c(10, 30)), levels = 3 # 每个参数取3个值,降低网格规模 ) # 用5折分层交叉验证,1626观测足够 cv_folds <- vfold_cv(ess_data, v = 5, strata = all_votes) # 运行调优,关闭冗余输出 tree_tune <- tune_grid( vote_recipe, model = tree_spec, resamples = cv_folds, grid = tree_grid, control = control_grid(verbose = TRUE, save_pred = FALSE) )
2. 直接用rpart时手动限制树的复杂度
不要用默认参数,强制限制树的深度和分裂条件:
library(rpart) # 先应用预处理 prepped_data <- vote_recipe %>% prep() %>% bake(new_data = NULL) # 建模时限制复杂度 tree_model <- rpart(all_votes ~ ., data = prepped_data, cp = 0.005, # 增大cp,强制剪枝 maxdepth = 10, # 限制树的最大深度 minsplit = 20, # 节点分裂所需最小观测数 minbucket = 10) # 叶子节点最小观测数
四、后续变量筛选
建模完成后,用vip::vip(tree_model)提取变量重要性,保留前30-50个重要变量,再代入后续GLM回归,既能减少计算量,也能提升模型稳定性。
内容的提问来源于stack exchange,提问作者Teresa Petra
相关产品推荐
相关产品推荐

