6

我是机器学习的新手,我正在按照 tensorflow 的教程创建一些简单的神经网络来学习 MNIST 数据。

我已经建立了一个单层网络(按照教程),准确度约为 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])

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

4

3 回答 3

10

第二层的输入是softmax第一层的输出。你不想那样做。

你强制这些值的总和为 1。如果某个值tf.matmul(x, W1) + b1约为 0(有些肯定是),softmax 操作会将这个值降低为 0。结果:你正在扼杀梯度,没有任何东西可以流过这些神经元。

如果您删除层之间的 softmax(但如果您想将值视为概率,则将其保留在输出层上的 softmax)您的网络将正常工作。

Tl;博士:

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])
于 2016-07-01T07:43:56.573 回答
0

遇到了完全相同的问题,梯度发散并得到了一堆nan预测y。不幸的是,实现了 nessuno 的建议,发散的梯度仍未修复。

相反,我尝试sigmoid作为第 1 层的激活函数,它起作用了!但是如果启动并作为零矩阵relu不起作用,则精度仅为 0.1135 。为了使和都能正常工作,最好随机化和的初始化。这是修改后的代码W1W2relusigmoidW1W2

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])

我发现这个链接很有帮助,请参阅问题 2 部分 (c),它给出了基本 2 层神经网络的反向传播导数。在我看来,当用户没有指定任何激活函数时,只需在第 1 层应用线性流,最终会反向传播一个看起来像 的梯度(sth)*W2^T*W1^T,并且当我们将W1和都初始化W2为零时,他们的产品可能小接近于零,这导致梯度消失。

更新

这是来自 Quora 回答 Ofir发布的关于神经网络中良好的初始权重的问题。

最常见的初始化是随机初始化和 Xavier 初始化。随机初始化只是从具有低偏差的标准分布(通常是正态分布)中对每个权重进行采样。低偏差允许您将网络偏向“简单”0 解决方案,而不会产生实际将权重初始化为 0 的不良影响。

于 2016-12-15T05:34:14.597 回答
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 -> 200000 我达到了 95.5%。

于 2017-06-07T21:24:43.463 回答