重复使用 GradientTape 进行多次雅可比计算



我正在尝试计算TensorFlow神经网络输出相对于其输入的雅可比量。这可以通过tf.GradientTape.jacobian方法轻松实现。TensorFlow文档中提供的简单示例如下:

with tf.GradientTape() as g:
x  = tf.constant([1.0, 2.0])
g.watch(x)
y = x * x
jacobian = g.jacobian(y, x)

如果我只想计算输入张量x单个实例的雅可比矩阵,这很好。但是,对于各种x实例,我需要多次反复评估这个雅各比亚。对于非平凡的雅可比计算(例如,对于具有非线性激活函数的深度卷积神经网络(,重复重新运行 GradientTape 计算并评估jacobian方法是非常昂贵的。我从 TensorFlow 文档中知道梯度(以及雅可比(是通过自动微分计算的。 我必须想象网络分析梯度(通过自动微分计算(有一些内部存储,它在给定的输入下进行评估。

我的问题:我假设TensorFlow构建并存储(至少部分(计算雅可比矩阵所需的分析梯度是否正确?如果是这样,有没有办法保存这个分析梯度并使用新的输入重新评估雅可比矩阵,而不必通过 GradientTape 方法重建它?

"持久"的GradientTape似乎不能解决这个问题:它只允许对单个GradientTape实例进行关于计算的多个内部参数的重复评估。

也许你觉得这很有帮助:

我需要多次计算任意函数的雅可比函数。我的问题是我不恰当地使用了GradientTape,但我发布的代码可能会帮助你或给你一些见解。我发布了一个自包含的示例,使用基于会话的tf.gradient()函数和现代GriadientTape方法计算雅可比函数。在帮助下,我让它们在彼此的相同数量级内运行。

  • 如果你的问题集中在尝试重用要求提高速度之间的中间计算,那么我认为尼克的答案更适用。
  • 如果你的问题集中在试图使GradientTape像静态图形一样快,那么请确保你把它包装在@tf.function,因为它就是这样做的。

请参阅我的问题:深渊tf。GradientTape 性能与 tf.gradients(( 相比,用于计算雅可比算法

我假设 TensorFlow 构建并存储(至少部分(计算雅可比矩阵所需的分析梯度是否正确?

不 - 我认为你一定误解了自动微分。

虽然 tf 中的每个基本运算都"知道"其输出相对于输入的解析导数,但在计算实际梯度或雅可比值时,伴随的数值(输出的导数(被传递给反向传递的操作,然后使用每个基本运算的解析公式和链式规则计算更多的数值。

如果是这样,有没有办法保存这个分析梯度并使用新的输入重新评估雅可比矩阵,而不必通过 GradientTape 方法重建它?

不。如果要计算新输入上的梯度或雅可比矩阵,则需要再次执行整个计算。对于深度神经网络来说,这是没有办法解决这个问题的。

顺便说一下,如果你对神经网络的损失函数相对于你的网络参数进行梯度,计算梯度的时间将是计算损失本身的成本的O(1(。这是反向传播,是反向模式自动微分之美的一部分。但是,如果您的网络有 N 个输出,并且您想要计算网络的完整雅可比量,这将花费 O(N( 计算网络输出的时间。这可能就是计算雅可比计算如此昂贵的原因。

例如,如果你在MNIST上训练一个网络,并且你的网络有10个输出,你把它们组合成一个损失函数,计算损失函数的梯度将需要O(1(时间,但计算10个输出中关于参数的雅可比量将需要O(10(时间。

最新更新