J'ai le code suivant, tiré du didacticiel PyBrain:
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]
Cependant, le résultat est un réseau de neurones mal formé. Lorsque le résultat d'erreur est affiché, le réseau est correctement formé, mais il utilise l'argument 'continueEpochs' pour en former davantage et le réseau fonctionne encore moins bien. Le réseau converge donc, mais il n’ya aucun moyen d’obtenir le réseau le mieux formé. La documentation de PyBrain implique que le réseau renvoyé est celui qui est le mieux formé, mais il renvoie un tuple d'erreurs.
Lorsque je termine continuEpochs sur 0, j'obtiens une erreur (ValueError: max () arg est une séquence vide), donc continueEpochs doit être supérieur à 0.
PyBrain est-il réellement maintenu car il semble qu'il existe une grande différence dans la documentation et le code.
Après avoir approfondi mes connaissances, j'ai trouvé que l'exemple du didacticiel de PyBrain était complètement déplacé.
Lorsque nous examinons la signature de la méthode dans le code source, nous trouvons:
def trainUntilConvergence(self, dataset=None, maxEpochs=None, verbose=None, continueEpochs=10, validationProportion=0.25):
Cela signifie que 25% de l'ensemble de formation est utilisé pour la validation. Bien que ce soit une méthode très valable pour former un réseau sur des données, vous ne le ferez pas si vous disposez de toutes les possibilités, à savoir une solution à 4 rangées XOR à deux entrées. ensemble. Lorsque vous souhaitez former un ensemble XOR et que vous supprimez une des lignes pour la validation, cela a pour conséquence immédiate d'obtenir un ensemble d'apprentissage très clairsemé dans lequel l'une des combinaisons possibles est omise, ce qui entraîne automatiquement la non-pondération qualifié.
Normalement, lorsque vous omettez 25% des données pour la validation, vous procédez ainsi en supposant que ces 25% couvrent "la plupart" de l'espace de solution déjà plus ou moins rencontré par le réseau. Dans ce cas, cela n’est pas vrai et couvre 25% de l’espace de la solution complètement inconnu du réseau puisque vous l’avez retiré pour validation.
Ainsi, le formateur entraînait correctement le réseau, mais en supprimant 25% du problème XOR, il en résulte un réseau mal formé.
Un exemple différent sur le site Web PyBrain en tant que quickstart serait très pratique, car cet exemple est tout simplement faux dans ce cas particulier XOR. Vous pourriez vous demander s'ils ont eux-mêmes essayé l'exemple, car il ne génère que des réseaux aléatoires mal entraînés.
J'ai suivi l'excellente classe Machine Learning de Coursera , enseignée par Andrew Ng, et une partie de la classe a consisté à former un petit réseau neuronal pour reconnaître xor. Je suis donc un peu troublé par l'exemple pybrain basé sur des parties du quickstart qui ne convergent pas.
Je pense qu'il y a de nombreuses raisons, y compris celle ci-dessus concernant le jeu de données minimal divisé en formation et validation. À un moment donné, Andrew a déclaré: "Ce n'est pas la personne qui a le meilleur algorithme qui gagne, mais celle qui contient le plus de données. Il a ensuite expliqué que l'explosion de la disponibilité des données dans les années 2000 était l'une des raisons de la résurgence de l'intelligence artificielle, maintenant appelée apprentissage machine.
Donc, avec tout cela à l'esprit, j'ai trouvé que
Alors, voici un code qui fonctionne:
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])
trainer = BackpropTrainer(net, ds, learningrate = 0.9, momentum=0.0, weightdecay=0.0, verbose=True)
trainer.trainEpochs(epochs=1000)
Cette façon peut converger. Si le taux d'apprentissage est trop petit (par exemple 0,01), il a perdu au minimum local. Comme je l’ai testé, le taux d’apprentissage en 0,3-30 peut converger.
Ce qui suit semble donner systématiquement les bons résultats:
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])