使用caret的train()使用公式训练的randomForest对象上使用predict()时出错

时间:2015-05-07 09:59:31

标签: r formula random-forest r-caret predict

在64位Linux机器上使用R 3.2.0 with caret 6.0-41和randomForest 4.6-10。

尝试在predict()使用公式randomForest包中使用train()函数训练的对象上使用caret方法时,该函数会返回错误。 通过randomForest()和/或使用x=y=而不是公式进行培训时,一切都顺利进行。

这是一个有效的例子:

library(randomForest)
library(caret)

data(imports85)
imp85     <- imports85[, c("stroke", "price", "fuelType", "numOfDoors")]
imp85     <- imp85[complete.cases(imp85), ]
imp85[]   <- lapply(imp85, function(x) if (is.factor(x)) x[,drop=TRUE] else x) ## Drop empty levels for factors.

modRf1  <- randomForest(numOfDoors~., data=imp85)
caretRf <- train( numOfDoors~., data=imp85, method = "rf" )
modRf2  <- caretRf$finalModel
modRf3  <- randomForest(x=imp85[,c("stroke", "price", "fuelType")], y=imp85[, "numOfDoors"])
caretRf <- train(x=imp85[,c("stroke", "price", "fuelType")], y=imp85[, "numOfDoors"], method = "rf")
modRf4  <- caretRf$finalModel

p1      <- predict(modRf1, newdata=imp85)
p2      <- predict(modRf2, newdata=imp85)
p3      <- predict(modRf3, newdata=imp85)
p4      <- predict(modRf4, newdata=imp85)

在最后4行中,只有第二行p2 <- predict(modRf2, newdata=imp85)返回以下错误:

Error in predict.randomForest(modRf2, newdata = imp85) : 
variables in the training data missing in newdata

此错误的原因似乎是predict.randomForest方法使用rownames(object$importance)来确定用于训练随机林object的变量的名称。而且,当看着

rownames(modRf1$importance)
rownames(modRf2$importance)
rownames(modRf3$importance)
rownames(modRf4$importance)

我们看到:

[1] "stroke"   "price"    "fuelType"
[1] "stroke"   "price"    "fuelTypegas"
[1] "stroke"   "price"    "fuelType"
[1] "stroke"   "price"    "fuelType"

所以,不知何故,当使用带有公式的caret train()函数时,会更改importance对象的randomForest字段中的(因子)变量的名称。 / p>

插入符train()函数的公式和非公式版本之间是否真的不一致?或者我错过了什么?

4 个答案:

答案 0 :(得分:27)

首先,几乎从未使用$finalModel对象进行预测。使用predict.train。这是一个很好的例子。

某些函数(包括randomForesttrain)如何处理虚拟变量之间存在一些不一致。 R中使用公式方法的大多数函数会将因子预测变量转换为虚拟变量,因为它们的模型需要数据的数字表示。对此的例外是基于树和规则的模型(可以分类为分类预测变量),朴素贝叶斯和其他一些模型。

因此randomForest 不会在您使用randomForest(y ~ ., data = dat)时创建虚拟变量,但train(以及大多数其他人)将使用train(y ~ ., data = dat)之类的调用。

发生错误是因为fuelType是一个因素。由train创建的虚拟变量具有相同的名称,因此predict.randomForest无法找到它们。

将非公式方法与train一起使用会将因子预测变量传递给randomForest,一切都会有效。

TL; DR

如果您想要相同级别使用train

,请将非公式方法与predict.train一起使用

最高

答案 1 :(得分:0)

出现此错误的原因有两个。

1。列车和测试集中的分类变量类别不匹配。要检查这一点,您可以运行以下内容。

首先,将自变量/特征保留在列表中是一种好习惯。说该列表是“vars”。并且说,您将“数据”分为“训练”和“测试”。我们走吧:

for (v in vars){
  if (class(Data[,v]) == 'factor'){
    print(v)
    # print(levels(Train[,v])) 
    # print(levels(Test[,v]))
    print(all.equal(levels(Train[,v]) , levels(Test[,v])))
  }  
}

找到不匹配的分类变量后,您可以返回,并将测试数据的类别强加到Train数据上,然后重新构建模型。在类似于上面的循环中,对于每个nonMatchingVar,您可以执行

levels(Test$nonMatchingVar) <- levels(Train$nonMatchingVar)

2。一个愚蠢的人。如果您不小心将因变量保留在自变量集中,则可能会遇到此错误消息。我犯了那个错误。解决方案:要小心点。

答案 2 :(得分:0)

另一种方法是使用model.matrix显式编码测试数据,例如

p2 <- predict(modRf2, newdata=model.matrix(~., imp85))

答案 3 :(得分:0)

这不是你问题的答案,但我相信它会帮助别人,因为它帮助了我。如果您在训练数据列中使用的测试数据列中缺少任何NA,则预测将不起作用。您需要首先估算这些值。