Paquete R para bosque aleatorio ponderado? opción classwt?

16

Estoy tratando de usar Random Forest para predecir el resultado de un conjunto de datos extremadamente desequilibrado (la tasa de clase minoritaria es de solo 1% o incluso menos). Debido a que el algoritmo tradicional de bosque aleatorio minimiza la tasa de error general, en lugar de prestar especial atención a las clases minoritarias, no es directamente aplicable a los datos desequilibrados. Así que quiero asignar un alto costo a la clasificación errónea de la clase minoritaria (aprendizaje sensible al costo).

He leído varias fuentes que podemos utilizar la opción classwtde randomForesten R, pero no sé cómo usar esto. ¿Y tenemos alguna otra alternativa a la randomForestfunción?

Metariado
fuente

Respuestas:

29

Este hilo se refiere a otros dos hilos y un buen artículo sobre este asunto. Parece que la ponderación de clase y la disminución de la resolución son igualmente buenas. Yo uso la disminución de resolución como se describe a continuación.

Recuerde que el conjunto de entrenamiento debe ser grande ya que solo el 1% caracterizará la clase rara. Menos de 25 ~ 50 muestras de esta clase probablemente serán problemáticas. Pocas muestras que caracterizan a la clase inevitablemente harán que el patrón aprendido sea crudo y menos reproducible.

RF utiliza el voto mayoritario por defecto. Las prevalencias de clase del conjunto de entrenamiento funcionarán como algún tipo de previo efectivo. Por lo tanto, a menos que la clase rara sea perfectamente separable, es poco probable que esta clase rara gane una mayoría de votos al predecir. En lugar de agregar por voto mayoritario, puede agregar fracciones de voto.

El muestreo estratificado se puede utilizar para aumentar la influencia de la clase rara. Esto se hace con el costo de reducir el muestreo de las otras clases. Los árboles crecidos serán menos profundos ya que se deben dividir muchas menos muestras, lo que limita la complejidad del patrón potencial aprendido. El número de árboles cultivados debe ser grande, por ejemplo, 4000, de modo que la mayoría de las observaciones participen en varios árboles.

En el siguiente ejemplo, he simulado un conjunto de datos de entrenamiento de 5000 muestras con 3 clases con prevalencias de 1%, 49% y 50% respectivamente. Por lo tanto, habrá 50 muestras de la clase 0. La primera figura muestra la verdadera clase de conjunto de entrenamiento en función de dos variables x1 y x2. Esta imagen muestra el patrón simulado para aprender

Se capacitaron cuatro modelos: un modelo predeterminado y tres modelos estratificados con estratificación de clases 1:10:10 1: 2: 2 y 1: 1: 1. Principal mientras que el número de muestras de bolsa (incl. Redibujos) en cada árbol será de 5000, 1050, 250 y 150. Como no uso el voto mayoritario, no necesito hacer una estratificación perfectamente equilibrada. En cambio, los votos en clases raras podrían ponderarse 10 veces o alguna otra regla de decisión. Su costo de falsos negativos y falsos positivos debe influir en esta regla.

La siguiente figura muestra cómo la estratificación influye en las fracciones de voto. Observe que las relaciones de clase estratificadas siempre son el centroide de las predicciones. estratificación y votación

Por último, puede usar una curva ROC para encontrar una regla de votación que le ofrezca un buen equilibrio entre especificidad y sensibilidad. La línea negra no es estratificación, la roja 1: 5: 5, la verde 1: 2: 2 y la azul 1: 1: 1. Para este conjunto de datos 1: 2: 2 o 1: 1: 1 parece la mejor opción. curva roc

Por cierto, las fracciones de voto están aquí fuera de bolsa con validación cruzada.

Y el código:

library(plotrix)
library(randomForest)
library(AUC)

make.data = function(obs=5000,vars=6,noise.factor = .2,smallGroupFraction=.01) {
X = data.frame(replicate(vars,rnorm(obs)))
yValue = with(X,sin(X1*pi)+sin(X2*pi*2)+rnorm(obs)*noise.factor)
yQuantile = quantile(yValue,c(smallGroupFraction,.5))
yClass = apply(sapply(yQuantile,function(x) x<yValue),1,sum)
yClass = factor(yClass)
print(table(yClass)) #five classes, first class has 1% prevalence only
Data=data.frame(X=X,y=yClass)
}

plot.separation = function(rf,...) {
triax.plot(rf$votes,...,col.symbols = c("#FF0000FF",
                                       "#00FF0010",
                                       "#0000FF10")[as.numeric(rf$y)])
}

#make data set where class "0"(red circles) are rare observations
#Class 0 is somewhat separateble from class "1" and fully separateble from class "2"
Data = make.data()
par(mfrow=c(1,1))
plot(Data[,1:2],main="separation problem: identify rare red circles",
     col = c("#FF0000FF","#00FF0020","#0000FF20")[as.numeric(Data$y)])

#train default RF and with 10x 30x and 100x upsumpling by stratification
rf1 = randomForest(y~.,Data,ntree=500, sampsize=5000)
rf2 = randomForest(y~.,Data,ntree=4000,sampsize=c(50,500,500),strata=Data$y)
rf3 = randomForest(y~.,Data,ntree=4000,sampsize=c(50,100,100),strata=Data$y)
rf4 = randomForest(y~.,Data,ntree=4000,sampsize=c(50,50,50)  ,strata=Data$y)

#plot out-of-bag pluralistic predictions(vote fractions).
par(mfrow=c(2,2),mar=c(4,4,3,3))
plot.separation(rf1,main="no stratification")
plot.separation(rf2,main="1:10:10")
plot.separation(rf3,main="1:5:5")
plot.separation(rf4,main="1:1:1")

par(mfrow=c(1,1))
plot(roc(rf1$votes[,1],factor(1 * (rf1$y==0))),main="ROC curves for four models predicting class 0")
plot(roc(rf2$votes[,1],factor(1 * (rf1$y==0))),col=2,add=T)
plot(roc(rf3$votes[,1],factor(1 * (rf1$y==0))),col=3,add=T)
plot(roc(rf4$votes[,1],factor(1 * (rf1$y==0))),col=4,add=T)
Soren Havelund Welling
fuente
oups leyenda de una figura dice 1: 5: 5 en lugar de 1: 2: 2
Soren Havelund Welling
Muchas gracias por su respuesta detallada, eso definitivamente me ayudará mucho en mi trabajo diario. Hay una oración que no entiendo: "Principal, mientras que el número de muestras de bolsa (incl. Redibujos) en cada árbol será 5000,1050, 250 y 150". ¿Podría explicarme de dónde provienen los números?
Metariat
1
es un placer;) en este ejemplo la clase rara tenía 50 miembros. Si estratificamos 1:10:10, deberíamos especificar sampsize = c (50,500,500). 50 + 500 + 500 = 1050. Un árbol completamente desarrollado de 1050 muestras tendrá nodos de 1050x2 en total.
Soren Havelund Welling
Lo siento si mi pregunta es idiota, pero ¿qué significa 1:10:10, 1: 2: 2 y 1: 1: 1 estratificación aquí? Y cuando dijiste "los votos en clases raras podrían ponderarse 10 veces". ¿Qué parte del código representa eso? ¿Es la 1:10:10? ¡Muchas gracias!
Metariat
1
1:10:10 son las proporciones entre las clases. El conjunto de datos simulados fue diseñado para tener las proporciones 1:49:50. Estas proporciones se modificaron mediante un muestreo descendente de las dos clases más grandes. Al elegir, por ejemplo, sampsize = c (50,500,500) lo mismo que c (1,10,10) * 50, cambia las proporciones de clase en los árboles. 50 es el número de muestras de la clase rara. Si además establece keep.inbag = TRUE e inspecciona rf $ inbag, verá que las muestras de las clases raras están en inbag en ~ 2/3 árboles, mientras que cada muestra de clase no rara se incluye en muy pocos árboles debido al muestreo descendente.
Soren Havelund Welling