我是机器学习的新手,我正在关注tensorflow的教程,以创建一些简单的神经网络来学习MNIST数据。
我已经构建了一个单层网络(遵循tutotial),准确率约为0.92,这对我来说没问题。但后来又添加了一层,精度降低到0.113,非常糟糕。
以下是2层之间的关系:
import tensorflow as tf
x = tf.placeholder(tf.float32, [None, 784])
#layer 1
W1 = tf.Variable(tf.zeros([784, 100]))
b1 = tf.Variable(tf.zeros([100]))
y1 = tf.nn.softmax(tf.matmul(x, W1) + b1)
#layer 2
W2 = tf.Variable(tf.zeros([100, 10]))
b2 = tf.Variable(tf.zeros([10]))
y2 = tf.nn.softmax(tf.matmul(y1, W2) + b2)
#output
y = y2
y_ = tf.placeholder(tf.float32, [None, 10])
我的结构好吗?导致它表现如此糟糕的原因是什么?我应该如何修改我的网络?
答案 0 :(得分:9)
第二层的输入是第一层输出的softmax
。你不想这样做。
你强迫这些值之和为1.如果tf.matmul(x, W1) + b1
的某个值约为0(当然有些值),则softmax操作将此值降低为0.结果:你是杀死梯度,没有任何东西可以流过这些神经元。
如果删除图层之间的softmax(但如果要将值视为概率,则将其输出为输出图层上的softmax),您的网络将正常工作。
铊; DR:
import tensorflow as tf
x = tf.placeholder(tf.float32, [None, 784])
#layer 1
W1 = tf.Variable(tf.zeros([784, 100]))
b1 = tf.Variable(tf.zeros([100]))
y1 = tf.matmul(x, W1) + b1 #remove softmax
#layer 2
W2 = tf.Variable(tf.zeros([100, 10]))
b2 = tf.Variable(tf.zeros([10]))
y2 = tf.nn.softmax(tf.matmul(y1, W2) + b2)
#output
y = y2
y_ = tf.placeholder(tf.float32, [None, 10])
答案 1 :(得分:0)
遇到完全相同的问题,渐变发散并为预测的nan
获得了一堆y
。实现了nessuno的建议,遗憾的是,不同的梯度仍未修复。
相反,我已经尝试sigmoid
作为第1层的激活功能,它有效!但是,如果将relu
和W1
作为零矩阵启动,则W2
无法正常工作,准确度仅为0.1135。为了使relu
和sigmoid
都有效,请更好地随机化W1
和W2
的初始化。这是修改后的代码
import tensorflow as tf
x = tf.placeholder(tf.float32, [None, 784])
# layer 1
with tf.variable_scope('layer1'):
W1 = tf.get_variable('w1',[784,200],
initializer=tf.random_normal_initializer())
b1 = tf.get_variable('b1',[1,],
initializer=tf.constant_initializer(0.0))
y1 = tf.nn.sigmoid(tf.matmul(x, W1) + b1)
# y1 = tf.nn.relu(tf.matmul(x, W1) + b1) # alternative choice for activation
# layer 2
with tf.variable_scope('layer2'):
W2 = tf.get_variable('w2',[200,10],
initializer= tf.random_normal_nitializer())
b2 = tf.get_variable('b2',[1,],
initializer=tf.constant_initializer(0.0))
y2 = tf.nn.softmax(tf.matmul(y1, W2) + b2)
# output
y = y2
y_ = tf.placeholder(tf.float32, [None, 10])
我发现this link是有帮助的,参见问题2(c)部分,它给出了基本2层神经网络的反向传播导数。在我看来,当用户没有指定任何acivation函数时,只需在第1层中应用线性流,最终会使用后向渐变的渐变看起来像(sth)*W2^T*W1^T
,并且当我们启动W1
时并且W2
为零,它们的产品可能非常小,接近于零,这会导致渐变的消失。
<强>更新强>
这是来自Quora的回答Ofir posted关于神经网络中良好的初始权重。
最常见的初始化是随机初始化和Xavier 初始化。随机初始化只是从a中采样每个权重 标准分布(通常是正态分布)低 偏差。低偏差允许您偏向网络 简单的&#39; 0解决方案,没有实际的不良后果 将权重初始化为0。
答案 2 :(得分:0)
我尝试运行上面的代码段。低于90%的结果被丢弃了,我从未真正确定我做了上面的评论。这是我的完整代码。
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
x = tf.placeholder(tf.float32, [None, 784])
#layer 1
W1 = tf.get_variable('w1', [784, 100], initializer=tf.random_normal_initializer())
b1 = tf.get_variable('b1', [1,], initializer=tf.random_normal_initializer())
y1 = tf.nn.sigmoid(tf.matmul(x, W1) + b1)
#layer 2
W2 = tf.get_variable('w2',[100,10], initializer=
tf.random_normal_initializer())
b2 = tf.get_variable('b2',[1,], initializer=tf.random_normal_initializer())
y2 = tf.nn.softmax(tf.matmul(y1, W2) + b2)
#output
y = y2
y_ = tf.placeholder(tf.float32, [None, 10])
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y),
reduction_indices=[1]))
train_step = tf.train.GradientDescentOptimizer(0.2).minimize(cross_entropy)
sess = tf.InteractiveSession()
tf.global_variables_initializer().run()
for _ in range(10000):
batch_xs, batch_ys = mnist.train.next_batch(100)
sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_:
mnist.test.labels}))
通过更改10000 - &gt; 200000我达到95.5%。