web-dev-qa-db-de.com

Neuronales Netzwerk-Training mit PyBrain läuft nicht zusammen

Ich habe den folgenden Code aus dem PyBrain-Tutorial:

from pybrain.datasets import SupervisedDataSet
from pybrain.supervised.trainers import BackpropTrainer
from pybrain.tools.shortcuts import buildNetwork
from pybrain.structure.modules import TanhLayer

ds = SupervisedDataSet(2, 1)
ds.addSample((0,0), (0,))
ds.addSample((0,1), (1,))
ds.addSample((1,0), (1,))
ds.addSample((1,1), (0,))

net     = buildNetwork(2, 3, 1, bias=True, hiddenclass=TanhLayer)
trainer = BackpropTrainer(net, ds)

for inp, tar in ds:
     print [net.activate(inp), tar]

errors  = trainer.trainUntilConvergence()

for inp, tar in ds:
     print [net.activate(inp), tar]

Das Ergebnis ist jedoch ein neuronales Netzwerk, das nicht gut trainiert ist. Bei der Betrachtung der Fehlerausgabe wird das Netzwerk richtig trainiert, es wird jedoch das Argument 'continueEpochs' verwendet, um noch etwas zu trainieren, und das Netzwerk arbeitet wieder schlechter. Das Netzwerk konvergiert, aber es gibt keine Möglichkeit, das best trainierte Netzwerk zu erhalten. Die Dokumentation von PyBrain impliziert, dass das Netzwerk zurückgegeben wird, das am besten trainiert wird, es wird jedoch ein Tupel von Fehlern zurückgegeben.

Wenn continueEpochs auf 0 gesetzt wird, erhalte ich einen Fehler (ValueError: max () arg ist eine leere Sequenz). Daher muss continueEpochs größer als 0 sein.

Ist PyBrain tatsächlich gepflegt, weil es so aussieht, als ob es einen großen Unterschied in der Dokumentation und im Code gibt. 

32
avanwieringen

Nach einigem Graben fand ich heraus, dass das Beispiel im PyBrain-Tutorial vollkommen fehl am Platz ist.

Wenn wir die Methodensignatur im Quellcode betrachten, finden wir:

def trainUntilConvergence(self, dataset=None, maxEpochs=None, verbose=None, continueEpochs=10, validationProportion=0.25):

Dies bedeutet, dass 25% des Trainingssatzes für die Validierung verwendet werden. Obwohl dies eine sehr gültige Methode ist, wenn Sie ein Netzwerk mit Daten trainieren, werden Sie dies nicht tun, wenn Sie über alle Möglichkeiten verfügen, nämlich ein 4-reihiges XOR 2-in-1- aus Lösung Set. Wenn Sie ein XOR -Set trainieren möchten und Sie eine der Zeilen für die Validierung entfernen, hat dies unmittelbar zur Folge, dass Sie ein sehr spärliches Trainingsset erhalten, bei dem eine der möglichen Kombinationen weggelassen wird, was automatisch zu diesen Gewichtungen führt nicht trainiert werden.

Wenn Sie 25% der Daten für die Validierung auslassen, gehen Sie normalerweise davon aus, dass diese 25% den größten Teil des Lösungsbereichs ausmachen, auf den das Netzwerk bereits mehr oder weniger gestoßen ist. In diesem Fall trifft dies nicht zu und deckt 25% des Lösungsbereichs ab, der dem Netzwerk völlig unbekannt ist, seit Sie es zur Validierung entfernt haben.

So trainierte der Trainer das Netzwerk richtig, aber wenn 25% des XOR -Problems weggelassen werden, führt dies zu einem schlecht trainierten Netzwerk.

Ein anderes Beispiel auf der PyBrain-Website als Schnellstart wäre sehr praktisch, da dieses Beispiel in diesem speziellen Fall XOR einfach falsch ist. Sie fragen sich vielleicht, ob sie das Beispiel selbst ausprobiert haben, weil es einfach schlecht trainierte Netzwerke ausgibt.

35
avanwieringen

Ich nahm an der hervorragenden Machine Learning-Klasse auf Coursera teil, die von Andrew Ng unterrichtet wurde, und ein Teil der Klasse befasste sich mit der Ausbildung eines kleinen neuronalen Netzes, um Xor zu erkennen. Ich war etwas beunruhigt über das Beispiel von pybrain, das auf Teilen des quickstart basiert, die nicht konvergieren.

Ich denke, es gibt viele Gründe, einschließlich des oben genannten, dass der minimale Datensatz in Training und Validierung aufgeteilt wird. An einem Punkt des Kurses sagte Andrew: "Es ist nicht die Person mit dem besten Algorithmus, die gewinnt, es ist die mit den meisten Daten. Und er erklärte weiter, dass die Explosion der Datenverfügbarkeit in den 2000er Jahren ein Grund für die Wiederaufleben in der KI, jetzt Machine Learning genannt.

Mit all dem habe ich das gefunden

  1. der Validierungssatz kann 4 Proben enthalten, da dies nach der Trainingsphase erfolgt.
  2. das Netzwerk benötigt nur 2 Knoten in der verborgenen Schicht, wie ich in der Klasse gelernt habe.
  3. die Lernrate muss in diesem Fall ziemlich niedrig sein (0,005). Andernfalls wird das Training manchmal übersprungen (dies ist ein wichtiger Punkt aus der Klasse, den ich durch das Spielen mit den Zahlen bestätigt habe).
  4. je kleiner die Lernrate ist, desto kleiner können die maxEpochs sein. Eine kleine Lernrate bedeutet, dass die Konvergenz entlang des Gradienten kleinere Schritte zur Minimierung erfordert. Wenn es größer ist, benötigen Sie einen größeren maxEpochs, damit er länger warten kann, bevor er entscheidet, dass er ein Minimum erreicht hat.
  5. Sie benötigen einen Bias = True im Netzwerk (wodurch den eingegebenen und den verborgenen Ebenen ein konstanter Knoten hinzugefügt wird). Lesen Sie die Antworten auf diese Frage über Voreingenommenheit.
  6. Schließlich und vor allem benötigen Sie ein großes Trainingsset. 1000 konvergierten in 75% der Fälle auf die richtige Antwort. Ich vermute, das hat mit dem Minimierungsalgorithmus zu tun. Kleinere Zahlen würden häufig versagen.

Hier ist also ein Code, der funktioniert:

from pybrain.datasets import SupervisedDataSet

dataModel = [
    [(0,0), (0,)],
    [(0,1), (1,)],
    [(1,0), (1,)],
    [(1,1), (0,)],
]

ds = SupervisedDataSet(2, 1)
for input, target in dataModel:
    ds.addSample(input, target)

# create a large random data set
import random
random.seed()
trainingSet = SupervisedDataSet(2, 1);
for ri in range(0,1000):
    input,target = dataModel[random.getrandbits(2)];
    trainingSet.addSample(input, target)

from pybrain.tools.shortcuts import buildNetwork
net = buildNetwork(2, 2, 1, bias=True)

from pybrain.supervised.trainers import BackpropTrainer
trainer = BackpropTrainer(net, ds, learningrate = 0.001, momentum = 0.99)
trainer.trainUntilConvergence(verbose=True,
                              trainingData=trainingSet,
                              validationData=ds,
                              maxEpochs=10)

print '0,0->', net.activate([0,0])
print '0,1->', net.activate([0,1])
print '1,0->', net.activate([1,0])
print '1,1->', net.activate([1,1])
17
toddInPortland
trainer = BackpropTrainer(net, ds, learningrate = 0.9, momentum=0.0, weightdecay=0.0, verbose=True) 
trainer.trainEpochs(epochs=1000)

Dieser Weg kann zusammenlaufen. Wenn die Lernrate zu gering ist (z. B. 0,01), geht das lokale Minimum verloren. Wie ich getestet habe, Lernrate in 0,3-30, kann es konvergieren.

2
lym

Folgendes scheint immer die richtigen Ergebnisse zu liefern:

from pybrain.tools.shortcuts import buildNetwork
from pybrain.structure import TanhLayer
from pybrain.datasets import SupervisedDataSet
from pybrain.supervised.trainers import BackpropTrainer

#net = buildNetwork(2, 3, 1, bias=True, hiddenclass=TanhLayer)
net = buildNetwork(2, 3, 1, bias=True)

ds = SupervisedDataSet(2, 1)
ds.addSample((0, 0), (0,))
ds.addSample((0, 1), (1,))
ds.addSample((1, 0), (1,))
ds.addSample((1, 1), (0,))
ds.addSample((0, 0), (0,))
ds.addSample((0, 1), (1,))
ds.addSample((1, 0), (1,))
ds.addSample((1, 1), (0,))
ds.addSample((0, 0), (0,))
ds.addSample((0, 1), (1,))
ds.addSample((1, 0), (1,))
ds.addSample((1, 1), (0,))
ds.addSample((0, 0), (0,))
ds.addSample((0, 1), (1,))
ds.addSample((1, 0), (1,))
ds.addSample((1, 1), (0,))
ds.addSample((0, 0), (0,))
ds.addSample((0, 1), (1,))
ds.addSample((1, 0), (1,))
ds.addSample((1, 1), (0,))
ds.addSample((0, 0), (0,))
ds.addSample((0, 1), (1,))
ds.addSample((1, 0), (1,))
ds.addSample((1, 1), (0,))

trainer = BackpropTrainer(net, ds, learningrate=0.001, momentum=0.99)

trainer.trainUntilConvergence(verbose=True)

print net.activate([0,0])
print net.activate([0,1])
print net.activate([1,0])
print net.activate([1,1])
0
bkanber