2

我正在尝试计算 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 实例。

4

2 回答 2

2

也许你觉得这很有帮助:

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

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

请参阅我的问题:Abysmal tf.GradientTape 性能与计算雅可比的 tf.gradients() 相比

于 2020-05-15T19:09:18.293 回答
1

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

不-我认为您一定对自动微分有误解。

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

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

没有。如果要在新输入上计算梯度或雅可比,则需要再次执行整个计算。深度神经网络没有办法解决这个问题。

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

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

于 2020-02-06T15:54:17.017 回答