我正在通过here进行TensorFlow Eager Execution,并发现很难理解自定义渐变部分。
@tfe.custom_gradient
def logexp(x):
e = tf.exp(x)
def grad(dy):
return dy * (1 - 1/(1 + e))
return tf.log(1 + e), grad
首先,很难理解dy在渐变函数中的作用。
当我阅读tf.contrib.eager.custom_gradient的实现时。 我无法理解磁带背后的工作机制。以下是我从tf.contrib.eager.custom_gradient的实现中借用的代码。谁能解释一下磁带在这里做了什么?
from tensorflow.python.eager import tape
from tensorflow.python.ops import array_ops
from tensorflow.python.ops import gen_array_ops
from tensorflow.python.util import nest
from tensorflow.python.framework import ops as tf_ops
def my_custom_gradient(f):
def decorated(*args, **kwargs):
for x in args:
print('args {0}'.format(x))
input_tensors = [tf_ops.convert_to_tensor(x) for x in args]
with tape.stop_recording():
result, grad_fn = f(*args, **kwargs)
flat_result = nest.flatten(result)
flat_result = [gen_array_ops.identity(x) for x in flat_result]
def actual_grad_fn(*outputs):
print(*outputs)
return nest.flatten(grad_fn(*outputs))
tape.record_operation(
f.__name__, # the name of f, in this case logexp
flat_result,
input_tensors,
actual_grad_fn) # backward_function
flat_result = list(flat_result)
return nest.pack_sequence_as(result, flat_result)
return decorated
即使我从here找到了磁带的实现。但由于文件很差,我无法从中得到很多。
答案 0 :(得分:0)
我将分别回答每个子问题:
Re:什么是dy
:渐变函数的主要用例是在反向传播期间。在反向传播期间,每个op的梯度必须采用其输出的梯度并产生其输入的梯度。这实际上是微积分链规则的结果。对于简单的操作,最终的渐变只是dy
与op的渐变(再次来自链规则)的乘法。在这种情况下,您可以看到dy * (1 - 1/(1 + e))
。
重新:custom_gradient
很复杂:是的,确实如此。渐变磁带的公共API是tfe.GradientTape
,它应该更容易理解和使用。您可以在其规范及其tests中找到简单的示例。一个更复杂的现实世界"示例可以找到here。如果其基本工作不清楚,请询问具体问题。此外,我们将很快发布更详细的指南,以便在执行时急切地使用渐变。
用于实现tape
和custom_gradient
的{{1}}是包含一些C ++代码的低级概念。最终用户不应该关心它(它没有在GradientTape
命名空间中公开)。它用于构建一个" tape"执行的操作。磁带类似于常规TF图,但更简单。它允许人们计算它记录的两个张量之间的梯度。