Bosque aleatorio: ¿cómo manejar los nuevos niveles de factores en el conjunto de pruebas?

13

Estoy tratando de hacer predicciones usando un modelo de bosque aleatorio en R.

Sin embargo, obtengo errores ya que algunos factores tienen valores diferentes en el conjunto de prueba que en el conjunto de entrenamiento. Por ejemplo, un factor Cat_2tiene valores 34, 68, 76, etc., en el conjunto de prueba que no aparecen en el conjunto de entrenamiento. Desafortunadamente, no tengo control sobre el conjunto de prueba ... Debo usarlo como está.

Mi única solución fue convertir los factores problemáticos de nuevo a valores numéricos, usando as.numeric(). Se trabaja , pero no estoy muy satisfecho, ya que estos valores son códigos que no tienen ningún sentido numérico ...

¿Crees que habría otra solución, eliminar los nuevos valores del conjunto de prueba? Pero sin eliminar todos los demás valores de factores (digamos valores 1, 2, 14, 32, etc.) que se encuentran tanto en el entrenamiento como en la prueba, y que contienen información potencialmente útil para las predicciones.

Benoit_Plante
fuente
1
Veo saber por qué los valores en la prueba tendrían que estar en el conjunto de entrenamiento. La idea de la clasificación es utilizar los datos de entrenamiento para tener una idea de cómo son las densidades condicionales de clase. No puede ver todos los valores posibles de la densidad. Si se usa una variable en una división en un árbol, la división determina qué rama seguir para los valores invisibles y los que se han visto.
Michael R. Chernick
Usted hace un punto válido, pero en un nivel práctico usando la herramienta específica consultada (el paquete RF en R) esto no está permitido. Mi respuesta que implica la imputación es una forma de evitarlo, aunque ciertamente no es la mejor solución. Esto al menos hace que el código no se bloquee, por lo que al menos funciona, para pequeños valores de trabajo.
Bogdanovist
Similar a mi pregunta aquí: stats.stackexchange.com/questions/18004/… . Creo que podría usar GBM en lugar de RF, ya que parece tratar mejor los nuevos niveles de factores. Además, ¿has mirado la implementación de RF en la fiesta? Nunca me ha gustado randomForest debido a estos problemas (y la incapacidad de manejar sin problemas los valores perdidos).
B_Miner

Respuestas:

2

Si el conjunto de prueba tiene muchos de estos puntos con nuevos valores de factores, entonces no estoy seguro de cuál es el mejor enfoque. Si se trata solo de un puñado de puntos, es posible que pueda salirse con la suya como tratar los niveles de factores errantes como datos faltantes e imputarlos con el enfoque que considere adecuado. La implementación de R tiene un par de formas de imputar datos faltantes, solo necesita establecer estos niveles de factor en NA para indicar que faltan.

Bogdanovist
fuente
8

King y Bonoit , este fragmento puede ser útil para armonizar niveles:

for(attr in colnames(training))
{
  if (is.factor(training[[attr]]))
  {
    new.levels <- setdiff(levels(training[[attr]]), levels(testing[[attr]]))
    if ( length(new.levels) == 0 )
    { print(paste(attr, '- no new levels')) }
    else
    {
      print(c(paste(attr, length(new.levels), 'of new levels, e.g.'), head(new.levels, 2)))
      levels(testing[[attr]]) <- union(levels(testing[[attr]]), levels(training[[attr]]))
    }
  }
}

También imprime qué atributos se cambian. No encontré una buena manera de escribirlo con más elegancia (con ldply o algo así). Cualquier consejo es apreciado.

usuario41330
fuente
4

Aquí hay un código que escribí que aborda la respuesta de @ King arriba. Se solucionó el error:

# loops through factors and standardizes the levels
for (f in 1:length(names(trainingDataSet))) {
    if (levels(testDataSet[,f]) > levels(trainingDataSet[,f])) {    
            levels(testDataSet[,f]) = levels(trainingDataSet[,f])       
    } else {
            levels(trainingDataSetSMOTEpred[,f]) = levels(testDataSet[,f])      
    }
}
lfarb
fuente
hola @ifarb, estoy tratando de entender tu solución: ¿qué es trainingDataSetSMOTEpred y dónde está definido en el código?
Kasia Kulma
3

El conjunto de prueba y entrenamiento debe combinarse como un conjunto y luego cambiar los niveles del conjunto de entrenamiento. Mis códigos son:

totalData <- rbind(trainData, testData)
for (f in 1:length(names(totalData))) {
  levels(trainData[, f]) <- levels(totalData[, f])
}

Esto funciona en cualquier caso donde el número de niveles en la prueba es más o menos que el entrenamiento.

Cscode Li
fuente
2

Tengo una solución pésima cuando uso randomForest en R. Probablemente no sea teóricamente sólido, pero hace que funcione.

levels(testSet$Cat_2) = levels(trainingSet$Cat_2)

O de otra forma. Básicamente, solo le dice a R que es un valor válido solo que hay 0 casos; así que deja de molestarme por el error.

No soy lo suficientemente inteligente como para codificarlo de modo que realice automáticamente la acción para todas las características categóricas. Envíame el código si sabes cómo ...

Rey
fuente
Pero esto no funciona si el número de niveles en la prueba es más que entrenamiento. Solo funciona si los niveles de factor de datos de prueba son <= niveles de factor de datos de entrenamiento.
KarthikS
1

Estoy seguro de que ya lo habría pensado si este fuera el caso, pero si el conjunto de prueba tiene valores reales y está utilizando el conjunto de prueba para fines de validación cruzada, luego vuelva a dividir el marco de datos en marcos de datos de entrenamiento y prueba donde los dos están equilibrados en estos factores evitaría su problema. Este método se conoce popularmente como validación cruzada estratificada .

goldisfine
fuente