序言:神经网络本质上就是自动求导,寻找最小误差的过程。使用pytorch的好处就在于它能提供自动求导工具包,在这里我将总结如何使用工具包。
目录
1.3.2 with torch.no_grad()进行测试集测试
1. 自动求导
1.1自动求类torch.tensor
- 在计算y对于x的梯度前,如何储存计算的梯度呢?
- 将属性.requires_grad设置为True, 它将追踪在这个类上定义的所有操作.
- 当代码要进行反向传播的时候, 直接调用.backward()就可以自动计算所有的梯度.
- 梯度储存在这个Tensor上的所有梯度将被累加进属性.grad中.
- 注意:我们不会在每次对一个参数求导时都分配新的内存。 因为我们经常会成千上万次地更新相同的参数,每次都分配新的内存可能很快就会将内存耗尽。默认是requires_grad_属性是FALSE
1.2 实现求导
- 举个例子: 求导
- 初始化x
import torch
x=torch.arange(4.0)
x
x.requires_grad_(True)#开启储存梯度
x.grad #默认是none,调用backward()累加梯度到grad属性
x
2. 计算y
y = 2 * torch.dot(x, x)
y
grad_fn=<MulBackward0>是计算对x做的操作
3.求导:y的导数是4x,验证是否正确
y.backward()
x.grad
x.grad == 4 * x
1.3 终止一个Tensor在计算图中的追踪回溯
1.3.1 .detach()求偏导数
- 高数小课堂开课了
- 例如,假设
y
是作为x
的函数计算的,而z
则是作为y
和x
的函数计算的。 想象一下,我们想计算z
关于x
的梯度,但由于某种原因,我们希望将y
视为一个常数, 并且只考虑到x
在y
被计算后发挥的作用。在这里,我们可以分离y
来返回一个新变量u
,该变量与y
具有相同的值, 但丢弃计算图中如何计算y
的任何信息。 换句话说,梯度不会向后流经u
到x
。 - 那么就是如何计算
z=u*x
关于x
的偏导数. - 求导结果z=u,即z=x^2
- 例如,假设
x.grad.zero_()#将之前梯度计算清零
y = x * x
u = y.detach()#剔除计算图
z = u * x
z.sum().backward()
x.grad == u
总结 注意:
- 执行.detach()就可以将该Tensor从计算图中撤下, 在未来的回溯计算中也不会再计算该Tensor。
- z.sum().backward()什么要用sum() ,去看了源码才知道只有对标量输出它才会计算梯度,也就是说如果是个矩阵要先转化为标量才可以使用。为什么要这么设计呢?这里其实是为了服务深度学习计算批量每个样本的偏导数之和。
1.3.2 with torch.no_grad()进行测试集测试
with torch.no_grad():
print((x ** 2).requires_grad_)
采用代码块的方式with torch.no_grad():, 这种方式非常适用于对模型进行预测的时候, 因为预测阶段不再需要对梯度进行计算.
with torch.no_grad():
print((x ** 2).requires_grad_)
2.总结参考
- 实现求导
- torch.ones(n, n, requires_grad=True)
- x.requires_grad_(True)
- y.backward()
- x.grad
- 终止对计算图的回溯
- .detach()
- with torch.no_grad():