viernes, 25 de diciembre de 2015

Regresion con Red Neuronal


El siguiente script utiliza el package neuralnet para hacer una regresión y predecir el valor de viviendas (expresado en \$1000), usando el data set Boston incluido en el package MASS.

Para un mejor ajuste del modelo (es decir, para que la red aprenda mejor), se hace un preprocesamiento de los datos, donde se normaliza el data set, quedando así:












# LIBRERIAS Y DATOS
# -----------------------------------------------------
library(MASS); library(neuralnet); library(ggplot2)
set.seed(65)
datos    <- Boston
n        <- nrow(datos)
muestra  <- sample(n, n * .70)
train    <- datos[muestra, ]
test     <- datos[-muestra, ]
 
 
# NORMALIZACION DE VARIABLES
# -----------------------------------------------------
maxs      <- apply(train, 2, max)
mins      <- apply(train, 2, min)
datos_nrm <- as.data.frame(scale(datos, center = mins, scale = maxs - mins))
train_nrm <- datos_nrm[muestra, ]
test_nrm  <- datos_nrm[-muestra, ]
 
 
# FORMULA
# -----------------------------------------------------
nms  <- names(train_nrm)
frml <- as.formula(paste("medv ~", paste(nms[!nms %in% "medv"], collapse = " + ")))
 
 
# MODELO
# -----------------------------------------------------
modelo.nn <- neuralnet(frml,
                       data          = train_nrm,
                       hidden        = c(7,5), # ver Notas para detalle 
                       threshold     = 0.05,   # ver Notas para detalle
                       algorithm     = "rprop+" 
                       )
 
 
# PREDICCION
# -----------------------------------------------------
pr.nn   <- compute(modelo.nn,within(test_nrm,rm(medv)))
 
# se transoforma el valor escalar al valor nominal original
medv.predict <- pr.nn$net.result*(max(datos$medv)-min(datos$medv))+min(datos$medv)
medv.real    <- (test_nrm$medv)*(max(datos$medv)-min(datos$medv))+min(datos$medv)
 
 
 
# SUMA DE ERROR CUADRATICO
# -----------------------------------------------------
(se.nn <- sum((medv.real - medv.predict)^2)/nrow(test_nrm))
 
 
#GRAFICOS
# -----------------------------------------------------
# Errores
qplot(x=medv.real, y=medv.predict, geom=c("point","smooth"), method="lm", 
      main=paste("Real Vs Prediccion. Summa de Error Cuadratico=", round(se.nn,2)))
# Red
plot(modelo.nn)

NOTAS:
El parametro threshol = 0.05 indica que las iteraciones se detendrán cuando el "Cambio" del error sea menor a 5% entre una iteracion de optimizacion y otra. Este "Cambio" es calculado como la derivada parcial de la función de error respecto a los pesos.

El parámetro algorithm = "rprop+" refiere al algoritmo "Resilient Backpropagation", que actualiza los pesos considerando únicamente el signo del cambio, es decir, si el cambio del error es en aumento (+) o disminución (-) entre una iteración y otra. Para detalles ver: https://en.wikipedia.org/wiki/Rprop

El parámetro hidden = c(7,5) especifica una primera capa oculta con 7 neuronas y una segunda capa oculta con 5 neuronas. 


Referencia:
http://www.r-bloggers.com/fitting-a-neural-network-in-r-neuralnet-package/


14 comentarios:

  1. Excelente blog, felicidades y gracias.

    ResponderEliminar
  2. Que tal Enmanuel, muy bueno el post, no tendrás un ejemplo de redes neuronales con series de tiempo.Saludos desde Perú.

    ResponderEliminar
  3. Gracias por tus aportes, saludos.

    ResponderEliminar
  4. ¿Por que as.formula(paste("medv ~", paste(nms[!nms %in% "medv"], collapse = " + ")))
    ? que consigues con esta formula?

    ResponderEliminar
    Respuestas
    1. Hola Valentin Garcia
      Se usa as.formula para obtener "medv ~ crim + zn + indus + etc...", y luego como formula en eltrain. Esto porque la libreria neuralnet (a diferencia de otras) no permite usar "medv ~." para indicar que todas las variables de data.frame son variables descriptoras de "medv".

      saludos

      Eliminar
  5. Buenas tardes,

    no me queda claro por qué se extrae el máximo y mínimo solo de train pero luego se normaliza toda la base de datos (train+test) con estos valores. En teoría mis datos de test se deben utilizar solo para validar el modelo

    ResponderEliminar
    Respuestas
    1. Hola Nathaly

      Esto se hace para evitar introducir informacion de test en el proceso de train, ya que el modelo entrendo siempre va a predecir sobre datos nuevos que no estaban disponible a al momento de entrenar.

      Te dejo links donde detallan mas este tema:

      https://stats.stackexchange.com/questions/77350/perform-feature-normalization-before-or-within-model-validation

      Espero te sirva

      Suerte!

      Eliminar
  6. Una consulta, que formula utilizo para normalizar los datos y cual para revertir el resultado?

    ResponderEliminar
  7. Hola, que libreria recomiendas para redes neuronales de tipo cascada.gracias

    ResponderEliminar
  8. Hola,

    Muy bueno su artículo. Tengo aun una duda, cuando se emplean muestras muy grandes y el error medio cuadrático da muy alto, ¿cuál es la interpretación de ese resultado?

    Mil gracias por su respuesta!!!

    ResponderEliminar
  9. Buenos días, hago una consulta ya que me hace ruido cuando luego de la predicción se transforma el valor escalar al valor nominal original... no deberían usarse los máximos y mínimos originales (sólo de test) en lugar de los máximos y mínimos del dataset completo? En caso de que no sea un error, por qué se hace de esa forma?

    Muchas gracias por la aclaración. Slds!

    ResponderEliminar
  10. Por favor alguien podría aclararme un par de dudas sobre pronóstico en series de tiempo con machine learning? Favor escribir a damadei@fen.uchile.cl
    Un abrazo

    ResponderEliminar
  11. saludos, mi inquietud es sobre la primera capa oculta, esos numeros son aleatorios o es un valor predeterminado que usas

    ResponderEliminar