MNIST Tensorflow против кода от Майкла Нильсена

Я прочитал книгу Майкла Нильсена «Nuralnetworksanddeeplearning.com» о нейронных сетях. Он всегда делает пример с данными MNIST. Я сейчас взял его код и спроектировал точно такую ​​же сеть в Tensorflow, но понял, что результаты в Tensorflow не такие (они намного хуже).

Вот подробности:

1) Код от Майкла Нильсена можно найти по адресу https://github.com/kanban1992/MNIST_Comparison/tree/master/Michael_Nielsen. можно начать все с

python start_2.py

В сети есть

  • 3 скрытых слоя по 30 нейронов.
  • все функции активации являются сигмоидами
  • Я использую стохастический градиентный спуск (скорость обучения 3.0) с обратным распространением. Размер партии 10
  • Используется квадратичная функция стоимости без какой-либо регуляризации.
  • Матрица весов, которая соединяет слой l и l+1, инициализируется гауссовской плотностью вероятности со stddev=1/sqrt (количество нейронов в слое l) и mu=0,0. Смещения инициализируются стандартным нормальным распределением.
  • после обучения в течение 5 эпох я получаю 95% изображений в проверочном наборе, классифицированном правильно.

Этот подход должен быть правильным, потому что он хорошо работает, и я его не модифицировал!

2) Реализация тензорного потока была сделана мной и имеет точно такую ​​же структуру, как сеть Нильсена, описанная выше в пункте 1). Полный код можно найти по адресу https://github.com/kanban1992/MNIST_Comparison/tree/master/tensorflow и запустите с

python start_train.py

С подходом тензорного потока я получаю точность 10% (это было бы то же самое, что и случайное угадывание!) Значит, что-то не работает, и я понятия не имею, что!?

Вот фрагмент самой важной части кода:

x_training,y_training,x_validation,y_validation,x_test,y_test = mnist_loader.load_data_wrapper()

N_training=len(x_training)
N_validation=len(x_validation)
N_test=len(x_test)


N_epochs = 5

learning_rate = 3.0 
batch_size = 10


N1 = 784 #equals N_inputs
N2 = 30
N3 = 30
N4 = 30
N5 = 10

N_in=N1
N_out=N5

x = tf.placeholder(tf.float32,[None,N1])#don't take the shape=(batch_size,N1) argument, because we need this for different batch sizes

W2 = tf.Variable(tf.random_normal([N1, N2],mean=0.0,stddev=1.0/math.sqrt(N1*1.0)))# Initialize the weights for one neuron with 1/sqrt(Number of weights which enter the neuron/ Number of neurons in layer before)
b2 = tf.Variable(tf.random_normal([N2]))
a2 = tf.sigmoid(tf.matmul(x, W2) + b2) #x=a1

W3 = tf.Variable(tf.random_normal([N2, N3],mean=0.0,stddev=1.0/math.sqrt(N2*1.0)))
b3 = tf.Variable(tf.random_normal([N3]))
a3 = tf.sigmoid(tf.matmul(a2, W3) + b3)

W4 = tf.Variable(tf.random_normal([N3, N4],mean=0.0,stddev=1.0/math.sqrt(N3*1.0)))
b4 = tf.Variable(tf.random_normal([N4]))
a4 = tf.sigmoid(tf.matmul(a3, W4) + b4)

W5 = tf.Variable(tf.random_normal([N4, N5],mean=0.0,stddev=1.0/math.sqrt(N4*1.0)))
b5 = tf.Variable(tf.random_normal([N5]))
y = tf.sigmoid(tf.matmul(a4, W5) + b5)

y_ = tf.placeholder(tf.float32,[None,N_out]) #  ,shape=(batch_size,N_out)


quadratic_cost= tf.scalar_mul(1.0/(N_training*2.0),tf.reduce_sum(tf.squared_difference(y,y_))) 

train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(quadratic_cost)
init = tf.initialize_all_variables()

#launch the graph
sess = tf.Session()
sess.run(init)


#batch size of training input
N_training_batch=N_training/batch_size #rounds to samllest integer

correct=[0]*N_epochs
cost_training_data=[0.0]*N_epochs

for i in range(0,N_epochs):
    for j in range(0,N_training_batch):
        start=j*batch_size
        end=(j+1)*batch_size
        batch_x=x_training[start:end]
        batch_y=y_training[start:end]

        sess.run(train_step, feed_dict={x: batch_x, 
        y_: batch_y})

    perm = np.arange(N_training)
    np.random.shuffle(perm)
    x_training = x_training[perm]
    y_training = y_training[perm]


    #cost after each epoch
    cost_training_data[i]=sess.run(quadratic_cost, feed_dict={x: x_training, 
        y_: y_training})
    #correct predictions after each epoch
    y_out_validation=sess.run(y,feed_dict={x: x_validation})
    for k in range(0,len(y_out_validation)):
        arg=np.argmax(y_out_validation[k])
        if 1.0==y_validation[k][arg]:
            correct[i]+=1

    print "correct after "+str(i)+ " epochs: "+str(correct[i])

Было бы очень здорово, если бы вы могли сказать мне, что происходит не так :-)


person jojo123456    schedule 18.06.2016    source источник


Ответы (1)


Ваша скорость обучения кажется высокой для Gradient Decent. Попробуйте число больше похожее на .0001. Поднимите или опустите оттуда.

Мне нравится оптимизатор Адама, убедитесь, что вы начинаете с меньшей скорости обучения (я думаю, что 001 по умолчанию для Адама):

оптимизатор = tf.train.AdamOptimizer (learning_rate)

person mazecreator    schedule 18.06.2016
comment
Дело в том, что я хочу точно воспроизвести сеть Нильсена, чтобы проверить, все ли работает нормально. Если я выберу GradientDescent с learningng_rate=0,001, я также получу точность только 10%. Если я выберу AdamOptimizer со скоростью обучения 0,001, я получу точность 95%, но это не решит мою проблему перекрестной проверки. - person jojo123456; 18.06.2016
comment
Может быть, в версии Нильсена есть ошибка, из-за которой она работает с таким высоким уровнем ошибок? Градиентный спуск TensorFlow прошел множество тестов - person Yaroslav Bulatov; 18.06.2016
comment
Сеть Nielsens отлично работает для упомянутой настройки, но тензорный поток — это плохо. Я думаю, что в тензорном потоке GradientDescentOptimizer есть ошибка. - person jojo123456; 18.06.2016
comment
Для GradientDescent убедитесь, что вы пробуете разные скорости обучения, попробуйте с шагом в десять в обоих направлениях. Я подозреваю, что вам нужно уменьшить его, так как вы все еще получаете 10% на 0,0001. - person mazecreator; 18.06.2016
comment
Если углубиться в код Нильсена, lmbda=0.0, в функции Gradient Descent (update_mini_batch ~ строка 205), вес корректируется на (1-eta*(lmbda/n))*w. Поскольку lmbda=0, eta, установленное на 3,0, умножается на 0,0, что означает, что вы можете установить eta на любое значение, чтобы получить те же результаты. Это определенно указывает на то, что его реализация отличается от TensorFlow. - person mazecreator; 18.06.2016
comment
У вас есть self.weights = [(1-eta*(lmbda/n))*w-(eta/len(mini_batch))*nw для w, nw в zip(self.weights, nabla_w)], но если lmnda=0.0 это не означает, что это не зависит от эта. Есть еще эта. - person jojo123456; 18.06.2016
comment
Только на 2-й срок, договорились. Я говорю вам, что эта и скорость обучения TensorFlow — это не одно и то же значение. Исследуйте GD с разной скоростью обучения в TensorFlow. - person mazecreator; 19.06.2016
comment
Хорошо, я думаю, здесь это определено: github .com/tensorflow/tensorflow/blob/master/tensorflow/core/, это будет означать, если я сравню это с формулой Нильсена, что eta/len(mini_batch)=learning_rate_tensorflow. Это означает, что я должен выбрать tensorflow=0,3 и eta=3,0, но это не сработало... - person jojo123456; 19.06.2016