Как указать разделение в дереве решений в программировании на языке R?

#r #machine-learning #split #tree #party

#r #машинное обучение #разделение #дерево #Вечеринка

Вопрос:

Я пытаюсь применить здесь дерево решений. Дерево решений само заботится о разделении на каждом узле. Но на первом узле я хочу разделить свое дерево на основе «возраста». Как мне это сделать.?

 library(party)    
fit2 <- ctree(Churn ~ Gender   Age   LastTransaction   Payment.Method   spend   marStat, data = tsdata)
  

Ответ №1:

Для этого нет встроенной опции ctree() . Самый простой способ сделать это «вручную» — это просто:

  1. Изучите дерево только Age как объясняющую переменную, maxdepth = 1 чтобы это создавало только одно разделение.

  2. Разделите свои данные, используя дерево из шага 1, и создайте поддерево для левой ветви.

  3. Разделите свои данные, используя дерево из шага 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 для построения дерева на основе полученных вами правил обучения.

Надеюсь, это то, что вы ищете.