tensorflow.python.eager.tape在tf.contrib.eager.custom_gradient的实现中做了什么?

时间:2018-03-21 21:37:02

标签: tensorflow

我正在通过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找到了磁带的实现。但由于文件很差,我无法从中得到很多。

1 个答案:

答案 0 :(得分:0)

我将分别回答每个子问题:

Re:什么是dy :渐变函数的主要用例是在反向传播期间。在反向传播期间,每个op的梯度必须采用其输出的梯度并产生其输入的梯度。这实际上是微积分链规则的结果。对于简单的操作,最终的渐变只是dy与op的渐变(再次来自链规则)的乘法。在这种情况下,您可以看到dy * (1 - 1/(1 + e))

重新:custom_gradient很复杂:是的,确实如此。渐变磁带的公共API是tfe.GradientTape,它应该更容易理解和使用。您可以在其规范及其tests中找到简单的示例。一个更复杂的现实世界"示例可以找到here。如果其基本工作不清楚,请询问具体问题。此外,我们将很快发布更详细的指南,以便在执行时急切地使用渐变。

用于实现tapecustom_gradient的{​​{1}}是包含一些C ++代码的低级概念。最终用户不应该关心它(它没有在GradientTape命名空间中公开)。它用于构建一个" tape"执行的操作。磁带类似于常规TF图,但更简单。它允许人们计算它记录的两个张量之间的梯度。