我尝试实现了来自以下网址的神经网络:
http://iamtrask.github.io/2015/07/12/basic-python-network/
但使用了TensorFlow。我在训练过程中两次打印了成本函数,错误似乎在减小,但是输出层的数值都接近1,而实际上只有两个应该如此。我猜想可能是我的数学计算有问题,但我不确定。当我尝试添加隐藏层或使用平方误差作为成本函数时,情况没有变化。以下是我的代码:
import tensorflow as tfimport numpy as npinput_layer_size = 3output_layer_size = 1x = tf.placeholder(tf.float32, [None, input_layer_size]) #holds input valuesy = tf.placeholder(tf.float32, [None, output_layer_size]) # holds true y valuestf.set_random_seed(1)input_weights = tf.Variable(tf.random_normal([input_layer_size, output_layer_size]))input_bias = tf.Variable(tf.random_normal([1, output_layer_size]))output_layer_vals = tf.nn.sigmoid(tf.matmul(x, input_weights) + input_bias)cross_entropy = -tf.reduce_sum(y * tf.log(output_layer_vals))training = tf.train.AdamOptimizer(0.1).minimize(cross_entropy)x_data = np.array( [[0,0,1], [0,1,1], [1,0,1], [1,1,1]])y_data = np.reshape(np.array([0,0,1,1]).T, (4, 1))with tf.Session() as ses: init = tf.initialize_all_variables() ses.run(init) for _ in range(1000): ses.run(training, feed_dict={x: x_data, y:y_data}) if _ % 500 == 0: print(ses.run(output_layer_vals, feed_dict={x: x_data})) print(ses.run(cross_entropy, feed_dict={x: x_data, y:y_data})) print('\n\n')
这是它的输出结果:
[[ 0.82036656] [ 0.96750367] [ 0.87607527] [ 0.97876281]]0.21947 #第一次交叉熵错误 [[ 0.99937409] [ 0.99998224] [ 0.99992537] [ 0.99999785]]0.00062825 #第二次交叉熵错误,如您所见,数值更小
回答:
首先:你没有隐藏层。据我所知,基本感知器可能可以模拟XOR问题,但需要一些调整。然而,人工智能虽然是由生物学启发发明的,但并不完全模拟真实的神经网络。因此,你至少需要构建一个多层感知器(MLP,Multilayer perceptron),它至少包括一个输入层、一个隐藏层和一个输出层。XOR问题至少需要隐藏层中有两个神经元加上偏置才能正确解决(具有高精度)。
此外,你的学习率太高。0.1
是一个非常高的学习率。简单来说,这意味着你通过单次学习步骤的10%来更新/调整当前状态。这会让你的网络迅速忘记已经学到的不变量。通常,学习率在1e-2到1e-6之间,具体取决于你的问题、网络大小和整体架构。
此外,你实现了交叉熵的“简化/短”版本。请参阅维基百科查看完整版本:交叉熵。然而,为了避免一些极端情况,TensorFlow已经有了自己的交叉熵版本:例如tf.nn.softmax_cross_entropy_with_logits
。
最后,你应该记住,交叉熵错误是一个对类别概率进行操作的逻辑损失函数。虽然你的sigmoid函数将输出层压缩到[0, 1]
的区间内,但在你的情况下这仅因为你只有一个输出神经元才有效。一旦你有多个输出神经元,你还需要输出层的总和恰好为1.0
,以便真正描述输出层上每个类别的概率。