R caret包(rpart):构建分类树

6

我已经苦恼了几天,试图使用caret包进行分类树的构建。

问题出在我的因子变量上。我生成了决策树,但是当我尝试使用最佳模型对测试样本进行预测时,失败了。这是因为train函数为我的因子变量创建了虚拟变量,然后predict函数在测试集中找不到这些新创建的虚拟变量。我该如何解决这个问题?

我的代码如下:

install.packages("caret", dependencies = c("Depends", "Suggests"))      
library(caret)                                      
db=data.frame(read.csv ("db.csv", head=TRUE, sep=";", na.strings ="?"))     
fix(db)
db$defaillance=factor(db$defaillance)
db$def=ifelse(db$defaillance==0,"No","Yes") 
db$def=factor(db$def)
db$defaillance=NULL
db$canal=factor(db$canal)
db$sect_isodev=factor(db$sect_isodev)
db$sect_risq=factor(db$sect_risq)       

#delete zero variance predictors                                
nzv <- nearZeroVar(db[,-78])
db_new <- db[,-nzv]

inTrain <- createDataPartition(y = db_new$def, p = .75, list = FALSE)                               
training <- db_new[inTrain,]
testing <- db_new[-inTrain,]
str(training)
str(testing)
dim(training)
dim(testing)

以下是用于训练/测试的str()函数示例:

代码如下:

 $ FDR        : num  1305 211 162 131 143 ...
 $ FCYC       : num  0.269 0.18 0.154 0.119 0.139 ...
 $ BFDR       : num  803 164 108 72 76 63 100 152 188 80 ...
 $ TRES       : num  502 47 54 59 67 49 53 -7 -103 -109 ...
 $ sect_isodev: Factor w/ 9 levels "1","2","3","4",..: 4 3 3 3 3 3 3 3 3 3 ...
 $ sect_risq  : Factor w/ 6 levels "0","1","2","3",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ def        : Factor w/ 2 levels "No","Yes": 1 1 1 1 1 1 1 1 1 1 ...
> dim(training)
[1] 14553    42
> dim(testing)
[1] 4850   42

然后我的代码如下:
fitControl <- trainControl(method = "repeatedcv",
                           number = 10,
                           repeats = 10,
                   classProbs = TRUE,
                   summaryFunction = twoClassSummary)

#CART1
set.seed(1234)
tree1 = train (def~.,
           training,
           method = "rpart",
           tuneLength=20,
           metric="ROC",
           trControl = fitControl)

一个简单的示例

summary(tree1$finalModel)

在这里

RNTB          38.397731
sect_isodev1   6.742289
sect_isodev3   4.005016
sect_isodev8   2.520850
sect_risq3     9.909127
sect_risq4     6.737908
sect_risq5     3.085714
SOLV          73.067539
TRES          47.906884
sect_isodev2   0.000000
sect_isodev4   0.000000
sect_isodev5   0.000000
sect_isodev6   0.000000
sect_isodev7   0.000000
sect_isodev9   0.000000
sect_risq0     0.000000
sect_risq1     0.000000
sect_risq2     0.000000

以下是错误提示:

model.tree1 <- predict(tree1$finalModel,testing) Error in eval(expr, envir, enclos) : object 'sect_isodev1' not found

我还有一个问题想问,我在Max Kuhn的《R预测建模》一书中发现以下语法:

predict(rpartTune$finalModel, newdata, type = "class")

其中rpartTune$finalModel是一棵与我的分类树完全相同(或者说与他的完全相同)的树。现在,R不接受type="class",只接受type="prob"。这让我很困扰。

提前感谢您的回复。

2个回答

13
不要使用predict.rparttrain$finalModel一起使用,除非您有非常充分的理由。 rpart对象并不知道train所做的任何事情,包括预处理。 它可能无法给出正确的答案。 毕竟,您可能正在使用train来避免琐碎的工作,因此让predict.train完成工作。

Max

编辑 -

关于type = "class"type = "prob"部分...

predict.rpart默认产生类别概率。尽管rpart是最早的软件包之一,但这是非典型的,因为大多数默认情况下会生成类别。

predict.train默认生成类别,您必须使用type = "prob"来获得概率。


9
据我所知,有两个问题:
- R找不到适用于`tree1$finalModel`的预测函数,应该是`predict.rpart`,因为`tree1$finalModel`属于类`rpart`。我也遇到了这个错误,不幸的是我不知道其中的原因。这也是为什么R不接受`type = "class"`的原因。`predict.rpart`会接受它。 - 向`train`函数提供公式而不是x和y对象会导致后续无法找到像`sect_isodev1`这样的变量。
在使用类似于您的`str`的随机数据(使用x和y对象并显式调用`rpart`中的`predict.rpart`)重现您的错误后,对我有效。
tree1 = train (y = training$def,
               x = training[, -which(colnames(training) == "def")],
               method = "rpart",
               tuneLength=20,
               metric="ROC",
               trControl = fitControl)
summary(tree1$finalModel)
# This still results in Error: could not find function "predict.rpart":
model.tree1 <- predict.rpart(tree1$finalModel, newdata = testing)
# Explicitly calling predict.rpart from the rpart package works:
rpart:::predict.rpart(object = tree1$finalModel, 
                      newdata = testing, 
                      type = "class") 

顺便说一下,predict(tree1, testing)表示使用train对象中的predict.train进行预测,同样可以返回预测类别。 编辑:正如Max指出的那样,通常最好只使用这种方法而不是让不同的predict函数起作用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接