R neuralnet - calcular da una respuesta constante

11

Estoy tratando de usar el neuralnetpaquete de R (documentación aquí ) para la predicción.

Aquí lo que estoy tratando de 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

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

Luckyi
fuente

Respuestas:

6

No soy un experto en redes neuronales, pero creo que los siguientes puntos podrían serle útiles. También hay algunas publicaciones agradables, por ejemplo, esta en unidades ocultas , que puede buscar en este sitio sobre lo que hacen las redes neuronales que podrían resultarle útiles.

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 pudo calcular la función de multiplicación que le asignó y la salida de un número constante en el medio del rango de y, independientemente de x, fue la mejor manera de minimizar los errores durante el entrenamiento. (Observe cómo 58749 está bastante cerca de la media de multiplicar dos números entre 1 y 500 juntos).

11

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

Sin embargo, incluso al intentar hacer una adición, se encuentra con problemas en su ejemplo: la red no se entrena correctamente. Creo que esto se debe a un segundo problema: obtener mínimos locales durante el entrenamiento. De hecho, para sumar, usar dos capas de 5 unidades ocultas es demasiado complicado para calcular la suma. Una red sin unidades ocultas entrena 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ía transformar su problema original en un problema de suma tomando registros, pero no creo que esto sea lo que desea, así que en adelante ...

3 Número de ejemplos de entrenamiento comparados con el número de parámetros para estimar

xk>ck=(1,2,3,4,5)c=3750

En el siguiente código, adopto un enfoque muy similar al suyo, excepto 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 lo netALLhace mucho mejor! ¿Por qué es esto? Echa un vistazo a lo que obtienes con un plot(netALL)comando:

ingrese la descripción de la imagen aquí

Hago 66 parámetros que se estiman durante el entrenamiento (5 entradas y 1 entrada de sesgo para cada uno de los 11 nodos). No puede estimar de manera confiable 66 parámetros con 50 ejemplos de entrenamiento. Sospecho que en este caso es posible que pueda reducir el número de parámetros a estimar reduciendo el número de unidades. Y puede ver, al construir una red neuronal para agregar, que una red neuronal más simple puede tener menos probabilidades de tener problemas durante el entrenamiento.

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

TooTone
fuente
1
Mucha información para pensar, ¡gracias! ¡Tienes toda la razón! Si las variables se normalizaron, el número de ejemplos de entrenamiento fue mayor y el número de neuronas en una capa oculta igual a uno, se verá mucho mejor. Por supuesto, no es una función de multiplicación sino algo similar. Ah, si obtuviera una respuesta tan buena hace 2 semanas, las cosas serían más fáciles. Sin embargo, muy agradecido por su respuesta, ¡gracias!
luckyi