You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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)

原因分析与解决办法

  1. 参数名错误是核心问题
    你在train()函数中使用的ntree是randomForest包的参数名,而ranger包对应的树数量参数是num.trees。caret会忽略它不识别的参数,导致所有模型都使用了ranger默认的树数量(默认值为500),所以不同ntree设置下的R平方完全一致。

  2. 验证方式
    你可以查看任意一个训练好的模型的实际树数量,验证这个问题:

    rf_maxtrees$finalModel$num.trees
    

    执行后会发现结果都是500,和你设置的ntree值无关。

  3. 代码修正
    只需要把循环中的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
    }
    
  4. 额外优化建议

    • 调优树数量时,没必要每次都通过caret的train()重新跑完整交叉验证流程。可以固定其他最优超参数后,直接用ranger函数训练不同树数量的模型,自己计算交叉验证的R平方,这样效率更高。
    • 随机森林的性能通常在树数量超过某个阈值后趋于稳定,你测试的范围可能很快进入平台期,但至少不会出现所有结果完全一致的情况。

内容的提问来源于stack exchange,提问作者Nikos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 20:18:08