R neuralnet - compute gibt eine konstante Antwort

11

Ich versuche, das neuralnetPaket von R (Dokumentation hier ) zur Vorhersage zu verwenden.

Hier, was ich versuche zu tun:

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

Kann mir jemand erklären, warum Fehler so groß sind und warum alle vorhergesagten Werte fast konstant sind?

Luckyi
quelle

Antworten:

6

Ich bin kein Experte für neuronale Netze, aber ich denke, die folgenden Punkte könnten für Sie hilfreich sein. Es gibt auch einige nette Beiträge, z. B. diesen über versteckte Einheiten , nach denen Sie auf dieser Website suchen können, welche neuronalen Netze Sie möglicherweise nützlich finden.

1 Große Fehler: Warum hat Ihr Beispiel überhaupt nicht funktioniert?

Warum sind die Fehler so groß und warum sind alle vorhergesagten Werte nahezu konstant?

Dies liegt daran, dass das neuronale Netzwerk die von Ihnen angegebene Multiplikationsfunktion nicht berechnen konnte und die Ausgabe einer konstanten Zahl in der Mitte des Bereichs yunabhängig davon xder beste Weg war, um Fehler während des Trainings zu minimieren. (Beachten Sie, dass 58749 dem Mittelwert der Multiplikation zweier Zahlen zwischen 1 und 500 ziemlich nahe kommt.)

Es ist sehr schwer zu erkennen, wie ein neuronales Netzwerk eine Multiplikationsfunktion auf sinnvolle Weise berechnen kann. Überlegen Sie, wie jeder Knoten im Netzwerk zuvor berechnete Ergebnisse kombiniert: Sie nehmen eine gewichtete Summe der Ausgaben vorheriger Knoten (und wenden dann eine Sigmoidfunktion darauf an, siehe z. B. eine Einführung in neuronale Netze , um die Ausgabe dazwischen zu zerlegen- -1 und 1). Wie erhalten Sie eine gewichtete Summe, um zwei Eingaben zu multiplizieren? (Ich nehme jedoch an, dass es möglich sein könnte, eine große Anzahl versteckter Ebenen zu verwenden, um die Multiplikation auf eine sehr konstruierte Weise zum Laufen zu bringen.)

2 Lokale Minima: Warum ein theoretisch vernünftiges Beispiel möglicherweise nicht funktioniert

Selbst wenn Sie versuchen, etwas hinzuzufügen, treten in Ihrem Beispiel Probleme auf: Das Netzwerk trainiert nicht erfolgreich. Ich glaube, dass dies auf ein zweites Problem zurückzuführen ist: das Erhalten lokaler Minima während des Trainings. Tatsächlich ist die Verwendung von zwei Schichten mit 5 versteckten Einheiten für die Addition viel zu kompliziert, um die Addition zu berechnen. Ein Netzwerk ohne versteckte Einheiten trainiert perfekt:

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

Natürlich könnten Sie Ihr ursprüngliches Problem in ein zusätzliches Problem verwandeln, indem Sie Protokolle erstellen, aber ich denke nicht, dass dies das ist, was Sie wollen, also weiter ...

3 Anzahl der Trainingsbeispiele im Vergleich zur Anzahl der zu schätzenden Parameter

Was wäre also ein vernünftiger Weg, um Ihr neuronales Netz mit zwei Schichten von 5 versteckten Einheiten zu testen, wie Sie es ursprünglich hatten? Neuronale Netze werden häufig zur Klassifizierung verwendet, um zu entscheiden, obxk>cschien eine vernünftige Wahl des Problems. ich benutztek=(1,2,3,4,5) und c=3750. Beachten Sie, dass mehrere Parameter gelernt werden müssen.

Im folgenden Code verfolge ich einen sehr ähnlichen Ansatz wie Sie, außer dass ich zwei neuronale Netze trainiere, eines mit 50 Beispielen aus dem Trainingssatz und eines mit 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 ist offensichtlich, dass das netALLviel besser macht! Warum ist das? Schauen Sie sich an, was Sie mit einem plot(netALL)Befehl erhalten:

Geben Sie hier die Bildbeschreibung ein

Ich mache es zu 66 Parametern, die während des Trainings geschätzt werden (5 Eingänge und 1 Bias-Eingang für jeden der 11 Knoten). Sie können 66 Parameter mit 50 Trainingsbeispielen nicht zuverlässig schätzen. Ich vermute, dass Sie in diesem Fall möglicherweise die Anzahl der zu schätzenden Parameter reduzieren können, indem Sie die Anzahl der Einheiten reduzieren. Und Sie können anhand des Aufbaus eines neuronalen Netzwerks erkennen, dass ein einfacheres neuronales Netzwerk während des Trainings möglicherweise weniger auf Probleme stößt.

In der Regel möchten Sie bei jedem maschinellen Lernen (einschließlich linearer Regression) viel mehr Trainingsbeispiele als zu schätzende Parameter haben.

TooTone
quelle
1
Viele Informationen zum Nachdenken, danke! Du liegst absolut richtig! Wenn die Variablen normalisiert würden, die Anzahl der Trainingsbeispiele größer wäre und die Anzahl der Neuronen auf einer verborgenen Schicht gleich eins wäre, würde es viel besser aussehen. Natürlich keine Multiplikationsfunktion, sondern etwas Ähnliches. Ah, wenn ich vor 2 Wochen eine so großartige Antwort bekommen hätte, wären die Dinge einfacher. Vielen Dank für Ihre Antwort, danke!
Luckyi