51 Stimmen

Neuronales Netzwerk erzeugt immer gleiche/ähnliche Ausgaben für jede Eingabe

Ich habe ein Problem, bei dem ich versuche, ein neuronales Netz für Tic-Tac-Toe zu erstellen. Aus irgendeinem Grund führt das Training des neuronalen Netzwerks jedoch dazu, dass es für jede beliebige Eingabe fast die gleiche Ausgabe erzeugt.

Ich habe einen Blick darauf geworfen Künstliche neuronale Netze Benchmark aber meine Netzimplementierung ist für Neuronen mit der gleichen Aktivierungsfunktion für jedes Neuron gebaut, d.h. keine konstanten Neuronen.

Um sicherzugehen, dass das Problem nicht nur auf meine Wahl des Trainingssatzes (1218 Brettzustände und Züge, die von einem genetischen Algorithmus generiert wurden) zurückzuführen ist, habe ich versucht, das Netz so zu trainieren, dass es XOR reproduziert. Dabei wurde die logistische Aktivierungsfunktion verwendet. Anstatt die Ableitung zu verwenden, habe ich den Fehler multipliziert mit output*(1-output) da in einigen Quellen behauptet wurde, dies sei gleichbedeutend mit der Verwendung des Derivats. Ich kann den Haskell-Quelltext auf HPaste stellen, aber es ist ein wenig peinlich, ihn anzusehen. Das Netzwerk hat 3 Schichten: die erste Schicht hat 2 Eingänge und 4 Ausgänge, die zweite hat 4 Eingänge und 1 Ausgang, und die dritte hat 1 Ausgang. Die Erhöhung auf 4 Neuronen in der zweiten Schicht hat nicht geholfen, und auch nicht die Erhöhung auf 8 Ausgänge in der ersten Schicht.

Anschließend berechnete ich die Fehler, die Netzwerkausgabe, die Bias-Aktualisierungen und die Gewichtungsaktualisierungen von Hand auf der Grundlage von http://hebb.mit.edu/courses/9.641/2002/lectures/lecture04.pdf um sicherzustellen, dass in diesen Teilen des Codes kein Fehler aufgetreten ist (das war nicht der Fall, aber ich werde es wahrscheinlich noch einmal tun, nur um sicherzugehen). Da ich Batch-Training verwende, habe ich nicht mit x in Gleichung (4). Ich füge jedoch die Gewichtsänderung hinzu http://www.faqs.org/faqs/ai-faq/neural-nets/part2/section-2.html schlägt vor, sie stattdessen zu subtrahieren.

Das Problem blieb auch in diesem vereinfachten Netz bestehen. Dies sind zum Beispiel die Ergebnisse nach 500 Epochen Batch-Training und inkrementellem Training.

Input    |Target|Output (Batch)      |Output(Incremental)
[1.0,1.0]|[0.0] |[0.5003781562785173]|[0.5009731800870864]
[1.0,0.0]|[1.0] |[0.5003740346965251]|[0.5006347214672715]
[0.0,1.0]|[1.0] |[0.5003734471544522]|[0.500589332376345]
[0.0,0.0]|[0.0] |[0.5003674110937019]|[0.500095157458231]

Wenn man subtrahiert statt addiert, hat man das gleiche Problem, nur dass alles 0,99 irgendwas statt 0,50 irgendwas ist. 5000 Epochen führen zum gleichen Ergebnis, außer dass das im Stapelverfahren trainierte Netzwerk in jedem Fall genau 0,5 liefert. (Sogar 10.000 Epochen haben beim Batch-Training nicht funktioniert.)

Gibt es irgendetwas, das dieses Verhalten hervorrufen könnte?

Außerdem habe ich mir die Zwischenfehler für das inkrementelle Training angesehen, und obwohl die Eingaben der versteckten/eingehenden Schichten variierten, war der Fehler für das Ausgangsneuron immer +/-0,12. Beim Stapeltraining stiegen die Fehler zwar an, aber extrem langsam, und die Fehler waren alle extrem klein (x10^-7). Unterschiedliche anfängliche Zufallsgewichte und Verzerrungen machten ebenfalls keinen Unterschied.

Beachten Sie, dass es sich um ein Schulprojekt handelt, daher wären Hinweise/Anleitungen hilfreicher. Obwohl es eine schreckliche Idee war, das Rad neu zu erfinden und mein eigenes Netzwerk zu erstellen (in einer Sprache, die ich nicht gut kenne!), hielt ich es für ein Schulprojekt für angemessener (damit ich weiß, was vor sich geht... zumindest in der Theorie. An meiner Schule scheint es keinen Informatiklehrer zu geben).

EDIT: Zwei Schichten, eine Eingabeschicht mit 2 Eingängen zu 8 Ausgängen und eine Ausgabeschicht mit 8 Eingängen zu 1 Ausgang, führen zu fast den gleichen Ergebnissen: 0,5+/-0,2 (oder so) für jeden Trainingsfall. Ich spiele auch mit pyBrain herum, um zu sehen, ob irgendeine Netzwerkstruktur dort funktionieren wird.

Edit 2: Ich verwende eine Lernrate von 0,1. Tut mir leid, dass ich das vergessen habe.

Edit 3: Pybrains "trainUntilConvergence" bringt mir auch kein vollständig trainiertes Netzwerk, aber 20000 Epochen schon, mit 16 Neuronen in der versteckten Schicht. 10000 Epochen und 4 Neuronen, nicht so viel, aber nahe dran. In Haskell, mit der Eingabeschicht mit 2 Eingängen und 2 Ausgängen, der versteckten Schicht mit 2 Eingängen und 8 Ausgängen und der Ausgabeschicht mit 8 Eingängen und 1 Ausgang... habe ich das gleiche Problem mit 10000 Epochen. Und mit 20000 Epochen.

Edit 4: Ich habe das Netzwerk auf der Grundlage des obigen MIT-PDFs noch einmal von Hand durchgespielt, und die Werte stimmen überein, so dass der Code korrekt sein sollte, es sei denn, ich habe die Gleichungen falsch verstanden.

Ein Teil meines Quellcodes ist unter http://hpaste.org/42453/neural_network__not_working Ich arbeite daran, meinen Code etwas aufzuräumen und ihn in ein Github-Repository (statt in ein privates Bitbucket-Repository) zu stellen.

Der gesamte relevante Quellcode ist jetzt unter https://github.com/l33tnerd/hsann .

49voto

Justas Punkte 5208

Ich hatte ähnliche Probleme, konnte sie aber durch eine Änderung lösen:

  • Verkleinern Sie das Problem auf eine überschaubare Größe. Ich habe zunächst versucht, zu viele Eingänge mit zu vielen Einheiten der versteckten Schicht zu verwenden. Sobald ich das Problem verkleinert hatte, konnte ich sehen, ob die Lösung für das kleinere Problem funktionierte. Das funktioniert auch deshalb, weil sich bei einer Verkleinerung die Zeiten für die Berechnung der Gewichte deutlich verringern, so dass ich viele verschiedene Dinge ausprobieren kann, ohne zu warten.
  • Stellen Sie sicher, dass Sie genügend versteckte Einheiten haben. Das war für mich ein großes Problem. Ich hatte etwa 900 Eingaben, die mit ~10 Einheiten in der versteckten Schicht verbunden waren. Das war viel zu wenig, um schnell zu konvergieren. Aber es wurde auch sehr langsam, wenn ich zusätzliche Einheiten hinzufügte. Die Verkleinerung der Anzahl der Eingänge half sehr.
  • Ändern Sie die Aktivierungsfunktion und ihre Parameter. Ich habe zuerst tanh verwendet. Dann habe ich andere Funktionen ausprobiert: Sigmoid, normalisiertes Sigmoid, Gauß, usw.. Ich stellte auch fest, dass das Ändern der Funktionsparameter, um die Funktionen steiler oder flacher zu machen, Auswirkungen darauf hatte, wie schnell das Netzwerk konvergierte.
  • Ändern Sie die Parameter des Lernalgorithmus. Versuchen Sie verschiedene Lernraten (0,01 bis 0,9). Probieren Sie auch verschiedene Momentum-Parameter aus, wenn Ihr Algo dies unterstützt (0,1 bis 0,9).

Ich hoffe, das hilft denjenigen, die diesen Thread bei Google finden!

21voto

Henry Punkte 309

Ich weiß, dass dies sehr spät für den ursprünglichen Beitrag ist, aber ich bin darauf gestoßen, weil ich ein ähnliches Problem hatte und keiner der Gründe, die hier gepostet wurden, das abdeckt, was in meinem Fall falsch war.

Ich arbeitete an einem einfachen Regressionsproblem, aber jedes Mal, wenn ich das Netzwerk trainierte, konvergierte es zu einem Punkt, an dem es mir für jede Eingabe die gleiche Ausgabe (oder manchmal ein paar verschiedene Ausgaben) lieferte. Ich spielte mit der Lernrate, der Anzahl der versteckten Schichten/Knoten, dem Optimierungsalgorithmus usw., aber es machte keinen Unterschied. Selbst als ich mir ein lächerlich einfaches Beispiel ansah und versuchte, die Ausgabe (1d) von zwei verschiedenen Eingaben (1d) vorherzusagen:

import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F

class net(nn.Module):
    def __init__(self, obs_size, hidden_size):
        super(net, self).__init__()
        self.fc = nn.Linear(obs_size, hidden_size)
        self.out = nn.Linear(hidden_size, 1)

    def forward(self, obs):
        h = F.relu(self.fc(obs))
        return self.out(h)

inputs = np.array([[0.5],[0.9]])
targets = torch.tensor([3.0, 2.0], dtype=torch.float32)

network = net(1,5)
optimizer = torch.optim.Adam(network.parameters(), lr=0.001)

for i in range(10000):
    out = network(torch.tensor(inputs, dtype=torch.float32))
    loss = F.mse_loss(out, targets)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    print("Loss: %f outputs: %f, %f"%(loss.data.numpy(), out.data.numpy()[0], out.data.numpy()[1]))

aber es wurde trotzdem immer der Durchschnittswert der Ausgänge für beide Eingänge ausgegeben. Es stellte sich heraus, dass der Grund dafür war, dass die Dimensionen meiner Ausgänge und Ziele nicht übereinstimmten: die Ziele waren Size[2] und die Ausgänge waren Size[2,1], und aus irgendeinem Grund gab PyTorch die Ausgänge als Size[2,2] im MSE-Verlust aus, was alles völlig durcheinander brachte. Sobald ich geändert:

targets = torch.tensor([3.0, 2.0], dtype=torch.float32)

まで

targets = torch.tensor([[3.0], [2.0]], dtype=torch.float32)

Es hat funktioniert, wie es sollte. Dies wurde offensichtlich mit PyTorch getan, aber ich vermute, dass vielleicht andere Bibliotheken Variablen auf die gleiche Weise übertragen.

7voto

user18853 Punkte 2601

Bei mir war es genau wie in Ihrem Fall, die Ausgabe des neuronalen Netzes war immer gleich, unabhängig von Training und Anzahl der Schichten usw.

Es stellte sich heraus, dass mein Back-Propagation-Algorithmus ein Problem hatte. An einer Stelle habe ich mit -1 multipliziert, wo dies nicht erforderlich war.

Es könnte ein weiteres Problem dieser Art geben. Die Frage ist, wie man es beheben kann?

Schritte zur Fehlersuche:

Step1 : Write the algorithm such that it can take variable number of input layers and variable number of input & output nodes.
Step2 : Reduce the hidden layers to 0. Reduce input to 2 nodes, output to 1 node.
Step3 : Now train for binary-OR-Operation.
Step4 : If it converges correctly, go to Step 8.
Step5 : If it doesn't converge, train it only for 1 training sample
Step6 : Print all the forward and prognostication variables (weights, node-outputs, deltas etc)
Step7 : Take pen&paper and calculate all the variables manually.
Step8 : Cross verify the values with algorithm.
Step9 : If you don't find any problem with 0 hidden layers. Increase hidden layer size to 1. Repeat step 5,6,7,8

Das hört sich nach viel Arbeit an, aber es funktioniert IMHO sehr gut.

2voto

arslanbenzer Punkte 459

Ich hatte das gleiche Problem mit meinem Modell, wenn die Anzahl der Schichten groß ist. Ich habe eine Lernrate von 0,0001 verwendet. Wenn ich die Lernrate auf 0,0000001 senke, scheint das Problem gelöst zu sein. Ich denke, die Algorithmen bleiben auf lokalen Minima hängen, wenn die Lernrate zu niedrig ist.

2voto

Ich weiß, dass dies für den ursprünglichen Beitrag viel zu spät ist, aber vielleicht kann ich jemandem damit helfen, da ich das gleiche Problem hatte.

Bei mir bestand das Problem darin, dass meine Eingabedaten in wichtigen Spalten fehlende Werte aufwiesen, während die Trainings-/Testdaten nicht fehlten. Ich ersetzte diese Werte durch Nullwerte und voilà, plötzlich waren die Ergebnisse plausibel. Überprüfen Sie also vielleicht Ihre Daten, vielleicht sind sie falsch dargestellt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X