¿Cómo crear una neural network simple de 3 capas y enseñarla usando un aprendizaje supervisado?

Basándome en los tutoriales de PyBrain, logré reunir el siguiente código:

#!/usr/bin/env python2 # coding: utf-8 from pybrain.structure import FeedForwardNetwork, LinearLayer, SigmoidLayer, FullConnection from pybrain.datasets import SupervisedDataSet from pybrain.supervised.trainers import BackpropTrainer n = FeedForwardNetwork() inLayer = LinearLayer(2) hiddenLayer = SigmoidLayer(3) outLayer = LinearLayer(1) n.addInputModule(inLayer) n.addModule(hiddenLayer) n.addOutputModule(outLayer) in_to_hidden = FullConnection(inLayer, hiddenLayer) hidden_to_out = FullConnection(hiddenLayer, outLayer) n.addConnection(in_to_hidden) n.addConnection(hidden_to_out) n.sortModules() ds = SupervisedDataSet(2, 1) ds.addSample((0, 0), (0,)) ds.addSample((0, 1), (1,)) ds.addSample((1, 0), (1,)) ds.addSample((1, 1), (0,)) trainer = BackpropTrainer(n, ds) # trainer.train() trainer.trainUntilConvergence() print n.activate([0, 0])[0] print n.activate([0, 1])[0] print n.activate([1, 0])[0] print n.activate([1, 1])[0] 

Se supone que debe aprender la función XOR, pero los resultados parecen bastante aleatorios:

0.208884929522

0.168926515771

0.459452834043

0.424209192223

o

0.84956138664

0.888512762786

0.564964077401

0.611111147862

Hay cuatro problemas con su enfoque, todos fáciles de identificar después de leer las Preguntas Frecuentes de la Red Neural :

  • ¿Por qué usar un sesgo / umbral? : debe agregar un nodo de sesgo. La falta de sesgo hace que el aprendizaje sea muy limitado: el hiperplano de separación representado por la red solo puede pasar por el origen. Con el nodo de sesgo, puede moverse libremente y ajustarse mejor a los datos:

     bias = BiasUnit() n.addModule(bias) bias_to_hidden = FullConnection(bias, hiddenLayer) n.addConnection(bias_to_hidden) 
  • ¿Por qué no codificar entradas binarias como 0 y 1? : todas sus muestras están en un solo cuadrante del espacio muestral. Muevalos para que se dispersen alrededor del origen:

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

    (Corrija el código de validación al final de su script en consecuencia).

  • trainUntilConvergence método trainUntilConvergence funciona con validación y hace algo que se parece al método de detención temprana . Esto no tiene sentido para un conjunto de datos tan pequeño. Utilice trainEpochs en trainEpochs lugar. 1000 épocas son más que suficientes para este problema para que la red pueda aprender:

     trainer.trainEpochs(1000) 
  • ¿Qué tasa de aprendizaje se debe utilizar para backprop? : Ajuste el parámetro de velocidad de aprendizaje. Esto es algo que haces cada vez que empleas una neural network. En este caso, el valor 0.1 o incluso 0.2 aumenta dramáticamente la velocidad de aprendizaje:

     trainer = BackpropTrainer(n, dataset=ds, learningrate=0.1, verbose=True) 

    (Tenga en cuenta el parámetro verbose=True . Es esencial observar cómo se comporta el error al ajustar los parámetros).

Con estas correcciones obtengo resultados consistentes y correctos para la red dada con el conjunto de datos dado, y error inferior a 1e-23 .