假设我将向量与标量相乘,例如:
a = tf.Variable(3.)
b = tf.Variable([1., 0., 1.])
with tf.GradientTape() as tape:
c = a*b
grad = tape.gradient(c, a)
我得到的梯度是一个标量,
<tf.Tensor: shape=(), dtype=float32, numpy=2.0>
而我们期望的矢量是:
<tf.Variable 'Variable:0' shape=(3,) dtype=float32, numpy=array([1., 0., 1.], dtype=float32)>
看看其他例子,张量流似乎对期望向量求和,也对标量矩阵乘法等求和。tensorflow为什么这么做?使用@custum_gradient
可能可以避免这种情况,有没有另一种不那么麻烦的方法来获得正确的梯度?
似乎有一些相关的问题,但这些问题似乎都考虑了在训练批次上聚合的损失函数的梯度。这里没有使用损失函数或聚合,所以我认为问题是其他方面的?
您获得缩放器值是因为您使用了梯度wrt缩放器。如果你把grad乘以某个向量,就会得到一个向量。看看下面的例子:
import tensorflow as tf
a = tf.Variable(3., trainable=True)
b = tf.Variable([1., 0, 1.], trainable=True)
c = tf.Variable(2., trainable=True)
d = tf.Variable([2., 1, 2.], trainable=True)
with tf.GradientTape(persistent=True) as tape:
e = a*b*c*d # abcd , abcd , abcd
tf.print(e)
grad = tape.gradient(e, [a, b, c, d])
grad[0].numpy(), grad[1].numpy(), grad[2].numpy(), grad[3].numpy()
[12 0 12]
(8.0,
array([12., 6., 12.], dtype=float32),
12.0,
array([6., 0., 6.], dtype=float32))
形式上,我要找的是向量场的微分,它是变量a
的函数。对于向量场,微分和雅可比是一样的。事实证明,我所寻找的可以通过tape.jacobian
来完成。