Esta entrada complementa las entradas:

En ellas, se hacía una búsqueda exhaustiva en rejilla de cuatro de los parámetros de gbm y posteriormente se visualizaban los resultados. Recordemos que la mejor combinación de parámetros era:

(p = parametros[which.min(Validacion)])
##    interaction.depth shrinkage n.minobsinnode n.trees Train Validacion  Time
## 1:                 4      0.05             10     100 7.227      10.51 1.645
p = p[,1:(ncol(p)-3), with=FALSE] # Quitamos los valores de Train, Validación y Time que no son parámetros realmente

De esa visualización, se concluía que podría ser interesante probar n.trees menores que 100, o shrinkage entre 0.01 y 0.05, o interaction.depth de 3 o 5, o n.minobsinnode entre 5 y 15 (exclusive). Para ello, simplemente cambiaremos los rangos de los parámetros y re-ejecutaremos el código de grid search.

semilla = 1            # semilla aleatoria
rango_nFolds = 1:5     # Validación cruzada de 5 folds

rango_n.trees = c(seq(10,100,10), seq(500,15000, 500))
rangos_parametros = list(c(1, 2, 3, 4, 5, 6, 8, 10, 12, 14),
                         c(0.0001, 0.0005, 0.001, 0.01, 0.02, 0.03, 0.04, 0.05, 0.1, 0.5),
                         c(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 20, 25, 30),
                         rango_nFolds
                         )

nombres_parametros = c("interaction.depth", "shrinkage", "n.minobsinnode", "nFold")
names(rangos_parametros) = nombres_parametros
claves = c(nombres_parametros, "n.trees")

Volvemos a calcular las medias de Train, Validacion y Time para los 5 folds asi:

nombres_parametros = c("interaction.depth", "shrinkage", "n.minobsinnode", "nFold")
claves = c(nombres_parametros, "n.trees")

semilla=1
nf = paste0("parametrosGBMexhaustivoFinal-",semilla,".txt")
parametros = fread(nf)
setkeyv(parametros, claves)
parametros = unique(parametros)
if(nrow(parametros)<length(rango_n.trees)*prod(sapply(rangos_parametros,length))) cat("Algunas combinaciones de parámetros han fallado. Se recomienda volver a ejecutar el código")
parametros = parametros[, list(Train=mean(Train), Validacion=mean(Validacion), Time=mean(Time)), by=eval(claves[claves!="nFold"])]

Ahora, la mejor combinación de parámetros corresponde a:

(p = parametros[which.min(Validacion)])
##    interaction.depth shrinkage n.minobsinnode n.trees Train Validacion  Time
## 1:                 4      0.05             10     100 7.227      10.51 1.697
p = p[,1:(ncol(p)-3), with=FALSE] # Quitamos los valores de Train, Validación y Time que no son parámetros realmente

Parece que la exploración de parámetros más fina no ha encontrado mejores combinaciones de parámetros. Volvemos a visualizar los plots que vimos en las entradas anteriores:

library(reshape2)
library(latticeExtra)
resultados_claves = list()
for(clave in claves[claves!="nFold"]){
  resultados_claves[[clave]] = parametros[,.SD[which.min(Validacion)], by=clave, .SDcols=c("Train","Validacion", "Time")]
  resultados_claves[[clave]][,variable:=clave]
  setnames(resultados_claves[[clave]], 1, "valor")
}

resultados = rbindlist(resultados_claves)
resultadosMin = resultados[,.SD[which.min(Validacion)],by="variable"]
resultadosMinLinea = copy(resultados)[,Validacion:=min(Validacion),by="variable"]
xyplot(Validacion~valor|variable, resultados, scales = "free", type=c("b"), auto.key=TRUE)+
  as.layer(xyplot(Validacion~valor|variable, data=resultadosMin, pch=0, cex=2))+
  as.layer(xyplot(Validacion~valor|variable, data=resultadosMinLinea, type="l", col="red"))

plot of chunk unnamed-chunk-10

xyplot(Validacion~valor|variable, resultados, scales = list(x="free"), type=c("b"), auto.key=TRUE)+
  as.layer(xyplot(Validacion~valor|variable, data=resultadosMin, pch=0, cex=2))+
  as.layer(xyplot(Validacion~valor|variable, data=resultadosMinLinea, type="l", col="red"))

plot of chunk unnamed-chunk-11

Puede ser interesante visualizar lo que ocurre con pocos árboles:

xyplot(Validacion~valor, resultados[variable=="n.trees" & valor <=500], scales = list(x="free"), type=c("b"), auto.key=TRUE)+
  as.layer(xyplot(Validacion~valor, data=resultadosMin[variable=="n.trees" & valor <=500], pch=0, cex=2))+
  as.layer(xyplot(Validacion~valor, data=resultadosMinLinea[variable=="n.trees" & valor <=500], type="l", col="red"))

plot of chunk unnamed-chunk-12

Por último, la visualización de los parámetros por parejas:

#library(manipulate)
library(gridExtra)
## Loading required package: grid
plotea = function(nivel, v1, v2, salida){
  param = parametros[,.SD[which.min(Validacion)], by=c(v1, v2), .SDcol="Validacion"]
  rango = param[,range(Validacion)]
  param = param[,v:=scale(Validacion,rango[1], diff(rango))]

  if(nivel>=0){
    param[,disc:=ifelse(v<=nivel/2,0, ifelse(v<=nivel, 0.5, 1.0))];
    levelplot(disc ~ factor(get(v1))+factor(get(v2)), param, xlab=v1, ylab=v2)
  } else {
    levelplot(v ~ factor(get(v1))+factor(get(v2)), param, xlab=v1, ylab=v2)
  }
}

#manipulate(plotea(nivel, v1, v2), nivel=slider(0,1))

v1 = "shrinkage"
v2 = "n.trees"
plotea(0,v1,v2)

plot of chunk unnamed-chunk-13

plotea(0.044,v1,v2)

plot of chunk unnamed-chunk-13

plotea(0.044*2,v1,v2)

plot of chunk unnamed-chunk-13

plotea(-1, v1, v2)

plot of chunk unnamed-chunk-13

A continuación se muestran las figuras de shrinkage vs. n.minobsinnode.

v1 = "shrinkage"
v2 = "n.minobsinnode";
plotea(0,v1,v2)

plot of chunk unnamed-chunk-14

plotea(0.044,v1,v2)

plot of chunk unnamed-chunk-14

plotea(0.044*2,v1,v2)

plot of chunk unnamed-chunk-14

plotea(-1, v1, v2)

plot of chunk unnamed-chunk-14

A continuación se muestran las figuras de shrinkage vs. interaction.depth.

v1 = "shrinkage"
v2 = "interaction.depth"
plotea(0,v1,v2)

plot of chunk unnamed-chunk-15

plotea(0.044,v1,v2)

plot of chunk unnamed-chunk-15

plotea(0.044*2,v1,v2)

plot of chunk unnamed-chunk-15

plotea(-1, v1, v2)

plot of chunk unnamed-chunk-15 Por último se muestran las figuras de n.trees vs. interaction.depth.

v1 = "n.trees"
v2 = "interaction.depth"
plotea(0,v1,v2)

plot of chunk unnamed-chunk-16

plotea(0.044,v1,v2)

plot of chunk unnamed-chunk-16

plotea(0.044*2,v1,v2)

plot of chunk unnamed-chunk-16

plotea(-1, v1, v2)

plot of chunk unnamed-chunk-16

Por último, puede ser interesante visitar esta aplicación realizada con los datos obtenidos en esta entrada.