Je suis curieux de connaître l'implémentation pratique d'une division binaire dans un arbre de décision - en ce qui concerne les niveaux d'un prédicteur catégorique .
Plus précisément, j'utilise souvent une sorte de schéma d'échantillonnage (par exemple, ensachage, suréchantillonnage, etc.) lors de la construction d'un modèle prédictif à l'aide d'un arbre de décision - afin d'améliorer sa précision et sa stabilité prédictives. Au cours de ces routines d'échantillonnage, il est possible qu'une variable catégorielle soit présentée à un algorithme d'ajustement d'arbre avec moins que l'ensemble de niveaux complet.
Disons qu'une variable X prend des niveaux {A,B,C,D,E}
. Dans un échantillon, peut-être que seuls les niveaux {A,B,C,D}
sont présents. Ensuite, lorsque l'arbre résultant est utilisé pour la prédiction, l'ensemble complet peut être présent.
En reprenant cet exemple, disons qu'un arbre se divise sur X et envoie {A,B}
à gauche et {C,D}
à droite. Je m'attendrais à ce que la logique de la division binaire dise alors, face à de nouvelles données: "Si X a la valeur A ou B, envoyez à gauche, sinon, envoyez ce cas à droite". Ce qui semble se produire dans certaines implémentations est "si X a la valeur A ou B, envoyer à gauche, si X a la valeur C ou D envoyer à droite". Lorsque ce cas prend la valeur E, l'algorithme tombe en panne.
Quelle est la "bonne" façon de gérer un fractionnement binaire? Il semble que le moyen beaucoup plus robuste soit implémenté souvent, mais pas toujours (voir Rpart ci-dessous).
Voici quelques exemples:
Rpart échoue, les autres vont 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