R: Что я вижу на графиках частичной зависимости gbm и RandomForest?

14

На самом деле, я думал, что понял, что можно показать на графике частичной зависимости, но на очень простом гипотетическом примере я немного озадачился. В следующем фрагменте кода я генерирую три независимые переменные ( a , b , c ) и одну зависимую переменную ( y ), где c показывает тесную линейную зависимость с y , тогда как a и b не связаны с y . Я делаю регрессионный анализ с помощью расширенного регрессионного дерева, используя пакет R gbm:

a <- runif(100, 1, 100)
b <- runif(100, 1, 100)
c <- 1:100 + rnorm(100, mean = 0, sd = 5)
y <- 1:100 + rnorm(100, mean = 0, sd = 5)
par(mfrow = c(2,2))
plot(y ~ a); plot(y ~ b); plot(y ~ c)
Data <- data.frame(matrix(c(y, a, b, c), ncol = 4))
names(Data) <- c("y", "a", "b", "c")
library(gbm)
gbm.gaus <- gbm(y ~ a + b + c, data = Data, distribution = "gaussian")
par(mfrow = c(2,2))
plot(gbm.gaus, i.var = 1)
plot(gbm.gaus, i.var = 2)
plot(gbm.gaus, i.var = 3)

Неудивительно, что для переменных a и b графики частичной зависимости дают горизонтальные линии вокруг среднего значения a . Что меня озадачивает, так это сюжет для переменной c . Я получаю горизонтальные линии для диапазонов c <40 и c > 60, а ось y ограничена значениями, близкими к среднему значению y . Так как a и b совершенно не связаны с y (и, следовательно, значение переменной в модели равно 0), я ожидал, что cпоказал бы частичную зависимость по всему ее диапазону вместо этой сигмовидной формы для очень ограниченного диапазона его значений. Я попытался найти информацию в Friedman (2001) «Приближение функции жадности: машина повышения градиента» и в Hastie et al. (2011) «Элементы статистического обучения», но мои математические навыки слишком низки, чтобы понять все уравнения и формулы в них. Таким образом, мой вопрос: что определяет форму графика частичной зависимости для переменной с ? (Пожалуйста, объясните словами, понятными для нематематика!)

ДОБАВЛЕНО 17 апреля 2014 года:

В ожидании ответа я использовал те же данные примера для анализа с помощью R-пакета randomForest. Графики частичной зависимости randomForest намного больше напоминают то, что я ожидал от графиков gbm: частичная зависимость объясняющих переменных a и b изменяется случайным образом и близко к 50, в то время как объясняющая переменная c показывает частичную зависимость во всем ее диапазоне (и почти над весь диапазон у ). Каковы могут быть причины этих различных форм графиков частичной зависимости в gbmи randomForest?

частичные участки gbm и randomForest

Вот модифицированный код, который сравнивает графики:

a <- runif(100, 1, 100)
b <- runif(100, 1, 100)
c <- 1:100 + rnorm(100, mean = 0, sd = 5)
y <- 1:100 + rnorm(100, mean = 0, sd = 5)
par(mfrow = c(2,2))
plot(y ~ a); plot(y ~ b); plot(y ~ c)
Data <- data.frame(matrix(c(y, a, b, c), ncol = 4))
names(Data) <- c("y", "a", "b", "c")

library(gbm)
gbm.gaus <- gbm(y ~ a + b + c, data = Data, distribution = "gaussian")

library(randomForest)
rf.model <- randomForest(y ~ a + b + c, data = Data)

x11(height = 8, width = 5)
par(mfrow = c(3,2))
par(oma = c(1,1,4,1))
plot(gbm.gaus, i.var = 1)
partialPlot(rf.model, Data[,2:4], x.var = "a")
plot(gbm.gaus, i.var = 2)
partialPlot(rf.model, Data[,2:4], x.var = "b")
plot(gbm.gaus, i.var = 3)
partialPlot(rf.model, Data[,2:4], x.var = "c")
title(main = "Boosted regression tree", outer = TRUE, adj = 0.15)
title(main = "Random forest", outer = TRUE, adj = 0.85)
user7417
источник
1
Возможно, вы захотите настроить гиперпараметры одним касанием. Я не уверен, какое количество деревьев по умолчанию указано в гбм, но оно может быть настолько маленьким, что не успевает выучить здоровую кривизну.
Ши Паркс
@Shea Parkes - Ты прав. Число деревьев по умолчанию составляет 100, что было недостаточно для создания хорошей модели. С 2000 деревьями участки частичной зависимости gbm и случайного леса практически идентичны.
user7417

Ответы:

7

Я потратил некоторое время на написание своего собственного «partfunction-plotter», прежде чем понял, что он уже включен в библиотеку R randomForest.

[РЕДАКТИРОВАТЬ ... но затем я потратил год на создание пакета CRAN forestFloor , который, по моему мнению, значительно лучше, чем классические графики частичной зависимости]

График Partial.function великолепен в тех случаях, когда этот пример моделирования показан здесь, где объясняющая переменная не взаимодействует с другими переменными. Если каждая объясняющая переменная вносит дополнительный вклад в target-Y какой-то неизвестной функцией, этот метод отлично подходит для демонстрации этой оцененной скрытой функции. Я часто вижу такое выравнивание в границах частичных функций.

Некоторые причины: randomForsest имеет аргумент под названием «nodeize = 5», что означает, что ни одно дерево не будет подразделять группу из 5 или менее членов. Поэтому каждое дерево не может различаться с большей точностью. Слой мешков / начальной загрузки сглаживает, голосуя за многие пошаговые функции отдельных деревьев - но только в середине области данных. При приближении к границам данных, представленных в пространстве, «амплитуда» частичной функции будет падать. Установка nodeize = 3 и / или получение большего количества наблюдений по сравнению с шумом может уменьшить этот эффект выравнивания границ ... Когда отношение сигнал / шум в общем случае падает в случайном лесу, шкала прогнозов сокращается. Таким образом, прогнозы не являются абсолютно точными терминами, а только линейно связаны с целью. Вы можете увидеть значения a и b в качестве примеров и чрезвычайно низкого отношения сигнал / шум, и поэтому эти частичные функции очень плоские. Это хорошая особенность случайного леса, что вы уже из диапазона предсказаний обучающего набора можете догадаться, насколько хорошо работает модель. OOB.прогноз также велик ..

Выравнивание частичного графика в регионах без данных является разумным: поскольку случайный лес и CART являются моделированием на основе данных, мне лично нравится концепция, что эти модели не экстраполируют. Таким образом, прогноз с = 500 или с = 1100 точно такой же, как с = 100, или в большинстве случаев также с = 98.

Вот пример кода с уменьшенной границей границы:

Я не пробовал пакет gbm ...

Вот несколько иллюстративных кодов, основанных на вашем примере ...

#more observations are created...
a <- runif(5000, 1, 100)
b <- runif(5000, 1, 100)
c <- (1:5000)/50 + rnorm(100, mean = 0, sd = 0.1)
y <- (1:5000)/50 + rnorm(100, mean = 0, sd = 0.1)
par(mfrow = c(1,3))
plot(y ~ a); plot(y ~ b); plot(y ~ c)
Data <- data.frame(matrix(c(y, a, b, c), ncol = 4))
names(Data) <- c("y", "a", "b", "c")
library(randomForest)
#smaller nodesize "not as important" when there number of observartion is increased
#more tress can smooth flattening so boundery regions have best possible signal to             noise, data specific how many needed

plot.partial = function() {
partialPlot(rf.model, Data[,2:4], x.var = "a",xlim=c(1,100),ylim=c(1,100))
partialPlot(rf.model, Data[,2:4], x.var = "b",xlim=c(1,100),ylim=c(1,100))
partialPlot(rf.model, Data[,2:4], x.var = "c",xlim=c(1,100),ylim=c(1,100))
}

#worst case! : with 100 samples from Data and nodesize=30
rf.model <- randomForest(y ~ a + b + c, data = Data[sample(5000,100),],nodesize=30)
plot.partial()

#reasonble settings for least partial flattening by few observations: 100 samples and nodesize=3 and ntrees=2000
#more tress can smooth flattening so boundery regions have best possiblefidelity
rf.model <- randomForest(y ~ a + b + c, data = Data[sample(5000,100),],nodesize=5,ntress=2000)
plot.partial()

#more observations is great!
rf.model <- randomForest(y ~ a + b + c,
 data = Data[sample(5000,5000),],
 nodesize=5,ntress=2000)
plot.partial()
Сорен Хавелунд Веллинг
источник
4

Как упоминалось в комментариях выше, модель gbm была бы лучше с некоторой настройкой параметров. Простой способ выявить проблемы в модели и необходимость таких параметров - это создать некоторые диагностические графики. Например, для приведенной выше модели gbm с параметрами по умолчанию (и с использованием пакета plotmo для создания графиков) мы имеем

gbm.gaus <- gbm(y~., data = Data, dist = "gaussian")
library(plotmo)   # for the plotres function
plotres(gbm.gaus) # plot the error per ntrees and the residuals

который дает

участок

На графике слева мы видим, что кривая ошибки не достигла дна. И на графике справа остатки не то, что мы хотели бы.

Если мы перестроим модель с большим количеством деревьев

gbm.gaus1 <- gbm(y~., data = Data, dist = "gaussian",
                 n.trees=5000, interact=3)
plotres(gbm.gaus1)

мы получаем

участок

Мы видим кривую погрешности с большим количеством деревьев, а график остатков более здоровый. Мы также можем построить графики частичной зависимости для новой модели gbm и модели случайного леса

library(plotmo)
plotmo(gbm.gaus1, pmethod="partdep", all1=TRUE, all2=TRUE)
plotmo(rf.model,  pmethod="partdep", all1=TRUE, all2=TRUE)

который дает

участок

Графики модели gbm и случайного леса теперь похожи, как и ожидалось.

Стивен Милборроу
источник
3

Вам нужно обновить ваш interaction.depthпараметр при создании вашей расширенной модели. По умолчанию он равен 1, и это приводит к тому, что все деревья, которые gbmстроит алгоритм, разделяются только по одному разу. Это будет означать, что каждое дерево просто разделяется на переменные, cи в зависимости от выборки наблюдений, которое оно использует, оно будет делиться где-то около 40 - 60.

Вот частичные участки с interaction.depth = 3

введите описание изображения здесь

Мэтт Миллс
источник
Хорошая мысль, это
Сорен Хавелунд Веллинг