Как я могу ускорить обучение моего случайного леса?

я пытаюсь обучить несколько случайных лесов (для регрессии), чтобы они конкурировали и видели, какой выбор функций и какие параметры дают лучшую модель.

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

набор данных, который я использую для тренировок (так называемый train ниже) имеет 217k строк и 58 столбцов (из которых только 21 служат предикторами в случайном лесу. Они все numeric или integer, за исключением логического, который имеет класс character. The y выход numeric).

я побежал следующий код четыре раза, давая значения 4, 100, 500, 2000 to nb_trees :

library("randomForest")
nb_trees <- #this changes with each test, see above
ptm <- proc.time()
fit <- randomForest(y ~ x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 
    + x10 + x11 + x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19 
    + x20 + x21, 
    data = train, 
    ntree = nb_trees, 
    do.trace=TRUE)
proc.time() - ptm

вот сколько времени каждый из них взял, чтобы тренироваться:

nb_trees | time
4          4mn
100        1h 41mn
500        8h 40mn
2000       34h 26mn

поскольку сервер моей компании имеет 12 ядер и 125Go ОЗУ, я решил, что могу попытаться распараллелить обучение, следуя ответ (впрочем, я использовал the doParallel пакет, потому что он, казалось, работает вечно с doSNOW, я не знаю, почему. И я не могу найти, где я это видел!--15--> тоже будет работать, к сожалению).

library("randomForest")
library("foreach")
library("doParallel")
nb_trees <- #this changes with each test, see table below
nb_cores <- #this changes with each test, see table below
cl <- makeCluster(nb_cores)
registerDoParallel(cl)
ptm <- proc.time()
fit <- foreach(ntree = rep(nb_trees, nb_cores), .combine = combine, .packages = "randomForest") 
    %dopar% {
        randomForest(y ~ x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 
        + x10 + x11 + x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19 
        + x20 + x21,
        data = train, 
        ntree = ntree,
        do.trace=TRUE)}
proc.time() - ptm
stopCluster(cl)

когда я запускаю его, он занимает меньше времени, чем не распараллеливают код :

nb_trees | nb_cores | total number of trees              | time
1          4          4                                    2mn13s
10         10         100                                  52mn
9          12         108 (closest to 100 with 12 cores)   59mn
42         12         504 (closest to 500 with 12 cores)   I won't be running this one
167        12         2004 (closest to 2000 with 12 cores) I'll run it next week-end

тем не менее, я думаю, что это все еще занимает много времени, не так ли ? Я знаю, что требуется время, чтобы объединить деревья в окончательный лес, поэтому я не ожидал, что он будет в 12 раз быстрее с 12 ядрами, но это всего лишь ~2 в разы быстрее...

  • это нормально ?
  • если это не так, есть ли что-нибудь, что я могу сделать с моими данными и/или моим кодом, чтобы радикально уменьшить время работы ?
  • если нет, должен ли я сказать парню, отвечающему за сервер, что он должен быть намного быстрее ?

Спасибо за ваши ответы.

Примечания :

  • я единственный, кто использует этот сервер
  • для моих следующих тестов, я избавлюсь от столбцы, которые не используются в случайном лесу
  • я довольно поздно понял, что могу улучшить время работы, позвонив randomForest(predictors,decision) вместо randomForest(decision~.,data=input), и я буду делать это теперь, но я думаю, что мои вопросы выше все еще держит.

2 ответов


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

в то время как обучение вашего случайного леса с использованием 2000 деревьев начинало становиться непомерно дорогим, обучение с меньшим количеством деревьев заняло более разумное время. Для начала, вы можете тренироваться с Сказать 4, 8, 16, 32, ..., 256, 512 деревья и тщательно соблюдать показатели, которые позволяют вам знать, насколько надежна модель. Эти показатели включают в себя такие вещи, как лучшая постоянная модель (насколько хорошо ваш лес выполняет набор данных по сравнению с моделью, которая предсказывает медиану для всех входных данных), а также ошибку из мешка. Кроме того, вы можете наблюдать верхние предикторы и их важность, и начинаете ли вы видеть сходимость там, как вы добавляете больше деревьев.

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

посмотреть значение переменной после каждого random forest run, вы можете попробовать что-то вроде следующего:

fit <- randomForest(...)
round(importance(fit), 2)

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


на randomForest() функция может признавать данные используя или "интерфейс формулы"или" интерфейс матрицы". Известно, что матричный интерфейс обеспечивает гораздо лучшие показатели производительности.

Формула интерфейса:

rf.formula = randomForest(Species ~ ., data = iris)

Матрица интерфейс:

rf.matrix = randomForest(y = iris[, 5], x = iris[, 1:4])