我正在尝试计算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(时间。