Нейронная сеть с одним скрытым слоем не может быть обучена - PullRequest
0 голосов
/ 03 июня 2018

Я пытался реализовать NN с одним скрытым слоем, используя 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))

1 Ответ

0 голосов
/ 03 июня 2018

Не инициализируйте модель со всеми нулями. Если вы это сделаете, вероятно, что градиент в этой точке (в пространстве параметров) также равен нулю.Это приводит к тому, что обновление градиента не существует, поэтому ваши параметры просто не изменятся.Чтобы избежать этого используйте случайную инициализацию .

т.е.

Измените

#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 из первого слоя и заменил его сигмоидом.Я сделал это потому, что слои softmax накладывают ограничения на вывод: он заставляет выход этого слоя складываться в один (это одна из причин, по которой его часто используют в самом последнем слое: для достижения вероятностной интерпретации конечного результата).Это ограничение заставило модель прекратить обучение с 30% точностью в быстром тесте.При использовании сигмоида точность достигла 89%, что значительно улучшило производительность.

Другими примерами нелинейностей, которые вы могли бы использовать в промежуточных слоях, могли бы быть:

  • Гиперболический тангенс
  • ReLU
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...