2017-02-22 49 views
1

Я хочу реализовать MLP (MultiLayer Perceptron) для решения проблемы XOR. Я сокрушаю голову, потому что я не большой ученый, и я хочу быть уверенным в понимании каждой линии этой программы.Алгоритм обратной просадки застрял в MultiLayer Perceptron

Начну вопросы:

  1. Есть конкретный метод для отладки нейронной сети? (например, предопределенные известные веса, которые приводят к ожидаемому решению)
  2. Является следующим алгоритм обратного распространения (in pseodocode) ?
  3. Должно ли предубеждение быть в этом алгоритме? Если нет, является ли предубеждение необходимым для решения проблемы XOR? И если да, то должно быть смещение 1 на нейрон, 1 на слой или 1 на сеть?
  4. Правильно ли реализована моя реализация python? Если нет, то это касается обратного распространения, прямого распространения, отсутствия смещения или чего-то еще?

Каждый ответ очень приветствуется. Это не «домашнее задание», но если вы очень боитесь этого, я буду очень доволен только хорошими советами. Я все еще не использую должным образом numpy, потому что я более дева, чем ученый, и иногда имею проблемы с матричными уравнениями (в настоящее время я работаю над этим). Таким образом, мне очень сложно хорошо понять различные реализации, которые я нашел.


EDIT: Теперь отлично алгоритм работы, и я остановлюсь различные проблемы была в реализации псевдокод/​​Python:

Теория:

  • pseudocode был неправильным при регулировке веса (я отредактировал код, чтобы отметить строку WRONG с исправлением). Я использовал выходы выходного уровня, где я должен использовать значения входов
  • Фактически можно решить проблему XOR без предубеждений и только 1 скрытый слой. Интересно, что он работает только с 4-мя нейронами в скрытом слое или более, но не с 3. Однако после бенчмарков добавление смещения может значительно ускорить время оптимальной конвергенции (5x speeder или более)

реализация питон:

  • веса были инициализированы в случайном порядке между 0 и 1, а не между -1 и 1, она не может работать, как это.

И, наконец, this resource был большой помощью, чтобы хорошо понять «волшебство нейронов». Это не помогло мне отладить backpropagation, но теперь это свидетельствует о том, что я никогда не смог бы заставить его работать без каких-либо теоретических знаний. Если, как я, вы больше дева, чем ученый, я настоятельно рекомендую вам проверить это.


на основе книги «Artifical интеллекта для разработчиков» по Виржини Матив, вот псевдокода для обратного распространения алгоритма (это французская книга, извините за плохой TRADUCTIONS):

While stop criteria is not achieved: 
    Initialize d(i) 

    For each example: 
     Compute output value s(i)       #1 

     For each output neuron weight:      #2 
      d(i) = s(i) * (1 - s(i)) * (y(i) - s(i)) 
     EndFor 

     For each hidden neuron weight: 
      sum = 0 
      For each link towards output neuron k: 
       sum += d(k) * w(i->k) 
      EndFor 
      d(i) = o(i) * (1 - o(i)) * sum 
     EndFor 

     For each weight of the network: 
      If link towards output neuron: 
       w(i) += rate * d(i) * o(i) 
      Else 
       w(i) += rate * d(i) * s(i) # WRONG: s(i) should be input(i) 
      EndIf 
     EndFor 
    EndFor 
EndWhile 

В приведенном выше примере d(x) являются дельтами, o(x) являются выходы скрытого уровня, s(x) - выходные выходы выходного уровня, y(x) - ожидаемые выходы и w(x) a re сетевые веса.

Я понимаю, что линия # 1 является прямым распространением, а линии после # 2 (включено) около обратного распространения. Таким образом, правильный алгоритм можно записать в виде:

While stop criteria is not achieved: 
    Initialize d(i) 

    For each example: 
     output = Forward propagation with example inputs     #1 
     Backpropagation of the error between output and expected output #2 
    EndFor 
EndWhile 

Моя проблема заключается в том, что алгоритм, кажется, идет по кругу с алгоритмом обратного распространения и изменения весов, например, вот выходы для скрытого слоя:

[Epoch 0, inputs (1.0, 1.0)]: hidden outputs: None 
[Epoch 0, inputs (0.0, 0.0)]: hidden outputs: [ 0.7755638 0.64556638 0.68163599] 
[Epoch 0, inputs (1.0, 0.0)]: hidden outputs: [ 0.5 0.5 0.5] 
[Epoch 0, inputs (0.0, 1.0)]: hidden outputs: [ 0.60747218 0.58975313 0.55246625] 
[Epoch 1, inputs (1.0, 1.0)]: hidden outputs: [ 0.68911554 0.55079694 0.62718831] 
[Epoch 1, inputs (1.0, 0.0)]: hidden outputs: [ 0.77449528 0.64107552 0.67770194] 
[Epoch 1, inputs (0.0, 0.0)]: hidden outputs: [ 0.60728756 0.58957687 0.55230354] 
[Epoch 1, inputs (0.0, 1.0)]: hidden outputs: [ 0.5 0.5 0.5] 
[Epoch 2, inputs (0.0, 0.0)]: hidden outputs: [ 0.68877278 0.54872848 0.6254074 ] 
[Epoch 2, inputs (1.0, 0.0)]: hidden outputs: [ 0.5 0.5 0.5] 
[Epoch 2, inputs (1.0, 1.0)]: hidden outputs: [ 0.60700878 0.58812487 0.5509695 ] 
[Epoch 2, inputs (0.0, 1.0)]: hidden outputs: [ 0.77344667 0.63591436 0.67311723] 
[Epoch 3, inputs (0.0, 0.0)]: hidden outputs: [ 0.68856723 0.54708942 0.62400827] 
[Epoch 3, inputs (1.0, 0.0)]: hidden outputs: [ 0.5 0.5 0.5] 

Ввод примеров в случайном порядке ничего не меняет. Более того, я пробовал каждый курс обучения (от 0,05 до 0,95) с тем же результатом, поэтому я думаю, что это не о плохой конвергенции. Вот моя реализация Python:

def sigmoid(x): 
    return 1/(1 + np.exp(-x)) 

def dsigmoid(y): 
    return y * (1.0 - y) 

class NeuralNetwork: 

    def __init__(self, nb_inputs, nb_hidden, nb_outputs, learning_rate): 
     self.nb_inputs = nb_inputs 
     self.nb_hidden = nb_hidden 
     self.nb_outputs = nb_outputs 
     self.learning_rate = learning_rate 

     self.output_deltas = None 
     self.output_weights = np.random.random((nb_outputs, nb_hidden)) # WRONG: should be between -1 and 1, not 0 and 1 
     self.outputs = None 
     self.hidden_deltas = None 
     self.hidden_weights = np.random.random((nb_hidden, nb_inputs)) # WRONG: should be between -1 and 1, not 0 and 1 
     self.hidden_outputs = None 

    def forward_propagation(self, inputs): 
     self.hidden_outputs = np.zeros((self.nb_hidden,)) 
     self.outputs = np.zeros((self.nb_outputs,)) 

     # get outputs for hidden layer 
     for i in range(self.nb_hidden): 
      aggregated = sum([inputs[j] * self.hidden_weights[i][j] for j in range(self.nb_inputs)]) 
      self.hidden_outputs[i] = sigmoid(aggregated) 

     # get inputs for output layer 
     for i in range(self.nb_outputs): 
      aggregated = sum([self.hidden_outputs[j] * self.output_weights[i][j] for j in range(self.nb_hidden)]) 
      self.outputs[i] = sigmoid(aggregated) 

    def backpropagation(self, expected_outputs): 

     # find deltas for output layer 
     for i in range(self.nb_outputs): 
      for j in range(self.nb_hidden): 
       self.output_deltas[i][j] = dsigmoid(self.outputs[i]) * (expected_outputs[i] - self.outputs[i]) 

     # find deltas for hidden layer 
     for i in range(self.nb_hidden): 
      for j in range(self.nb_inputs): 
       total = 0.0 
       for k in range(self.nb_outputs): 
        total += self.output_deltas[k][i] * self.output_weights[k][i] 
       self.hidden_deltas[i][j] = dsigmoid(self.hidden_outputs[i]) * total 

     # change weights for output layer 
     for i in range(self.nb_outputs): 
      for j in range(self.nb_hidden): 
       self.output_weights[i][j] += self.learning_rate * self.output_deltas[i][j] * self.outputs[i] # WRONG: should be self.hidden_outputs[j] 

     # change weights for inputs layer 
     for i in range(self.nb_hidden): 
      for j in range(self.nb_inputs): 
       self.hidden_weights[i][j] += self.learning_rate * self.hidden_deltas[i][j] * self.hidden_outputs[i] # WRONG: should be inputs[j] 

    def train(self, data, nb_iterations): 
     for i in range(nb_iterations): 
      # Init deltas 
      self.output_deltas = np.zeros((self.nb_outputs, self.nb_hidden), dtype=np.float64) 
      self.hidden_deltas = np.zeros((self.nb_hidden, self.nb_inputs), dtype=np.float64) 

      # Train on examples with different orders 
      for inputs, expected_output in sorted(data.items(), key=lambda x: random.random()): 
       expected_outputs = np.array([expected_output]) 

       self.forward_propagation(inputs) 
       self.backpropagation(expected_outputs) # WRONG: need inputs: backpropagation(inputs, expected_outputs) 

    def predict(self, inputs): 
     self.forward_propagation(inputs) 
     return self.outputs 
+0

'алгоритм, кажется, идет в circles' <- как правило, является показатель скорости обучения, который слишком высоко – inspectorG4dget

+0

Спасибо за ваш ответ. К сожалению, я пробовал много обучающих курсов (от 0,05 до 0,95) с точно такими же результатами. Я отредактировал мое сообщение с этой точностью – Loheek

+0

У вас может быть смещение для каждого узла и для каждого слоя, и также часто бывает, что вы добавляете эти смещения. Проблема XOR не может быть решена без предвзятости, кроме использования 3 скрытых нейронов, где один из них фактически действует как смещение. – Jodo

ответ

0

Я дробильно мою голову на него, так как долгое время, потому что я не большой ученый, и я хочу быть уверенным, чтобы понять каждую строку этой программы.

Вы получили мой ответ на это. Продолжайте так, вы будете качать!

Отказ от ответственности: частичный ответ. Я могу улучшить его со временем.

Есть ли специальный метод для отладки нейронной сети? (например, предопределенных известных весов, которые приводят к ожидаемому решению)

В общем нет. В большинстве случаев это почти невозможно, поскольку количество весов. Вы все равно можете попытаться контролировать активность нейронов (переменная aggregated в вашем коде), например. отправляйте сетевые аналогичные входы два раза подряд и посмотрите, если он учится i.e. он приближается и приближается к правильному значению.

Правильно ли применяется следующий алгоритм обратного распространения (в псевдокоде)?

Попробуйте проверить. Это от вас?

Должно ли предубеждение в этом алгоритме?Если нет, необходимо ли смещение решить проблему XOR? И если да, должен ли смещение быть 1 на нейрон, 1 на слой или 1 на сеть?

Обычно существует 1 biais на нейрон. Нет проблем, если вы просто проигнорируете это.

Правильно ли реализована моя реализация python? Если нет, речь идет об обратном распространении , прямом распространении, отсутствии смещения или прочего?

Будет проверять. Отсутствие смещения в порядке.

В качестве сноски я бы рекомендовал эту онлайн-книгу: http://neuralnetworksanddeeplearning.com/chap1.html есть довольно много математики, не тратьте время на математику, постарайтесь получить концепцию. Я нахожу это супер дидактическим.

Надеется, что это поможет (немного)
pltrdy

+0

Спасибо, это очень мотивирует! Я уверен, что знаю, что не пропущу какой-либо метод отладки. Я попытаюсь контролировать агрегированные значения. Что касается предвзятости, ответ Джодо выше говорит о том, что для решения проблемы XOR необходимо одно смещение, вы уверены, что я могу сделать рабочую программу без нее? В других вопросах, связанных с СО, я не нашел ясного ответа. Псевдокод из французской книги «Intelligence artificielle pour les développeurs» от Virginie MATHIVET, Большое спасибо за ресурс, я проверю его как можно скорее! Вы очень помогаете! – Loheek

+0

Я знаю, что смещение используется только для переключения функции активации (сигмоида здесь), но я думал, что в XOR-проблеме нет необходимости в этом, потому что нам нужен выход диапазона от 0 до 1, но я, вероятно, ошибаюсь? – Loheek

+0

Моя интуиция заключается в том, что это невозможно без предубеждений. Я не понимаю, как это возможно. Теоретически, в любом случае большее количество слоев/нейронов могло решить проблему. Тем не менее, это, очевидно, полезно. Может быть, ваша установка (nlayers x hidden_neurons) не может учиться без предвзятости. – pltrdy