求梯度测试

08 Jun 2020

静态图

1. tf.gradients

x=tf.ones([4.0,1.0])
t=tf.ones([4.0,1.0])
# 注意这里合并了
X= tf.concat([x,t],1)
w=tf.constant([[2.0],[1.0]])
y=tf.matmul(X,w)
g1=tf.gradients(y,x)
g2=tf.gradients(y,t)
with tf.compat.v1.Session() as sess:
    print(sess.run(g1))
    print(sess.run(g2))
# 结果正确
def gra_fun(X):
    w=tf.constant([[2.0],[1.0]])
    y=tf.tanh(tf.matmul(X,w))
    return y
x=tf.ones([4.0,1.0])
t=tf.ones([4.0,1.0])
X= tf.concat([x,t],1)

y=gra_fun(X)
g1=tf.gradients(y,x)
# g1,g2=tf.gradients(y,[x,t]) 也正确
g2=tf.gradients(y,t)
gg1=tf.gradients(g1,x)
ggg1=tf.gradients(gg1,x)
# 在调用函数的情况下,求导正确
# 分别为:0.01973224
# 0.00986612
# -0.07853862
# 0.31104344
# 又测试了y=X^4,结果完全正确。

2. tf.GradientTape()

# 如果tape1和tape2都对大X求导,可运行,结果为[x',t'], 二阶导结果为[x'',t'']
# 如果只对最后一个小x求导,可运行,但xiaox求导结果为0
# 如果对倒数第二个对小x求导,失败。
x=tf.ones([4.0,1.0])
t=tf.ones([4.0,1.0])
X= tf.concat([x,t],1)

w=tf.constant([[2.0],[1.0]])

with tf.GradientTape() as tape1:
    tape1.watch(X)
    with tf.GradientTape() as tape2:
        tape2.watch(X)
        y=gra_fun(X)
        g1=tape2.gradient(y,X)
#            g2=tape2.gradient(y,t)
    gg1=tape1.gradient(g1,x)
#ggg1=tape.gradient(gg1,x)
# Cannot convert value None to a TensorFlow DType.
x=tf.ones([4.0,1.0])
t=tf.ones([4.0,1.0])*2.0
X= tf.concat([x,t],1)

w=tf.constant([[2.0],[1.0]])
#X=X**4
#y=tf.sin(tf.matmul(X,w))


with tf.GradientTape() as tape1:
    tape1.watch(X)
    with tf.GradientTape() as tape2:
        tape2.watch(X)
        y=gra_fun(X)
        g1=tape2.gradient(y,X)
#            g2=tape2.gradient(y,t)
    gg1=tape1.gradient(g1,X)
#ggg1=tape.gradient(gg1,x)
with tf.compat.v1.Session() as sess:
    print(sess.run(g1))
#    print(sess.run(g2))
    print(sess.run(gg1[:,0:1]))
#    print(sess.run(ggg1))
# results
[[ 4. 32.]
 [ 4. 32.]
 [ 4. 32.]
 [ 4. 32.]]
[[12.]
 [12.]
 [12.]
 [12.]]

即刻执行模式

tf.graidents无法使用

或者加上@tf.function可以用

2. tf.GradientTape()

x=tf.constant([[4.0],[1.0]])
t=tf.constant([[4.0],[1.0]])*2.0
X= tf.concat([x,t],1)

w=tf.constant([[2.0],[1.0]])
#X=X**4
#y=tf.sin(tf.matmul(X,w))


with tf.GradientTape() as tape1:
    tape1.watch(X)
    with tf.GradientTape() as tape2:
        tape2.watch(X)
        # 这里也可以调用y=fun(x)
        y=X*X*X*X
        g1=tape2.gradient(y,X)
#            g2=tape2.gradient(y,t)
    gg1=tape1.gradient(g1,X)
#ggg1=tape.gradient(gg1,x)
[[ 256. 2048.]
 [   4.   32.]]
[[192. 768.]
 [ 12.  48.]]

求偏导数

x=tf.constant([[4.0],[1.0]])
t=tf.constant([[4.0],[1.0]])*2.0
X= tf.concat([x,t],1)

w=tf.constant([[2.0],[1.0]])
#X=X**4
#y=tf.sin(tf.matmul(X,w))


with tf.GradientTape() as tape1:
    tape1.watch(X)
    with tf.GradientTape() as tape2:
        tape2.watch(X)
        y=gra_fun(X)
        g1=tape2.gradient(y,X)
#            g2=tape2.gradient(y,t)
    g1_t=g1[:,1:2]
#    gg1=tape1.gradient(g1,X)
    gg1_t=tape1.gradient(g1_t,X)
#ggg1=tape.gradient(gg1,x)
print(g1.numpy())
#print(gg1.numpy())
print(g1_t.numpy())
print(gg1_t.numpy())
[[ 256. 2048.]
 [   4.   32.]]
[[2048.]
 [  32.]]
[[  0. 768.]
 [  0.  48.]]

似乎可行

总结

即刻模式下,用tf.GradientTape()对直接自变量(函数中输入的那个量,而不是其变换前的量)求导,

静态图模式下,可以用tf.gradients对自变量(包括变换过的量)求导,但必须全部在tensor中运行,然后用session变为数组