使用caret包Adaptive Resampling调参mlpWeightDecayML/glmnet遇随机报错
解决caret中adaptive_cv结合mlpWeightDecayML/glmnet时的随机行数不匹配报错
问题重现
使用caret的自适应交叉验证(adaptive_cv)调优mlpWeightDecayML或glmnet模型时,会随机触发行数不匹配的报错,最简复现代码如下:
control = caret::trainControl( method = "adaptive_cv", number = 10, repeats = 3, adaptive = list(min = 5, alpha = 0.05, method = "gls", complete = TRUE), search = "random", ) caretModel <- caret::train( x = iris[, -5], y = iris[, 5], method = "mlpWeightDecayML", trControl = control, tuneLength = 10 )
随机出现的报错:
Error in { :
task 6 failed - "arguments imply differing number of rows: 0, 15"
更换数据集或R版本(4.2.2/4.3.1/4.3.2)均无法解决,但ranger、xgbTree等模型无此问题。
核心原因
这类报错源于自适应交叉验证的迭代过程中:
- 随机搜索到的极端调优参数(比如mlpWeightDecayML的过大权重衰减值),在小样本的交叉验证折叠上训练时,模型无法有效拟合,返回的预测结果行数为空。
- 空结果与测试集的实际行数(如iris折叠的15行)不匹配,触发行数不一致的错误。
ranger、xgbTree这类模型对极端参数的鲁棒性更强,不会出现空输出的情况,因此无报错。
可行解决方案
1. 限定调优参数范围
放弃tuneLength=10的随机搜索,手动指定合理的参数区间,避免极端值导致拟合失败。以mlpWeightDecayML为例:
# 手动设置参数网格,限定size和decay的合理范围 tune_grid <- expand.grid( size = c(1, 2, 3), # 神经网络隐藏层节点数 decay = seq(0.001, 0.1, length.out = 5) # 权重衰减值,避免过大 ) caretModel <- caret::train( x = iris[, -5], y = iris[, 5], method = "mlpWeightDecayML", trControl = control, tuneGrid = tune_grid # 使用自定义参数网格 )
2. 调整自适应验证的控制参数
调大adaptive列表中的min值,减少在极少量折叠上做早期停止的概率,避免小样本下的拟合失败:
control = caret::trainControl( method = "adaptive_cv", number = 10, repeats = 3, adaptive = list(min = 10, # 从5改为10,要求更多折叠参与评估后再停止 alpha = 0.05, method = "gls", complete = TRUE), search = "random", )
3. 给模型添加错误捕获机制
自定义模型训练函数,捕获拟合失败的异常,返回结构合法的默认结果,避免整个调优过程中断:
# 包装mlpWeightDecayML,添加异常捕获 safe_mlp <- function(x, y, wts, param, lev, last, weights, classProbs, ...) { tryCatch({ # 正常训练模型 model <- mlpWeightDecayML(x, y, wts = wts, param = param, lev = lev, last = last, weights = weights, classProbs = classProbs, ...) model }, error = function(e) { # 拟合失败时,返回符合格式的默认结果 list( pred = factor(rep(lev[1], nrow(x))), # 全预测为第一类 prob = matrix(0, nrow(x), length(lev)) # 概率矩阵全为0 ) }) } # 注册自定义模型 mlp_info <- caret::modelLookup("mlpWeightDecayML") mlp_info$fit <- "safe_mlp" # 使用自定义模型训练 caretModel <- caret::train( x = iris[, -5], y = iris[, 5], method = mlp_info, trControl = control, tuneLength = 10 )
4. 更换自适应调优的评估方法
将adaptive中的method从"gls"改为"BT"(Bootstrap),可能提升对这类模型的兼容性:
control = caret::trainControl( method = "adaptive_cv", number = 10, repeats = 3, adaptive = list(min = 5, alpha = 0.05, method = "BT", # 更换为Bootstrap方法 complete = TRUE), search = "random", )
内容的提问来源于stack exchange,提问作者Savo
相关产品推荐
相关产品推荐

