使用 ReLU 作为激活函数的注意事项

Posted

技术标签:

【中文标题】使用 ReLU 作为激活函数的注意事项【英文标题】:Considerations for using ReLU as activation function 【发布时间】:2017-05-23 04:25:48 【问题描述】:

我正在实现一个神经网络,并想使用 ReLU 作为神经元的激活函数。此外,我正在使用 SDG 和反向传播训练网络。我正在用范式 XOR 问题测试神经网络,到目前为止,如果我使用逻辑函数或双曲正切作为激活函数,它可以正确分类新样本。

我一直在阅读有关使用 Leaky ReLU 作为激活函数的好处,并在 Python 中实现它,如下所示:

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

npNumPy 的名称。相关的导数是这样实现的:

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

【问题讨论】:

修改梯度计算部分后是否有效? @KrishnaKishoreAndhavarapu 修改后我得到了正确的结果,但 10 次中有 5 次。我相信我每次都应该得到正确的结果。这个激活函数显然缺少一些东西。 你确定gradients = 1. * (data &gt; epsilon) 有意义吗?你对泄漏 ReLU 函数的定义是什么?对于某些大于零的数据值,这会将梯度设置为等于 epsilon。 @NickBecker 我对 Leaky ReLU 的定义来自*** (en.wikipedia.org/wiki/Rectifier_(neural_networks)#Leaky_ReLUs)。该行返回一个由 0 和 1 组成的数组。 0 来自所有小于epsilon 的值,而 1 来自所有大于epsilon 的剩余值。在这种情况下,我使用的是epsilon = 0.1 当我查看有关 Leaky ReLU 的***部分中的分段函数 f(x) 时,我看到当 x > 0 时为 1 的分段导数,否则为 alpha。不过,我可能会遗漏一些东西。 【参考方案1】:

你的relu_prime 函数应该是:

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

注意数据矩阵中每个值与 0 的比较,而不是 epsilon。这遵循leaky ReLUs 的标准定义,当x &gt; 0epsilon 时创建分段梯度1

我无法评论泄漏的 ReLU 是否是 XOR 问题的最佳选择,但这应该可以解决您的梯度问题。

【讨论】:

现在我大部分时间都能得到正确的结果。除了@ArnisShaykh 的回答和你的回答外,我现在了解到激活函数的选择取决于数据值。【参考方案2】:

简答

不要将 ReLU 与二进制数字一起使用。它旨在以更大的价值运行。也避免在没有负值时使用它,因为这基本上意味着您使用的不是最好的线性激活函数。最好与卷积神经网络一起使用。

长答案

不能说python代码是否有任何问题,因为我是用Java编写的。但从逻辑上讲,我认为在这种情况下使用 ReLU 是一个糟糕的决定。由于我们预测 XOR,因此您的 NN [0,1] 的值范围有限。这也是 sigmoid 激活函数的范围。使用 ReLU,您可以使用值 [0,infinity] 进行操作,这意味着您永远不会使用大量值,因为它是 XOR。但是 ReLU 仍然会考虑这个值,并且你将得到的错误会增加。这就是为什么你大约有 50% 的时间得到正确答案的原因。事实上,这个值可以低至 0%,高至 99%。故事的寓意 - 在决定使用哪个激活函数时,请尝试将 NN 中的输入值范围与激活函数值的范围相匹配。

【讨论】:

感谢您指出这一事实。我没有考虑。完全有道理。 很高兴有帮助。

以上是关于使用 ReLU 作为激活函数的注意事项的主要内容,如果未能解决你的问题,请参考以下文章

注意力机制+ReLU激活函数:自适应参数化ReLU激活函数

注意力机制+ReLU激活函数=自适应参数化ReLU

注意力机制下的激活函数:自适应参数化ReLU

激活函数 sigmoid、tanh、relu

激活函数 sigmoid、tanh、relu

激活函数——Relu,Swish