Tidymodels调参出现秩亏预测警告与model.frame.default报错如何解决?
问题原因与解决方案
问题1:lm模型秩亏警告 prediction from a rank-deficient fit may be misleading
核心触发点如下:
- 预处理步骤冗余:
step_normalize本身等价于step_center+step_scale,同时使用两类操作属于重复计算,无额外收益还可能干扰特征分布判断。 - 哑变量生成规则错误:对
Site.Type做哑变量转换时开启了one_hot = TRUE,会生成与类别数相等的k个哑变量,k个哑变量的和恒为1,天生存在完全共线性,直接导致矩阵秩亏。 - 预处理过滤逻辑不完整:lm的recipe没有添加
step_lincomb移除完全线性相关的特征,且step_corr仅能移除高于相关系数阈值的特征,无法处理完全共线的情况;同时所有过滤步骤是基于全训练集计算的,拆分到每折CV的训练子集时,仍可能出现特征无变异、特征共线的情况。 - 交叉验证拆分不合理:空间CV设置
v=20,如果训练集总样本量偏小,每折的训练子集样本过少,很容易出现Site.Type的稀有类别无样本、特征无变异的情况,进一步触发秩亏。
问题2:glm模型报错 Error in elnet(...)
glmnet的底层要求输入特征矩阵必须满秩,不能存在任何完全共线的特征,上述导致lm秩亏的所有问题,在glm模型中都会直接触发报错而非警告;即使你在glm的recipe中添加了step_lincomb,但该步骤基于全训练集计算,仍无法覆盖每折CV子集的特征共线情况。
修复方案
1. 清理并调整预处理逻辑
移除冗余步骤,调整步骤顺序,修正哑变量规则,参考修改后的recipe如下:
# 通用recipe(lm和glm可共用,无需单独定义) common_recipe <- recipe(formula = logRR ~ ., data = af.train) %>% update_role(Site.Type, new_role = "predictor") %>% update_role(Latitude, Longitude, Tree, new_role = "sample ID") %>% # 合并占比低于5%的稀有类别,避免分折后类别缺失 step_other(Site.Type, threshold = 0.05, other = "other") %>% step_novel(Site.Type, -all_outcomes()) %>% # 关闭one_hot,默认生成k-1个哑变量,避免天生共线 step_dummy(Site.Type, naming = partial(dummy_names,sep = "_")) %>% # 先过滤无价值特征,再做数值转换 step_zv(all_predictors()) %>% step_nzv(all_predictors()) %>% step_corr(all_numeric_predictors()) %>% # 强制移除完全线性相关的特征,彻底避免秩亏 step_lincomb(all_numeric_predictors()) %>% # 仅保留一次标准化操作即可 step_normalize(all_numeric_predictors())
2. 调整交叉验证参数
如果训练集样本量小于1000,将空间CV的折数v从20调整为5-10,普通CV的折数也同步调整,避免每折训练子集样本量过少导致的特征变异不足问题。
3. 调整控制参数(可选)
如果不需要后续做模型堆叠,将control_stack_grid()替换为普通的重采样控制参数即可:
model.control <- control_resamples(save_pred = TRUE, save_workflow = FALSE)
内容的提问来源于stack exchange,提问作者Kamau Lindhardt
相关产品推荐
相关产品推荐

