viernes, 25 de diciembre de 2015

Regresion con Red Neuronal


El siguiente script utiliza el package neuralnet para hacer una regresion 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 asi:











# 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 detendran 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 funcion de error respecto a los pesos.

El parametro 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 parametro 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/


9 comentarios:

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

    ResponderEliminar
  2. Gracias por tus aportes, saludos.

    ResponderEliminar
  3. ¿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
  4. 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
  5. Una consulta, que formula utilizo para normalizar los datos y cual para revertir el resultado?

    ResponderEliminar