tflearn/tensorflow不学习xor

rde*_*com 8 python machine-learning deep-learning tensorflow

编写以下代码以学习XOR功能,但是大约一半的时间网络没有学习并且每个时期之后的损失保持不变.

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.]]))
Run Code Online (Sandbox Code Playgroud)

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

Testing XOR operator
0 xor 0: [[0.1487255096435547]]
0 xor 1: [[0.9297153949737549]]
1 xor 0: [[0.9354135394096375]]
1 xor 1: [[0.1487255096435547]]
Run Code Online (Sandbox Code Playgroud)

但通常这样:

Testing XOR operator
0 xor 0: [[0.4999997615814209]]
0 xor 1: [[0.5000002384185791]]
1 xor 0: [[0.4999997615814209]]
1 xor 1: [[0.5000001788139343]]
Run Code Online (Sandbox Code Playgroud)

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

我也试图在RELU层改为乙状结肠,执行2048次迭代,并作出一个4x4x1和6x6x1网络,但同样的问题仍然时有发生.

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

Ish*_*ael 9

带有relus 的网络(因为它写在代码片段中)预计通常无法训练.原因是如果relu的输入小于零,则输出为零,因此返回的梯度也为零.

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

由于每一层都有25%的几率造成这种伤害,因此整个网络总共有45%左右1 - (1 - 0.25)^2的失败率().网络在开始时还没有处于这种状态的非零概率,但是在训练期间恰好使自己处于这种状态,这进一步增加了分歧的可能性.

对于四个神经元,机会将显着降低,但仍然不是零.

现在,我不能回答的唯一的事情就是为什么当你更换您的网络不收敛relusigmoid-这样的网络应该总是能够学习"异".我唯一的假设是,您更换一个只relusigmoid,不是他们两个.

你可以relusigmoids 代替两个s 并确认你仍然观察到分歧吗?

  • 事实上,“线性”是其中最不令人惊讶的。如果两个密集层之间有一个“线性”激活(实际上没有激活),那么这两个密集层将作为一个密集层。这种“多层”网络无法学习单层网络无法学习的任何内容,并且单层网络无法学习异或(换句话说,通过线性激活,您的网络永远不应该收敛)。Sigmoid 和 tanh 令人费解。我稍后会玩一下,看看是否能解决这个问题。 (2认同)

Aen*_*ed1 7

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

在略读这篇论文后,我突然意识到你没有看到收敛的原因可能与初始权重有关.本文特别引用了Hirose等人(Hirose,Yamashita和Huiya 1991)的一些工作,他们发现用有限范围的权重进行初始化会导致收敛的概率非常低."甜蜜点"似乎平均在0.5到1之间,可靠地收敛.

事实证明,tflearn将默认使用截断的正常初始化,其stddev为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.]]))
Run Code Online (Sandbox Code Playgroud)

请注意,我使用均方误差.令我惊讶的是,它似乎最适合这个问题.交叉熵似乎导致优化器在问题空间的相对平坦的区域中萎缩.我原以为是相反的; 也许精通数学的人将能够更好地解释这一点.