在简单多层前馈神经网络中,仅使用ReLU激活函数无法收敛

我正在学习TensorFlow和深度学习,并尝试各种激活函数。

我为MNIST问题创建了一个多层前馈神经网络。主要基于TensorFlow官方网站的教程,只是增加了三个隐藏层。

我尝试过的激活函数包括:tf.sigmoidtf.nn.tanhtf.nn.softsigntf.nn.softmaxtf.nn.relu。只有tf.nn.relu无法收敛,网络输出随机噪声(测试准确率约为10%)。以下是我的源代码:

import tensorflow as tffrom tensorflow.examples.tutorials.mnist import input_datamnist = input_data.read_data_sets("MNIST_data/", one_hot=True)x = tf.placeholder(tf.float32, [None, 784])W0 = tf.Variable(tf.random_normal([784, 200]))b0 = tf.Variable(tf.random_normal([200]))hidden0 = tf.nn.relu(tf.matmul(x, W0) + b0)W1 = tf.Variable(tf.random_normal([200, 200]))b1 = tf.Variable(tf.random_normal([200]))hidden1 = tf.nn.relu(tf.matmul(hidden0, W1) + b1)W2 = tf.Variable(tf.random_normal([200, 200]))b2 = tf.Variable(tf.random_normal([200]))hidden2 = tf.nn.relu(tf.matmul(hidden1, W2) + b2)W3 = tf.Variable(tf.random_normal([200, 10]))b3 = tf.Variable(tf.random_normal([10]))y = tf.matmul(hidden2, W3) + b3y_ = tf.placeholder(tf.float32, [None, 10])cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y))train_step = tf.train.GradientDescentOptimizer(0.1).minimize(cross_entropy)with tf.Session() as session:    session.run(tf.global_variables_initializer())    for _ in range(10000):        batch_xs, batch_ys = mnist.train.next_batch(128)        session.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})        if _ % 1000 == 0:            correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))            accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))            print(_, session.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))    correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))    print('final:', session.run(accuracy, feed_dict={x: mnist.test.images,            y_: mnist.test.labels}))

代码输出类似如下内容:

0 0.0981000 0.0982000 0.0983000 0.0984000 0.0985000 0.0986000 0.0987000 0.0988000 0.0989000 0.098final: 0.098

如果将tf.nn.relu替换为其他激活函数,网络的准确率会逐渐提高(尽管最终准确率不同),这是预期的结果。

我在许多教科书/教程中读到,ReLU应该是首选的激活函数。

我的问题是为什么ReLU在我的网络中不起作用?还是我的程序有问题?


回答:

您使用的是ReLU激活函数,它的计算方式如下,

max(features, 0)

由于它输出的是最大值,这有时会导致梯度爆炸

梯度下降优化器通过以下方式更新权重,

∆wij = −η∂Ei/∂wij

其中,η是学习率,∂Ei/∂wij是损失相对于权重的偏导数。当最大值越来越大时,偏导数也会越来越大,导致梯度爆炸。因此,正如您在方程中可以观察到的那样,您需要调整学习率(η)来克服这种情况。

一个常见的规则是降低学习率,通常每次降低10倍。

在您的情况下,将学习率设置为0.001将提高准确率。

希望这对您有帮助。

Related Posts

Keras Dense层输入未被展平

这是我的测试代码: from keras import…

无法将分类变量输入随机森林

我有10个分类变量和3个数值变量。我在分割后直接将它们…

如何在Keras中对每个输出应用Sigmoid函数?

这是我代码的一部分。 model = Sequenti…

如何选择类概率的最佳阈值?

我的神经网络输出是一个用于多标签分类的预测类概率表: …

在Keras中使用深度学习得到不同的结果

我按照一个教程使用Keras中的深度神经网络进行文本分…

‘MatMul’操作的输入’b’类型为float32,与参数’a’的类型float64不匹配

我写了一个简单的TensorFlow代码,但不断遇到T…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注