【发布时间】:2021-01-22 22:45:52
【问题描述】:
我需要计算一个元素梯度作为神经网络的输入。
我决定使用tf.data.Dataset 来存储输入数据。
预处理数据和计算梯度是昂贵的,我想分批做,然后存储数据。
我简化了函数以使用形状 (batch_size, x, y),并且我想分别计算每个 y 的梯度。
使用tf.GradientTape 如下所示:
import tensoflow as tf
# @tf.function
def test(inp):
with tf.GradientTape(persistent=True) as tape:
tape.watch(inp)
out = inp**2
out = tf.unstack(out, axis=-1)
grad = []
for x in out:
grad.append(tape.gradient(x, inp))
del tape
return tf.stack(grad, axis=-1)
inp = tf.random.normal((32, 100, 50))
test(inp)
这段代码需要 ~76 ms 来执行而不需要 3.1 s 和 tf.function 装饰器。
不幸的是,当将它与 tf.data.Dataset.map 一起使用时,会出现同样的减速,我假设它会将其转换为 tf.function
我尝试改用tf.batch_jacobian,它不会受到tf.function 减速的影响,但会计算出更多的梯度,我必须减少它们。执行大约需要 15 秒。
@tf.function
def test(inp):
with tf.GradientTape() as tape:
tape.watch(inp)
out = inp**2
grad = tape.batch_jacobian(out, inp)
return tf.math.reduce_sum(grad, axis=3)
x = test(inp)
对于更大的数据集和更多的资源繁重的计算,我试图避免这种减速,但我还没有找到解决方案,我也不明白为什么它的计算速度要慢得多。 有没有办法重塑数据并使用雅可比方法或其他东西,可以克服这个问题?
【问题讨论】:
-
您如何进行测量?
tf.function必须先跟踪函数,这有一些开销,但通常是您只需支付一次的代价。
标签: python tensorflow