Мені цікаво практична реалізація бінарного розколу на дереві рішень - оскільки це стосується рівнів категоричного предиктора .
Зокрема, я часто буду використовувати якусь схему відбору зразків (наприклад, розфасування, пересимплінг тощо), коли будую модель прогнозування за допомогою дерева рішень, щоб поліпшити її точність прогнозування та стабільність. Під час цих процедур вибірки категорична змінна може бути представлена в алгоритмі встановлення дерева з меншим, ніж повний набір рівнів.
Скажімо, змінна 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 не вдається, з іншими нормально.
#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