使用caret调优ranger随机森林时不同树数量下R²一致的问题排查
问题:调优随机森林树数量时R平方值完全一致的原因
我正在使用caret包结合ranger包调优随机森林(RF)模型。由于ranger包无法直接调优树的数量,因此借助caret包进行调优。选取R平方(R-Squared)作为寻找最优树数量的指标,测试的树数量范围为500到3000,步长为500(即500、1000、1500……3000)。
但每个树数量对应的R平方值都完全相同,这一结果明显不合理,怀疑代码存在问题,请问为什么会出现所有树数量下R平方都一致的情况?
我的代码
library(caret) library(ranger) # Load the data block.data <- read.csv("path/block.data.csv") eq1 = ntl ~ . # Define the cross-validation method for hyperparameter tuning control <- trainControl(method = "cv", number = 10, savePredictions = FALSE, search = 'grid', allowParallel = TRUE) # default model rf_default = train(eq1, data = block.data, method = "ranger", metric = "Rsquared", trControl = control) print(rf_default) # Define the grid of hyperparameters to be tuned tuneGrid <- expand.grid(mtry = c(2, 3, 4, 5, 6, 7), # number of predictor variables to sample at each split splitrule = c("variance", "extratrees"), # splitting rule min.node.size = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) # minimum size of terminal nodes # Train the model with hyperparameter tuning using caret set.seed(234) rf_model <- train(eq1, # formula for the response and predictors data = block.data, method = "ranger", trControl = control, tuneGrid = tuneGrid) rf_model$bestTune tuneGrid <- expand.grid(mtry = rf_model$bestTune$mtry, splitrule = rf_model$bestTune$splitrule, min.node.size = rf_model$bestTune$min.node.size) store_maxtrees <- list() for (ntree in c(500, 1000, 1500, 2000, 2500, 3000)) { set.seed(345) rf_maxtrees <- train(eq1, data = block.data, method = "ranger", metric = "Rsquared", tuneGrid = tuneGrid, trControl = control, ntree = ntree) key <- toString(ntree) store_maxtrees[[key]] <- rf_maxtrees } results_tree <- resamples(store_maxtrees) summary(results_tree)
原因分析与解决办法
参数名错误是核心问题
你在train()函数中使用的ntree是randomForest包的参数名,而ranger包对应的树数量参数是num.trees。caret会忽略它不识别的参数,导致所有模型都使用了ranger默认的树数量(默认值为500),所以不同ntree设置下的R平方完全一致。验证方式
你可以查看任意一个训练好的模型的实际树数量,验证这个问题:rf_maxtrees$finalModel$num.trees执行后会发现结果都是500,和你设置的
ntree值无关。代码修正
只需要把循环中的ntree = ntree修改为num.trees = ntree即可:for (ntree in c(500, 1000, 1500, 2000, 2500, 3000)) { set.seed(345) rf_maxtrees <- train(eq1, data = block.data, method = "ranger", metric = "Rsquared", tuneGrid = tuneGrid, trControl = control, num.trees = ntree) # 修改参数名 key <- toString(ntree) store_maxtrees[[key]] <- rf_maxtrees }额外优化建议
- 调优树数量时,没必要每次都通过
caret的train()重新跑完整交叉验证流程。可以固定其他最优超参数后,直接用ranger函数训练不同树数量的模型,自己计算交叉验证的R平方,这样效率更高。 - 随机森林的性能通常在树数量超过某个阈值后趋于稳定,你测试的范围可能很快进入平台期,但至少不会出现所有结果完全一致的情况。
- 调优树数量时,没必要每次都通过
内容的提问来源于stack exchange,提问作者Nikos
相关产品推荐
相关产品推荐

