首页 文章

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

提问于
浏览
2

是否有可能在部分中使用TensorFlow的 tf.gradients() 函数,即 - 计算从损失w.r.t一些张量的梯度,以及那个张量w.r.t的权重,然后将它们相乘以得到从损失到重量的原始梯度?

例如,让 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

    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

    来自docstf.gradients (强调我的)

    构造ys w.r.t的和的符号导数 . xs中的x .

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

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

相关问题