Нейронная сеть функции relu выводит 0 или 1

Я попытался реализовать простую нейронную сеть, используя как сигмовидную, так и релу-функции. с сигмовидной функцией я получил хорошие результаты. но при использовании relu я получил массив 0 или 1. (Мне нужна функция relu, потому что я хочу использовать код для некоторых выходов> 1).

def relu(x):
return np.maximum(0,x)

def reluDerivative(x):
  x[x<=0] = 0
  x[x>0] = 1
  return x
training_inputs = np.array([[9, 0 , 1],
[7, 1, 1],
[8, 0, 1],
[5, 1, 1]
])

training_outputs = np.array([[9, 7, 8, 5]]).T

np.random.seed(1)

synaptic_weights = 2 * np.random.random((3,1)) - 1


for iteration in range(100000):

   outputs = relu(np.dot(training_inputs, synaptic_weights))


   error = training_outputs - outputs
   adjustments = error * reluDerivative(outputs)
   synaptic_weights += np.dot(training_inputs.T, adjustments )

print("output after training: \n" , outputs)

person yo bar    schedule 26.09.2019    source источник


Ответы (1)


Обновление:

(Спасибо за включение методов relu и reluDerivative)

Ошибка действительно в методе reluDerivative(x).

Когда вы делаете x[x<=0] = 0, вы изменяете данный массив numpy. Аргумент x не является клоном/глубокой копией outputs, это точно такой же массив numpy. Таким образом, когда вы изменяете x, вы также изменяете outputs.

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

Обновление 2

Похоже, что в коде больше проблем, чем в приведенном выше, и они немного сложнее:

  • Если вы пройдете код с помощью отладчика, вы заметите, что, к сожалению, с текущим случайным начальным числом (1) синаптические веса инициализируются таким образом, что все ваши обучающие примеры дают отрицательное скалярное произведение, которое ReLU затем устанавливает в ноль. . Градиент нуля равен нулю, и это один из рисков использования ReLU. Как смягчить это?

    • Well, you could use other seeds (e.g. seed=10) but this is not a satisfying solution
    • Эта проблема была бы гораздо менее вероятной, если бы у вас был гораздо больший обучающий набор (например, 100 вместо 4), потому что маловероятно, что все 100 приведут к отрицательным скалярным произведениям.
    • Я заметил, что первый элемент в каждой строке данных намного больше остальных. Выполнение «нормализации» набора данных позволило бы избежать этой проблемы. Вы можете прочитать больше о том, как нормализовать ввод.
    • Наконец, именно из-за проблемы «нулевого градиента» с ReLU был изобретен «LeakyReLU». В более крупных нейронных сетях обычных ReLU может быть достаточно, но в вашем упрощенном примере LeaklyReLU наверняка избежал бы этой проблемы.
  • Как только вы решите эти вышеперечисленные проблемы, вы все равно заметите другую проблему. Ошибки и градиенты исчезнут через несколько итераций. Это связано с тем, что вы еще не используете параметр «скорость обучения» для ограничения скорости обновления весов. Узнайте, как использовать параметр скорости обучения (или альфа-канала).

Удачи!

person enerve    schedule 26.09.2019
comment
если я понял ваш комментарий, я должен изменить свою производную функцию relu, чтобы она не изменила мой вывод. Благодарность - person yo bar; 28.09.2019
comment
Я пробовал это, но он продолжает выдавать мне 0 на выходе - person yo bar; 28.09.2019
comment
Хорошо, я сам протестировал код и обновил свой ответ. - person enerve; 29.09.2019
comment
Большое спасибо, я попытаюсь реализовать это и выяснить, что происходит - person yo bar; 29.09.2019
comment
Я думаю, что исправил все первые четыре проблемы, о которых вы упоминали ранее. Но что касается скорости обучения и ее эффекта, я этого не понял... На самом деле, после того, как я исправил эти четыре проблемы, у меня все еще есть тот же результат. - person yo bar; 30.09.2019
comment
что ты уже испробовал? Что вы обнаружите, когда используете отладчик для пошагового выполнения кода (или операторов печати/регистратора)? - person enerve; 01.10.2019
comment
да, я отлаживаю его с помощью vscode, я пытался уменьшить количество итераций, чтобы посмотреть, как он себя ведет, но я не понял - person yo bar; 02.10.2019
comment
Если вы запустите одну итерацию, каково значение градиента (корректировки) в конце? Каковы обновленные веса? Изменяет ли изменение параметра обучения его работу? Вы можете поместить строку отладчика в метод relu abd reluDerivative и посмотреть, что там происходит. - person enerve; 02.10.2019