SGD сходится, но пакетное обучение не, простая регрессия в tensorflow

Я столкнулся с проблемой, когда пакетное обучение в tensorflow не сходится к правильному решению для простой выпуклой задачи оптимизации, в то время как SGD сходится. Небольшой пример находится ниже, в языках программирования Julia и python, я проверил, что то же самое точное поведение является результатом использования tensorflow от Julia и python.

Я пытаюсь соответствовать линейной модели y = s*W + Bс параметрами Wи B
Функция стоимости квадратична, поэтому задача выпуклая и должна быть легко решена с помощью достаточно малого размера шага. Если я подаю все данные сразу, конечный результат — это просто прогноз среднего yзначения . Если, Однако, я подаю одну точку данных в то время (прокомментированный код в версии julia), оптимизация сходится к правильным параметрам очень быстро.

Я также проверил, что градиенты, вычисленные tensorflow, отличаются между примером пакета и суммированием градиентов для каждой точки данных по отдельности.

Есть идеи о том, где я потерпел неудачу?

using TensorFlow

s = linspace(1,10,10)
s = [s reverse(s)]
y = s*[1,4] + 2
session = Session(Graph())

s_ = placeholder(Float32, shape=[-1,2])
y_ = placeholder(Float32, shape=[-1,1])

W = Variable(0.01randn(Float32, 2,1), name="weights1")
B = Variable(Float32(1), name="bias3")

q =    s_*W + B
loss = reduce_mean((y_ - q).^2)
train_step = train.minimize(train.AdamOptimizer(0.01), loss)

function train_critic(s,targets)
    for i = 1:1000
        # for i = 1:length(y)
        #     run(session, train_step, Dict(s_ => s[i,:]', y_ => targets[i]))
        # end
        ts = run(session, [loss,train_step], Dict(s_ => s, y_ => targets))[1]
        println(ts)
    end
    v = run(session, q, Dict(s_ => s, y_ => targets))
    plot(s[:,1],v, lab="v (Predicted value)")
    plot!(s[:,1],y, lab="y (Correct value)")
    gui();
end

run(session, initialize_all_variables())
train_critic(s,y)

Тот же код в python (я не пользователь python, поэтому это может быть некрасиво)

import matplotlib
import numpy as np
import matplotlib.pyplot as plt
import sklearn.datasets
import tensorflow as tf
from tensorflow.python.framework.ops import reset_default_graph

s = np.linspace(1,10,50).reshape((50,1))
s = np.concatenate((s,s[::-1]),axis=1).astype('float32')
y = np.add(np.matmul(s,[1,4]), 2).astype('float32')

reset_default_graph()
rng = np.random
s_ = tf.placeholder(tf.float32, [None, 2])
y_ = tf.placeholder(tf.float32, [None])

weight_initializer = tf.truncated_normal_initializer(stddev=0.1)
with tf.variable_scope('model'): 
    W = tf.get_variable('W', [2, 1], 
                          initializer=weight_initializer)
    B = tf.get_variable('B', [1], 
                          initializer=tf.constant_initializer(0.0))

q = tf.matmul(s_, W) + B

loss = tf.reduce_mean(tf.square(tf.sub(y_ , q)))


optimizer = tf.train.AdamOptimizer(learning_rate=0.1)
train_op = optimizer.minimize(loss)

num_epochs = 200

train_cost= []
with tf.Session() as sess:
    init = tf.initialize_all_variables()
    sess.run(init)
    for e in range(num_epochs):
        feed_dict_train = {s_: s, y_: y}
        fetches_train = [train_op, loss]
        res = sess.run(fetches=fetches_train, feed_dict=feed_dict_train)
        train_cost = [res[1]]
        print train_cost

1 ответ

  1. Ответ оказался таким: когда я вводил цели, я вводил вектор, а не матрицу Nx1. Затем операция y_-qпревратилась в широковещательную операцию и вместо того, чтобы возвращать разность элементов, она вернула NxNматрицу с требуемой разностью по диагонали. В Julia я решил это, изменив строку

    train_critic(s,y)
    к
    train_critic(s,reshape(y, length(y),1))

    чтобы yбыть матрицей.

    Тонкая ошибка, которая заняла у меня очень много времени, чтобы найти! Часть путаницы заключалась в том, что TensorFlow, похоже, рассматривает векторы как векторы строк, а не как векторы столбцов, как Julia, поэтому операция трансляции в y_-q