pycharm笔记-动手学深度学习(李沐)自动微分课后习题

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)

pycharm笔记-动手学深度学习(李沐)自动微分课后习题_第1张图片

 

你可能感兴趣的:(深度学习,python,机器学习)