最近对pytorch的梯度计算产生了一点兴趣,然后现在就总结一下,我看到的几篇讲得挺好的博客。
创建带有grad的tensor
input = torch.tensor([1., 2., 3., 4.,], requires_grad=True)
参看tensor,是否带有grad
print(input.requires_grad)
参看tensor中的grad值
print(input.grad)
不过模型的输入tensor一般不使用grad,而是将模型参数空间输入到优化器中,然后通过loss.backward()去根据模型参数空间中的梯度,自动更新模型参数。
optimizer = Adam(model.parameters(), lr=LR) # 输入参数空间,定义优化器
然后就是常用的
loss.backward()
optimizer.step()
这便是更新模型参数空间中的参数。一般这两行代码是放在batch里面的,为的是将每一个batch的训练都看做独立的一次训练。
另外,在执行这两行代码之前,需要将参数空间中的梯度清零,防止上次的留存梯度,对本次的训练产生影响。
optimizer.zero_grad()
组合起来的顺序是
optimizer = Adam(model.parameters(), lr=LR) #定义优化器
optimizer.zero_grad()#将梯度初始化为零
outputs = net(inputs)#前向传播求出预测值
loss = criterion(outputs, labels)#求损失值
loss.backward()#反向传播求梯度
optimizer.step()#更新所有参数
此外,如果你希望能够查看模型中参数的梯度可以
loss.backward()
for name_1, param_1 in self.manhattan_lstm.named_parameters():
print(name_1,param_1.grad)
记住,在反向传播后面,否则输出为None,原因是loss.backward()之前,都还没有计算,自然是没有的。
如果想看参数的值可以
for name_1, param_1 in self.manhattan_lstm.named_parameters():
print(name_1,param_1.data)
参考博客
深入Pytorch中的Tensor,梯度以及权重
torch代码解析 为什么要使用optimizer.zero_grad()
Pytorch optimizer.step() 和loss.backward()和scheduler.step()的关系与区别 (Pytorch 代码讲解)