TensorFlow自动求导

166 阅读1分钟

导入库

import tensorflow as tf  
from matplotlib import pyplot as plt

定义函数f(x)=2x210xf(x)=2{x}^{2}-10x

f = lambda x: 2*x**2-10*x

生成函数图像

x1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]  
y1 = list(map(f, x1))  
plt.figure(figsize=(5, 3))  
plt.plot(x1, y1)  
plt.show()

output.png

使用tf.random.uniform生成噪声,取值范围为[1,1]\left [ {-1,1} \right ]

rand = tf.random.uniform(shape=(1, 11), minval=-1, maxval=1)  
print(rand)
----------------------------------------------------------------------
输出:
tf.Tensor(
[[-0.6656029   0.10860205 -0.20757294 -0.77165437  0.24008727  0.8869231
   0.06983256 -0.47813797  0.3115518   0.3219154   0.34084868]], shape=(1, 11), dtype=float32)

使用tf.Variable(list(map(f, x2 + rand)))生成y2变量,并显示函数图像

图像整体趋势呈先下降后上升,与(x1,y1)的数据整体趋势相同

x2 = tf.Variable([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], dtype='float32')  
y2 = tf.Variable(list(map(f, x2 + rand)))  
y2 = tf.squeeze(y2)  
plt.figure(figsize=(5, 3))  
plt.plot(x2, y2)  
plt.show()

out1put.png

通过求导时实现对y2变量的更新

for i in range(50)实现了50次的计算更新

这里我们使用了tf.GradientTape()上下文管理器来计算函数 f(x2) 对变量 x2 的梯度

tape.watch(x2)将 x2 加入到梯度记录列表中

y2 = f(x2)这一步可以理解为前向传播

最后,通过调用tape.gradient(y2, x2)方法求得函数 f(x2) 对 x2 的梯度,得到的即误差(loss)

tape.gradient(y2, x2)中,表示 y2 对 x2 的梯度

参数的更新公式:w=lr×f(w)w\, -=\, lr\, \times \, f'(w)

y2 -= 0.01 * grad这里学习率 lr 设置为了0.01

for i in range(50):  
with tf.GradientTape() as tape:  
tape.watch(x2)  
y2 = f(x2)  
grad = tape.gradient(y2, x2)  
y2 -= 0.01 * grad  
  
print(y1)  
print(y2)  
  
plt.figure(figsize=(5, 3))  
plt.plot(x2, y2)  
plt.show()
----------------------------------------------------------------------
输出:
[0, -8, -12, -12, -8, 0, 12, 28, 48, 72, 100]
tf.Tensor(
[  0.09999999  -7.94       -11.98       -12.02        -8.06
  -0.09999999  11.86        27.82        47.78        71.74
  99.7       ], shape=(11,), dtype=float32)

output22.png

经过50次的迭代后,y1 与 y2 已经非常接近