如何在MNIST数据上使用TensorFlow和python创建2层神经网络

时间:2016-07-01 04:16:05

标签: python tensorflow mnist

我是机器学习的新手,我正在关注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])

我的结构好吗?导致它表现如此糟糕的原因是什么?我应该如何修改我的网络?

3 个答案:

答案 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层的激活功能,它有效!但是,如果将reluW1作为零矩阵启动,则W2无法正常工作,准确度仅为0.1135。为了使relusigmoid都有效,请更好地随机化W1W2的初始化。这是修改后的代码

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%。