¿Las predicciones de un modelo de bosque aleatorio tienen un intervalo de predicción?

52

Si ejecuto un randomForestmodelo, puedo hacer predicciones basadas en el modelo. ¿Hay alguna manera de obtener un intervalo de predicción de cada una de las predicciones de modo que sepa cuán "seguro" es el modelo de su respuesta? Si esto es posible, ¿se basa simplemente en la variabilidad de la variable dependiente para todo el modelo o tendrá intervalos más amplios y más estrechos dependiendo del árbol de decisión particular que se siguió para una predicción particular?

Dean MacGregor
fuente
3
AFAIK, todas las bibliotecas de RF tienen algún tipo de scorefunción para evaluar el rendimiento. Dado que el resultado se basa en el voto mayoritario de los árboles en el bosque, en caso de clasificación, le dará una probabilidad de que este resultado sea verdadero, en función de la distribución del voto. Sin embargo, no estoy seguro de la regresión ... ¿Qué biblioteca utilizas?
sashkello
1
Deberías leer esto: stats.stackexchange.com/questions/12425/…
0asa

Respuestas:

40

Esto es en parte una respuesta a @Sashikanth Dareddy (ya que no cabe en un comentario) y en parte una respuesta a la publicación original.

Recuerde lo que es un intervalo de predicción, es un intervalo o un conjunto de valores en el que predecimos que se ubicarán las observaciones futuras. Generalmente, el intervalo de predicción tiene 2 piezas principales que determinan su ancho, una pieza que representa la incertidumbre sobre la media pronosticada (u otro parámetro), esta es la parte del intervalo de confianza, y una pieza que representa la variabilidad de las observaciones individuales en torno a esa media. El intervalo de confianza es robusto debido al Teorema del límite central y, en el caso de un bosque aleatorio, el arranque también ayuda. Pero el intervalo de predicción depende completamente de los supuestos sobre cómo se distribuyen los datos dadas las variables predictoras, CLT y bootstrapping no tienen efecto en esa parte.

El intervalo de predicción debe ser más amplio donde el intervalo de confianza correspondiente también sería más amplio. Otras cosas que afectarían el ancho del intervalo de predicción son suposiciones sobre igual varianza o no, esto tiene que venir del conocimiento del investigador, no del modelo de bosque aleatorio.

Un intervalo de predicción no tiene sentido para un resultado categórico (podría hacer un conjunto de predicción en lugar de un intervalo, pero la mayoría de las veces probablemente no sería muy informativo).

Podemos ver algunos de los problemas relacionados con los intervalos de predicción simulando datos donde sabemos la verdad exacta. Considere los siguientes datos:

set.seed(1)

x1 <- rep(0:1, each=500)
x2 <- rep(0:1, each=250, length=1000)

y <- 10 + 5*x1 + 10*x2 - 3*x1*x2 + rnorm(1000)

Estos datos particulares siguen los supuestos para una regresión lineal y son bastante sencillos para un ajuste aleatorio del bosque. Sabemos por el modelo "verdadero" que cuando ambos predictores son 0 que la media es 10, también sabemos que los puntos individuales siguen una distribución normal con una desviación estándar de 1. Esto significa que el intervalo de predicción del 95% basado en el conocimiento perfecto para estos puntos serían de 8 a 12 (bueno, en realidad 8.04 a 11.96, pero el redondeo lo hace más simple). Cualquier intervalo de predicción estimado debe ser más amplio que esto (no tener información perfecta agrega ancho para compensar) e incluir este rango.

Veamos los intervalos de regresión:

fit1 <- lm(y ~ x1 * x2)

newdat <- expand.grid(x1=0:1, x2=0:1)

(pred.lm.ci <- predict(fit1, newdat, interval='confidence'))
#        fit       lwr      upr
# 1 10.02217  9.893664 10.15067
# 2 14.90927 14.780765 15.03778
# 3 20.02312 19.894613 20.15162
# 4 21.99885 21.870343 22.12735

(pred.lm.pi <- predict(fit1, newdat, interval='prediction'))
#        fit      lwr      upr
# 1 10.02217  7.98626 12.05808
# 2 14.90927 12.87336 16.94518
# 3 20.02312 17.98721 22.05903
# 4 21.99885 19.96294 24.03476

Podemos ver que existe cierta incertidumbre en las medias estimadas (intervalo de confianza) y eso nos da un intervalo de predicción que es más amplio (pero incluye) el rango de 8 a 12.

Ahora veamos el intervalo basado en las predicciones individuales de árboles individuales (deberíamos esperar que estos sean más amplios ya que el bosque aleatorio no se beneficia de los supuestos (que sabemos que son ciertos para estos datos) que sí hace la regresión lineal):

library(randomForest)
fit2 <- randomForest(y ~ x1 + x2, ntree=1001)

pred.rf <- predict(fit2, newdat, predict.all=TRUE)

pred.rf.int <- apply(pred.rf$individual, 1, function(x) {
  c(mean(x) + c(-1, 1) * sd(x), 
  quantile(x, c(0.025, 0.975)))
})

t(pred.rf.int)
#                           2.5%    97.5%
# 1  9.785533 13.88629  9.920507 15.28662
# 2 13.017484 17.22297 12.330821 18.65796
# 3 16.764298 21.40525 14.749296 21.09071
# 4 19.494116 22.33632 18.245580 22.09904

Los intervalos son más amplios que los intervalos de predicción de regresión, pero no cubren todo el rango. Incluyen los valores verdaderos y, por lo tanto, pueden ser legítimos como intervalos de confianza, pero solo predicen dónde está la media (valor predicho), no la pieza agregada para la distribución alrededor de esa media. Para el primer caso donde x1 y x2 son ambos 0, los intervalos no van por debajo de 9.7, esto es muy diferente del verdadero intervalo de predicción que baja a 8. Si generamos nuevos puntos de datos, habrá varios puntos (mucho más del 5%) que se encuentran en los intervalos verdadero y de regresión, pero no se encuentran en los intervalos aleatorios del bosque.

Para generar un intervalo de predicción necesitará hacer algunas suposiciones fuertes sobre la distribución de los puntos individuales alrededor de los medios pronosticados, luego podría tomar las predicciones de los árboles individuales (la parte del intervalo de confianza bootstrapped) y luego generar un valor aleatorio a partir de lo supuesto distribución con ese centro. Los cuantiles para esas piezas generadas pueden formar el intervalo de predicción (pero aún así lo probaría, es posible que deba repetir el proceso varias veces más y combinarlo).

Aquí hay un ejemplo de cómo hacer esto agregando desviaciones normales (ya que sabemos que los datos originales usaron una normal) a las predicciones con la desviación estándar basada en el MSE estimado de ese árbol:

pred.rf.int2 <- sapply(1:4, function(i) {
  tmp <- pred.rf$individual[i, ] + rnorm(1001, 0, sqrt(fit2$mse))
  quantile(tmp, c(0.025, 0.975))
})
t(pred.rf.int2)
#           2.5%    97.5%
# [1,]  7.351609 17.31065
# [2,] 10.386273 20.23700
# [3,] 13.004428 23.55154
# [4,] 16.344504 24.35970

Estos intervalos contienen aquellos basados ​​en un conocimiento perfecto, por lo que debe parecer razonable. Pero, dependerán en gran medida de las suposiciones hechas (las suposiciones son válidas aquí porque utilizamos el conocimiento de cómo se simularon los datos, pueden no ser tan válidos en casos de datos reales). Todavía repetiría las simulaciones varias veces para datos que se parecen más a sus datos reales (pero simulados para que sepa la verdad) varias veces antes de confiar completamente en este método.

Greg Snow
fuente
11

Me doy cuenta de que esta es una publicación antigua, pero he estado ejecutando algunas simulaciones sobre esto y pensé que compartiría mis hallazgos.

[μ+σ,μσ][μ+1.96σ,μ1.96σ]

Al realizar este cambio en el código @GregSnow, obtenemos los siguientes resultados

set.seed(1)
x1 <- rep( 0:1, each=500 )
x2 <- rep( 0:1, each=250, length=1000 )
y <- 10 + 5*x1 + 10*x2 - 3*x1*x2 + rnorm(1000)

library(randomForest)
fit2 <- randomForest(y~x1+x2)
pred.rf <- predict(fit2, newdat, predict.all=TRUE)
pred.rf.int <- t(apply( pred.rf$individual, 1, function(x){ 
  c( mean(x) + c(-1.96,1.96)*sd(x), quantile(x, c(0.025,0.975)) )}))

pred.rf.int
                          2.5%    97.5%
1  7.826896 16.05521  9.915482 15.31431
2 11.010662 19.35793 12.298995 18.64296
3 14.296697 23.61657 14.749248 21.11239
4 18.000229 23.73539 18.237448 22.10331

Ahora, comparando estos con los intervalos generados al agregar la desviación normal a las predicciones con la desviación estándar como MSE como @GregSnow sugirió que obtuviéramos,

pred.rf.int2 <- sapply(1:4, function(i) {
   tmp <- pred.rf$individual[i,] + rnorm(1000, 0, sqrt(fit2$mse))
   quantile(tmp, c(0.025, 0.975))
   })
t(pred.rf.int2)
          2.5%    97.5%
[1,]  7.486895 17.21144
[2,] 10.551811 20.50633
[3,] 12.959318 23.46027
[4,] 16.444967 24.57601

El intervalo entre ambos enfoques ahora se ve muy cercano. Trazar el intervalo de predicción para los tres enfoques contra la distribución de errores en este caso se ve a continuación

ingrese la descripción de la imagen aquí

  • Líneas negras = intervalos de predicción de regresión lineal,
  • Líneas rojas = intervalos de bosque aleatorios calculados en predicciones individuales,
  • Líneas azules = intervalos de bosque aleatorios calculados agregando desviación normal a las predicciones

Ahora, volvamos a ejecutar la simulación, pero esta vez aumentando la varianza del término de error. Si nuestros cálculos de intervalos de predicción son buenos, deberíamos terminar con intervalos más amplios que los que obtuvimos arriba.

set.seed(1)
x1 <- rep( 0:1, each=500 )
x2 <- rep( 0:1, each=250, length=1000 )
y <- 10 + 5*x1 + 10*x2 - 3*x1*x2 + rnorm(1000,mean=0,sd=5)

fit1 <- lm(y~x1+x2)
newdat <- expand.grid(x1=0:1,x2=0:1)
predict(fit1,newdata=newdat,interval = "prediction")
      fit       lwr      upr
1 10.75006  0.503170 20.99695
2 13.90714  3.660248 24.15403
3 19.47638  9.229490 29.72327
4 22.63346 12.386568 32.88035

set.seed(1)
fit2 <- randomForest(y~x1+x2,localImp=T)
pred.rf.int <- t(apply( pred.rf$individual, 1, function(x){ 
  c( mean(x) + c(-1.96,1.96)*sd(x), quantile(x, c(0.025,0.975)) )}))
pred.rf.int
                          2.5%    97.5%
1  7.889934 15.53642  9.564565 15.47893
2 10.616744 18.78837 11.965325 18.51922
3 15.024598 23.67563 14.724964 21.43195
4 17.967246 23.88760 17.858866 22.54337

pred.rf.int2 <- sapply(1:4, function(i) {
   tmp <- pred.rf$individual[i,] + rnorm(1000, 0, sqrt(fit2$mse))
   quantile(tmp, c(0.025, 0.975))
   })
t(pred.rf.int2)
         2.5%    97.5%
[1,] 1.291450 22.89231
[2,] 4.193414 25.93963
[3,] 7.428309 30.07291
[4,] 9.938158 31.63777

ingrese la descripción de la imagen aquí

Ahora, esto deja en claro que calcular los intervalos de predicción mediante el segundo enfoque es mucho más preciso y está dando resultados bastante cercanos al intervalo de predicción a partir de la regresión lineal.

μiMSEiN(μi,RMSEi)N(μi/n,RMSEi/n)

mean.rf <- pred.rf$aggregate
sd.rf <- mean(sqrt(fit2$mse))
pred.rf.int3 <- cbind(mean.rf - 1.96*sd.rf, mean.rf + 1.96*sd.rf)
pred.rf.int3
1  1.332711 22.09364
2  4.322090 25.08302
3  8.969650 29.73058
4 10.546957 31.30789

Estos coinciden muy bien con los intervalos del modelo lineal y también con el enfoque sugerido por @GregSnow. Pero tenga en cuenta que la suposición subyacente en todos los métodos que discutimos es que los errores siguen una distribución Normal.

ab90hi
fuente
10

Si usa R, puede producir fácilmente intervalos de predicción para las predicciones de una regresión aleatoria de bosques: simplemente use el paquete quantregForest(disponible en CRAN ) y lea el documento de N. Meinshausen sobre cómo se pueden inferir los cuantiles condicionales con los bosques de regresión cuantil y cómo se puede usar para construir intervalos de predicción. Muy informativo incluso si no trabajas con R!

usuario7417
fuente
Parece que el documento se trasladó aquí: jmlr.org/papers/volume7/meinshausen06a/meinshausen06a.pdf
Restablezca a Monica el
2
Esta parece ser la respuesta adecuada y no requiere supuestos de distribución con respecto al intervalo predictivo. Aquí hay un tutorial sobre cómo hacer esto en Python: blog.datadive.net/prediction-intervals-for-random-forests
colin el
6

Esto es fácil de resolver con randomForest.

Primero déjenme ocuparme de la tarea de regresión (suponiendo que su bosque tenga 1000 árboles). En la predictfunción, tiene la opción de devolver resultados de árboles individuales. Esto significa que recibirá una salida de 1000 columnas. Podemos tomar el promedio de las 1000 columnas para cada fila; esta es la salida regular que RF habría producido de cualquier manera. Ahora para obtener el intervalo de predicción, digamos +/- 2 std. desviaciones todo lo que necesita hacer es, para cada fila, de los 1000 valores calcular +/- 2 std. desviaciones y hacer que estos sean sus límites superior e inferior en su predicción.

En segundo lugar, en el caso de la clasificación, recuerde que cada árbol genera 1 o 0 (por defecto) y la suma sobre los 1000 árboles divididos por 1000 da la probabilidad de clase (en el caso de la clasificación binaria). Para poner un intervalo de predicción en la probabilidad, necesita modificar el mínimo. opción de tamaño de nodo (consulte la documentación aleatoria de Forest para obtener el nombre exacto de esa opción) una vez que establezca un valor >> 1, los árboles individuales generarán números entre 1 y 0. Ahora, a partir de ahora, puede repetir el mismo proceso descrito anteriormente para La tarea de regresión.

Espero que tenga sentido.


fuente
No lo he probado pero parece tener sentido. Gracias por responder mi vieja pregunta.
Dean MacGregor
1
Creo que este método daría algo más como un intervalo de confianza que un intervalo de predicción. Los resultados deben compararse con un modelo lineal donde la teoría de los intervalos de predicción está bien establecida. Mejor en algunos datos simulados donde se conoce la verdad y se cumplen todos los supuestos.
Greg Snow
1
@ GregSnow: Lo que obtendrá de lo que describí anteriormente es definitivamente el intervalo de predicción. Tenga en cuenta que los intervalos de predicción son generalmente mucho más amplios que los intervalos de confianza, ya que los intervalos de confianza realmente especifican dónde se encuentra la estadística media de una cantidad, ya que la predicción se refiere a una sola observación, por lo tanto, a una mayor incertidumbre y, por lo tanto, a intervalos más amplios. Las 1000 predicciones que recibe de 1000 árboles pueden considerarse como una muestra de arranque y no es necesario aplicar aquí los supuestos de normalidad. Incluso un simple análisis de deciles dará buenos resultados.
55
@SashikanthDareddy, lo que obtendrá de lo que describe definitivamente no es un intervalo de predicción. Un intervalo de predicción está determinado por algo más que ser más amplio. Sí, los árboles individuales forman un bootstrap, pero el bootstrap estima parámetros, no valores individuales. El intervalo de predicción depende mucho de la distribución de los puntos individuales. Esto demuestra el hecho de que su método proporciona un intervalo para las proporciones con un resultado categórico en lugar de las categorías. Vea mi ejemplo en la respuesta agregada.
Greg Snow
0

He probado algunas opciones (todo esto WIP):

  1. De hecho, convertí la variable dependiente en un problema de clasificación con los resultados como rangos, en lugar de un solo valor. Los resultados que obtuve fueron pobres, en comparación con el uso de un valor simple. Renuncié a este enfoque.

  2. Luego lo convertí en múltiples problemas de clasificación, cada uno de los cuales era un límite inferior para el rango (el resultado del modelo era si cruzaría el límite inferior o no) y luego ejecuté todos los modelos (~ 20), y luego combinó el resultado para obtener una respuesta final como un rango. Esto funciona mejor que 1 arriba pero no tan bueno como lo necesito. Todavía estoy trabajando para mejorar este enfoque.

Usé OOB y estimaciones de dejar uno afuera para decidir qué tan buenas / malas son mis modelos.

Nuevo record
fuente
0

El problema de construir intervalos de predicción para predicciones forestales aleatorias se ha abordado en el siguiente documento:

Zhang, Haozhe, Joshua Zimmerman, Dan Nettleton y Daniel J. Nordman. "Intervalos de predicción de bosque aleatorio". El estadístico estadounidense, 2019.

El paquete R "rfinterval" es su implementación disponible en CRAN.

Instalación

Para instalar el paquete R rfinterval :

#install.packages("devtools")
#devtools::install_github(repo="haozhestat/rfinterval")
install.packages("rfinterval")
library(rfinterval)
?rfinterval

Uso

Inicio rápido:

train_data <- sim_data(n = 1000, p = 10)
test_data <- sim_data(n = 1000, p = 10)

output <- rfinterval(y~., train_data = train_data, test_data = test_data,
                     method = c("oob", "split-conformal", "quantreg"),
                     symmetry = TRUE,alpha = 0.1)

### print the marginal coverage of OOB prediction interval
mean(output$oob_interval$lo < test_data$y & output$oob_interval$up > test_data$y)

### print the marginal coverage of Split-conformal prediction interval
mean(output$sc_interval$lo < test_data$y & output$sc_interval$up > test_data$y)

### print the marginal coverage of Quantile regression forest prediction interval
mean(output$quantreg_interval$lo < test_data$y & output$quantreg_interval$up > test_data$y)

Ejemplo de datos:

oob_interval <- rfinterval(pm2.5 ~ .,
                            train_data = BeijingPM25[1:1000, ],
                            test_data = BeijingPM25[1001:2000, ],
                            method = "oob",
                            symmetry = TRUE,
                            alpha = 0.1)
str(oob_interval)
xiaolongmao
fuente
1
Bienvenido al sitio, @ xiaolongmao. Es posible que desee realizar nuestro recorrido . Por favor, no publique respuestas idénticas a múltiples hilos. Intente personalizar sus respuestas a la pregunta específica en cada hilo. Si tiene un caso en el que realmente cree que una respuesta idéntica responde completamente a la pregunta, eso implica que la pregunta es un duplicado. Cuando alcances 50 reputación, puedes publicar un comentario en el OP. Mientras tanto, puede marcar la Q para cerrar como un duplicado.
gung - Restablece a Monica