【问题标题】:tflearn / tensorflow does not learn xortflearn / tensorflow 不学习异或
【发布时间】:2016-05-11 14:52:32
【问题描述】:

以下代码用于学习 XOR 函数,但大约有一半的时间网络没有学习,并且每个 epoch 后的损失保持不变。

train_f = [[0, 0], [0, 1], [1, 0], [1, 1]]
train_c = [[0], [1], [1], [0]]
test_f = train_f
test_c = train_c

import tensorflow as tf
import tflearn

X = [[0., 0.], [0., 1.], [1., 0.], [1., 1.]]
Y_xor = [[0.], [1.], [1.], [0.]]

# Graph definition
with tf.Graph().as_default():
    # Building a network with 2 optimizers
    net = tflearn.input_data(shape=[None, 2])
    # Nand operator definition
    net = tflearn.fully_connected(net, 2, activation='relu')
    net = tflearn.fully_connected(net, 2, activation='relu')
    net = tflearn.fully_connected(net, 1, activation='sigmoid')
    regressor = tflearn.regression(net, optimizer='adam', learning_rate=0.005, loss="mean_square",)

    # Training
    m = tflearn.DNN(regressor)
    m.fit(X, Y_xor, n_epoch=256, snapshot_epoch=False)

    # Testing
    print("Testing XOR operator")
    print("0 xor 0:", m.predict([[0., 0.]]))
    print("0 xor 1:", m.predict([[0., 1.]]))
    print("1 xor 0:", m.predict([[1., 0.]]))
    print("1 xor 1:", m.predict([[1., 1.]]))

有时我会得到这样的正确结果:

Testing XOR operator
0 xor 0: [[0.1487255096435547]]
0 xor 1: [[0.9297153949737549]]
1 xor 0: [[0.9354135394096375]]
1 xor 1: [[0.1487255096435547]]

但通常是这样的:

Testing XOR operator
0 xor 0: [[0.4999997615814209]]
0 xor 1: [[0.5000002384185791]]
1 xor 0: [[0.4999997615814209]]
1 xor 1: [[0.5000001788139343]]

我的 2x2x1 网络应该能够执行 XOR,甚至有一些证据表明这个网络应该总是收敛 http://www.ncbi.nlm.nih.gov/pubmed/12662805

我也试过把relu层改成sigmoid,进行2048次迭代,做成4x4x1和6x6x1的网络,但是有时候还是会出现同样的问题。

权重的初始化方式可能有问题吗? 如何使用 tflearn 让神经网络学习 xor 函数?

【问题讨论】:

  • 尝试普通的 SGD(而不是 Adam),调整学习率...
  • 不幸的是,SGD 没有帮助(使用任何激活函数)

标签: python machine-learning tensorflow deep-learning


【解决方案1】:

带有relus 的网络(如代码 sn-p 中所写)预计经常无法训练。原因是如果 relu 的输入小于零,则输出为零,因此返回的梯度也为零。

由于您有两层,每层只有两个 relu 单元,通过随机初始化,这两层中的每一层都有 25% 的所有神经元返回零,因此返回的梯度为零 => 神经网络不会在全部。在这样的网络中,最后一层(在最终 sigmoid 之前)的输出将为零,其中 sigmoid 为 0.5——这正是您在网络未收敛的尝试中观察到的结果。

由于每一层都有 25% 的几率造成这种损害,因此整个网络从一开始就有大约 45% (1 - (1 - 0.25)^2) 的几率无法训练。还有一个非零的可能性是网络一开始并不处于这样的状态,但在训练过程中恰好将自己带入这样的状态,进一步增加了发散的机会。

四个神经元的几率会明显降低,但仍然不是零。

现在,我唯一无法回答的是为什么当您将 relu 替换为 sigmoid 时您的网络不收敛——这样的网络应该总是能够学习“异或”。我唯一的假设是您只用sigmoid 替换了一个relu,而不是两个。

您能否将relus 都替换为sigmoids 并确认您仍然观察到分歧?

【讨论】:

  • 感谢您的解释!我在这里看到了 relu 的问题,但是,如果我对所有层都使用线性、sigmoid、softmax 或 tanh,则会出现同样的问题......对我来说,这在线性的情况下尤其令人惊讶。
  • 实际上,“线性”是最不令人惊讶的。如果您在两个密集层之间有“线性”激活(实际上,没有激活),那么这两个密集层将作为一个。这种“多层”网络无法学习单层网络无法学习的任何东西,单层网络无法学习 XOR(换句话说,使用线性激活,您的网络永远不会收敛)。 Sigmoids 和 tanh 令人费解。我稍后会玩它并尝试看看我是否能解决这个问题。
【解决方案2】:

我决定添加另一个答案:我进行了更多研究,并提供了一些截然不同的建议。

在浏览this 论文后,我突然意识到您没有看到收敛的原因可能与初始权重有关。该论文特别引用了 Hirose 等人(Hirose、Yamashita 和 Hijiya 1991)的一些工作,他们发现使用有限权重范围进行初始化会导致收敛概率非常低。 “甜蜜点”似乎是平均 0.5 到 1 之间的范围,以可靠地收敛。

事实证明,tflearn 将默认使用标准差为 0.02 的截断正常初始化。所以权重的范围非常有限。我发现使用 -1.0 到 1.0 的随机统一初始化可以获得相当可靠的结果。

另外,顺便说一句,您添加了第 3 层。 XOR 只需要一个隐藏层,因此您可以删除第二个。这是对我有用的代码:

import tensorflow as tf
import tflearn

X = [[0., 0.], [0., 1.], [1., 0.], [1., 1.]]
Y_xor = [[0.], [1.], [1.], [0.]]

# Graph definition
with tf.Graph().as_default():
    tnorm = tflearn.initializations.uniform(minval=-1.0, maxval=1.0)
    net = tflearn.input_data(shape=[None, 2])
    net = tflearn.fully_connected(net, 2, activation='sigmoid', weights_init=tnorm)
    net = tflearn.fully_connected(net, 1, activation='sigmoid', weights_init=tnorm)
    regressor = tflearn.regression(net, optimizer='sgd', learning_rate=2., loss='mean_square')

    # Training
    m = tflearn.DNN(regressor)
    m.fit(X, Y_xor, n_epoch=10000, snapshot_epoch=False) 

    # Testing
    print("Testing XOR operator")
    print("0 xor 0:", m.predict([[0., 0.]]))
    print("0 xor 1:", m.predict([[0., 1.]]))
    print("1 xor 0:", m.predict([[1., 0.]]))
    print("1 xor 1:", m.predict([[1., 1.]]))

请注意,我使用的是均方误差。令我惊讶的是,它似乎最适合这个问题。交叉熵似乎会导致优化器在问题空间的相对平坦区域中萎靡不振。我会预料到相反的情况;也许更精通数学的人能够更好地解释这一点。

【讨论】:

  • 谢谢!除了您所有有用的评论外,我注意到您将学习率从我的 0.005 更改为 2.0。没有这种变化,网络就不会收敛。
  • +5 非常感谢!根据我的尝试,没有设置统一权重,tflearn 实际上不适用于任何非线性回归。
  • 论文链接已损坏。可以贴一下论文的名字吗?
【解决方案3】:

除了@Ishamael 的建议,考虑使用不同的损失函数。均方误差通常不是 sigmoid 激活的好选择,因为由于饱和,梯度可能缩小得太小而无法用于学习。

【讨论】:

  • 我尝试了各种其他损失函数,但没有帮助
【解决方案4】:

我遇到了模拟问题,当时我正在寻找学习 XOR 所需的最小神经元网络架构,它应该是 (2,2,1) 网络。事实上,数学表明 (2,2,1) 网络可以解决 XOR 问题,但数学并没有表明 (2,2,1) 网络易于训练。也就是说,使用 (2,3,1) 或 (2,4,1) 网络架构,我很容易得到很好的结果。此外,使用 0.5 到 1.0 之间的随机数初始化权重有助于收敛。

这个问题似乎与许多局部最小值的存在有关。看看理查德·布兰德 1998 年的这篇论文,«Learning XOR: exploring the space of a classic problem»。也许你可以尝试不同的随机初始化权重或改变你的损失函数。

使用损失函数“mean_squared_error”、sigmoid 激活和 Adam 优化器,它可以与 Keras 或 TensorFlow 完美配合。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-08
    • 1970-01-01
    • 2020-10-29
    • 2023-04-09
    • 1970-01-01
    相关资源
    最近更新 更多