我尝试编写一个简单的XOR神经网络,但它始终无法收敛
我创建了一个具有2个输入、2个隐藏节点和1个输出的神经网络。
我在第一个隐藏层使用了ReLU激活函数,并在最后使用了Softmax来获取输出结果。
理论上它应该能够学习并解决这个问题并收敛,对吗?
import tensorflow as tfsess = tf.InteractiveSession()# define placeholder for input and outputx_ = tf.placeholder(tf.float32, shape=[4,2], name="x-input")y_ = tf.placeholder(tf.float32, shape=[4,1], name="y-input")# Configure weights and layersW = tf.Variable(tf.random_uniform([2, 2], -.01, .01))b = tf.Variable(tf.random_uniform([2], -.01, .01))hidden = tf.nn.relu(tf.matmul(x_,W) + b) # first layer.W2 = tf.Variable(tf.random_uniform([2,1], -.1, .1))b2 = tf.Variable(tf.zeros([1]))hidden2 = tf.matmul(hidden, W2 + b2)y = tf.nn.softmax(hidden2)# Training functioncross_entropy = -tf.reduce_sum(y_*tf.log(hidden2))train_step = tf.train.GradientDescentOptimizer(0.2).minimize(cross_entropy)XOR_X = [[0,0],[0,1],[1,0],[1,1]]XOR_Y = [[0],[1],[1],[0]]init = tf.global_variables_initializer()sess.run(init)# Train on the input datafor i in range(100): sess.run([cross_entropy, train_step], feed_dict={x_: XOR_X, y_: XOR_Y}) print ('W1', sess.run(W)) print('Output ', sess.run(y, feed_dict={x_: XOR_X, y_: XOR_Y}))
回答:
错误之处…
-
W2权重应该在-1到1之间,因为它们没有使用ReLU。另外,第一层权重使用ReLU,所以我将它们设置为正值以尝试避免死神经元。
-
除非是1热向量层,否则使用Softmax没有意义。Sigmoid更合理。了解Softmax的工作原理会有所帮助。
-
Reduce sum应该对y进行操作,而不是hidden2
-
hidden2 = tf.matmul(hidden, W2 + b2)
的括号位置不正确。应该为hidden2 = tf.matmul(hidden, W2) + b2
-
-Log作为误差函数只有在试图将输出调整到1时才有效,因为-log(1) = 0,而-log(0)时为无穷大。这会鼓励输出趋向于1而不是0。适用于1热向量,但如果你试图将一个输入的输出调整到0而另一个调整到1,则不适用。
-
隐藏层中的2个神经元确实可以工作。但它对初始化的随机性非常敏感。使用更多的神经元(10个而不是2个)可以减少对初始化错误的敏感性。
下面的代码是有效的。它使用了一个成本函数,帮助收敛到0和1以适应不同的输入。
import tensorflow as tfsess = tf.InteractiveSession()# define placeholder for input, None as first argument means tensor can be any lengthx_ = tf.placeholder(tf.float32, shape=[4,2], name="x-input")y_ = tf.placeholder(tf.float32, shape=[4,1], name="y-input")# Configure weights and layersW = tf.Variable(tf.random_uniform([2, 10], 0.001, .01))b = tf.Variable(tf.zeros([10]))hidden = tf.nn.relu(tf.matmul(x_,W) + b) # first layer.W2 = tf.Variable(tf.random_uniform([10,1], -1, 1))b2 = tf.Variable(tf.zeros([1]))hidden2 = tf.matmul(hidden, W2) + b2y = tf.nn.sigmoid(hidden2)# Training function + datacost = tf.reduce_mean(( (y_ * tf.log(y)) +((1 - y_) * tf.log(1.0 - y)) ) * -1)train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cost)XOR_X = [[0,0],[0,1],[1,0],[1,1]]XOR_Y = [[0],[1],[1],[0]]init = tf.global_variables_initializer()sess.run(init)# Train on the input datafor i in range(100000): sess.run(train_step, feed_dict={x_: XOR_X, y_: XOR_Y}) if i % 2000 == 0: print ('W1', sess.run(W)) print('Output ', sess.run(y, feed_dict={x_: XOR_X, y_: XOR_Y}))