R's randomForest не может обрабатывать более 32 уровней. Что такое обходной путь?

22

R-пакет randomForest не может обрабатывать фактор с более чем 32 уровнями. Когда ему дается более 32 уровней, выдается сообщение об ошибке:

Не может обрабатывать категориальные предикторы с более чем 32 категориями.

Но у меня есть несколько факторов. Некоторые из них имеют более 1000 уровней, а некоторые - более 100. У этого даже есть 'государство' Соединенных Штатов, которое является 52.

Итак, вот мой вопрос.

  1. Почему существует такое ограничение? randomForest отказывается работать даже для простого случая.

    > d <- data.frame(x=factor(1:50), y=1:50)
    > randomForest(y ~ x, data=d)
      Error in randomForest.default(m, y, ...) : 
      Can not handle categorical predictors with more than 32 categories.
    

    Если это просто из-за ограничения памяти, как может SciKit Learn случайныйForeestRegressor работать с более чем 32 уровнями?

  2. Каков наилучший способ справиться с этой проблемой? Предположим, что у меня есть независимые переменные X1, X2, ..., X50, а Y - зависимая переменная. И предположим, что X1, X2 и X3 имеет более 32 уровней. Что мне делать?

    Я думаю о том, чтобы запустить алгоритм кластеризации для каждого из X1, X2 и X3, где расстояние определяется как разница в Y. Я проведу три кластеризации, так как есть три проблемные переменные. И в каждой кластеризации я бы хотел найти похожие уровни. И я объединю их.

    Как это звучит?

Минко Сео
источник
Поиск в Интернете по имени пакета и сообщению об ошибке дает некоторые ответы.
Роланд
5
@Roland На самом деле это привело меня сюда ...
isomorphismes
1
Вы можете попробовать себя в науке о данных, поскольку у нескольких статистических специалистов есть опыт программирования данных для многих измерений.
aeroNotAuto
2
ОБНОВЛЕНИЕ: начиная с версии 4.6-9, randomForestможет обрабатывать категориальные предикторы до 53 уровней. Новости
Бен
Как случайный лес R определяет количество уровней? Я думаю, уровень означает категории.
AJP

Ответы:

25

На самом деле это довольно разумное ограничение, потому что разделение на фактор с уровнями - это на самом деле выбор одной из 2 N - 2 возможных комбинаций. Так что даже с N, как 25, пространство комбинаций настолько велико, что такой вывод имеет незначительный смысл.N2N-2N

Большинство других реализаций просто рассматривают фактор как порядковый (т. Е. Целые числа от 1 до ), и это один из вариантов, как вы можете решить эту проблему. На самом деле RF часто бывает достаточно мудрым, чтобы разделить это на произвольные группы с несколькими разбиениями.N

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

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

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


источник
4
Это может быть легко перемещено, хотя немного утомительным способом. Например, если у вас есть от 33 до 1024 уровней, создайте два фактора, каждый из которых <= 32 уровня.
KalEl
15

Основная причина в том, как реализован randomForest. Реализация из R во многом вытекает из оригинальных спецификаций Бреймана. Здесь важно отметить, что для факторных / категориальных переменных критерий разделения является двоичным с некоторыми значениями меток слева, а остальные значения меток справа.

01[0;2M-1]

Почему работает реализация от Weka и Python?

Реализация weka по умолчанию не использует деревья CART. Он использует деревья C45, у которых нет этой вычислительной проблемы, поскольку для категориальных входных данных он разделяется на несколько узлов, по одному на каждое значение уровня.

Реализация случайного леса Python не может использовать категориальные / факторные переменные. Вы должны закодировать эти переменные в фиктивные или числовые переменные.

M

rapaio
источник
2
Большое спасибо! Из вашего ответа следует, что реализация R для обработки категориальных значений превосходит реализацию Python (я помню, что Макс Кун упомянул, что группировка категориальных переменных для RF дает несколько лучшие результаты, чем их дублирование), или, по крайней мере, случайный лес в R против Python У меня очень хорошие шансы получить разные результаты (точность и т. Д.)? Из вашего опыта, при моделировании, имеет ли смысл пробовать как группирование переменных (в R), так и их дублирование, а затем сравнивать два подхода?
Сергей Бушманов
2
Фиктивное кодирование работает, но оно может создать только одну категорию против всех. После кодирования переменные проверяются по одному за раз. Таким образом, невозможно реализовать дублирование. Если эта функция может помочь, я думаю, что практически нет больших различий. Однако есть и другие вещи, которые могут требовать внимания при работе с переменной важностью: некоторые реализации смещены в сторону категориальности с несколькими уровнями. Подробности см. В статьях Каролин Штробл: statistik.uni-dortmund.de/useR-2008/slides/Strobl+Zeileis.pdf . В R есть несколько реализаций, которые не имеют этого смещения.
Рапайо
2

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

Минимальный жизнеспособный код;

example <- as.data.frame(c("A", "A", "B", "F", "C", "G", "C", "D", "E", "F"))
names(example) <- "strcol"

for(level in unique(example$strcol)){
      example[paste("dummy", level, sep = "_")] <- ifelse(example$strcol == level,     1, 0)
}

Обратите внимание, что каждое значение в исходном столбце теперь становится отдельным фиктивным столбцом.

Более обширный пример кода;

set.seed(0)
combs1 = sample.int(33, size= 10000, replace=TRUE)
combs2 = sample.int(33, size= 10000, replace=TRUE)
combs3 = combs1 * combs2 + rnorm(10000,mean=0,100)
df_hard = data.frame(y=combs3, first=factor(combs1), second=factor(combs2))

for(level in unique(df_hard$first)){
    df_hard[paste("first", level, sep = "_")] <- ifelse(df_hard$first == level, 1, 0)
}

for(level in unique(df_hard$second)){
    df_hard[paste("second", level, sep = "_")] <- ifelse(df_hard$second == level, 1, 0)
}

example$first <- NULL
example$second <- NULL

rf_mod = randomForest( y ~ ., data=example )

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

Для получения дополнительной информации, пожалуйста, проверьте этот блог пост:

https://blog.cloudera.com/blog/2013/02/how-to-resample-from-a-large-data-set-in-parallel-with-r-on-hadoop/

Винсент Вармердам
источник
Второй блок кода выглядит сбивающим с толку, хотя вы используете df_hard по всему телу, в последних строках вы устанавливаете «first» и «second» в NULL, а также используете «example» в качестве данных для randomForest, но это не имеет смысла меня, так как нет никакой связи между примером и df_hard.
Озгюр
Винсент, ты не чувствуешь, что у меня будут такие большие проблемы, если у меня будет уровни порядка 100+, ты предлагаешь добавлять каждый столбец в качестве входных данных в случайный?
Хардик Гупта
Другой альтернативой является использование реализации randomforest в h2o; это лучше поддерживает большие наборы данных. Я не понимаю бит «добавить каждый столбец в качестве входных данных в случайный».
Винсент Вармердам
0

Вместо этого вы можете использовать пакет extraTrees. Алгоритм крайне рандомизированных лесов не пробует какую-либо точку останова / разбиение, а только ограниченное случайное подмножество разбиений.

Сорен Хавелунд Веллинг
источник
1
У extraTrees есть ограничение, в том смысле, что ваш ввод должен быть числовой матрицей данных, верно?
Хардик Гупта
0

Другой вариант: в зависимости от количества уровней и количества наблюдений в ваших данных, вы можете объединить несколько уровней. Помимо превышения предела, это может уменьшить дисперсию, если у вас много уровней с несколькими наблюдениями. Hadley «S forcats: fct_lump делает это.

Скотт Кайзер
источник