自动求导

https://zh.d2l.ai/chapter_preliminaries/autograd.html

x = tf.range(-4, 4, 0.01)

with tf.GradientTape() as t:
    t.watch(x)
    y = tf.sin(x)
    dy_dx = t.gradient(y, x)
    
plot(x, [y, dy_dx], 'x', 'y', legend=['y=sin(x)', 'y=sin\'(x)'])

问题5需要用到t.watch(x)这个函数,不然dy_dx是个None。而且with tf.GradientTape() as t:下面这三句的顺序是不能改的,我理解一下大概是t要watch每个来的x,watch它是怎么得到y的,然后才能得到这个y对这个x的梯度。
没学过python不太懂with,之前用来维持打开文件的引用,又看到这里有个tape,前面提到说是什么磁带,所以python大概给了一个磁带的抽象,tf.GradientTape()就是TensorFlow给的一个磁带专门用来画计算图(计算图又只用来传播梯度)的,画出一个计算图只能求一次梯度。
下面绘曲线图的时候并不是每给个x然后现求函数值才得到点的(x, y),而是在with里就把函数值全都求出来了。实际上确实是只求了一次梯度,只是一下子把需要的都求出来了。
然后加上persistent=True还能把dy_dx = t.gradient(y, x)提到with外面。

x = tf.range(-4, 4, 0.01)

with tf.GradientTape(persistent=True) as t:
    t.watch(x)
    y = tf.sin(x)
dy_dx = t.gradient(y, x)
    
plot(x, [y, dy_dx], 'x', 'y', legend=['y=sin(x)', 'y=sin\'(x)'])

如果加上persistent=True而不提到外面,会警告你说效率低。可能加上是多此一举了吧。
主要问题还是这个watch(),菜鸟教程上也没有,胡乱百度我也不知道我是从哪看来这么一句了。