pytorch 自动求导
内容来自于https://zhuanlan.zhihu.com/p/67184419
requires_grad简介
Pytorch中的变量可以分为需要求导的,和不需要求导的,可以通过requires_grad
来查看一个张量是否需要求导,一个简单的张量默认是不需要求导的
1 | In [4]: inp = torch.tensor([1,2,3]) |
但是在nn中的所有的参数默认是需要求导的,比如
1 | In [17]: con1 = nn.Conv2d(in_channels=1, out_channels=1, kernel_size=2,stride=1,padding=0) |
在张量间的计算过程中,如果在所有输入中,有一个输入需要求导,那么输出一定会需要求导;相反,只有当所有输入都不需要求导的时候,输出才会不需要。
requires_grad 冻结参数
在训练的过程中冻结部分网络,让这些层的参数不再更新,这在迁移学习中很有用处
1 | model = torchvision.models.resnet18(pretrained=True) |
grad计算举例
$y = \sum_i 2x_i$
1 | x = torch.tensor([-1.0, 0.0, 1.0], requires_grad=True) |
结果
1 | tensor([2., 2., 2.]) |
对应运算
$y = 2x$
1 | x = torch.tensor([-1.0, 0.0, 1.0], requires_grad=True) |
结果
1 | RuntimeError: grad can be implicitly created only for scalar outputs |
这是因为,在backward()
这样操作,只有当y是标量才可以进行求导,而我们给出的y是三维的,因此不可以求导
代码修改
1 | x = torch.tensor([-1.0, 0.0, 1.0], requires_grad=True) |
结果
1 | tensor([2., 2., 2.]) |
实际运算
在backward里面添加的数,为梯度的系数,如果是
1 | y.backward(torch.tensor([1,2,2])) |
结果
1 | tensor([2., 4., 4.]) |
$y = ax$
注意,该例子里,求导对象是变量$a$, 而不是$x$
1 | x = torch.tensor([-1.0, 0.0, 1.0]) |
结果
1 | tensor(0) |
对应运算
torch.min
min 函数表示取其中一个数,其对应位置的grad为1, 其他的全部为0。
1 | x = torch.tensor([-1.0, 0.0, 1.0], requires_grad=True) |
结果
1 | tensor([2., 0., 0.]) |
对应运算
取x的最小值,假设最小值为为x1=-1.0.那么上述y即等价于
因此
注意
上述例子只可以求导一次,看下面例子
1 | x = torch.tensor([-1.0, 0.0, 1.0], requires_grad=True) |
结果
1 | tensor([4., 8., 8.]) |
第二次求导会迭代第一次的结果。
/如果求导两次,必须在第二次求导前使变量的导数为0
1 | x = torch.tensor([-1.0, 0.0, 1.0], requires_grad=True) |
结果
1 | tensor([2., 4., 4.]) |
案例
1 | # # -*- coding: utf-8 -*- |
Comments