#r #machine-learning #split #tree #party
#r #машинное обучение #разделение #дерево #Вечеринка
Вопрос:
Я пытаюсь применить здесь дерево решений. Дерево решений само заботится о разделении на каждом узле. Но на первом узле я хочу разделить свое дерево на основе «возраста». Как мне это сделать.?
library(party)
fit2 <- ctree(Churn ~ Gender Age LastTransaction Payment.Method spend marStat, data = tsdata)
Ответ №1:
Для этого нет встроенной опции ctree()
. Самый простой способ сделать это «вручную» — это просто:
-
Изучите дерево только
Age
как объясняющую переменную,maxdepth = 1
чтобы это создавало только одно разделение. -
Разделите свои данные, используя дерево из шага 1, и создайте поддерево для левой ветви.
-
Разделите свои данные, используя дерево из шага 1, и создайте поддерево для правой ветви.
Это делает то, что вы хотите (хотя я обычно не рекомендовал бы этого делать …).
Если вы используете ctree()
реализацию из partykit
, вы также можете снова объединить эти три дерева в одно дерево для визуализации, прогнозирования и т. Д. Это требует немного взлома, но все же возможно.
Я проиллюстрирую это, используя iris
данные, и я принудительно разделю переменную Sepal.Length
, которая в противном случае не использовалась бы в дереве. Изучить три дерева, описанные выше, легко:
library("partykit")
data("iris", package = "datasets")
tr1 <- ctree(Species ~ Sepal.Length, data = iris, maxdepth = 1)
tr2 <- ctree(Species ~ Sepal.Length ., data = iris,
subset = predict(tr1, type = "node") == 2)
tr3 <- ctree(Species ~ Sepal.Length ., data = iris,
subset = predict(tr1, type = "node") == 3)
Однако обратите внимание, что важно использовать формулу с Sepal.Length .
, чтобы гарантировать, что переменные во фрейме модели упорядочены точно так же во всех деревьях.
Далее следует самый технический шаг: нам нужно извлечь исходную node
структуру из всех трех деревьев, настроить узлы id
так, чтобы они находились в правильной последовательности, а затем интегрировать все в один узел:
fixids <- function(x, startid = 1L) {
id <- startid - 1L
new_node <- function(x) {
id <<- id 1L
if(is.terminal(x)) return(partynode(id, info = info_node(x)))
partynode(id,
split = split_node(x),
kids = lapply(kids_node(x), new_node),
surrogates = surrogates_node(x),
info = info_node(x))
}
return(new_node(x))
}
no <- node_party(tr1)
no$kids <- list(
fixids(node_party(tr2), startid = 2L),
fixids(node_party(tr3), startid = 5L)
)
no
## [1] root
## | [2] V2 <= 5.4
## | | [3] V4 <= 1.9 *
## | | [4] V4 > 1.9 *
## | [5] V2 > 5.4
## | | [6] V4 <= 4.7
## | | | [7] V4 <= 3.6 *
## | | | [8] V4 > 3.6 *
## | | [9] V4 > 4.7
## | | | [10] V5 <= 1.7 *
## | | | [11] V5 > 1.7 *
И, наконец, мы настраиваем фрейм объединенной модели, содержащий все данные, и объединяем его с новым объединенным деревом. Добавлена некоторая информация о подогнанных узлах и ответах, чтобы можно было превратить дерево в a constparty
для хорошей визуализации и прогнозирования. Подробнее vignette("partykit", package = "partykit")
об этом см.:
d <- model.frame(Species ~ Sepal.Length ., data = iris)
tr <- party(no,
data = d,
fitted = data.frame(
"(fitted)" = fitted_node(no, data = d),
"(response)" = model.response(d),
check.names = FALSE),
terms = terms(d),
)
tr <- as.constparty(tr)
И тогда мы закончили и можем визуализировать наше объединенное дерево с принудительным первым разделением:
plot(tr)
Ответ №2:
На каждой итерации дерево решений выбирает наилучшую переменную для разделения (либо на основе прироста информации / индекса Джини, для CART, либо на основе критерия хи-квадрат, как для дерева условного вывода). Если у вас есть лучшая предикторная переменная, которая разделяет классы больше, чем это может сделать возраст предиктора, тогда эта переменная будет выбрана первой.
Я думаю, исходя из ваших требований, вы можете выполнить следующие несколько действий:
(1) Без присмотра: дискретизируйте переменную Age (создайте ячейки, например, 0-20, 20-40, 40-60 и т. Д., В соответствии с вашими знаниями в области) И подмножьте данные для каждой из ячеек age, затем обучите отдельное дерево решений для каждого из этих сегментов.
(2) Контролируемый: продолжайте удалять другие переменные-предикторы, пока возраст не будет выбран первым. Теперь вы получите дерево решений, в котором возраст выбран в качестве первой переменной. Используйте правила для возраста (например, Возраст> 36 и возраст <= 36), созданные деревом решений, чтобы разделить данные на 2 части. Для каждой из частей изучите полное дерево решений со всеми переменными отдельно.
(3) Контролируемый ансамбль: вы можете использовать классификатор Randomforest, чтобы увидеть, насколько важна ваша возрастная переменная.
Ответ №3:
Вы можете использовать комбинацию rpart и partykit для достижения такой операции.
Обратите внимание, что если вы используете ctree для обучения DT, а затем используете функцию data_party для извлечения данных из другого узла, единственными переменными, включенными в извлеченный набор данных, будут только обучающие переменные, в вашем случае Возраст.
Мы должны использовать rpart на первом этапе для обучения модели с выбранной переменной, потому что есть способ с помощью rpart обучить DT таким образом, чтобы вы могли сохранить все свои переменные в извлеченном наборе данных, не помещая эти переменные в качестве обучающих переменных:
library(rpart)
fit2 <- rpart(Churn ~ . -(Gendere LastTransaction Payment.Method spend marStat) , data = tsdata, maxdepth = 1)
Используя этот метод, вашей единственной обучающей переменной будет возраст, и вы можете преобразовать свое дерево rpart в partykit и извлекать данные из разных узлов и отчаянно их обучать:
library(partykit)
fit2party <- as.party(fit2)
dataset1 <- data_party(fit2party, id = 2)
dataset2 <- data_party(fit2party, id = 3)
Теперь у вас есть два набора данных, разделенных по возрасту, со всеми переменными, которые вы хотите использовать для обучения DT в будущем, вы можете создавать DT на основе этих подмножеств, как считаете нужным, используйте rpart или ctree.
Позже вы можете использовать partynode и partysplit combo для построения дерева на основе полученных вами правил обучения.
Надеюсь, это то, что вы ищете.