在简单多层前馈神经网络中,仅使用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

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

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