11 votos

R neuralnet - compute give a constant answer

Estoy tratando de usar la herramienta de R neuralnet paquete (documentación aquí ) para la predicción.

Esto es lo que intento hacer:

library(neuralnet)
x <- cbind(runif(50, min=1, max=500), runif(50, min=1, max=500))
y <- x[, 1] * x[, 2]
train <- data.frame(x, y)
n <- names(train)
f <- as.formula(paste('y ~', paste(n[!n %in% 'y'], collapse = ' + ')))
net <- neuralnet(f, train, hidden = c(5, 5), threshold=0.01)
print(net)

all: neuralnet(formula = f, data = train, hidden = c(5, 5), threshold = 0.01)

1 repetition was calculated.

    Error Reached Threshold Steps
1 66136930789    0.004658283648 97938

test <- cbind(runif(10, min=1, max=500), runif(10, min=1, max=500))
res <- compute(net, test)
res$net.result
         [,1]
[1,] 58749.01798
[2,] 58749.01798
[3,] 58749.01798
[4,] 58749.01798
[5,] 58749.01798
[6,] 58749.01798
[7,] 58749.01798
[8,] 58749.01798
[9,] 58749.01798
[10,] 58749.01798

¿Puede alguien explicarme por qué los errores son tan grandes y por qué todos los valores predichos son casi constantes?

6voto

tylerharms Puntos 79

No soy un experto en redes neuronales, pero creo que los siguientes puntos pueden serte útiles. También hay algunos buenos posts, por ejemplo este en unidades ocultas que puede buscar en este sitio sobre lo que hacen las redes neuronales y que podría serle útil.

1 Grandes errores: por qué su ejemplo no funcionó en absoluto

¿por qué los errores son tan grandes y por qué todos los valores predichos son casi constantes?

Esto se debe a que la red neuronal no ha sido capaz de calcular la función de multiplicación que le has dado y ha emitido un número constante en medio del rango de y independientemente de x La mejor manera de minimizar los errores durante el entrenamiento. (Fíjate en que 58749 se acerca bastante a la media de multiplicar juntos dos números entre 1 y 500).

Es muy difícil ver cómo una red neuronal podría calcular una función de multiplicación de forma sensata. Piensa en cómo cada nodo de la red combina los resultados calculados previamente: se toma un suma ponderada de las salidas de los nodos anteriores (y luego aplicarle una función sigmoidal, véase, por ejemplo Introducción a las redes neuronales , para estrujar la salida entre $-1$ y $1$ ). ¿Cómo vas a conseguir que una suma ponderada te dé la multiplicación de dos entradas? (Supongo, sin embargo, que podría ser posible tomar un gran número de capas ocultas para conseguir que la multiplicación funcione de forma muy artificiosa).

2 Mínimos locales: por qué un ejemplo teóricamente razonable puede no funcionar

Sin embargo, incluso intentando hacer la adición te encuentras con problemas en tu ejemplo: la red no se entrena con éxito. Creo que esto se debe a un segundo problema: conseguir mínimos locales durante la formación. De hecho, para la suma, utilizar dos capas de 5 unidades ocultas es demasiado complicado para calcular la suma. Una red con no Las unidades ocultas entrenan perfectamente bien:

x <- cbind(runif(50, min=1, max=500), runif(50, min=1, max=500))
y <- x[, 1] + x[, 2]
train <- data.frame(x, y)
n <- names(train)
f <- as.formula(paste('y ~', paste(n[!n %in% 'y'], collapse = ' + ')))
net <- neuralnet(f, train, hidden = 0, threshold=0.01)
print(net) # Error 0.00000001893602844

Por supuesto, podrías transformar tu problema original en un problema de adición tomando registros, pero no creo que esto sea lo que quieres, así que adelante...

3 Número de ejemplos de entrenamiento comparado con el número de parámetros a estimar

Entonces, ¿cuál sería una forma razonable de probar tu red neuronal con dos capas de 5 unidades ocultas como tenías originalmente? Las redes neuronales se utilizan a menudo para la clasificación, por lo que decidir si $\mathbf{x}\cdot\mathbf{k} > c$ parecía una elección razonable del problema. Utilicé $\mathbf{k} = (1, 2, 3, 4, 5)$ y $c = 3750$ . Obsérvese que hay varios parámetros que hay que aprender.

En el código que aparece a continuación adopto un enfoque muy similar al tuyo, salvo que entreno dos redes neuronales, una con 50 ejemplos del conjunto de entrenamiento y otra con 500.

library(neuralnet)
set.seed(1) # make results reproducible
N=500
x <- cbind(runif(N, min=1, max=500), runif(N, min=1, max=500), runif(N, min=1, max=500), runif(N, min=1, max=500), runif(N, min=1, max=500))
y <- ifelse(x[,1] + 2*x[,1] + 3*x[,1] + 4*x[,1] + 5*x[,1] > 3750, 1, 0)
trainSMALL <- data.frame(x[1:(N/10),], y=y[1:(N/10)])
trainALL <- data.frame(x, y)
n <- names(trainSMALL)
f <- as.formula(paste('y ~', paste(n[!n %in% 'y'], collapse = ' + ')))
netSMALL <- neuralnet(f, trainSMALL, hidden = c(5,5), threshold = 0.01)
netALL <- neuralnet(f, trainALL, hidden = c(5,5), threshold = 0.01)
print(netSMALL) # error 4.117671763
print(netALL) # error 0.009598461875

# get a sense of accuracy w.r.t small training set (in-sample)
cbind(y, compute(netSMALL,x)$net.result)[1:10,]
      y                 
 [1,] 1  0.587903899825
 [2,] 0  0.001158500142
 [3,] 1  0.587903899825
 [4,] 0  0.001158500281
 [5,] 0 -0.003770868805
 [6,] 0  0.587903899825
 [7,] 1  0.587903899825
 [8,] 0  0.001158500142
 [9,] 0  0.587903899825
[10,] 1  0.587903899825

# get a sense of accuracy w.r.t full training set (in-sample)
cbind(y, compute(netALL,x)$net.result)[1:10,]
      y                 
 [1,] 1  1.0003618092051
 [2,] 0 -0.0025677656844
 [3,] 1  0.9999590121059
 [4,] 0 -0.0003835722682
 [5,] 0 -0.0003835722682
 [6,] 0 -0.0003835722199
 [7,] 1  1.0003618092051
 [8,] 0 -0.0025677656844
 [9,] 0 -0.0003835722682
[10,] 1  1.0003618092051

Es evidente que el netALL ¡lo hace mucho mejor! ¿Por qué? Echa un vistazo a lo que obtienes con un plot(netALL) comando:

enter image description here

Lo hago con 66 parámetros que se estiman durante el entrenamiento (5 entradas y 1 entrada de sesgo a cada uno de los 11 nodos). No se pueden estimar 66 parámetros de forma fiable con 50 ejemplos de entrenamiento. Sospecho que en este caso podrías reducir el número de parámetros a estimar reduciendo el número de unidades. Y se puede ver desde la construcción de una red neuronal para hacer la adición que una red neuronal más simple puede ser menos propensa a tener problemas durante el entrenamiento.

Pero, como regla general, en cualquier aprendizaje automático (incluida la regresión lineal) es conveniente tener muchos más ejemplos de entrenamiento que parámetros a estimar.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X