我正在学习TensorFlow和深度学习,并尝试各种激活函数。
我为MNIST问题创建了一个多层前馈神经网络。主要基于TensorFlow官方网站的教程,只是增加了三个隐藏层。
我尝试过的激活函数包括:tf.sigmoid
,tf.nn.tanh
,tf.nn.softsign
,tf.nn.softmax
,tf.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将提高准确率。
希望这对您有帮助。