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"))
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"))
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"))
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)
plotea(0.044,v1,v2)
plotea(0.044*2,v1,v2)
plotea(-1, v1, v2)
A continuación se muestran las figuras de shrinkage vs. n.minobsinnode.
v1 = "shrinkage"
v2 = "n.minobsinnode";
plotea(0,v1,v2)
plotea(0.044,v1,v2)
plotea(0.044*2,v1,v2)
plotea(-1, v1, v2)
A continuación se muestran las figuras de shrinkage vs. interaction.depth.
v1 = "shrinkage"
v2 = "interaction.depth"
plotea(0,v1,v2)
plotea(0.044,v1,v2)
plotea(0.044*2,v1,v2)
plotea(-1, v1, v2)
Por último se muestran las figuras de n.trees vs. interaction.depth.
v1 = "n.trees"
v2 = "interaction.depth"
plotea(0,v1,v2)
plotea(0.044,v1,v2)
plotea(0.044*2,v1,v2)
plotea(-1, v1, v2)
Por último, puede ser interesante visitar esta aplicación realizada con los datos obtenidos en esta entrada.