python - 无法训练具有一个隐藏层的神经网络
问题描述
我试图通过使用 TensorFlow 识别 MNIST 手写数字来实现具有一个隐藏层的 NN。我使用梯度下降法来训练神经网络。然而,似乎我对 NN 的训练根本没有奏效,因为在训练过程中测试准确度根本没有改变。
谁能帮我弄清楚出了什么问题?
这是我的代码。
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data", one_hot=True)
batch_size = 100
n_batch = mnist.train.num_examples // batch_size
x = tf.placeholder(tf.float32, [None, 784])
y = tf.placeholder(tf.float32, [None, 10])
#First layer of the NN
W1 = tf.Variable(tf.zeros([784,10]))
b1 = tf.Variable(tf.zeros([10]))
out1 = tf.nn.softmax(tf.matmul(x, W1) + b1)
#Second layer of the NN
W2 = tf.Variable(tf.zeros([10,10]))
b2 = tf.Variable(tf.zeros([10]))
prediction = tf.nn.softmax(tf.matmul(out1, W2) + b2)
loss = tf.reduce_mean(tf.square(y - prediction))
train_step = tf.train.GradientDescentOptimizer(0.1).minimize(loss)
init = tf.global_variables_initializer()
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(prediction, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
with tf.Session() as sess:
sess.run(init)
for epoch in range(101):
for batch in range(n_batch):
batch_xs, batch_ys = mnist.train.next_batch(batch_size)
sess.run(train_step, feed_dict={x:batch_xs, y:batch_ys})
acc = sess.run(accuracy, feed_dict={x:mnist.test.images, y:mnist.test.labels})
print("Iter " + str(epoch) + ", Testing Accuracy " + str(acc))
解决方案
不要用全零初始化模型。如果这样做,那么该点(在参数空间中)的梯度很可能也为零。这导致梯度更新不存在,因此您的参数将根本不会改变。为避免这种情况,请使用随机初始化。
IE
改变
#First layer of the NN
W1 = tf.Variable(tf.zeros([784,10]))
b1 = tf.Variable(tf.zeros([10]))
out1 = tf.nn.softmax(tf.matmul(x, W1) + b1)
#Second layer of the NN
W2 = tf.Variable(tf.zeros([10,10]))
b2 = tf.Variable(tf.zeros([10]))
到
#First layer of the NN
W1 = tf.Variable(tf.truncated_normal([784,10], stddev=0.1))
b1 = tf.Variable(tf.truncated_normal([10], stddev=0.1))
out1 = tf.nn.sigmoid(tf.matmul(x, W1) + b1)
# out1 = tf.nn.softmax(tf.matmul(x, W1) + b1)
#Second layer of the NN
W2 = tf.Variable(tf.truncated_normal([10,10], stddev=0.1))
b2 = tf.Variable(tf.truncated_normal([10],stddev=0.1))
现在模型可以训练了。您还会看到我从第一层中删除了 softmax 非线性,并用 sigmoid 代替了它。我这样做是因为 softmax 层对输出施加了限制:它强制该层的输出加起来为 1(这是它经常用于最后一层的原因之一:实现对最终输出的概率解释)。这种限制导致模型在快速测试中以 30% 的准确率停止学习。通过使用 sigmoid,准确率达到了 89%,性能要好得多。
您可以在中间层中使用的其他非线性示例可能是:
- 双曲正切
- ReLU
推荐阅读
- scala - Scala Dataframe 获取特定行的最大值
- python - 控制 datetime.isocalendar()
- opencv - 使用 Opencv 将 JPG 转换为 TIFF
- json - Logstash:展平嵌套 JSON,组合数组内的字段
- python - 使用 Python IS NOT NULL 的 SQLite 查询无效
- python-3.x - 获取无效语法
VSCode上带有Pylint的打印功能错误 - data-science - Vowpal Wabbit:如何在使用 --keep 和 --ignore 时使用 --interactions
- javascript - 使用 Facebook JavaScript SDK 将“response_type”从“token”更改为“code”
- ms-access - 表达式在表单中有效,但在计算列 Access 2016 中无效
- css - 如何在 React 中设置 DraftJS 编辑器的样式