繁体   English   中英

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

[英]How to create 2-layers neural network using TensorFlow and python on MNIST data

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

我已经建立了一个单层网络(遵循tutotial),精度约为0.92,对我来说还可以。 但是后来我又增加了一层,精度降低到0.113,这是非常糟糕的。

以下是两层之间的关系:

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

我的结构还好吗? 是什么原因使其性能如此差? 我应该如何修改我的网络?

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

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

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

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

遇到了完全相同的问题,梯度发散并为预测y得到了一堆nan 不幸的是,按照nessuno的建议实施,发散的梯度仍然不固定。

相反,我尝试将sigmoid用作第1层的激活功能,它起作用了! 但是因为如果将W1W2初始化为零矩阵,则relu无法正常工作,因此精度仅为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])

我发现此链接很有用,请参阅问题2(c),其中提供了基本2层神经网络的反向传播导数。 在我看来,当用户未指定任何接受函数时,只需在第1层中应用线性流,最终将对(sth)*W2^T*W1^T的梯度进行反向传播,并同时初始化W1如果W2为零,则它们的乘积可能非常小,接近于零,从而导致梯度消失。

更新

这是Ofir Ofir在Quora上发表的关于神经网络中良好初始权重的答案。

最常见的初始化是随机初始化和Xavier初始化。 随机初始化仅从标准分布(通常为正态分布)中以低偏差对每个权重进行采样。 低偏差使您可以将网络偏向“简单” 0解决方案,而不会产生将权重实际初始化为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%。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM