使用TensorFlow的简单前馈神经网络将无法学习

时间:2017-07-12 15:40:33

标签: python tensorflow neural-network

我正在尝试使用TensorFlow构建一个简单的神经网络。目标是在32像素x 32像素图像中找到矩形的中心。矩形由五个向量描述。第一个矢量是位置矢量,另外四个是方向矢量,构成矩形边。一个向量有两个值(x和y)。

enter image description here

此图像的相应输入为(2,5)(0,4)(6,0)(0,-4)( - 6,0)。 中心(因此所需的输出)位于(5,7)

我想出的代码如下所示:

    import tensorflow as tf 
    import numpy as np
    import Rectangle_Records

    def init_weights(shape):
        """ Weight initialization """
        weights = tf.random_normal(shape, stddev=0.1)
        return tf.Variable(weights)

    def forwardprop(x, w_1, w_2):
        """ Forward-propagation """
        h = tf.nn.sigmoid(tf.matmul(x, w_1))
        y_predict = tf.matmul(h, w_2)
        return y_predict

    def main():
        x_size = 10
        y_size = 2
        h_1_size = 256

        # Prepare input data
        input_data = Rectangle_Records.DataSet()

        x = tf.placeholder(tf.float32, shape = [None, x_size])
        y_label = tf.placeholder(tf.float32, shape = [None, y_size])

        # Weight initializations
        w_1 = init_weights((x_size, h_1_size))
        w_2 = init_weights((h_1_size, y_size))

        # Forward propagation
        y_predict = forwardprop(x, w_1, w_2)

        # Backward propagation
        cost = tf.reduce_mean(tf.square(y_predict - y_label))

        updates = tf.train.GradientDescentOptimizer(0.01).minimize(cost)

        # Run
        sess = tf.Session()
        init = tf.global_variables_initializer()
        sess.run(init)

        for i in range(200):
            batch = input_data.next_batch(10)
            sess.run(updates, feed_dict = {x: batch[0], y_label: batch[1]})

        sess.close()

    if __name__ == "__main__":
        main()

可悲的是,网络无法正常学习。结果太过分了。例如,[[3.74561882,3.70766664]]应该是[[3.,7.]]。我究竟做错了什么?

4 个答案:

答案 0 :(得分:12)

主要问题是您的整个培训仅针对one epoch进行,即没有足够的培训。请尝试以下更改:

sess = tf.Session()
init = tf.global_variables_initializer()
sess.run(init)
for j in range(30):
    input_data = Rectangle_Records.DataSet()
    for i in range(200):
        batch = input_data.next_batch(10)
        loss, _ = sess.run([cost,updates], feed_dict = {x: batch[0], y_label: batch[1]})

    pred = sess.run(y_predict, feed_dict={x: batch[0]})
    print('Cost:', loss  )
    print('pred:', pred)
    print('actual:', batch[1])
sess.close()

将优化器更改为动量优化器,以加快收敛速度​​:tf.train.AdamOptimizer(0.01).minimize(cost)

答案 1 :(得分:2)

你忘了添加偏见。

def init_bias(shape):
    biases = tf.random_normal(shape)
    return tf.Variable(biases)

def forwardprop(x, w_1, w_2, b_1, b_2):
    """ Forward-propagation """
    h = tf.nn.sigmoid(tf.matmul(x, w_1) + b_1)
    y_predict = tf.matmul(h, w_2) + b_2
    return y_predict

内部主要更改为此

w_1 = init_weights((x_size, h_1_size))
w_2 = init_weights((h_1_size, y_size))
b_1 = init_bias((h_1_size,))
b_2 = init_bias((y_size,))

# Forward propagation
y_predict = forwardprop(x, w_1, w_2, b_1, b_2)

这将为您提供更好的准确性。然后,您可以尝试添加更多图层,尝试不同的激活函数等,如上所述,以进一步改进它。

答案 2 :(得分:1)

有很多方法可以改善神经网络的性能。尝试以下一项或多项:

  1. 每层添加更多图层或更多节点
  2. 更改您的激活功能(我发现它非常有效)
  3. 使用NN的集合,其中每个NN通过其R ^ 2得分加权投票
  4. 带来更多培训数据
  5. 执行网格搜索以优化参数

答案 3 :(得分:1)

您的网络要学习解决的问题看起来很容易,甚至单层双神经元感知器应该能够解决。 ReLU激活功能可能是最好的,因为问题是线性的。

200次迭代并不多。尝试更多迭代,例如1000或更多。例如,每100次迭代打印成本值,或者收集数据并在结尾绘图,看看学习进展如何。

import matplotlib.pyplot as plt
cost_history = np.arange(learning_steps, dtype=np.float)
...
for epoch in range(learning_steps):
  ...
  cost_history[epoch] = sess.run(cost, feed_dict = {y: predict, y_:label})

plt.plot(cost_history, 'r', label='Cost fn')
plt.yscale('log')
plt.show()

如果线路熄火,那很好。如果它非常粗糙并且没有下降,那么学习速度可能太大。在这种情况下,学习速度非常低,这就是为什么在200次迭代后你没有很好的结果。尝试更大的值,比如0.1甚至更多。 NN可能仍然趋同。并观察学习曲线。