Введение

Недавно я читал свою копию Введение в статистическое обучение (моя партнерская ссылка на Amazon) и получил главу о различных методах на основе дерева. Я довольно хорошо знаком со случайным лесом, но некоторые другие методы для меня новы. Давайте рассмотрим эти различные техники.

Для этих примеров я буду исследовать набор данных Glass с сайта openml. Этот набор данных имеет 9 различных функций, используемых для прогнозирования типа стекла. Набор данных содержит 214 наблюдений.

Набор данных загружается с помощью следующего кода. Для этого требуется, чтобы пакет farff открывал файлы arff, используемые на сайте openml.

library(tidyverse)
download.file("https://www.openml.org/data/download/41/dataset_41_glass.arff", "data.arff")
df <- farff::readARFF("data.arff")

Оттуда мы можем начать исследовать набор данных и настроить разделение обучения и тестирования для данных.

df %>% str()
df <- droplevels(df)

set.seed(1234)
test <- sample(1:nrow(df), floor(nrow(df)*0.2))

testdf <- df[test,]
traindf <- df[-test,]
'data.frame': 214 obs. of  10 variables:
 $ RI  : num  1.52 1.52 1.52 1.51 1.53 ...
 $ Na  : num  12.8 12.2 13.2 14.4 12.3 ...
 $ Mg  : num  3.5 3.52 3.48 1.74 0 2.85 3.65 2.84 0 3.9 ...
 $ Al  : num  1.12 1.35 1.41 1.54 1 1.44 0.65 1.28 2.68 1.3 ...
 $ Si  : num  73 72.9 72.6 74.5 70.2 ...
 $ K   : num  0.64 0.57 0.59 0 0.12 0.57 0.06 0.55 0.08 0.55 ...
 $ Ca  : num  8.77 8.53 8.43 7.59 16.19 ...
 $ Ba  : num  0 0 0 0 0 0.11 0 0 0.61 0 ...
 $ Fe  : num  0 0 0 0 0.24 0.22 0 0 0.05 0.28 ...
 $ Type: Factor w/ 7 levels "build wind float",..: 1 3 1 6 2 2 3 1 7 2 ...

Древо решений

Наиболее простой моделью является дерево решений. В этой модели все классы хранятся в контейнере в корне дерева. Корень разделен определенными значениями функций на два меньших контейнера. Эти меньшие контейнеры называются листьями. После этих начальных двух листьев мы выполняем дополнительное разделение, в результате чего получается 4 новых листа. На этом этапе должна быть улучшена сортировка значения ответа в новых листах. Разделение и создание новых листьев продолжается до тех пор, пока не будут получены желаемые результаты.

Основным недостатком деревьев решений является то, что они очень склонны к переобучению. Довольно легко представить себе дерево, которое расщеплялось столько раз, что теперь каждый лист представляет собой одно наблюдение. Это дерево будет иметь 100% точность на тренировочном наборе, но не будет хорошо работать на тестовом наборе. Мы предотвращаем чрезмерную подгонку, отрезая или сокращая количество листьев до определенного значения.

В нашем примере дерево решений создается с помощью пакета tree. Он довольно прост в использовании, вы просто предоставляете ему функцию и данные.

mdltree <- tree::tree(Type ~., data = traindf)

Визуализация дерева легко создается с помощью команды печати. С помощью дополнительной строки мы можем добавить текст, показывающий, где разделяется каждый лист. Трудно понять расщепления при переходе к листам нижнего уровня.

Теперь мы можем проверить производительность дерева решений на тестовых данных. Поскольку ответ является фактором, результирующий прогноз представляет собой матрицу с вероятностью, присвоенной каждому ответу для каждого наблюдения. Мы можем обобщить наиболее вероятный ответ с помощью функции max.col.

treevalues <- predict(mdltree, newdata = testdf)
treepred <- colnames(treevalues)[max.col(treevalues)]
Acctree <- mean(treepred == testdf$Type)
Acctree
[1] 0.5

Из этого прогноза видно, что дерево решений не обеспечивает высокого уровня точности (точность 50%). Для более высокого уровня точности давайте рассмотрим некоторые дополнительные методы.

Бэгинг

Начальная загрузка — полезный метод, когда у нас есть ограниченное количество наблюдений. Обычно мы берем каждое тренировочное наблюдение из сумки и обучаем с его помощью нашу модель. При начальной загрузке после того, как мы обучим нашу модель с помощью наблюдения, мы кладем наблюдение обратно в корзину, позволяя повторять выборку. Повторный выбор создает более плавное распределение наблюдений.

Бэггинг продвигает этот процесс еще на один шаг вперед. Мы берем несколько моделей из загруженных обучающих данных и усредняем их значения. Каждая загруженная модель уникальна, поскольку обучающие наблюдения выбираются случайным образом.

Упаковку можно выполнить с помощью функции randomForest. По умолчанию функция создает деревья из подмножества функций, но мы можем создавать деревья в мешках, используя все функции. Поведение по умолчанию для случайного леса состоит в том, чтобы получить большинство голосов за построенные деревья или усреднить их прогноз.

library(randomForest)
mdlbag <- randomForest(Type ~., data = droplevels(traindf), mtry = ncol(df)-1, n.trees = 500)
bagpreds <- predict(mdlbag, newdata = testdf)
Accbag <- mean(bagpreds == testdf$Type)
Accbag
[1] 0.6666667

Случайный лес

Случайный лес — это ансамблевая модель, то есть прогноз создается путем объединения нескольких моделей. Это очень похоже на предыдущий пример с бэггингом. Основное отличие состоит в том, что случайный лес выбирает случайный набор признаков при создании каждого дерева.

Обоснованием случайного выбора признаков является создание более уникальных деревьев. Если в бэггинге есть сильная особенность, то большинство деревьев будут использовать ее для создания своего первого разделения. Это создает очень похожие деревья.

mdlforest <- randomForest(Type ~., data = droplevels(traindf), n.trees = 500)
rfpreds <- predict(mdlforest, newdata = testdf)
Accrf <- mean(rfpreds == testdf$Type)
Accrf
[1] 0.6666667

Повышение

Бустирование — еще одна техника многократного использования, очень похожая на бэггинг. Вместо того, чтобы воздействовать на обучающие данные для создания разных деревьев, бустинг строит деревья в последовательном порядке с обучающим набором по умолчанию. Вместо того, чтобы подгонять деревья к ответу, деревья подгоняют к своим остаткам. Затем каждое дерево медленно учится на остатках предыдущего дерева.

Для этой модели мы будем использовать две библиотеки, caret и gbm. Пакет gbm — это пакет, предоставляющий фактическую модель, но при использовании функции gbm отображается предупреждение. Чтобы обойти эту проблему, мы можем использовать пакет caret с функцией train. Эта функция может принимать множество различных моделей и автоматически проходит через параметры настройки.

library(caret)
library(gbm)
mdlboost <- caret::train(Type ~., data = traindf, method = 'gbm', verbose = FALSE)
boostpreds <- predict(mdlboost, newdata = testdf)
Accboost <- mean(boostpreds == testdf$Type)
Accboost
[1] 0.7142857

Байесовская аддитивная регрессия

Деревья байесовской аддитивной регрессии (BART) аналогичны ранее упомянутым моделям, создавая деревья с некоторыми случайными элементами, которые моделируют сигнал, не захваченный в предыдущих деревьях.

В первой итерации модели все деревья инициализируются одним и тем же корневым узлом. После очередной итерации поочередно обновляется каждое из k-х деревьев. Во время b-й итерации мы вычитаем предсказанные значения из каждого ответа, чтобы получить частичный остаток. i представляет каждую итерацию.

Вместо того, чтобы подгонять новое дерево к этому остатку, BART случайным образом выбирает дерево из предыдущей итерации (f^b-1), отдавая предпочтение деревьям, которые лучше подходят.

К сожалению, мне не удалось заставить какую-либо модель BART работать для этого примера классификации нескольких классов. Пакет bartMachine не имеет реализации, а реализация пакета BART мне не подходит. Все значения для меня возвращали NA. В пакете BART также очень мало ресурсов для устранения неполадок.

Дерево решений как простая для понимания модель, но оно склонно к переподгонке данных. Сокращение требуется, чтобы уменьшить это, но также снизит точность (точность 50% для этого примера).

Затем модели ансамбля вводятся с помощью бэггинга, который усредняет группу деревьев, созданных на основе набора различных наблюдений. Это увеличивает нашу точность (66,67%). Это очень похоже на модель случайного леса, но вместо этого мы увеличиваем случайный элемент, чтобы включить выбранные функции (66,67%).

Окончательные модели создают деревья, которые строятся из ранее сгенерированных деревьев с повышением и деревом байесовской аддитивной регрессии. К сожалению, для модели BART результатов нет, но бустинг дает хорошие результаты (69,05%).

Таким образом, нет однозначного ответа, какая модель лучше, они используют очень похожие методы и дают схожие результаты. Я бы порекомендовал обучить их всех и определить, какие из них лучше всего работают с вашими данными.

Первоначально опубликовано на https://datasandbox.netlify.app 15 ноября 2022 г.