1、为什么计算二阶导数比一阶导数的开销要更大?
因为二阶导数是在一阶导数运算的基础上进行的,所以二阶导数要比一阶导数的开销要大。
2、在运行反向传播函数后,立即再次运行它,看看会发生什么?
import torch x = torch.arange(4.0) x.requires_grad_(True) x.grad #默认值为None y = 2*torch.dot(x, x) y.backward()#第一次backward() x.grad print(x.grad) y.backward()#第二次backward()
输出结果:
tensor([ 0., 4., 8., 12.]) Variable._execution_engine.run_backward( # Calls into the C++ engine to run the backward pass RuntimeError: Trying to backward through the graph a second time (or directly access saved tensors after they have already been freed). Saved intermediate values of the graph are freed when you call .backward() or autograd.grad(). Specify retain_graph=True if you need to backward through the graph a second time or if you need to access saved tensors after calling backward.
连续运行两次backward()会报错,要更新x.grad
3、在控制流动的例子中,我们计算d关于a的导数,如果我们将变量a更改为随机向量或矩阵,会发生什么?
例子:
def f(a): b = a * 2 while b.norm() < 1000: b = b * 2 if b.sum() > 0: c = b else: c = 100 * b return c a = torch.randn(size=(),requires_grad=True) d = f(a) d.backward() a.grad print(a.grad)
将a改成随机向量或矩阵
def f(a): b = a * 2 while b.norm() < 1000: b = b * 2 if b.sum() > 0: c = b else: c = 100 * b return c a = torch.randn(size(3,1),requires_grad=True) d = f(a) d.backward() a.grad print(a.grad)
输出结果:
tensor(1024.) RuntimeError: grad can be implicitly created only for scalar outputs
从两次结果可以看出,将变量a改成矩阵或向量时,会出错。因为pytorch中只能对标量求导,所以对结果求和变成一个标量后就能求导了。
将d.backward()--->d.sum().backward()即可。
4、重新设计一个求控制流梯度的例子,运行并分析结果。
import torch def f(a): if a.norm() > 10: b = a*a else: b = a return b.sum() a1 = torch.arange(15., requires_grad=True) a2 = torch.arange(5., requires_grad=True) d1 = f(a1) d2 = f(a2) d1.backward() d2.backward() print(a1.grad, a2.grad)
输出结果:
tensor([ 0., 2., 4., 6., 8., 10., 12., 14., 16., 18., 20., 22., 24., 26.,28.]) tensor([1., 1., 1., 1., 1.])
当a>10时,输出梯度为2a;当a<10时,输出梯度为1.
5、使()=sin(),绘制()和()/的图像,其中后者不使用′()=cos()。
import torch import matplotlib.pyplot as plt x = torch.arange(-10, 10, 0.1) x.requires_grad_(True) y = torch.sin(x) y.sum().backward() x.grad plt.plot(x.detach(), y.detach(), 'r') plt.plot(x.detach(), x.grad, 'b') plt.show()
不使用f'(x)=cos(x),用y.sum().backward()反向求导来计算。
torch.sin(x,out=None):提供对Pytorch中正弦函数的支持。输入类型为张量。
输出结果:
红色:y=sin(x)
蓝色:y'=cos(x)