Tengo curiosidad acerca de la implementación práctica de una división binaria en un árbol de decisión, ya que se relaciona con los niveles de un predictor categórico .
Específicamente, a menudo utilizaré algún tipo de esquema de muestreo (por ejemplo, embolsado, sobremuestreo, etc.) al construir un modelo predictivo utilizando un árbol de decisión, con el fin de mejorar su precisión y estabilidad predictivas. Durante estas rutinas de muestreo, es posible presentar una variable categórica a un algoritmo de ajuste de árbol con un conjunto de niveles inferior al completo.
Digamos que una variable X toma niveles {A,B,C,D,E}
. En una muestra, quizás solo {A,B,C,D}
hay niveles presentes. Luego, cuando el árbol resultante se usa para la predicción, el conjunto completo puede estar presente.
Continuando con este ejemplo, digamos que un árbol se divide en X y envía {A,B}
a la izquierda y {C,D}
a la derecha. Esperaría que la lógica de la división binaria diga, cuando se enfrente con nuevos datos: "Si X tiene el valor A o B, envíe a la izquierda, de lo contrario, envíe este caso a la derecha". Lo que parece suceder en algunas implementaciones es "si X tiene el valor A o B, enviar a la izquierda, si X tiene el valor C o D enviar a la derecha". Cuando este caso adquiere el valor E, el algoritmo se descompone.
¿Cuál es la forma "correcta" de manejar una división binaria? Parece que la forma mucho más robusta se implementa a menudo, pero no siempre (ver Rpart más abajo).
Aqui hay un par de ejemplos:
Rpart falla, los otros están bien.
#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