在 R 中使用插入符号进行分类的 predict(model) 和 predict(model$finalModel) 之间的区别

Posted

技术标签:

【中文标题】在 R 中使用插入符号进行分类的 predict(model) 和 predict(model$finalModel) 之间的区别【英文标题】:Difference between predict(model) and predict(model$finalModel) using caret for classification in R 【发布时间】:2014-02-01 12:44:04 【问题描述】:

有什么区别

predict(rf, newdata=testSet)

predict(rf$finalModel, newdata=testSet) 

我用preProcess=c("center", "scale")训练模型

tc <- trainControl("repeatedcv", number=10, repeats=10, classProbs=TRUE, savePred=T)
rf <- train(y~., data=trainingSet, method="rf", trControl=tc, preProc=c("center", "scale"))

当我在居中和缩放的测试集上运行它时,我收到 0 个真阳性

testSetCS <- testSet
xTrans <- preProcess(testSetCS)
testSetCS<- predict(xTrans, testSet)
testSet$Prediction <- predict(rf, newdata=testSet)
testSetCS$Prediction <- predict(rf, newdata=testSetCS)

但是当我在未缩放的测试集上运行它时会收到一些真正的肯定。 我必须使用 rf$finalModel 在居中和缩放的 testSet 上接收一些真正的正数,在未缩放的测试集上接收 rf 对象......我错过了什么?


编辑

测试:

tc <- trainControl("repeatedcv", number=10, repeats=10, classProbs=TRUE, savePred=T)
RF <-  train(Y~., data= trainingSet, method="rf", trControl=tc) #normal trainingData
RF.CS <- train(Y~., data= trainingSet, method="rf", trControl=tc, preProc=c("center", "scale")) #scaled and centered trainingData

在正常的测试集上:

RF predicts reasonable              (Sensitivity= 0.33, Specificity=0.97)
RF$finalModel predicts bad       (Sensitivity= 0.74, Specificity=0.36)
RF.CS predicts reasonable           (Sensitivity= 0.31, Specificity=0.97)
RF.CS$finalModel same results like RF.CS    (Sensitivity= 0.31, Specificity=0.97)

在居中和缩放的 testSetCS 上:

RF predicts very bad                (Sensitivity= 0.00, Specificity=1.00)
RF$finalModel predicts reasonable       (Sensitivity= 0.33, Specificity=0.98)
RF.CS predicts like RF              (Sensitivity= 0.00, Specificity=1.00)
RF.CS$finalModel predicts like RF       (Sensitivity= 0.00, Specificity=1.00)

所以看起来 $finalModel 需要相同格式的 trainingSet 和 testSet,而经过训练的对象只接受未居中和未缩放的数据,而不管选择的 preProcess 参数如何?

预测代码(其中testSet是普通数据,testSetCS是居中缩放的):

testSet$Prediction <- predict(RF, newdata=testSet)
testSet$PredictionFM <- predict(RF$finalModel, newdata=testSet)
testSet$PredictionCS <- predict(RF.CS, newdata=testSet)
testSet$PredictionCSFM <- predict(RF.CS$finalModel, newdata=testSet)

testSetCS$Prediction <- predict(RF, newdata=testSetCS)
testSetCS$PredictionFM <- predict(RF$finalModel, newdata=testSetCS)
testSetCS$PredictionCS <- predict(RF.CS, newdata=testSetCS)
testSetCS$PredictionCSFM <- predict(RF.CS$finalModel, newdata=testSetCS)

【问题讨论】:

能否请您发布您的最后一个火车对象的预测代码,即 RF、RF.CS? 【参考方案1】:

弗兰克,

这与您在Cross Validated 上的其他问题非常相似。

你真的需要

1) 显示每个结果的准确预测代码

2) 给我们一个可重现的例子。

使用普通的testSetRF.CSRF.CS$finalModel 应该不会给您相同的结果,我们应该能够重现该结果。另外,您的代码中存在语法错误,因此它不能完全是您执行的内容。

最后,我不确定你为什么要使用finalModel 对象。 train 的重点是处理细节并以这种方式做事(这是您的选择)绕过通常会应用的完整代码集。

这是一个可重现的例子:

 library(mlbench)
 data(Sonar)

 set.seed(1)
 inTrain <- createDataPartition(Sonar$Class)
 training <- Sonar[inTrain[[1]], ]
 testing <- Sonar[-inTrain[[1]], ]

 pp <- preProcess(training[,-ncol(Sonar)])
 training2 <- predict(pp, training[,-ncol(Sonar)])
 training2$Class <- training$Class
 testing2 <- predict(pp, testing[,-ncol(Sonar)])
 testing2$Class <- testing2$Class

 tc <- trainControl("repeatedcv", 
                    number=10, 
                    repeats=10, 
                    classProbs=TRUE, 
                    savePred=T)
 set.seed(2)
 RF <-  train(Class~., data= training, 
              method="rf", 
              trControl=tc)
 #normal trainingData
 set.seed(2)
 RF.CS <- train(Class~., data= training, 
                method="rf", 
                trControl=tc, 
                preProc=c("center", "scale")) 
 #scaled and centered trainingData

以下是一些结果:

 > ## These should not be the same
 > all.equal(predict(RF, testing,  type = "prob")[,1],
 +           predict(RF, testing2, type = "prob")[,1])
 [1] "Mean relative difference: 0.4067554"
 > 
 > ## Nor should these
 > all.equal(predict(RF.CS, testing,  type = "prob")[,1],
 +           predict(RF.CS, testing2, type = "prob")[,1])
 [1] "Mean relative difference: 0.3924037"
 > 
 > all.equal(predict(RF.CS,            testing, type = "prob")[,1],
 +           predict(RF.CS$finalModel, testing, type = "prob")[,1])
 [1] "names for current but not for target"
 [2] "Mean relative difference: 0.7452435" 
 >
 > ## These should be and are close (just based on the 
 > ## random sampling used in the final RF fits)
 > all.equal(predict(RF,    testing, type = "prob")[,1],
 +           predict(RF.CS, testing, type = "prob")[,1])
 [1] "Mean relative difference: 0.04198887"

最大

【讨论】:

我使用了 $finalModel 对象,因为我认为它包含最终(最佳)树,因此可以计算新数据集的预测和概率。 确实如此,这就是predict.train 使用的。但是,它可能会对中间的数据做一些事情。 也许您可以澄清testingtesting2 之间的区别,因为preProcess 以及predict.train 上的调用确实在内部使用preProcesspredict(xx$finalModel) 没有。否则,由于preProcess 的角色从未被澄清,该帖子会显示为“voodoo-stuff-happens”。 (不过显然 +1。) 最后一个例子不应该比较RF + testing2 vs RF.CS + testing吗?

以上是关于在 R 中使用插入符号进行分类的 predict(model) 和 predict(model$finalModel) 之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

在使用插入符号的 train() 使用公式训练的 randomForest 对象上使用 predict() 时出错

如何一次在 R 中的插入符号中为所有算法查找算法类型(回归、分类)?

在 R 中使用插入符号训练模型的时机

插入符号上的 R xgboost 尝试执行分类而不是回归

summaryFunction 插入符号分类的自定义指标 (hmeasure)

在插入符号交叉验证期间计算模型校准?