在深度学习中,我们经常需要对函数求梯度(gradient), tensorflow2.0 提供的 GradientTape 可自动求梯度。
x = tf.constant(3.0) #创建tensor
with tf.GradientTape() as g: # 创建一个GradientTape对象
g.watch(x) # 监视watch要求导的变量
y = x * x
dy_dx = g.gradient(y, x) # 对函数进行求导
默认情况下,调用 GradientTape.gradient() 方法时, GradientTape 占用的资源会立即得到释放。通过创建一个持久的梯度带, 参数 persistent=True, 可以计算同个函数的多个导数,但是注意要手动释放资源del tape。例如:
with tf.GradientTape(persistent=True) as g:
g.watch(x)
y = x * x
z = y * Y
dz_dx = g.gradient(z, x) # 求一阶导数
dy_dx = g.gradient(y, x) # 求二阶导数
del g #手动释放资源
在 ‘GradientTape’ 上下文管理器中记录的操作会用于自动微分。如果导数是在上下文中计算的,导数的函数也会被记录下来,因此 “同个 API ” 可以用于高阶导数。例如:
二阶导数(高阶导数同理)
x = tf.Variable(1.0) # 创建可优化的tensor(具有可求导的特性)
with tf.GradientTape() as t:
with tf.GradientTape() as t2:
y = x * x * x
dy_dx = t2.gradient(y, x) #计算一阶导数
d2y_dx2 = t.gradient(dy_dx, x) #计算二阶导数
##coding:utf-8
import tensorflow as tf
#举例-MSE Gradient
x = tf.random.normal([2,4],seed=1)
w = tf.random.normal([4,3],seed=1)
b = tf.zeros([3])
y = tf.constant([2,0])
with tf.GradientTape() as tape:
tape.watch([w,b])
prob = tf.nn.softmax(x@w+b,axis=1)
loss = tf.reduce_mean(tf.losses.MSE(tf.one_hot(y,depth=3),prob))
grads = tape.gradient(loss,[w,b])
print(grads[0])
"""
输出:
tf.Tensor(
[[-5.5192433e-02 -4.8389734e-06 5.5197272e-02]
[ 3.6337111e-02 1.7934163e-04 -3.6516447e-02]
[-4.5821436e-02 1.3292905e-04 4.5688514e-02]
[ 3.6436778e-02 -5.4880476e-04 -3.5887983e-02]], shape=(4, 3), dtype=float32)
"""
print(grads[1])
"""
输出:
tf.Tensor([-0.02586884 0.00025355 0.0256153 ], shape=(3,), dtype=float32)
"""
#举例-Crossentropy gradient
x = tf.random.normal([2,4],seed=1)
w = tf.random.normal([4,3],seed=1)
b = tf.zeros([3])
y = tf.constant([2,0])
with tf.GradientTape() as tape:
tape.watch([w,b])
logits = x@w+b
loss = tf.reduce_mean(tf.losses.categorical_crossentropy(tf.one_hot(y,depth=3),logits))
grads = tape.gradient(loss,[w,b])
print(grads[0])
"""
输出:
tf.Tensor(
[[-0.08838065 -0.06390739 0.03672602]
[ 0.08741999 0.23320754 0.04906246]
[-0.0506487 0.09553305 0.0874298 ]
[-0.03325637 -0.55674076 -0.25375524]], shape=(4, 3), dtype=float32)
"""
print(grads[1])
"""
输出:
tf.Tensor([0.00102822 0.24761406 0.12357714], shape=(3,), dtype=float32)
"""
参考:
https://blog.csdn.net/suiyueruge1314/article/details/103963598