使用 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 使用前馈神经网络实现手写数字识别