使用 ReLU 作为激活函数的注意事项
Considerations for using ReLU as activation function
我正在实现一个神经网络,想使用 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]
可以看出输出结果与预期的异或结果相差很大。那么问题来了,使用 ReLU 作为激活函数有什么特殊的考虑吗?
请不要犹豫,向我询问更多上下文或代码。提前致谢。
编辑: 导数中存在错误,因为它只有 returns 单个浮点值,而不是 NumPy 数组。正确的代码应该是:
def relu_prime(data, epsilon=0.1):
gradients = 1. * (data > epsilon)
gradients[gradients == 0] = epsilon
return gradients
简答
不要对二进制数字使用 ReLU。它旨在以更大的价值运作。当没有负值时也要避免使用它,因为这基本上意味着您使用的线性激活函数不是最好的。最好与卷积神经网络一起使用。
长答案
不能说 python 代码是否有问题,因为我在 Java 中编写代码。但从逻辑上讲,我认为在这种情况下使用 ReLU 是一个错误的决定。当我们预测 XOR 时,您的 NN [0,1] 的值范围有限。这也是 sigmoid 激活函数的范围。使用 ReLU,您可以使用值 [0,infinity] 进行操作,这意味着您永远不会使用大量值,因为它是 XOR。但是 ReLU 仍会考虑这些值,并且您将获得的错误会增加。这就是为什么您在大约 50% 的时间内得到正确答案的原因。事实上,这个值可以低至 0%,也可以高达 99%。故事的寓意 - 在决定使用哪个激活函数时,尝试将 NN 中的输入值范围与激活函数值的范围相匹配。
您的 relu_prime
函数应该是:
def relu_prime(data, epsilon=0.1):
gradients = 1. * (data > 0)
gradients[gradients == 0] = epsilon
return gradients
注意数据矩阵中每个值与0的比较,而不是epsilon
。这遵循 leaky ReLUs 的标准定义,当 x > 0
时创建 1
的分段梯度,否则创建 epsilon
。
我无法评论 leaky ReLU 是否是解决 XOR 问题的最佳选择,但这应该可以解决您的梯度问题。
我正在实现一个神经网络,想使用 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]
可以看出输出结果与预期的异或结果相差很大。那么问题来了,使用 ReLU 作为激活函数有什么特殊的考虑吗?
请不要犹豫,向我询问更多上下文或代码。提前致谢。
编辑: 导数中存在错误,因为它只有 returns 单个浮点值,而不是 NumPy 数组。正确的代码应该是:
def relu_prime(data, epsilon=0.1):
gradients = 1. * (data > epsilon)
gradients[gradients == 0] = epsilon
return gradients
简答
不要对二进制数字使用 ReLU。它旨在以更大的价值运作。当没有负值时也要避免使用它,因为这基本上意味着您使用的线性激活函数不是最好的。最好与卷积神经网络一起使用。
长答案
不能说 python 代码是否有问题,因为我在 Java 中编写代码。但从逻辑上讲,我认为在这种情况下使用 ReLU 是一个错误的决定。当我们预测 XOR 时,您的 NN [0,1] 的值范围有限。这也是 sigmoid 激活函数的范围。使用 ReLU,您可以使用值 [0,infinity] 进行操作,这意味着您永远不会使用大量值,因为它是 XOR。但是 ReLU 仍会考虑这些值,并且您将获得的错误会增加。这就是为什么您在大约 50% 的时间内得到正确答案的原因。事实上,这个值可以低至 0%,也可以高达 99%。故事的寓意 - 在决定使用哪个激活函数时,尝试将 NN 中的输入值范围与激活函数值的范围相匹配。
您的 relu_prime
函数应该是:
def relu_prime(data, epsilon=0.1):
gradients = 1. * (data > 0)
gradients[gradients == 0] = epsilon
return gradients
注意数据矩阵中每个值与0的比较,而不是epsilon
。这遵循 leaky ReLUs 的标准定义,当 x > 0
时创建 1
的分段梯度,否则创建 epsilon
。
我无法评论 leaky ReLU 是否是解决 XOR 问题的最佳选择,但这应该可以解决您的梯度问题。