tensorflow在梯度计算时如何处理不可微节点?
How does tensorflow handle non differentiable nodes during gradient calculation?
我了解自动微分的概念,但找不到任何解释 tensorflow 如何计算不可微分函数的误差梯度,例如我的损失函数中的 tf.where
或我的 tf.cond
图形。它工作得很好,但我想了解 tensorflow 如何通过这些节点反向传播错误,因为没有公式可以计算它们的梯度。
在 tf.where
的情况下,您有一个具有三个输入的函数,条件 C
,真值 T
和假值 F
,以及一个输出 Out
。梯度接收一个值并且必须 return 三个值。目前,没有为条件计算梯度(这几乎没有意义),所以你只需要为 T
和 F
计算梯度。假设输入和输出是向量,假设 C[0]
是 True
。然后 Out[0]
来自 T[0]
,它的梯度应该传播回来。另一方面,F[0]
会被丢弃,所以它的梯度应该为零。如果 Out[1]
是 False
,那么 F[1]
的梯度应该传播,但 T[1]
的梯度不会传播。因此,简而言之,对于 T
,您应该在 C
为 True
的地方传播给定的梯度,并在 False
的地方将其设为零,而 F
则相反].如果您查看 the implementation of the gradient of tf.where
(Select
operation),它确实是这样做的:
@ops.RegisterGradient("Select")
def _SelectGrad(op, grad):
c = op.inputs[0]
x = op.inputs[1]
zeros = array_ops.zeros_like(x)
return (None, array_ops.where(c, grad, zeros), array_ops.where(
c, zeros, grad))
注意输入值本身不用于计算,这将由产生这些输入的操作的梯度来完成。对于tf.cond
、the code is a bit more complicated,因为在不同的上下文中使用了相同的操作(Merge
),而且tf.cond
内部也使用了Switch
操作。不过思路是一样的。本质上,Switch
操作用于每个输入,因此被激活的输入(第一个如果条件为 True
,否则第二个)获得接收到的梯度,另一个输入获得 "switched off" 梯度(如 None
),并且不会进一步向后传播。
我了解自动微分的概念,但找不到任何解释 tensorflow 如何计算不可微分函数的误差梯度,例如我的损失函数中的 tf.where
或我的 tf.cond
图形。它工作得很好,但我想了解 tensorflow 如何通过这些节点反向传播错误,因为没有公式可以计算它们的梯度。
在 tf.where
的情况下,您有一个具有三个输入的函数,条件 C
,真值 T
和假值 F
,以及一个输出 Out
。梯度接收一个值并且必须 return 三个值。目前,没有为条件计算梯度(这几乎没有意义),所以你只需要为 T
和 F
计算梯度。假设输入和输出是向量,假设 C[0]
是 True
。然后 Out[0]
来自 T[0]
,它的梯度应该传播回来。另一方面,F[0]
会被丢弃,所以它的梯度应该为零。如果 Out[1]
是 False
,那么 F[1]
的梯度应该传播,但 T[1]
的梯度不会传播。因此,简而言之,对于 T
,您应该在 C
为 True
的地方传播给定的梯度,并在 False
的地方将其设为零,而 F
则相反].如果您查看 the implementation of the gradient of tf.where
(Select
operation),它确实是这样做的:
@ops.RegisterGradient("Select")
def _SelectGrad(op, grad):
c = op.inputs[0]
x = op.inputs[1]
zeros = array_ops.zeros_like(x)
return (None, array_ops.where(c, grad, zeros), array_ops.where(
c, zeros, grad))
注意输入值本身不用于计算,这将由产生这些输入的操作的梯度来完成。对于tf.cond
、the code is a bit more complicated,因为在不同的上下文中使用了相同的操作(Merge
),而且tf.cond
内部也使用了Switch
操作。不过思路是一样的。本质上,Switch
操作用于每个输入,因此被激活的输入(第一个如果条件为 True
,否则第二个)获得接收到的梯度,另一个输入获得 "switched off" 梯度(如 None
),并且不会进一步向后传播。