决策树中二分法实现的差异

机器算法验证 大车 rpart 分区
2022-03-21 07:50:56

我对决策树中二元拆分的实际实现感到好奇——因为它与分类预测器的级别有关Xj.

具体来说,在使用决策树构建预测模型时,我经常会使用某种采样方案(例如装袋、过采样等),以提高其预测准确性和稳定性。在这些采样例程中,分类变量有可能呈现给小于完整水平集的树拟合算法。

假设变量 X 具有水平{A,B,C,D,E}在样本中,可能只{A,B,C,D}存在水平。然后,当结果树用于预测时,可能会出现完整集。

继续这个例子,假设一棵树在 X 上分裂并{A,B}向左和{C,D}向右发送。我希望二进制拆分的逻辑在面对新数据时会说:“如果 X 具有值 A 或 B,则发送到左侧,否则,将这种情况发送到右侧”。在某些实现中似乎发生的是“如果 X 具有值 A 或 B,则发送到左侧,如果 X 具有值 C 或 D 发送到右侧”。当这种情况取值为 E 时,算法就会崩溃。

处理二进制拆分的“正确”方式是什么?似乎经常实现更健壮的方式,但并非总是如此(参见下面的 Rpart)。

这里有几个例子:

Rpart 失败,其他都正常。

#test trees and missing values

summary(solder)
table(solder$PadType)

# create train and validation
set.seed(12345)
t_rows<-sample(1:nrow(solder),size=360, replace=FALSE)
train_solder<-solder[t_rows,]
val_solder<-solder[-t_rows,]

#look at PadType
table(train_solder$PadType)
table(val_solder$PadType)
#set a bunch to missing
levels(train_solder$PadType)[train_solder$PadType %in% c('L8','L9','W4','W9')] <- 'MISSING'


#Fit several trees, may have to play with the parameters to get them to split on the variable

####RPART
mod_rpart<-rpart(Solder~PadType,data=train_solder)
predict(mod_rpart,val_solder)
#Error in model.frame.default(Terms, newdata, na.action = na.action, xlev = attr(object,  : 
#factor 'PadType' has new level(s) D6, L6, L7, L8, L9, W4

####TREE
mod_tree<-tree(Solder~PadType,data=train_solder,split="gini")
predict(mod_tree,val_solder) #works fine

####ctree
mod_ctree<-ctree(Solder~PadType,data=train_solder,control = ctree_control(mincriterion = 0.05))
predict(mod_ctree,val_solder) #works fine
1个回答

事实上,有两种类型的因子——有序(如 Tiny < Small < Medium < Big < Huge)和无序(Cucumber、Carrot、Fennel、Aubergine)。
第一类与连续类相同——只是更容易检查所有枢轴,扩展级别列表也没有问题。
对于第二个类,您必须创建一组元素,这些元素将被引导到一个分支中,其余部分留给另一个分支——在这种情况下,您可以:

  1. 抛出错误
  2. 假设看不见的课程进入你最喜欢的分支
  3. 将此视为 NA 并以更随机的方式选择分支。

现在,直接处理无序因子是很棘手的,所以许多算法“作弊”并声称无序因子是有序因子,所以他们甚至没有触及这个问题*。其余的通常使用 int 掩码,即优化一个整数12#categories11并对待i-th 位作为因子级别的分支选择i. (有没有想过为什么经常限制在 32 个级别?)在这种情况下,看不见的级别很自然地会悄悄地进入“0”分支。然而这似乎不太“正确”,因为我们为什么要这样做呢?那么在属性选择中熵杠杆所需的层数呢?

我想说最明智的想法是让用户定义完整的因素集(例如 R 有机地做到这一点,通过子集操作保留级别)并使用选项 1. 未声明的级别和选项 2. 声明的级别. 如果您已经有一些 NA 处理基础设施,选项 3. 可能有意义。

*) 还有一种辅助策略是将级别重新编码为数字,例如 Breiman 编码——但这会产生更多问题。