Рекомендации по использованию ReLU в качестве функции активации

Я реализую нейронную сеть и хотел использовать ReLU в качестве функции активации нейронов. Кроме того, я обучаю сеть с помощью SDG и обратного распространения. Я тестирую нейронную сеть с парадигматической проблемой XOR, и до сих пор она правильно классифицирует новые образцы, если я использую логистическую функцию или гиперболический тангенс в качестве функций активации.

Я читал о преимуществах использования Leaky ReLU в качестве функции активации и реализовал его на Python следующим образом:

def relu(data, epsilon=0.1):
    return np.maximum(epsilon * data, data)

где np - имя NumPy. Соответствующая производная реализована следующим образом:

def relu_prime(data, epsilon=0.1):
    if 1. * np.all(epsilon < data):
        return 1
    return epsilon

Используя эту функцию в качестве активации, я получаю неверные результаты. Например:

  • Вход = [0, 0] -> Выход = [0,43951457]

  • Вход = [0, 1] -> Выход = [0.46252925]

  • Вход = [1, 0] -> Выход = [0.34939594]

  • Вход = [1, 1] -> Выход = [0.37241062]

Видно, что выходы сильно отличаются от ожидаемых XOR. Возникает вопрос: есть ли какие-то особые соображения по поводу использования ReLU в качестве функции активации?

Пожалуйста, не стесняйтесь спрашивать меня о дополнительном контексте или коде. Заранее спасибо.

РЕДАКТИРОВАТЬ: в производной есть ошибка, поскольку она возвращает только одно значение с плавающей запятой, а не массив NumPy. Правильный код должен быть:

def relu_prime(data, epsilon=0.1):
    gradients = 1. * (data > epsilon)
    gradients[gradients == 0] = epsilon
    return gradients

person tulians    schedule 08.01.2017    source источник
comment
это сработало после изменения части расчета градиента?   -  person Krishna Kishore Andhavarapu    schedule 09.01.2017
comment
@KrishnaKishoreAndhavarapu После внесения изменений я получаю правильные результаты, но примерно 5 раз из 10. Я считаю, что я должен каждый раз получать правильные результаты. В этой функции активации явно чего-то не хватает.   -  person tulians    schedule 09.01.2017
comment
Вы уверены, что gradients = 1. * (data > epsilon) имеет смысл? Каково ваше определение дырявой функции ReLU? Это установило бы градиент равным эпсилону для некоторых значений данных, которые больше нуля.   -  person Nick Becker    schedule 09.01.2017
comment
@NickBecker Мое определение Leaky ReLU взято из Википедии (en.wikipedia.org/ wiki / Rectifier_ (neural_networks) #Leaky_ReLUs). Эта строка возвращает массив из нулей и единиц. 0 берутся из всех значений, которые меньше epsilon, а 1 берутся из всех остальных значений больше epsilon. В данном случае я использую epsilon = 0.1.   -  person tulians    schedule 09.01.2017
comment
Когда я смотрю на кусочную функцию f(x) в том разделе википедии о Leaky ReLUs, я вижу кусочную производную от 1 при x> 0 и альфа в противном случае. Хотя я мог что-то упустить.   -  person Nick Becker    schedule 09.01.2017
comment
@NickBecker Это кусочное поведение - это то, что я генерирую во второй строке relu_prime. Я уже использовал значение 0,01 в эпсилоне. В других сообщениях я видел, что значение epsilon может быть переменным, если оно мало.   -  person tulians    schedule 09.01.2017
comment
gradients == 0 будет True для значений x больше 0, но меньше эпсилон, тем не менее, делая производную эпсилон для значений x больше 0, но меньше эпсилон. Следует ли это из определения f (x)?   -  person Nick Becker    schedule 09.01.2017
comment
Позвольте нам продолжить это обсуждение в чате.   -  person Nick Becker    schedule 09.01.2017


Ответы (2)


Ваша relu_prime функция должна быть:

def relu_prime(data, epsilon=0.1):
    gradients = 1. * (data > 0)
    gradients[gradients == 0] = epsilon
    return gradients

Обратите внимание на сравнение каждого значения в матрице данных с 0 вместо epsilon. Это следует из стандартного определения дырявых ReLU, которое создает кусочный градиент 1, когда x > 0, и epsilon в противном случае.

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

person Nick Becker    schedule 09.01.2017
comment
Теперь я в большинстве случаев получаю правильные результаты. Помимо того, что ответил @ArnisShaykh и ваш, я теперь узнал, что выбор функции активации зависит от значений данных. - person tulians; 09.01.2017

Краткий ответ

Не используйте ReLU с двоичными цифрами. Он разработан для работы с гораздо большими значениями. Также избегайте его использования, когда нет отрицательных значений, потому что в основном это будет означать, что вы используете функцию линейной активации, которая не является лучшей. Лучше всего использовать со сверточными нейронными сетями.

Длинный ответ

Не могу сказать, что с кодом Python что-то не так, потому что я кодирую на Java. Но с точки зрения логики я считаю, что использование ReLU в данном случае - плохое решение. Поскольку мы прогнозируем XOR, существует ограниченный диапазон значений вашего NN [0,1]. Это также диапазон функции активации сигмовидной кишки. С ReLU вы работаете со значениями [0, бесконечность], что означает, что существует очень много значений, которые вы никогда не собираетесь использовать, поскольку это XOR. Но ReLU все равно будет принимать эти значения во внимание, и ошибка, которую вы собираетесь получить, будет увеличиваться. Вот почему вы получаете правильные ответы примерно в 50% случаев. Фактически это значение может быть от 0% до 99%. Мораль истории - при принятии решения, какую функцию активации использовать, попробуйте сопоставить диапазон входных значений в вашей сети с диапазоном значений функции активации.

person Arnis Shaykh    schedule 09.01.2017
comment
Спасибо, что указали на этот факт. Я не думал об этом. Имеет смысл. - person tulians; 09.01.2017
comment
Рад, что это было полезно. - person Arnis Shaykh; 09.01.2017