Почему tf.train.GradientOptimizer не работает на моей модели распознавания цифр, в то время как ShampooOptimizer из tenorflow.contrib работает просто отлично? - PullRequest
0 голосов
/ 10 января 2019

Я разработал модель нейронной сети для распознавания цифр с использованием тензорного потока. Я использовал tf.train.GradientDescent в качестве моего оптимизатора, и у меня была очень низкая точность прогнозирования (около 11%). Но если я только изменил свой оптимизатор на ShampooOptimizer с tenorsflow.contrib, он имел хорошую точность данных проверки (около 92%).

Я буквально только что изменил одну строку моего кода: от opt = tf.train.GradientDescentOptimizer(0.001) до opt = ShampooOptimizer() и это сработало

Я пытался остановиться в середине тренировки, и я обнаружил некоторую разницу. Для GradientDescentOptimizer: после 60 итераций лучший W имел одинаковое число по измерениям (я установил 87 измерений для первого слоя), лучший b имел одинаковое число по измерениям. Для шампуня: после 60 итераций лучший W имел разные числа по измерениям, так же как и лучший b. Я заметил эту разницу, но не знаю почему.

import tensorflow as tf
import numpy as np
from mnist import MNIST
from tensorflow.contrib.opt.python.training.shampoo import *

mndata = MNIST()
data, labels = mndata.load_training()
data = np.array(data)
nb_classes = 10
labels = np.eye(nb_classes)[labels]

test_data, test_labels = mndata.load_testing()
test_data = np.array(test_data)
nb_classes = 10
test_labels = np.eye(nb_classes)[test_labels]

X = tf.placeholder(dtype='float32',shape = (None,784))          
y = tf.placeholder(dtype='float32',shape = (None, 10))

W = tf.Variable(initial_value=np.ones((784,87)),dtype='float32',name='W',trainable=True) 
b = tf.Variable(initial_value=np.ones((1,87)),dtype='float32',name='b', trainable=True)
preds_t1= tf.matmul(X,W) + b
preds_a1 = tf.nn.relu(preds_t1)                          

W2 = tf.Variable(initial_value=np.ones((87,10)),dtype='float32',name = 'W2')    
b2 = tf.Variable(initial_value=np.ones((1,10)),dtype='float32', name = 'b2')
logits = tf.matmul(preds_a1,W2) + b2
preds = tf.nn.softmax(logits, axis=1)

loss = tf.losses.softmax_cross_entropy(onehot_labels=y, logits=logits)
opt = tf.train.GradientDescentOptimizer(0.001)
opt_op = opt.minimize(loss = loss, var_list = [W, b, W2, b2])

s_preds = tf.argmax(preds, axis = 1)
s_labels = tf.argmax(y, axis = 1)
sacc, sacc_op = tf.metrics.accuracy(s_labels, s_preds)

saver = tf.train.Saver()

with tf.Session() as sess:
    sess.run(tf.initializers.global_variables())
    sess.run(tf.local_variables_initializer())

    best_W, best_b, best_W2, best_b2 = sess.run((W, b, W2, b2))
    stop_count = 0
    patience = 40
    best_loss = np.inf
    train_data, train_labels, valid_data, valid_labels = 
train_valid_split(data, labels, split = 0.2)
    for i in range(300):
        batch_X, batch_y = random_sampling(train_data, train_labels, 12000)
        sess.run((opt_op), feed_dict={X: batch_X, y: batch_y})
        s_loss, s_accuracy = sess.run((loss, sacc_op), feed_dict={X: valid_data, y: valid_labels})       # validation
        print('epoch: ' + str(i) + '; loss is: ' + str(s_loss) + '; slack_accuracy is :' + str(s_accuracy))
        # early stopping thing
        if s_loss < best_loss:
            best_loss = s_loss
            best_W, best_b, best_W2, best_b2 = sess.run((W, b, W2, b2))
        else:
            stop_count += 1
            if (stop_count >=  patience):
                print('Stopped at iteration: ' + str(i))
                break

Может кто-нибудь объяснить мне разницу между этими двумя оптимизаторами, которые приводят к этой разнице в точности?

1 Ответ

0 голосов
/ 10 января 2019

Вы инициализируете все веса одним и тем же значением (используя np.ones). Это нарушает вашу модель, потому что все скрытые юниты будут вычислять одну и ту же вещь (и получать одни и те же ошибки), поэтому они также будут учиться одной и той же вещи, а это означает, что у вас фактически есть только одна скрытая юнит. Я не знаю, что делает оптимизатор шампуня, но я предполагаю, что у него есть какое-то нарушение симметрии.
Ваша модель должна работать с градиентным спуском по умолчанию, если вы замените начальные значения веса случайными числами (например, tf.random_uniform([784,87], minval=-0.1, maxval=0.1) для скрытого слоя). Это предотвращает идентичность всех юнитов.

...