La precisión de la máquina de aumento de gradiente disminuye a medida que aumenta el número de iteraciones

15

Estoy experimentando con el algoritmo de la máquina de aumento de gradiente a través del caretpaquete en R.

Usando un pequeño conjunto de datos de admisión a la universidad, ejecuté el siguiente código:

library(caret)

### Load admissions dataset. ###
mydata <- read.csv("http://www.ats.ucla.edu/stat/data/binary.csv")

### Create yes/no levels for admission. ### 
mydata$admit_factor[mydata$admit==0] <- "no"
mydata$admit_factor[mydata$admit==1] <- "yes"             

### Gradient boosting machine algorithm. ###
set.seed(123)
fitControl <- trainControl(method = 'cv', number = 5, summaryFunction=defaultSummary)
grid <- expand.grid(n.trees = seq(5000,1000000,5000), interaction.depth = 2, shrinkage = .001, n.minobsinnode = 20)
fit.gbm <- train(as.factor(admit_factor) ~ . - admit, data=mydata, method = 'gbm', trControl=fitControl, tuneGrid=grid, metric='Accuracy')
plot(fit.gbm)

y encontré para mi sorpresa que la precisión de validación cruzada del modelo disminuyó en lugar de aumentar a medida que aumentó el número de iteraciones de refuerzo, alcanzando una precisión mínima de aproximadamente .59 a ~ 450,000 iteraciones.

ingrese la descripción de la imagen aquí

¿Implementé incorrectamente el algoritmo GBM?

EDITAR: Siguiendo la sugerencia de Underminer, volví a ejecutar el caretcódigo anterior pero me concentré en ejecutar de 100 a 5,000 iteraciones de refuerzo:

set.seed(123)
fitControl <- trainControl(method = 'cv', number = 5, summaryFunction=defaultSummary)
grid <- expand.grid(n.trees = seq(100,5000,100), interaction.depth = 2, shrinkage = .001, n.minobsinnode = 20)
fit.gbm <- train(as.factor(admit_factor) ~ . - admit, data=mydata, method = 'gbm', trControl=fitControl, tuneGrid=grid, metric='Accuracy')
plot(fit.gbm)

El gráfico resultante muestra que la precisión realmente alcanza su punto máximo en casi .705 a ~ 1,800 iteraciones:

ingrese la descripción de la imagen aquí

Lo curioso es que la precisión no se estabilizó en ~ .70, sino que disminuyó después de 5.000 iteraciones.

RobertF
fuente

Respuestas:

14

En general, el error de aumento puede aumentar con el número de iteraciones, específicamente cuando los datos son ruidosos (por ejemplo, casos mal etiquetados). Este podría ser su problema, pero no podría decirlo sin saber más sobre sus datos

Básicamente, impulsar puede 'enfocarse' en predecir correctamente los casos que contienen información errónea y, en el proceso, deteriorar el rendimiento promedio en otros casos que son más sustantivos.

Este enlace ( Impulso y ruido ) muestra una mejor descripción de la que puedo proporcionar sobre el problema.

Este documento ( Ruido de clasificación aleatoria ) de Long y Servedio proporciona más detalles técnicos del problema.

Socavador
fuente
16

Lo que ha mostrado es un ejemplo clásico de sobreajuste. El pequeño aumento en el error proviene del peor rendimiento en la parte de validación de su conjunto de datos con validación cruzada. Más iteraciones casi siempre deberían mejorar el error en el conjunto de entrenamiento, pero lo contrario es cierto para el conjunto de validación / prueba.

Ryan Zotti
fuente
Entonces, ¿overfit de aumento de gradiente basado en el número de iteraciones de aumento? Interesante. Pensé que la precisión se habría estabilizado después de alcanzar el número óptimo de iteraciones.
RobertF
44
Eso es correcto. En el aumento de gradiente, cada árbol posterior se construye a partir de los residuos de los árboles anteriores, por lo que el GBM continuará intentando eliminar el error restante en el conjunto de datos de entrenamiento incluso a costa de poder generalizar a conjuntos de validación / prueba. Es por eso que realiza la validación cruzada, porque el algoritmo de ajuste no sabe de forma nativa cuándo detenerse
Ryan Zotti
1
Gradient Boosting está inspirado en AdaBoost. AdaBoost rara vez se sobreajusta y cuando lo hace, es solo un poco y después de muchas, muchas iteraciones. Creo que la explicación de @Underminer es más probable que sea representativa de lo que está sucediendo que este comentario, especialmente teniendo en cuenta que no hay referencias en este comentario.
Ricardo Cruz
2
@RicardoCruz Creo que es interesante que rara vez hayas visto un sobreajuste que aumenta el gradiente. Durante los más o menos cuatro años que lo he estado usando, he visto lo contrario: demasiados árboles conducen a un sobreajuste. Una vez tuve que demostrar algo similar a un colega y pude reducir el error en el conjunto de entrenamiento a casi cero, pero el error de validación aumentó significativamente más que el del GBM no ajustado. Todavía creo que el aumento de gradiente es un gran algoritmo. Por lo general, es el primer algoritmo que utilizo; solo hay que tener cuidado con demasiados árboles, que puede rastrear a través de la validación cruzada
Ryan Zotti
2
@RyanZotti Estoy corregido entonces. He leído un montón de artículos sobre AdaBoost de Schapire et al porque disfruto de su hermosa y sólida base teórica. Los autores argumentan que impulsar es propenso a sobreajustar, pero que es extremadamente difícil. No tengo mucha experiencia en su uso, y no tienen una base teórica sólida para argumentar esto, y, por supuesto, los autores son autores, son naturalmente celosos de su invención, por lo que si tiene experiencia en contrario Estoy parado corregido.
Ricardo Cruz
4

Códigos para reproducir un resultado similar, sin búsqueda de cuadrícula,

mod = gbm(admit ~ .,
      data = mydata[,-5],
      n.trees=100000,
      shrinkage=0.001,
      interaction.depth=2,
      n.minobsinnode=10,
      cv.folds=5,
      verbose=TRUE,
      n.cores=2)

best.iter <- gbm.perf(mod, method="OOB", plot.it=TRUE, oobag.curve=TRUE, overlay=TRUE)
print(best.iter)
[1] 1487
pred = as.integer(predict(mod, newdata=mydata[,-5], n.trees=best.iter) > 0)
y = mydata[,1]
sum(pred == y)/length(y)
[1] 0.7225
horaceT
fuente
3

El paquete gbm tiene una función para estimar el número óptimo de iteraciones (= # de árboles, o # de funciones básicas),

gbm.perf(mod, method="OOB", plot.it=TRUE, oobag=TRUE, overlay=TRUE)

No necesitas el tren de Caret para eso.

horaceT
fuente
No sé si eso resuelve el problema que estoy teniendo: parece que el número óptimo de iteraciones es de 5,000 en mi caso, donde la precisión es máxima, cercana a 0,70 (el primer punto de datos en mi gráfico). Pero eso parece estar mal. Más iteraciones deberían conducir a una mayor precisión, no menor, ¿verdad?
RobertF
1
@RobertF Primero, creo que no es necesario convertir la admisión en un factor. Funciona igual de bien: mod = gbm (admitir ~., Datos = mydata [, - 5], n.trees = 100000, contracción = 0.001, interacción.depth = 2, n.minobsinnode = 10, cv.folds = 5 , detallado = VERDADERO, n.cores = 2). Puede ver dónde gbm elige el iter óptimo de la siguiente manera: best.iter <- gbm.perf (mod, method = "OOB", plot.it = TRUE, oobag.curve = TRUE, overlay = TRUE). Es decir, cuando el cambio en la desviación se vuelve negativo (ver el gráfico generado a partir de esto).
horaceT
1
@RobertF Una cosa más. Al especificar n.trees = (un millón) en la llamada gbm, habría ejecutado todos los números de iteraciones de 1 a 1,000,000. Así que no necesitas preocuparte por hacer eso por ti.
horaceT
1
@RobertF Más seguimiento. Acabo de ejecutar 100k árboles / iteraciones. La precisión que obtuve al elegir la mejor iteración con gbm.perf es 0.7225, que está bastante cerca de la suya ejecutando una cuadrícula completa de iteraciones.
horaceT