расчетная стоимость не равна значению потерь тензорного потока

avatar
quant
8 апреля 2018 в 08:55
199
1
0

Я создал простой сценарий градиентного спуска, чтобы лучше понять тензорный поток. Однако, когда я запускаю его и использую «догадки» для расчета значения потерь вручную, я не получаю того же значения, что и тензорный поток, и я не понимаю, почему.

Написанная мной программа использует градиентный спуск для обработки результата матричной операции f(X*A) * B, где f() — сигмовидная функция, где X (1xn) — заполнитель/входное значение и A (nxn) и B (nx1) — это матрицы, которые необходимо обнаружить. Значения для A и B заполняются в начале линейно возрастающими значениями. Для начала я просто установил n на 2.

Вот тестовая программа, иллюстрирующая проблему:

n = 2
A_actual = numpy.linspace(0, 1, n**2).reshape(n, n)
B_actual = numpy.linspace(0, 1, n).reshape(n, 1)

A = tensorflow.Variable(tensorflow.ones((n, n)), name='A')
B = tensorflow.Variable(tensorflow.ones((n, 1)), name='B')

X = tensorflow.placeholder("float", shape=[1, n], name='X')
y = tensorflow.placeholder("float", name='y')

y_hat = tensorflow.matmul(tensorflow.nn.sigmoid(tensorflow.matmul(X, A)), B)

loss = tensorflow.losses.mean_squared_error(labels=y, predictions=y_hat)
cost = tensorflow.reduce_mean(loss)
updates = tensorflow.train.GradientDescentOptimizer(0.01).minimize(cost)
with tensorflow.Session() as sess:
    init = tensorflow.global_variables_initializer()
    sess.run(init)

    for epoch in range(1, 10):
        train_X = numpy.random.rand(n).reshape(1, n)

        h = numpy.matmul(train_X, A_actual)
        train_y = numpy.matmul(h / (numpy.exp(-h) + 1), B_actual)

        _, c = sess.run([updates, loss], {X: train_X, y: train_y })

        A_guess = A.eval()
        B_guess = B.eval()

        # work out the expected loss:
        h_guess = numpy.matmul(train_X, A_guess)

        train_y = numpy.matmul(h / (numpy.exp(-h) + 1), B_actual)
        y_hat = numpy.matmul(h_guess / (numpy.exp(-h_guess) + 1), B_guess)

        expected_cost = (train_y - y_hat)**2

        print "A={}, B={}, train_X = {}, c={}, expected_c={}".format(A_guess, B_guess, train_X, c, expected_cost)

Я ожидал бы, что в каждую эпоху значения c и expected_c будут совпадать, но это не так. Вот вывод для пары эпох:

A=[[0.99831355 0.99831355]
 [0.9978205  0.9978205 ]], B=[[0.9855833]
 [0.9855833]], train_X = [[0.43161333 0.55779766]], c=0.977798759937, expected_c=[[0.90071899]]
A=[[0.99674106 0.99674106]
 [0.99594545 0.99594545]], B=[[0.97247064]
 [0.97247064]], train_X = [[0.75101306 0.89550778]], c=0.612140238285, expected_c=[[3.25077074]]
A=[[0.9963331 0.9963331]
 [0.9934323 0.9934323]], B=[[0.9615876]
 [0.9615876]], train_X = [[0.15488769 0.95426499]], c=0.524783551693, expected_c=[[0.73085703]]
A=[[0.99290335 0.99290335]
 [0.9930714  0.9930714 ]], B=[[0.9457934]
 [0.9457934]], train_X = [[0.7305608  0.07687351]], c=1.30655503273, expected_c=[[0.74179058]]
A=[[0.9906516 0.9906516]
 [0.9914385 0.9914385]], B=[[0.93114746]
 [0.93114746]], train_X = [[0.74625195 0.54115622]], c=0.876540482044, expected_c=[[1.72666188]]
A=[[0.9897084 0.9897084]
 [0.9894199 0.9894199]], B=[[0.91981167]
 [0.91981167]], train_X = [[0.39296997 0.84106038]], c=0.538159787655, expected_c=[[1.05986646]]
A=[[0.9873394 0.9873394]
 [0.9880559 0.9880559]], B=[[0.9053085]
 [0.9053085]], train_X = [[0.7454906  0.42922246]], c=0.906145870686, expected_c=[[1.32207708]]
A=[[0.98699   0.98699  ]
 [0.9865663 0.9865663]], B=[[0.89463204]
 [0.89463204]], train_X = [[0.0955704 0.4074265]], c=0.737196862698, expected_c=[[0.08112794]]
A=[[0.9847778 0.9847778]
 [0.9857968 0.9857968]], B=[[0.88113374]
 [0.88113374]], train_X = [[0.5787612  0.20131812]], c=0.975076794624, expected_c=[[0.47560335]]

Кажется, нет никакой связи между c и expected_c, но я перепроверил свой расчет стоимости (со ссылкой на tf.sigmoid и tf .losses.mean_squared_error страниц) и не могу найти никаких различий.

Почему эти значения не совпадают?

(Обратите внимание, что меня пока не беспокоит тот факт, что мои предположения не сходятся, я буду беспокоиться об этом, когда пойму функцию стоимости!)

Источник
xdurch0
8 апреля 2018 в 14:23
0

Возможно, потери TF вычисляются до обновления параметра, тогда как ваши "ожидаемые" потери вычисляются со значениями после обновления. Можете ли вы отделить запуск updates и loss и проверить еще раз?

quant
9 апреля 2018 в 10:55
1

@ xdurch0 Я попытался заменить [updates, loss] просто на loss (т.е. просто пропустив обновления), и значения стоимости по-прежнему сильно различаются (но веса не обновляются), поэтому я не думаю, что это проблема.

Ответы (1)

avatar
9 апреля 2018 в 11:32
0

Как правильно указал xdurch0, параметр loss вычисляется как часть оценки графика, поэтому обновление происходит после этого вычисления.

Чтобы это исправить, я заменил эту строку:

_, c = sess.run([updates, loss], {X: train_X, y: train_y })

С этой строкой:

sess.run(updates, {X: train_X, y: train_y })
c = sess.run(loss, {X: train_X, y: train_y })

Это приводит к тому, что loss оценивается дважды: один раз для вызова updates и снова после применения градиентного спуска.