Regresión con redes neuronales en R

La última técnica que me estoy estudiando este verano es la regresión con redes neuronales. El ejemplo que os voy a poner es completamente análogo a este: http://heuristically.wordpress.com/2011/11/17/using-neural-network-for-regression/ Vamos a trabajar con el paquete nnet, si dispusiera de tiempo replicaría este ejemplo en otra entrada con neuranet. Para realizar el ejemplo tenemos el conjunto de datos housing que contiene el censo de 1970 de 506 hogares de Boston. Empecemos a trabajar con la consola de RStudio (¡!)

#install.packages("mlbench")
library(mlbench)
data(BostonHousing)
summary(BostonHousing$medv)

Como variable dependiente vamos a emplear el valor mediano de las vivendas ocupadas en dólares.  El primer paso será realizar un modelo de regresión lineal:

lm.fit <- lm(medv ~ ., data=BostonHousing)
lm.predict <- predict(lm.fit)
mean((lm.predict - BostonHousing$medv)^2)

plot(BostonHousing$medv, lm.predict,
main="Regresión lineal",
xlab="Actual")

El ajuste ofrece una suma de cuadrados de 21.9  Vamos a realizar este modelo con redes neuronales:

library(nnet)
#Vamos a construir un conjunto de datos con las variables
#independientes centradas
Boston.escalado=subset(BostonHousing,selec=-c(chas,medv))
Boston.escalado=scale(Boston.escalado)
summary(Boston.escalado)
#Dividimos por 50 para tener una respuesta entre 0 y 1
nnet.fit <- nnet(BostonHousing$medv/50 ~ Boston.escalado,
size=2, linout=T,trace=F)

nnet.predict <- predict(nnet.fit)*50
mean((nnet.predict - BostonHousing$medv)^2)

plot(BostonHousing$medv, nnet.predict,
main="Neural network predictions vs actual",
xlab="Actual")

Para realizar el modelo vamos a emplear la librería nnet, nuestro modelo tiene como variable dependiente medv dividida por 50 para que sea un valor entre 0 y 1 Como variables independientes tendremos las mismas pero centradas por su media para evitar que nuestra red tenga pesos 0. En la función nnet especificamos que deseamos 2 nodos en la única capa oculta (size=2) y con linout=T la salida habrá de ser lineal y no binomial. Con trace=F evitamos que R nos presente todas las iteraciones necesarias para llegar a la convergencia del modelo. Para estudiar el comportamiento predictivo vemos la media de la suma de cuadrados con respecto a las predicciones y obtenemos un valor de 11.17 que mejora mucho la estimación realizada con el modelo.

Podríamos buscar un mejor modelo con un proceso iterativo y añadiendo más nodos a nuestra capa oculta:

#Mejor solución con proceso iterativo
bestrss <- 10000
for(i in 1:100){
nnmdl <- nnet(BostonHousing$medv/50 ~ Boston.escalado,
size=4, linout=T,trace=F,decay=0.00001)
cat(nnmdl$value,"\n")
if(nnmdl$value < bestrss){
bestnn <- nnmdl
bestrss <- nnmdl$value
}}
bestnn$value
summary(bestnn)

Partimos de una suma de cuadrados subabsurda y si nuestro modelo lo mejora pues será nuestro mejor modelo posible, así hasta 100 veces y el mejor modelo será el objeto bestnn:

nnet.predict <- predict(bestnn)*50
mean((nnet.predict - BostonHousing$medv)^2)

Ahora la media del cuadrado de los errores es 5,4. Hay que destacar que en la función nnet del proceso iterativo hemos añadido la opción decay evitamos el problema de los pesos más altos, algo que ya se mitiga empleando datos centrados. Nuestra red tiene 12 nodos de entrada, 4 nodos en la capa oculta y un sólo nodo en la salida, sólo uno porque estamos realizando un modelo de regresión, no de clasificación.

Si deseamos analizar el comportamiento de nuestras variables independientes en la red neuronal hemos de analizar los pesos de los nodos. Esta tarea es complicada si lo hacemos a través de la salida de texto de R, sin embargo existe un código que nos permite visualizar objetos nnet:

http://beckmw.wordpress.com/2013/03/04/visualizing-neural-networks-from-the-nnet-package/

Simplemente asombroso eso si que es una entrada interesante . En la siguiente entrada del blog visualizaremos la red creada y estudiaremos el comportamiento de las variables regresoras.

7 comentarios en “Regresión con redes neuronales en R

  1. Hola, quería consultar que esta pasando en esta parte del codigo:

    #Mejor solución con proceso iterativo
    bestrss <- 10000
    for(i in 1:100){
    nnmdl <- nnet(BostonHousing$medv/50 ~ Boston.escalado,size=4, linout=T,trace=F,decay=0.00001)
    cat(nnmdl$value,”\n”)
    if(nnmdl$value < bestrss){
    bestnn <- nnmdl
    bestrss <- nnmdl$value
    }}
    bestnn$value

    ya que dentro del for, no entiendo cual es el "i" que está iterando???
    Ademas que está indica nnmdl$value???

    Gracias de antemano. Saludos!

  2. Hola, el i solo hace de índice, no tiene ninguna función en este bucle.

    El bucle genera un objeto de nnet llamado nnmdl y uno de los elementos de ese objeto es $value que corresponde a la suma del cuadrado de los errores del ajuste. El bucle lo que hace es hacer 100 iteracciones buscando la menor suma de cuadrados de los errores. Esto se hace debido a los diferentes pesos que toma el algoritmo de la red neuronal.

    Saludos.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

[bws_google_captcha]