不使用caret的随机森林回归训练验证测试及参数调优疑问
随机森林超参数调优疑问与代码分析
我把数据集拆分为70%训练集、15%验证集和15%测试集,在超参数调优阶段存在疑惑,担心操作有误,以下是我的随机森林回归代码:
1. 训练阶段
初始训练
rf_model <- ranger(y ~., data = train , # 注:原代码笔误将data写为date,已修正 num.trees = 500, mtry = 5, min.node.size = 100, importance = "impurity")
训练集评估
pred_rf <- predict(rf_model,train) pred_rf <- data.frame(pred = pred_rf, obs = train$y) RMSE_rf <- RMSE(pred_rf$pred, pred_rf$obs) R2_rf <- (cor(pred_rf$pred, pred_rf$obs)) ^2 # 注:原代码笔误将cor写为color,已修正
2. 参数优化阶段
构建参数网格
hyper_grid <- expand.grid(mtry = seq(3, 12, by = 4), sample_size = c(0.5,1), min.node.size = seq(20, 500, by = 100), MSE = as.numeric(NA), R2 = as.numeric(NA), OOB_RMSE = as.numeric(NA) )
基于OOB误差搜索最优模型
for (i in 1:nrow(hyper_grid)) { model <- ranger(formula = y ~ ., data = train, # 注:原代码笔误将data写为date,已修正 num.trees = 500, mtry = hyper_grid$mtry[i], sample.fraction = hyper_grid$sample_size[i], min.node.size = hyper_grid$min.node.size[i], importance = "impurity", replace = TRUE, oob.error = TRUE, verbose = TRUE ) hyper_grid$OOB_RMSE[i] <- sqrt(model$prediction.error) hyper_grid[i, "MSE"] <- model$prediction.error hyper_grid[i, "R2"] <- model$r.squared hyper_grid[i, "OOB_RMSE"] <- sqrt(model$prediction.error) }
选择并构建最终模型
x <- hyper_grid[which.min(hyper_grid$OOB_RMSE), ]
rf_fit_model <- ranger(formula = y ~ ., data = train, # 注:原代码笔误将data写为date,已修正 num.trees = 100, mtry = x$mtry, sample.fraction = x$sample_size, min.node.size = x$min.node.size, oob.error = TRUE, verbose = TRUE, importance = "impurity" )
验证集评估
rf_predict_val <- predict(rf_fit_model, validation) rf_predict_val <- as.data.frame(rf_predict_val[1]) names(rf_predict_val) <- "pred" rf_predict_val <- data.frame(pred = rf_predict_val, obs = validation$y) RMSE_rf_fit <- RMSE(rf_predict_val$pred, rf_predict_val$obs) # 注:原代码缺少括号,已修正语法 R2_rf_fit <- (cor(rf_predict_val$pred, rf_predict_val$obs)) ^ 2
核心疑问
- 是否需要用测试集重复评估?
- 目前的验证集是不是没发挥有效作用?
- 因为caret的交叉验证运行极慢,所以想手动实现调优,当前的做法是否正确?
对比用的caret代码(运行极慢)
ctrl <- trainControl(method = "repeatedcv", repeats = 10) grid <- expand.grid(interaction.depth = seq(1, 7, by = 2), n.trees = 1000, shrinkage = c(0.01,0.1), n.minobsinnode = 50) gbmTune <- train(y ~ ., data = train, method = "gbm", tuneGrid = grid, verbose = TRUE, trControl = ctrl)
解答
1. 测试集必须用,且仅用一次
测试集是完全独立的“未知数据模拟”,用来给出模型最终的无偏性能结果。你当前仅用验证集评估,调优过程已间接用到验证集信息,最终必须用测试集做确认,避免过拟合到验证集。
2. 验证集的作用可优化
你现在仅用验证集评估最终模型,其实可以把它作为参数筛选的辅助依据:比如在OOB误差最小的前3组参数里,选验证集RMSE最低的组合,这样能降低OOB偶然最优的风险,但注意不要反复用验证集调参,否则会过拟合验证集。
3. 手动实现的做法可行,但需优化细节
- 先修正代码里的语法笔误(data/date、cor/color、RMSE调用括号),否则代码无法正常运行。
- 保持树的数量一致:参数搜索用了500棵树,最终模型却只用100棵,会导致性能下降,建议统一为500或1000棵。
- 避免过拟合OOB:如果参数网格较大,可能出现OOB误差偶然最优的情况,结合验证集结果筛选更稳妥。
- 替代caret的快速交叉验证:如果觉得caret慢,可手动在训练集内部做3-5折交叉验证,取平均性能选参数,比repeatedcv快很多,也比仅用OOB更可靠。
内容的提问来源于stack exchange,提问作者j_3265
相关产品推荐
相关产品推荐

