Нейронная сеть ReLU выводит все нули

Вот ссылка на мой проект: 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 моей программы (показанной выше), когда я пытаюсь применить градиентный спуск. Как я могу это исправить, чтобы программа действительно обновляла веса должным образом? Моя реализация relu выглядит следующим образом:

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

person Aaron    schedule 05.12.2018    source источник
comment
Добро пожаловать в SO! Пожалуйста, пройдите экскурсию и прочитайте , как спросить. Вы всегда должны публиковать минимальный, полный и проверяемый экзамен, так как ваш вопрос должен быть понятным, не требуя читатель переходить по любым ссылкам.   -  person cheersmate    schedule 06.12.2018


Ответы (1)


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

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

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

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

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

person cheersmate    schedule 06.12.2018