使用 TensorFlow 的简单前馈神经网络不会学习

Posted

技术标签:

【中文标题】使用 TensorFlow 的简单前馈神经网络不会学习【英文标题】:Simple Feedforward Neural Network with TensorFlow won't learn 【发布时间】:2017-12-17 03:33:12 【问题描述】:

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

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

我想出的代码如下所示:

将张量流导入为 tf 将 numpy 导入为 np 导入 Rectangle_Records 定义初始化权重(形状): """权重初始化""" 权重 = tf.random_normal(形状,stddev=0.1) 返回 tf.Variable(权重) def forwardprop(x, w_1, w_2): """ 前向传播 """ h = tf.nn.sigmoid(tf.matmul(x, w_1)) y_predict = tf.matmul(h, w_2) 返回 y_predict 定义主(): x_size = 10 y_size = 2 h_1_size = 256 # 准备输入数据 input_data = Rectangle_Records.DataSet() x = tf.placeholder(tf.float32, shape = [None, x_size]) y_label = tf.placeholder(tf.float32, shape = [None, y_size]) # 权重初始化 w_1 = init_weights((x_size, h_1_size)) w_2 = init_weights((h_1_size, y_size)) # 前向传播 y_predict = forwardprop(x, w_1, w_2) # 反向传播 成本 = tf.reduce_mean(tf.square(y_predict - y_label)) 更新 = tf.train.GradientDescentOptimizer(0.01).minimize(cost) # 跑步 sess = tf.Session() 初始化 = tf.global_variables_initializer() sess.run(初始化) 对于我在范围内(200): 批处理 = input_data.next_batch(10) sess.run(更新,feed_dict = x:batch[0],y_label:batch[1]) sess.close() 如果 __name__ == "__main__": 主要的()

遗憾的是,网络无法正确学习。结果差得太远了。例如,[[ 3.74561882 , 3.70766664]] 应该在 [[ 3. , 7.]] 周围。我究竟做错了什么?

【问题讨论】:

您是否正在跟踪和绘制 R^2 或 MSE? 不,我不知道怎么做。我发现 TensorFlow 很难做到这一点。 您可以针对为此目的保留的测试数据集手动执行此操作。我问是因为 3.71 似乎接近 3.7 3.74561882 到 3. 和 3.70766664 到 7. 你能把整个代码和数据集分享给我吗? 【参考方案1】:

主要问题是你的整个训练只针对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)

【讨论】:

【参考方案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

在main里面改成这个

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)

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

【讨论】:

【参考方案3】:

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

    添加更多层,或每层添加更多节点 更改您的激活函数(我发现 relu 非常有效) 使用 NN 集合,其中每个 NN 获得按其 R^2 分数加权的投票 引入更多训练数据 执行网格搜索以优化参数

【讨论】:

【参考方案4】:

您的网络要学习解决的问题看起来很简单,即使是单层双神经元感知器也应该能够解决。 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 可能仍会收敛。并观察学习曲线。

【讨论】:

以上是关于使用 TensorFlow 的简单前馈神经网络不会学习的主要内容,如果未能解决你的问题,请参考以下文章

第二节,TensorFlow 使用前馈神经网络实现手写数字识别

前馈神经网络练习:使用tensorflow进行葡萄酒种类识别

TensorFlow TensorFlow的基础用法

TensorFlow 优化实践

全方面讲解TensorFlow

TensorFlow力学101笔记[4]