【问题标题】:Different results with randomForest() and caret's randomForest (method = "rf")随机森林()和插入符号随机森林(方法=“rf”)的不同结果
【发布时间】:2016-08-10 08:49:35
【问题描述】:

我是插入符号的新手,我只是想确保我完全理解它在做什么。为此,我一直在尝试复制我从 randomForest() 模型中获得的结果,使用插入符号的 train() 函数 for method="rf"。不幸的是,我无法获得匹配的结果,我想知道我忽略了什么。

我还要补充一点,鉴于 randomForest 使用引导生成样本以适应每个 ntree,并根据袋外预测估计误差,我对指定“oob”之间的区别有点模糊和 trainControl 函数调用中的“启动”。这些选项生成不同的结果,但都不匹配 randomForest() 模型。

虽然我已经阅读了 caret Package 网站 (http://topepo.github.io/caret/index.html),以及似乎可能相关的各种 StackOverflow 问题,但我无法弄清楚为什么 caret method = "rf" 模型会产生不同的随机森林()的结果。非常感谢您提供的任何见解。

这是一个可复制的示例,使用 MASS 包中的 CO2 数据集。

library(MASS)
data(CO2)

library(randomForest)
set.seed(1)
rf.model <- randomForest(uptake ~ ., 
                       data = CO2,
                       ntree = 50,
                       nodesize = 5,
                       mtry=2,
                       importance=TRUE, 
                       metric="RMSE")

library(caret)
set.seed(1)
caret.oob.model <- train(uptake ~ ., 
                     data = CO2,
                     method="rf",
                     ntree=50,
                     tuneGrid=data.frame(mtry=2),
                     nodesize = 5,
                     importance=TRUE, 
                     metric="RMSE",
                     trControl = trainControl(method="oob"),
                     allowParallel=FALSE)

set.seed(1)
caret.boot.model <- train(uptake ~ ., 
                     data = CO2,
                     method="rf",
                     ntree=50,
                     tuneGrid=data.frame(mtry=2),
                     nodesize = 5,
                     importance=TRUE, 
                     metric="RMSE",
                     trControl=trainControl(method="boot", number=50),
                     allowParallel=FALSE)

 print(rf.model)
 print(caret.oob.model$finalModel) 
 print(caret.boot.model$finalModel)

产生以下内容:

打印(rf.model)

      Mean of squared residuals: 9.380421
                % Var explained: 91.88

打印(caret.oob.model$finalModel)

      Mean of squared residuals: 38.3598
                % Var explained: 66.81

打印(caret.boot.model$finalModel)

      Mean of squared residuals: 42.56646
                % Var explained: 63.16

以及查看变量重要性的代码:

importance(rf.model)

importance(caret.oob.model$finalModel)

importance(caret.boot.model$finalModel)

【问题讨论】:

  • 没有使用您的实际数据并尝试重现您构建的模型,您是否检查过插入符号和 randomForest 模型的行为?如果两者都表现出非常相似的重要预测因子,具有相似的权重,那么您可能不太关心其他变化。
  • 嗨蒂姆 - 感谢您的时间和投入。我查看了变量重要性(我更新了上面的代码以反映这一点),并且我得到了预测变量的不同权重。即使重量没有那么不同,但我仍然想了解导致差异的原因。当我无法解释的事情时,我总是担心我不知道我不知道的事情!
  • 在 train 中使用公式接口将因子转换为 dummy。要与 randomForest 进行比较,您应该使用非公式接口。例如train(CO2[, -5], CO2$uptake, method="rf", ...)
  • 嗨 Lluís - 谢谢你的建议!插入符号模型的结果现在更接近于原始的 randomForest 模型。但是,它们仍然不准确。这里还有其他可能发生的事情吗?

标签: r random-forest r-caret


【解决方案1】:

在 train 中使用公式接口将因子转换为 dummy。要将caretrandomForest 的结果进行比较,您应该使用非公式接口。

在您的情况下,您应该在trainControl 中提供一个种子,以获得与randomForest 相同的结果。

Section training 在插入符号网页中,有一些关于再现性的注释,其中解释了如何使用种子。

library("randomForest")
set.seed(1)
rf.model <- randomForest(uptake ~ ., 
                         data = CO2,
                         ntree = 50,
                         nodesize = 5,
                         mtry = 2,
                         importance = TRUE, 
                         metric = "RMSE")

library("caret")
caret.oob.model <- train(CO2[, -5], CO2$uptake, 
                         method = "rf",
                         ntree = 50,
                         tuneGrid = data.frame(mtry = 2),
                         nodesize = 5,
                         importance = TRUE, 
                         metric = "RMSE",
                         trControl = trainControl(method = "oob", seed = 1),
                         allowParallel = FALSE)

如果您要进行重采样,则应为每次重采样迭代提供种子,并为最终模型提供额外的种子。 ?trainControl 中的示例展示了如何创建它们。

在以下示例中,最后一个种子用于最终模型,我将其设置为 1。

seeds <- as.vector(c(1:26), mode = "list")

# For the final model
seeds[[26]] <- 1

caret.boot.model <- train(CO2[, -5], CO2$uptake, 
                          method = "rf",
                          ntree = 50,
                          tuneGrid = data.frame(mtry = 2),
                          nodesize = 5,
                          importance = TRUE, 
                          metric = "RMSE",
                          trControl = trainControl(method = "boot", seeds = seeds),
                          allowParallel = FALSE)

使用carettrainControl 中的种子正确定义非公式接口,您将在所有三个模型中获得相同的结果:

rf.model
caret.oob.model$final
caret.boot.model$final

【讨论】:

  • 模型解释的残差平方和方差的均值现在在 randomForest 和 caret 模型之间完全匹配。但是,即使使用非公式接口,%IncMSE 预测器重要性估计仍然不同。这可以解释什么?
  • 我在importance(rf.model)importance(caret.oob.model$finalModel)importance(caret.boot.model$finalModel) 中得到相同的结果。
  • 为了正确比较你应该像我一样在rf.modelcaret.oob.model$finalModel中使用importance函数。你在做这个吗?
  • 嗨 Lluís - 啊,就是这样!你是对的。我没有为插入符号包这样做。我已经更改了我的代码,现在一切都匹配了。非常感谢你,Lluís!
  • 我们如何将seed 设置为randomForest 包构建模型?我没有看到任何具体的论据,也没有trainControl
猜你喜欢
  • 2015-10-08
  • 1970-01-01
  • 1970-01-01
  • 2021-05-29
  • 2020-07-23
  • 2021-03-25
  • 2017-03-15
  • 2015-02-12
  • 2016-04-10
相关资源
最近更新 更多