【问题标题】:Big difference when using Relu over Tanh on a simple problem在一个简单的问题上使用 Relu 而不是 Tanh 有很大的不同
【发布时间】:2020-06-16 09:35:39
【问题描述】:

我正在测试一个玩具问题,输入 0 和 1,输出是奇数还是偶数(简单性本身)。使用使用 Tanh 激活的 MLP,我从未设法绕过随机猜测性能(~50%)!完全是偶然的,我尝试了 Relu(出于绝望),并且......它工作得很好(大部分时间都获得了 100% 的准确度)。

然后,在与朋友讨论时,我们想看看如果我们将零替换为 -1 会发生什么(任务保持不变,奇数或偶数)。令我惊讶的是,它与 Tanh 一起工作(性能在 75~90% 之间)。 Relu 仍然表现更好。

代码

import numpy as np
from sklearn.neural_network import MLPClassifier
# from sklearn.preprocessing import StandardScaler
def generate_data(batch_size, data_length=10, zeros=True):
    x = np.random.randint(0, 2, (batch_size, data_length))

    y = x.sum(axis=1) % 2
    y = y.astype(np.int16).reshape(-1)

    if not zeros: # in this case, convert the zeros to -1
        x[x==0] = -1 
    return x, y

# With ReLU, it is perfect!. With Tanh, it is shit
# clf = MLPClassifier(solver='adam', verbose=True, batch_size=512, activation="relu")
clf = MLPClassifier(solver='adam', verbose=True, batch_size=512, activation="tanh")

X_train, y_train = generate_data(batch_size=10000, data_length=10, zeros=True)
X_test, y_test = generate_data(batch_size=1000, data_length=10, zeros=True)

clf.fit(X_train, y_train)
print(clf.score(X_test, y_test))

要获得 -1 而不是零,只需在使用 generate_data 函数时将 zeros 参数设为 False

谁能解释一下这里发生了什么?

编辑: 感谢@BlackBear 和@Andreas K. 提供答案。所以显然使用 Tanh 会导致神经元饱和(梯度不移动)。通过更好地选择学习率,或者让网络优化更长的时间,它确实有效。例如,将分类器选项更新为

clf = MLPClassifier(solver='adam', verbose=True, batch_size=512, activation="tanh", max_iter=5000, learning_rate="adaptive", n_iter_no_change=100)

它总是有效的!

【问题讨论】:

  • 通过将学习率提高到 learning_rate_init=0.05(默认值为 0.001),我能够使用 tanhzeros=True 获得 1.0 的满分(经过几次试验,直到我得到很好的随机权重初始化)。所以 tanh 也可以,但总的来说 ReLU 更好,将输入集中到 [-1, 1] 也有帮助。
  • 感谢您的尝试!你是对的,改变学习率会有所帮助。但我仍然对以下问题感到困惑:1)这么小的网络如何对初始权重敏感?在这种情况下,什么是好的初始化策略? 2)还是不明白为什么Relu表现更好——它提供了什么优势——?

标签: python numpy machine-learning scikit-learn neural-network


【解决方案1】:

这只是优化过程的一个问题,无法找到合适的权重值。你可以在隐藏层构建一个有 2^10=1024 个神经元的网络,每个输入模式一个,让输出神经元响应偶数个输入对应的神经元。通过此过程,您可以对每个布尔函数进行建模。

【讨论】:

  • 我不明白为什么我需要这么多神经元来模拟这样一个微不足道的函数。它们对神经元的激活不是二元激活。无论如何,我试了一下(有一个 1024 个神经元的隐藏层,带有 Tanh),它给出了相同的结果,这是预期的
  • @OSM 我刚刚给了你一个非正式的证据,证明有一个网络在做你要求的事情,这意味着问题出在优化器上(正如上面的评论所证实的那样)。如果你真的希望我可以告诉你如何建立这样一个网络。
  • 我非常清楚该任务是可学习的,并且确实存在一个网络来解决它(好吧,我刚刚通过 Relu 激活展示了这一点)。我的问题只是关于 Tanh 与 Relu 在如此简单的任务上的行为。 @Andreas 的评论表明学习率是一个因素,我之前没有注意到。尽管如此,您仍然可以清楚地看到,在 Tanh 的情况下,网络对初始权重非常敏感,而 Relu 似乎很容易优化任务。我不明白为什么? Relu 在 Tanh 上提供什么?
  • @OSM:tanh 的训练速度很慢,因为饱和神经元会消失梯度等等。您也可以在不改变学习率但训练数千次迭代的情况下达到 100% 的准确率。
  • 谢谢!你说的对。我刚刚重试了一遍,epoch 更大,停止条件更宽松,它确实优化得很好!
猜你喜欢
  • 2010-11-05
  • 2011-11-14
  • 1970-01-01
  • 1970-01-01
  • 2019-06-01
  • 1970-01-01
  • 2021-04-29
  • 2011-09-25
  • 2020-09-10
相关资源
最近更新 更多