Разбиение вычисления градиента TensorFlow на две (или более) части - PullRequest
0 голосов
/ 28 апреля 2018

Можно ли использовать функцию TensorFlow tf.gradients() по частям, то есть вычислить градиент потерь с некоторым тензором и этого тензора с весом, а затем умножить их, чтобы получить исходный градиент от потерь до вес?

Например, пусть W,b будет некоторым весом, пусть x будет входом сети, и пусть y0 обозначает метки.

Предположим, что прямой график, например

h=Wx+b
y=tanh(h)
loss=mse(y-y0)

Мы можем вычислить tf.gradients(loss,W) и затем применить (пропуская некоторые детали) optimizer.apply_gradients(), чтобы обновить W.

Затем я пытаюсь извлечь промежуточный тензор, используя var=tf.get_default_graph().get_tensor_by_name(...), а затем вычисляю два градиента: g1=tf.gradients(loss,var) и g2=tf.gradients(var,W). Тогда я бы по правилу цепочки ожидал, что размеры g1 и g2 сработают, так что я могу в некотором смысле написать g=g1*g2 и получить обратно tf.gradients(loss,W).

К сожалению, это не тот случай. Размеры неверны. Размеры каждого градиента будут такими же, как у переменной w.r.t, поэтому между первым градиентом и вторым не будет соответствия. Чего мне не хватает, и как я могу это сделать?

Спасибо.

Ответы [ 2 ]

0 голосов
/ 28 апреля 2018

tf.gradients будет суммироваться по градиентам входного тензора. Чтобы избежать этого, нужно разбить тензор на скаляры и применить tf.gradients к каждому из них:

import tensorflow as tf

x = tf.ones([1, 10])

w = tf.get_variable("w", initializer=tf.constant(0.5, shape=[10, 5]))
out = tf.matmul(x, w)
out_target = tf.constant(0., shape=[5])

loss = tf.reduce_mean(tf.square(out - out_target))

grad = tf.gradients(loss, x)

part_grad_1 = tf.gradients(loss, out)
part_grad_2 = tf.concat([tf.gradients(i, x) for i in tf.split(out, 5, axis=1)], axis=1)

grad_by_parts = tf.matmul(part_grad_1, part_grad_2)

init = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)
    print(sess.run([grad]))
    print(sess.run([grad_by_parts]))
0 голосов
/ 28 апреля 2018

Из документов , tf.gradients (выделено мной)

строит символические производные от суммы от ys w.r.t. х в хз.

Если какой-либо тензор в ys в многомерном, то reduce_sum med прежде чем сам итоговый список скаляров будет суммирован, перед тем как будет дифференцирован. Вот почему выходной градиент имеет тот же размер, что и xs.

Это также объясняет, почему потери могут быть многомерными в тензорном потоке: они неявно суммируются перед дифференцированием.

...