Entrenamiento de neural network con PyBrain no convergerá

Tengo el siguiente código, del tutorial de 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] 

Sin embargo, el resultado es una neural network que no está bien entrenada. Al observar la salida de error, la red se entrena adecuadamente, sin embargo, utiliza el argumento ‘continueEpochs’ para entrenar un poco más y la red vuelve a empeorar. Así que la red está convergiendo, pero no hay manera de obtener la red mejor entrenada. La documentación de PyBrain implica que la red es devuelta, la cual está mejor entrenada, sin embargo, devuelve una Tupla de errores.

Cuando se escriben continueEpochs a 0, obtengo un error (ValueError: max () arg es una secuencia vacía), por lo que continueEpochs debe ser mayor que 0.

PyBrain se mantiene realmente porque parece que hay una gran diferencia en la documentación y el código.

Después de algunas excavaciones más, descubrí que el ejemplo del tutorial de PyBrain está completamente fuera de lugar.

Cuando miramos la firma del método en el código fuente encontramos:

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

Esto significa que el 25% del conjunto de entrenamiento se utiliza para la validación. Si bien este es un método muy válido para entrenar una red en datos, no lo va a hacer cuando tenga la gama completa de posibilidades a su disposición, es decir, un conjunto de soluciones XOR 2-in-1-out de 4 filas. Cuando uno quiere entrenar un conjunto XOR y elimina una de las filas para validación, tiene como consecuencia inmediata que obtiene un conjunto de entrenamiento muy escaso donde se omite una de las combinaciones posibles, lo que se traduce automáticamente en los pesos que no se están entrenando.

Normalmente, cuando omite el 25% de los datos para la validación, lo hace asumiendo que ese 25% cubre “la mayoría” del espacio de la solución que la red ya ha encontrado más o menos. En este caso, esto no es cierto y cubre el 25% del espacio de la solución completamente desconocido para la red desde que lo eliminó para validación.

Entonces, el capacitador estaba entrenando la red correctamente, pero al omitir el 25% del problema de XOR, esto se traduce en una red mal entrenada.

Un ejemplo diferente en el sitio web de PyBrain como un inicio rápido sería muy útil, porque este ejemplo es simplemente erróneo en este caso específico de XOR. Podría preguntarse si ellos mismos probaron el ejemplo, porque solo genera redes aleatorias mal entrenadas.

Tomé la excelente clase de Aprendizaje automático en Coursera , impartida por Andrew Ng, y una parte de la clase cubrió el entrenamiento de una pequeña neural network para reconocer xor. Así que me preocupó un poco el ejemplo de Pybrain basado en partes del inicio rápido que no convergían.

Creo que hay muchas razones, incluida la anterior sobre la división del conjunto mínimo de datos en capacitación y validación. En un momento del curso, Andrew dijo que “no es la persona con el mejor algoritmo que gana, sino la que tiene más datos. Y continuó explicando que la explosión en la disponibilidad de datos en la década de 2000 es parte de la razón de la Resurgimiento en la IA, ahora llamado Aprendizaje Automático.

Así que con todo eso en mente encontré que

  1. El conjunto de validación puede tener 4 muestras, porque eso viene después de la fase de entrenamiento.
  2. la red solo necesita 2 nodos en la capa oculta, como aprendí en la clase,
  3. la tasa de aprendizaje debe ser bastante pequeña en este caso, como 0.005, o de lo contrario el entrenamiento a veces saltará la respuesta (este es un punto importante de la clase que confirmé jugando con los números).
  4. cuanto menor sea la velocidad de aprendizaje, más pequeños pueden ser los maxEpochs. Una pequeña tasa de aprendizaje significa que la convergencia toma pasos más pequeños a lo largo del gradiente hacia la minimización. Si es más grande, necesita un maxEpochs más grande para que espere más tiempo antes de decidir que ha alcanzado un mínimo.
  5. Necesita un sesgo = Verdadero en la red (lo que agrega un nodo constante 1 a las capas de entrada y ocultas). Lee las respuestas a esta pregunta sobre el sesgo.
  6. Finalmente, y lo más importante, necesitas un gran conjunto de entrenamiento. 1000 convergieron en la respuesta correcta aproximadamente el 75% del tiempo. Sospecho que esto tiene que ver con el algoritmo de minimización. Los números más pequeños fallarían con frecuencia.

Así que aquí hay un código que funciona:

 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) 

De esta manera puede converger. Si la tasa de aprendizaje es demasiado pequeña (por ejemplo, 0.01), se pierde en el mínimo local. Como he probado, la tasa de aprendizaje en 0.3-30, puede converger.

Lo siguiente parece dar consistentemente los resultados correctos:

 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])