如何在 TensorFlow 中提供自定义梯度

Hem*_*ant 7 python-2.7 tensorflow

我试图了解如何使用@tf.custom_gradient TensorFlow 1.7 中提供的函数来提供向量相对于向量的自定义梯度。下面的代码是解决以下问题的最小工作示例dz/dx

y=Ax
z=||y|| 2

另外,此附图描述了手动计算所期望的解决方案

如果我不使用,@tf.custom_gradient那么 TensorFlow 会按预期给出所需的解决方案。我的问题是如何为 y=Ax 提供自定义渐变?我们知道,dy/dx = A^T如上面的附件所示,它显示了与 TensorFlow 输出相匹配的计算步骤。

import tensorflow as tf

#I want to write custom gradient for this function f1
def f1(A,x):
    y=tf.matmul(A,x,name='y')
    return y

#for y= Ax, the derivative is: dy/dx= transpose(A)
@tf.custom_gradient
def f2(A,x):
    y=f1(A,x)
    def grad(dzByDy): # dz/dy = 2y reaches here correctly.
        dzByDx=tf.matmul(A,dzByDy,transpose_a=True) 
        return dzByDx
    return y,grad


x= tf.constant([[1.],[0.]],name='x')
A= tf.constant([ [1., 2.], [3., 4.]],name='A')

y=f1(A,x) # This works as desired
#y=f2(A,x) #This line gives Error


z=tf.reduce_sum(y*y,name='z')

g=tf.gradients(ys=z,xs=x)

with tf.Session() as sess:
    print sess.run(g)
Run Code Online (Sandbox Code Playgroud)

Pet*_*dan 3

由于您的函数f2()有两个输入,因此您必须提供一个梯度以流回每个输入。您看到的错误:

为操作名称生成的 Num 梯度 2:“IdentityN”[...] 与 num 输入 3 不匹配

不过,这确实是相当神秘的。假设您不想计算 d y /d A,您可以只返回 None, dzByDx。下面的代码(经过测试):

import tensorflow as tf

#I want to write custom gradient for this function f1
def f1(A,x):
    y=tf.matmul(A,x,name='y')
    return y

#for y= Ax, the derivative is: dy/dx= transpose(A)
@tf.custom_gradient
def f2(A,x):
    y=f1(A,x)
    def grad(dzByDy): # dz/dy = 2y reaches here correctly.
        dzByDx=tf.matmul(A,dzByDy,transpose_a=True) 
        return None, dzByDx
    return y,grad

x= tf.constant([[1.],[0.]],name='x')
A= tf.constant([ [1., 2.], [3., 4.]],name='A')

#y=f1(A,x) # This works as desired
y=f2(A,x) #This line gives Error

z=tf.reduce_sum(y*y,name='z')

g=tf.gradients(ys=z,xs=x)

with tf.Session() as sess:
    print sess.run( g )
Run Code Online (Sandbox Code Playgroud)

输出:

[数组([[20.], [28.]], dtype=float32)]

如预期的。