Как создать простую трехслойную нейронную сеть и обучить ее с помощью обучения с учителем?

На основе учебников PyBrain мне удалось собрать воедино следующий код:

#!/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]

Предполагается изучить функцию XOR, но результаты кажутся довольно случайными:

0.208884929522

0.168926515771

0.459452834043

0.424209192223

or

0.84956138664

0.888512762786

0.564964077401

0.611111147862


person Luke    schedule 18.09.2015    source источник


Ответы (1)


В вашем подходе есть четыре проблемы, которые легко определить после прочтения часто задаваемых вопросов о нейронных сетях. :

  • Зачем использовать смещение/порог?: вам следует добавить узел смещения. Отсутствие смещения делает обучение очень ограниченным: разделяющая гиперплоскость, представленная сетью, может проходить только через начало координат. С узлом смещения он может свободно перемещаться и лучше соответствовать данным:

    bias = BiasUnit()
    n.addModule(bias)
    
    bias_to_hidden = FullConnection(bias, hiddenLayer)
    n.addConnection(bias_to_hidden)
    
  • Почему бы не кодировать двоичные входные данные как 0 и 1?: все ваши образцы лежали в одном квадранте выборочного пространства. Переместите их, чтобы они были разбросаны вокруг начала координат:

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

    (Соответствующим образом исправьте код проверки в конце скрипта.)

  • trainUntilConvergence работает с использованием проверки и делает что-то похожее на метод ранней остановки . Это не имеет смысла для такого небольшого набора данных. Вместо этого используйте trainEpochs. 1000 эпох более чем достаточно для этой задачи, чтобы сеть научилась:

    trainer.trainEpochs(1000)
    
  • Какую скорость обучения следует использовать для обратного распространения?: Настройте параметр скорости обучения. . Это то, что вы делаете каждый раз, когда используете нейронную сеть. В этом случае значение 0.1 или даже 0.2 резко увеличивает скорость обучения:

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

    (Обратите внимание на параметр verbose=True. При настройке параметров очень важно наблюдать за поведением ошибки.)

С этими исправлениями я получаю согласованные и правильные результаты для данной сети с заданным набором данных, а ошибка меньше 1e-23.

person BartoszKP    schedule 20.09.2015
comment
Есть ли способ обучать сеть до тех пор, пока средняя ошибка не станет меньше (или равна) требуемой или не будет достигнут предел количества эпох? - person Luke; 20.09.2015
comment
В документации @Luke PyBrain честно говорится, что эта документация содержит лишь субъективную выдержку из доступных методов. Поэтому вам нужно изучить реализацию вашего конкретного дистрибутива PyBrain. Но даже если его нет, такой цикл очень легко реализовать самостоятельно. - person BartoszKP; 20.09.2015