R's randomForest no puede manejar más de 32 niveles. ¿Qué es la solución?

22

El paquete randomForest de R no puede manejar factores con más de 32 niveles. Cuando se le dan más de 32 niveles, emite un mensaje de error:

No puede manejar predictores categóricos con más de 32 categorías.

Pero los datos que tengo tienen varios factores. Algunos de ellos tienen más de 1000 niveles y algunos de ellos tienen más de 100. Incluso tiene 'estado' de Estados Unidos que es 52.

Entonces, esta es mi pregunta.

  1. ¿Por qué hay tal limitación? randomForest se niega a correr incluso por el simple caso.

    > 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.
    

    Si se debe simplemente a una limitación de memoria, ¿cómo puede ejecutar scikit learn's randomForeestRegressor con más de 32 niveles?

  2. ¿Cuál es la mejor manera de manejar este problema? Supongamos que tengo X1, X2, ..., X50 variables independientes e Y es una variable dependiente. Y supongamos que X1, X2 y X3 tienen más de 32 niveles. ¿Qué tengo que hacer?

    Lo que estoy pensando es ejecutar un algoritmo de agrupación para cada uno de X1, X2 y X3, donde la distancia se define como la diferencia en Y. Ejecutaré tres agrupaciones ya que hay tres variables problemáticas. Y en cada agrupación, desearía poder encontrar niveles similares. Y los fusionaré.

    ¿Como suena esto?

Minkoo Seo
fuente
Buscar en la web con el nombre del paquete y el mensaje de error proporciona algunas respuestas.
Roland
55
@Roland En realidad me llevó aquí ...
isomorphismes
1
puede probar la ciencia de datos, ya que varias mentes estadísticas tienen experiencia en la programación de datos con muchas dimensiones.
aeroNotAuto
2
ACTUALIZACIÓN: desde la versión 4.6-9, randomForestpuede manejar predictores categóricos con hasta 53 niveles. Noticias
Ben
¿Cómo determina el bosque aleatorio de R el número de niveles? Supongo que nivel significa categorías.
ajp

Respuestas:

25

En realidad, es una restricción bastante razonable porque una división en un factor con niveles es en realidad una selección de una de las combinaciones posibles . Entonces, incluso con como 25, el espacio de combinaciones es tan grande que tal inferencia tiene menor sentido.2 N - 2 NN2N2N

La mayoría de las otras implementaciones simplemente tratan el factor como uno ordinal (es decir, enteros de 1 a ), y esta es una opción para resolver este problema. En realidad, RF suele ser lo suficientemente inteligente como para dividir esto en grupos arbitrarios con varias divisiones.N

La otra opción es cambiar la representación; tal vez su resultado no depende directamente de la entidad estatal, pero, por ejemplo, el área, la población, la cantidad de pinos per cápita u otros atributos que puede conectar a su sistema de información.

También puede ser que cada estado sea una entidad tan aislada y no correlacionada que requiera un modelo separado para sí mismo.

La agrupación basada en una decisión es probablemente una mala idea porque de esta manera se pasa de contrabando información de la decisión a atributos, lo que a menudo termina en un sobreajuste.


fuente
44
Se puede mover fácilmente, aunque de una manera un poco tediosa. Por ejemplo, si tiene entre 33 y 1024 niveles, cree dos factores cada uno de <= 32 niveles.
KalEl
15

La razón principal es cómo se implementa randomForest. La implementación de R sigue mucho de las especificaciones originales de Breiman. Es importante tener en cuenta que para los factores / variables categóricas, el criterio de división es binario con algunos valores de etiqueta a la izquierda y los valores de etiqueta restantes a la derecha.

Eso significa que busca todas las combinaciones de valores de etiquetas de agrupación en dos grupos. Si denota con el grupo izquierdo y con el grupo derecho y enumera para cada etiqueta un dígito, obtendrá un número en el rango combinaciones, lo cual es prohibitivo desde un punto de vista computacional .1 [ 0 ; 2 M - 1 ]01[0;2M1]

¿Por qué funcionan las implementaciones de Weka y Python?

La implementación de weka no usa árboles CART por defecto. Utiliza árboles C45 que no tienen este problema computacional, ya que para entradas categóricas se divide en múltiples nodos, uno para cada valor de nivel.

La implementación de bosque aleatorio python no puede usar variables categóricas / factoriales. Tiene que codificar esas variables en variables ficticias o numéricas.

Otras implementaciones pueden permitir múltiples niveles (incluido weka aquí) porque incluso si usan CART, no necesariamente implementan dosificación. Lo que significa que permiten encontrar la mejor división para una variable de factor solo al agrupar una etiqueta con todos los demás valores. Esto requiere mucho menos cómputo ya que solo necesita verificar puntos divididos.M

rapaio
fuente
2
¡Muchas gracias! ¿Se deduce de su respuesta que la implementación de R para tratar los valores categóricos es superior a la de Python (recuerdo que Max Kuhn mencionó que agrupar variables categóricas para RF proporciona resultados ligeramente mejores que dummificarlas), o al menos ejecutar Random Forest en R vs Python ¿Tengo muchas posibilidades de obtener resultados diferentes (precisiones, etc.)? Según su experiencia, al modelar, ¿tiene sentido intentar agrupar vars (en R) y dummificarlos y luego comparar dos enfoques?
Sergey Bushmanov
2
La codificación ficticia funciona pero solo puede producir una categoría frente a todas. Después de la codificación, las variables se prueban una a la vez. Entonces, es imposible implementar dosificación. Si esta característica puede ayudar, creo que prácticamente no hay grandes diferencias. Sin embargo, hay otras cosas que pueden requerir atención cuando se trabaja con importancia variable: algunas implementaciones están sesgadas hacia categorías con múltiples niveles. Consulte los documentos de Carolin Strobl para obtener más información: statistik.uni-dortmund.de/useR-2008/slides/Strobl+Zeileis.pdf . En R hay algunas implementaciones que no tienen este sesgo.
rapaio
2

Puede intentar representar esa columna de manera diferente. Podría representar los mismos datos que un marco de datos disperso.

Código mínimo viable;

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)
}

Observe cómo cada valor en la columna original ahora se convierte en una columna ficticia separada.

Código de ejemplo más extenso;

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 )

Aunque este código muestra que ya no recibirá el error, notará que el algoritmo randomForest ahora necesita mucho tiempo antes de que finalice. Esto se debe a una restricción de la CPU, ahora también puede reducir esta tarea a través del muestreo.

Para obtener más información, consulte esta publicación de blog:

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

Vincent Warmerdam
fuente
El segundo bloque de código parece confuso, aunque usa df_hard en todo el cuerpo, en las últimas líneas, establece "first" y "second" en NULL, y también usa "example" como datos para randomForest, esto no tiene sentido yo, ya que no hay conexión entre ejemplo y df_hard.
Özgür
Vincent, ¿no crees que terminaré con tantos problemas si tengo niveles del orden 100+, sugieres agregar cada columna como entrada al azar?
Hardik Gupta
Otra alternativa es usar la implementación randomforest en h2o; Esto tiene un mejor soporte para grandes conjuntos de datos. No entiendo el bit "agregar cada columna como entrada al azar".
Vincent Warmerdam el
0

Puede usar el paquete extraTrees en su lugar. El algoritmo de bosques extremadamente aleatorio no prueba ningún punto de ruptura / división, sino solo un subconjunto aleatorio limitado de divisiones.

Soren Havelund Welling
fuente
1
extraTrees tiene limitaciones, en el sentido de que su entrada debe ser una matriz de datos numéricos, ¿verdad?
Hardik Gupta
0

Otra opción: dependiendo de la cantidad de niveles y la cantidad de observaciones en sus datos, podría fusionar algunos niveles. Más allá de llegar al límite, puede reducir la varianza si tiene muchos niveles con solo unas pocas observaciones. Los forcats de Hadley : fct_lump hace esto.

Scott Kaiser
fuente