2

我正在尝试学习如何创建一个混合模型,该模型专门训练基本模型的输出。按照网上的建议(来自约翰霍普金斯大学数据科学课程),我可以在能够在相同的标记测试数据上训练我的模型的小例子中成功地做到这一点,然后我预测。

理论上,这个过程相对简单。

  1. 建立基础模型
  2. 对于每个模型,预测测试数据
  3. 结合 newDF 中的预测,将 testingData 中的标记结果作为附加列包含在内。
  4. 在 newDF 上训练组合或“元”模型。这个模型应该学会“说”这样的话:“当 mod1 预测 0,mod2 预测 1 等等,最可能的真实结果是 0”
  5. 对验证数据重复步骤 2 和 3
  6. 使用组合模型对验证数据进行最终预测。

下面显示了一个有效的过程:

library(caret)
library(gbm)
set.seed(3433)
library(AppliedPredictiveModeling)
data(AlzheimerDisease)
adData = data.frame(diagnosis,predictors)
inTrain = createDataPartition(adData$diagnosis, p = 3/4)[[1]]
training = adData[ inTrain,]
testing = adData[-inTrain,]


set.seed(62433)
modRF <- train(diagnosis ~., method = "rf", data = training)
modGBM <- train(diagnosis ~., method = "gbm", data = training) 
modLDA <- train(diagnosis ~., method = "lda", data = training, preProcess=c("center","scale")) 

# STACK THE PREDICTIONS
# make predictions
predRF <- predict(modRF,testing)
predGBM <- predict(modGBM, testing)
predLDA <- predict(modLDA, testing)

# Fit a model that combines all (both of the predictors)
predDF <- data.frame(predRF,predGBM,predLDA,diagnosis=testing$diagnosis)
#train a new model on the predictions
combModFit <- train(diagnosis ~.,method="rf",data=predDF)
predComb <- predict(combModFit,testing)

然而,下面的代码似乎表明组合模型没有产生新的预测,它只是回收它的训练信息。有效的代码(上图)和无效的代码(下图)之间的具体区别在于前者有效地训练和预测相同大小的标记数据帧,而后者在 1 大小的 DF 上训练并预测另一个大小的未标记 DF。

#create a sudo holdout set by modifying the existing test set
library(dplyr)
otherTest <- testing %>% select(-diagnosis) #remove diagnosis so df is unlabled
otherTest <- otherTest[1:70,] # remove rows so that the test set changes size
newPreds <- predict(combModFit, otherTest) 
# Warning message: 'newdata' had 70 rows but variables found have 82 rows 
# newPreds now has 82 rows, but there were only 70 rows in otherTest to predict on. 

identical(predComb,newPreds) #TRUE

我完全确定我错过了一个简单的概念,我只是不确定它是什么。

4

2 回答 2

3

我已经通过源代码搜索predict.train,到目前为止,这是我能做出来的

predict.train <- function (object, newdata = NULL, type = "raw", 
na.action = na.omit, ...) 

在你的函数调用中

newPreds <- predict(combModFit, otherTest)

参数已设置

object <- combModFit
newdata <- otherTest

函数内predict.train是行

newdata <- as.data.frame(newdata)
rn <- row.names(newdata)
Terms <- delete.response(object$terms)
m <- model.frame(Terms, newdata, na.action = na.action, 
      xlev = object$xlevels)

从哪里来Terms_ combModFit$terms_

diagnosis ~ predRF + predGBM + predLDA

在删除响应之前,当它变成公式时

~ predRF + predGBM + predLDA

现在,回到model.frame调用,这些列名都不在testing数据框中

c("predRF", "predGBM", "predLDA") %in% names(testing)

[1] FALSE FALSE FALSE

但是,在前面的代码中,您已经定义了 objects predRFpredGBMpredLDA作为因子,每个长度为 82。因此,model.frame在调用它时不会返回错误。相反,它只返回之前的这三个因素。

结果,对象m变成了具有这三个对象(作为列)和 82 行的数据框。

换一种说法,model.frame旨在从testing数据框中提取名称predRF为 、predGBMpredLDA的列,但不能(因为这些列不存在)。相反,它返回您之前定义的对象。因此,无论是什么newdata,只要它们没有必要的列名,您都会得到相同的结果。

编辑:从评论中回答您的问题

中的所有变量名称都不modRF$terms对应于您环境中的对象。

table(all.vars(delete.response(modRF$terms)) %in% ls())
FALSE 
 130

因此,当您尝试进行预测modRF时,cars您会遇到错误

predict(modRF, cars)
Error in eval(expr, envir, enclos) : 
object 'ACE_CD143_Angiotensin_Converti' not found

中的第一项modRF$terms未找到

all.vars(delete.response(modRF$terms))[1]
[1] "ACE_CD143_Angiotensin_Converti"

但是,其中的术语combModFit确实与环境中对象的名称相匹配。

table(all.vars(delete.response(combModFit$terms)) %in% ls())
TRUE 
 3

所以当你尝试预测时没有错误,尽管这是一个意想不到的结果。

如果在运行之前从环境中删除predRFpredGBM和,则会收到错误消息。predLDApredict(combModFit, cars)

# before deleting
predict(combModFit, cars)     
 [1] Control  Control  Impaired  ....

# after deleting the three objects you get an error
rm(list = c("predRF", "predGBM", "predLDA"))
predict(combModFit, cars)
Error in eval(expr, envir, enclos) : object 'predRF' not found

请注意,这predRF是第一个术语combModFit

all.vars(delete.response(combModFit$terms))[1]
[1] "predRF"

所以caret函数的行为是一致的。您的情况很不寻常,因为其中一些术语的名称combModFit对应于环境中的其他对象。

希望有帮助。

于 2015-08-21T01:57:02.060 回答
2

caretEnsemble软件包可以为您完成所有这些工作。

于 2015-08-21T15:19:19.080 回答