将TensorFlow梯度计算分解为两个(或更多)部分

时间:2018-04-28 11:18:08

标签: tensorflow automatic-differentiation

是否可以在部分中使用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)。 然后,根据链式规则,我希望g1g2的维度能够解决,以便我可以在某种意义上编写g=g1*g2并返回tf.gradients(loss,W)

不幸的是,事实并非如此。尺寸不正确。每个渐变的尺寸都是" w.r.t变量"的尺寸,因此不会是第一个渐变和第二个渐变之间的对应关系。我错过了什么,我该怎么做?

感谢。

2 个答案:

答案 0 :(得分:1)

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]))

答案 1 :(得分:0)

来自docstf.gradients(强调我的)

  

构造ys w.r.t的 sum 的符号导数。 x在xs。

如果ys中的任何张量是多维的,那么在得到的标量列表之前它是reduce_sum med,然后才会被差异化。这就是输出渐变与xs具有相同大小的原因。

这也解释了为什么损失在张量流中可以是多维的:它们在分化之前被隐含地总结。