我正在创建一个确定决策树模型的闪亮应用程序,然后根据用户输入提出预测。
该模型的开发方式如下:
tr<-prune.tree(tree(Y ~ ., dataset,split="gini"),best=4)
总共有20个变量,实际上只有5个变量在树中使用。所以,我想创建我的应用程序,使用户只需要输入这5个变量,而不是所有变量。这是我尝试的内容(仅显示重要代码):
在server.r中:
output$treepred<-renderText({
predict(tr,data.frame(PREVIOUS=input$numeric6,NR_EMPLOYED=input$numeric1,CAMPAIGN=input$numeric7,EMP_VAR_RATE=input$numeric8,CONS_PRICE_IDX=input$numeric9),type="class")
})
在ui.r:
box(textOutput("treepred"))
只需运行此操作即可返回错误&#34; object&#39; AGE&#39;找不到&#34; (其中AGE是未使用的变量)。如果我仅使用被发现相关的变量重建树,我会得到一个完全不同(甚至更糟)的树。 (我也试过包含那些不相关的变量,但是将它们设置为NULL或NA,但这也没有用。)
实质上,问题在于r希望用户在他们真的不需要时输入所有数据。有谁知道怎么解决这个问题?
编辑:
一个小例子:
dir <- "Your directory"
dataset <- read.csv(paste(dir, "Data.csv",sep = ""))
dataset[, c(1, 11:13)] <- lapply(dataset[, c(1, 11:13)],as.integer)
dataset[, c(2:10, 14, 20)] <- lapply(dataset[, c(2:10,14,20)], as.factor)
dataset[, c(15:19)] <- lapply(dataset[, c(15:19)],as.numeric)
dataset$PDAYS[dataset$PDAYS == 999] <- NA #this is NA by the definition of the data
library(tree)
tree<-prune.tree(tree(Y ~ ., dataset,split="gini"),best=4)
plot(tree, type="uniform")
text(tree, pretty=0)
predict(tree,newdata=dataset,type="class")
#The above all works perfectly.
summary(tree)
#This tells us which variables are relevant
predict(tree,newdata=data.frame(PREVIOUS=1,CAMPAIGN=1,EMP_VAR_RATE=50,CONS_PRICE_IDX=100,NR_EMPLOYED=5000))
#returns error: object 'AGE' not found.
#Retraining the tree with only relevant variables:
tree2<-prune.tree(tree(Y ~ PREVIOUS+NR_EMPLOYED+CAMPAIGN+EMP_VAR_RATE+CONS_PRICE_IDX, dataset,split="gini"),best=4)
plot(tree2, type="uniform")
text(tree2, pretty=0)
#This tree is completely different and only ever predicts "no"
以下是数据:
答案 0 :(得分:1)
好的,我看了一眼。当然令人费解的是为什么第二棵树看起来与第一棵树差别很大。如果要保留相同的变量,则根分割应该相同,因为具有最大信息增益的维度不应更改。我花了一段时间,但你实际上可以在树输出中看到问题。这是第一棵树:
> tree
node), split, n, deviance, yval, (yprob)
* denotes terminal node
1) root 1515 1983.00 yes ( 0.3617 0.6383 )
2) PREVIOUS < 1.5 865 1167.00 yes ( 0.4035 0.5965 )
4) CAMPAIGN < 1.5 460 618.40 yes ( 0.3978 0.6022 )
8) EMP_VAR_RATE < -3.2 91 110.70 yes ( 0.2967 0.7033 ) *
9) EMP_VAR_RATE > -3.2 369 502.70 yes ( 0.4228 0.5772 )
18) CONS_PRICE_IDX < 93.2845 221 303.50 no ( 0.5566 0.4434 ) *
19) CONS_PRICE_IDX > 93.2845 148 157.10 yes ( 0.2230 0.7770 ) *
5) CAMPAIGN > 1.5 405 548.20 yes ( 0.4099 0.5901 )
10) CAMPAIGN < 2.5 256 338.70 yes ( 0.3750 0.6250 )
20) NR_EMPLOYED < 5087.65 193 220.80 yes ( 0.2591 0.7409 ) *
21) NR_EMPLOYED > 5087.65 63 73.47 no ( 0.7302 0.2698 ) *
11) CAMPAIGN > 2.5 149 206.00 yes ( 0.4698 0.5302 ) *
3) PREVIOUS > 1.5 650 800.80 yes ( 0.3062 0.6938 ) *
这是第二个。
> tree2
node), split, n, deviance, yval, (yprob)
* denotes terminal node
1) root 41188 29000 no ( 0.88735 0.11265 )
2) PREVIOUS < 0.5 35563 21240 no ( 0.91168 0.08832 )
4) NR_EMPLOYED < 5087.65 2634 3496 no ( 0.62073 0.37927 ) *
5) NR_EMPLOYED > 5087.65 32929 15850 no ( 0.93495 0.06505 ) *
3) PREVIOUS > 0.5 5625 6522 no ( 0.73351 0.26649 )
6) PREVIOUS < 1.5 4561 4713 no ( 0.78799 0.21201 )
12) NR_EMPLOYED < 5087.65 1433 1986 no ( 0.51082 0.48918 ) *
13) NR_EMPLOYED > 5087.65 3128 1820 no ( 0.91496 0.08504 ) *
7) PREVIOUS > 1.5 1064 1475 no ( 0.50000 0.50000 ) *
>
第一棵树在PREVIOUS = 1.5
找到了最大的基尼分裂,第二棵树在0.5。但是你也可以看到第一棵树出于某种原因只看了1515点,但第二棵树看了41188,还有更多。
为什么呢?如果查看公式,您会看到第一个树查看了所有列,第二个树查看了子集。因此,让我们计算所有行而不会丢失数据:
> sum(complete.cases(dataset))
[1] 1515
这是你的答案。没有为第一个树查看缺少数据的行,但是当您将其限制为某些列时,它们位于第二个树中。难怪树木不同......
至于你的另一个问题,那就是predict.tree
算法的工作方式,它确保所有数据都在前面。这允许它使用与其他predict.xxx
函数共同的编码基础结构。答案很简单,只需确保在您不关心的所有列中都有虚拟数据。你可以使用这样的东西:
ddf1 <- dataset[1,]
ddf1$PREVIOUS <- 1
ddf1$CAMPAIGN <- 1
ddf1$EMP_VAR_RATE <- 50
ddf1$CONS_PRICE_IDX <- 100
ddf1$CONS_PRICE_IDX <- 5000
predict(tree,newdata=ddf1)
最后一点是,即使在你的第二棵树中,也不是一直只是预测“不”。那些不可能的概率(也可以在树输出中看到)变化很大。您可以通过查看tree$frame
数据框以编程方式访问这些分支和值。