Нейронная сеть ReLU, выводящая все 0 - PullRequest
0 голосов
/ 05 декабря 2018

Вот ссылка на мой проект: https://github.com/aaronnoyes/neural-network/blob/master/nn.py

Я реализовал базовую нейронную сеть в Python.По умолчанию он использует функцию активации сигмоида, и это прекрасно работает.Я пытаюсь сравнить изменения в скорости обучения между функциями активации, поэтому я попытался реализовать опцию для использования ReLU.Однако когда он запускается, все веса сразу падают до 0.

 if (self.activation == 'relu'):
        d_weights2 = np.dot(self.layer1.T, (2*(self.y - self.output) * self.relu(self.output, True)))
        d_weights1 = np.dot(self.input.T,  (np.dot(2*(self.y - self.output) * self.relu(self.output, True), self.weights2.T) * self.relu(self.layer1, True)))

Я почти уверен, что проблема в строках 54-56 моей программы (показанной выше), когда я пытаюсь применить градиентный спуск.Как я могу это исправить, чтобы программа действительно обновляла веса соответствующим образом?Моя реальная реализация выглядит следующим образом:

def relu(self, x, derivative=False):
    if derivative:
        return 1. * (x > 0)
    else:
        return x * (x > 0)

1 Ответ

0 голосов
/ 06 декабря 2018

Есть две проблемы с вашим кодом:

  • Вы также применяете relu к выходному слою.Рекомендуемый стандартный подход - использовать идентификацию как активацию выходного уровня для регрессии и сигмоид / софтмакс для классификации.

  • Вы используете скорость обучения 1, которая является высокой.(Обычные тестовые значения - 1e-2 и меньше.)

Я изменил выходную активацию на сигмовидную, даже когда использовал повторную активацию в скрытых слоях

def feedforward(self):
   ...

   if (self.activation == 'relu'):
        self.layer1 = self.relu(np.dot(self.input, self.weights1))
        self.output = self.sigmoid(np.dot(self.layer1, self.weights2))

    return self.output

def backprop(self):
    ...

    if (self.activation == 'relu'):
        d_weights2 = np.dot(self.layer1.T, (2*(self.y - self.output) * self.sigmoid(self.output, True)))
        d_weights1 = np.dot(self.input.T,  (np.dot(2*(self.y - self.output) * self.relu(self.output, True), self.weights2.T) * self.relu(self.layer1, True)))

ииспользовал меньшую скорость обучения

    # update the weights with the derivative (slope) of the loss function
    self.weights1 += .01 * d_weights1
    self.weights2 += .01 * d_weights2

, и это результат:

Фактический результат: [[0,00000] [1,00000] [1,00000] [0,00000]]

Прогнозируемый результат: [[0.10815] [0.92762] [0.94149] [0.05783]]

...