I have the following code, from the 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]
However the result is a neural network that is not trained well. When looking at the error output the network gets trained properly however it uses the 'continueEpochs' argument to train some more and the network is performing worse again. So the network is converging, but there is no way to get the best trained network. The documentation of PyBrain implies that the network is returned which is trained best, however it returns a Tuple of errors.
Whens etting continueEpochs to 0 I get an error (ValueError: max() arg is an empty sequence) so continueEpochs must be larger than 0.
Is PyBrain actually maintained because it seems there is a big difference in documentation and code.
The amount of the training data is low or the data we are pushing on the model is corrupted or not collected with the data integrity. The activation function we are using with the network often leads to good results from the model but if complexity is higher then the model can fail to converge.
There are two ways to test for convergence: either the weights or the value of the objective do not change significantly (up to some numerical threshold), or the error rate does not decrease further. They are not exclusive but, rather, complementary (as pointed out previously).
After some more digging I found that the example on the PyBrain's tutorial is completely out of place.
When we look at the method signature in the source code we find:
def trainUntilConvergence(self, dataset=None, maxEpochs=None, verbose=None, continueEpochs=10, validationProportion=0.25):
This means that 25% of the training set is used for validation. Although that is a very valid method when training a network on data you are not going to do this when you have the complete range of possiblities at your disposal, namely a 4-row XOR 2-in-1-out solution set. When one wants to train an XOR set and you remove one of the rows for validation that has as an immediate consequence that you get a very sparse training set where one of the possible combinations is omitted resulting automatically into those weights not being trained.
Normally when you omit 25% of the data for validation you do this by assuming that those 25% cover 'most' of the solution space the network already has encountered more or less. In this case this is not true and it covers 25% of the solution space completely unknown to the network since you removed it for validation.
So, the trainer was training the network correctly, but by omitting 25% of the XOR problem this results in a badly trained network.
A different example on the PyBrain website as a quickstart would be very handy, because this example is just plain wrong in this specific XOR case. You might wonder if they tried the example themselves, because it just outputs random badly trained networks.
I took the excellent Machine Learning class on Coursera, taught by Andrew Ng, and one part of the class covered training a small neural net to recognize xor. So I was a bit troubled by the pybrain example based on parts of the quickstart that did not converge.
I think there are many reasons, including the one above about the minimal dataset being split into training and validation. At one point in the course Andrew said "its not the person with the best algorithm that wins, its the one with the most data. And he went on to explain that the explosion in data availability in the 2000's is part of the reason for the resurgence in AI, now called Machine Learning.
So with all that in mind I found that
So here's some code that works:
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])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With