R neuralnet: il calcolo fornisce una risposta costante


11

Sto cercando di usare il neuralnetpacchetto di R (documentazione qui ) per la previsione.

Ecco cosa sto cercando di fare:

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

Qualcuno può spiegarmi perché gli errori sono così grandi e perché tutti i valori previsti sono quasi costanti?

Risposte:


6

Non sono un esperto di reti neurali ma penso che i seguenti punti potrebbero esserti utili. Ci sono anche alcuni bei post, ad esempio questo su unità nascoste , che puoi cercare in questo sito su quali reti neurali fanno che potresti trovare utili.

1 Grandi errori: perché il tuo esempio non ha funzionato affatto

perché gli errori sono così grandi e perché tutti i valori previsti sono quasi costanti?

Ciò è dovuto al fatto che la rete neurale non è stata in grado di calcolare la funzione di moltiplicazione che gli era stata assegnata e di emettere un numero costante al centro dell'intervallo y, indipendentemente da x, era il modo migliore per ridurre al minimo gli errori durante l'allenamento. (Nota come 58749 sia abbastanza vicino alla media di moltiplicare due numeri tra 1 e 500 insieme.)

È molto difficile vedere come una rete neurale possa calcolare una funzione di moltiplicazione in modo sensato. Pensa a come ciascun nodo della rete combina risultati calcolati in precedenza: prendi una somma ponderata degli output dei nodi precedenti (e quindi applica una funzione sigmoidale ad esso, vedi, ad esempio, Introduzione alle reti neurali , per scrunch l'output tra e ). Come hai intenzione di ottenere una somma ponderata per darti la moltiplicazione di due input? (Suppongo, tuttavia, che potrebbe essere possibile prendere un gran numero di livelli nascosti per far funzionare la moltiplicazione in modo molto artificioso.)11

2 Minimi locali: perché un esempio teoricamente ragionevole potrebbe non funzionare

Tuttavia, anche provando a fare l'addizione si incontrano problemi nell'esempio: la rete non si allena correttamente. Credo che ciò sia dovuto a un secondo problema: ottenere minimi locali durante l'allenamento. In effetti, per l'aggiunta, l'utilizzo di due strati di 5 unità nascoste è troppo complicato per calcolare l'aggiunta. Una rete senza unità nascoste si allena perfettamente:

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

Certo, potresti trasformare il tuo problema originale in un problema di aggiunta prendendo i registri, ma non penso che questo sia quello che vuoi, quindi in seguito ...

3 Numero di esempi di allenamento rispetto al numero di parametri da stimare

Quindi quale sarebbe un modo ragionevole per testare la tua rete neurale con due strati di 5 unità nascoste come avevi originariamente? Le reti neurali sono spesso usate per la classificazione, quindi decidere se sembrava una ragionevole scelta del problema. Ho usato e . Si noti che ci sono diversi parametri da imparare.k = ( 1 , 2 , 3 , 4 , 5 ) c = 3750xk>ck=(1,2,3,4,5)c=3750

Nel codice seguente seguo un approccio molto simile al tuo, tranne per il fatto che alleno due reti neurali, una con 50 esempi dal set di addestramento e una 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

È evidente che lo netALLfa molto meglio! Perchè è questo? Dai un'occhiata a quello che ottieni con un plot(netALL)comando:

inserisci qui la descrizione dell'immagine

Faccio 66 parametri che vengono stimati durante l'allenamento (5 input e 1 input bias per ciascuno di 11 nodi). Non è possibile stimare in modo affidabile 66 parametri con 50 esempi di allenamento. Ho il sospetto che in questo caso potresti essere in grado di ridurre il numero di parametri da stimare riducendo il numero di unità. E puoi vedere dalla costruzione di una rete neurale per aggiungere che una rete neurale più semplice potrebbe avere meno probabilità di incorrere in problemi durante l'allenamento.

Ma come regola generale in qualsiasi apprendimento automatico (inclusa la regressione lineare) si desidera avere molti più esempi di formazione rispetto ai parametri da stimare.


1
Molte informazioni a cui pensare, grazie! Hai assolutamente ragione! Se le variabili fossero normalizzate, il numero di esempi di allenamento fosse maggiore e il numero di neuroni su uno strato nascosto uguale a uno, sembrerebbe molto meglio. Certo, non una funzione di moltiplicazione ma qualcosa di simile. Ah, se avessi una risposta così grande 2 settimane fa, le cose sarebbero più facili. Tuttavia, molto grato per la tua risposta, grazie!
luckyi
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.