2015-05-07 49 views
9

在使用插入符号训练(()的randomForest对象上使用predict()时发生错误在64位Linux机器上使用R 3.2.0与脱字符6.0-41和randomForest 4.6-10。使用公式

当试图使用predict()方法使用公式从caret包与train()功能培养了randomForest对象上,该函数返回一个错误。 当通过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" 

所以在某种程度上,使用带有公式的carettrain()功能时,在randomForest对象的importance场改变(要素)的名称变量。

这个插入符号的公式和非公式版本之间是否真的存在不一致?或者我错过了什么?

+2

'modRf3 < - 随机森林(X = dataTrain [,C( “中风”, “价格”, “fuelType”)],Y = dataTrain [ “numOfDoors”],数据= imp85) 错误randomForest(x = dataTrain [,c(“stroke”,“price”,“fuelType”)],: object'dataTrain'not found' –

+0

正如你指出的,你没有在你的例子中定义dataTrain,问题不是[可重现的](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example)。如果我们无法运行代码,要帮助你并不容易并得到和你一样的结果 – MrFlick

+0

我的不好的'dataTrain'应该是'imp85',我在原始问题中编辑了代码,我还在调用中删除了'data = imp85'选项, y'明确提及为t这里没有用。 –

回答

21

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

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

所以randomForest当您使用randomForest(y ~ ., data = dat)train(和大多数人)将使用类似train(y ~ ., data = dat)通话不创建虚拟变量。

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

train一起使用非公式方法会将因子预测变量传递到randomForest,并且所有内容都将工作。

TL; DR

,如果你想在同一水平使用predict.train

最大使用与train非公式法

+1

不幸的是,我没有足够的声望来提高你的答案,但你完全回答了我的问题。如果在函数调用的公式和非公式版本之间处理数据的方式有所不同,我一直想知道所有允许使用公式的函数。现在我明白了!对于'$ finalModel'的使用,我同意使用它通常不是一个好主意。在这里,我只是想比较'caret'和'randomForest'方法的结果。 –

0

可以有,为什么你得到这个错误有两个原因。

1.列车和测试集中的分类变量的类别不匹配。要检查这一点,你可以运行如下的东西。

嗯,首先,将独立变量/要素保存在列表中是一种很好的做法。说这个清单是“变数”。并说,你把“数据”分为“火车”和“测试”。让我们去:

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]))) 
    } 
} 

一旦你找到了不匹配的分类变量,你可以回去,并处测试数据的类别火车上的数据,然后重新建立模型。在类似上述的循环,每个nonMatchingVar,你可以做

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

2.是一个愚蠢的一个。如果您不小心将独立变量置于独立变量集中,则可能会遇到此错误消息。我犯了这个错误。解决方案:只需更小心。

0

另一种方法是使用model.matrix(例如,

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