学习Pytorch官方文档的自动微分一章,有许多细节没有看懂。查了一些资料,汇总在这里。
PS:建议大家上手Pytorch深度学习还是直接看官方文档吧。我之前东看西看了许多教程,但是脑子还是一团浆糊,耐下心来五六个小时就能读完官方文档,脑子清楚多了。
Pytorch官方文档Automatic Differentiation的链接
反向传播(back propagation)根据损失函数对某个参数的梯度(gradient)来调整参数。
pytorch使用torch.autograd()
来计算梯度。
为了进行参数优化,我们需要计算损失函数相对于这些参数的梯度(gradients)。梯度告诉我们在当前参数值下,沿着哪个方向以及多大程度上调整参数可以减小损失函数的值。通过梯度下降等优化算法,我们可以根据梯度的方向调整参数的值,逐渐接近最优解。
在PyTorch等深度学习框架中,张量(tensors)是计算图中的关键组件,用于表示数据和参数。默认情况下,张量的requires_grad属性被设置为False,表示它们不需要计算梯度。然而,对于需要优化的参数,我们需要将其requires_grad属性设置为True,以便在后续的反向传播过程中计算梯度。
通过将参数的requires_grad属性设置为True,框架会跟踪这些参数的计算历史,并在需要时自动计算它们的梯度。这使得我们可以使用自动微分(automatic differentiation)技术来计算损失函数相对于参数的梯度,从而进行优化。
# 创建一个张量
x = torch.tensor([1.0, 2.0, 3.0])
# 将requires_grad属性设置为True
x.requires_grad_(True)
# 或者可以使用下面的方式
x.requires_grad = True
# 创建一个张量并设置requires_grad为True
x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)
Tensor.backward(gradient=None, retain_graph=None, create_graph=False, inputs=None)
用于计算当前张量相对于计算图的叶节点的梯度,使用链式求导法则。
梯度累积
叶节点(Graph Leaves):计算图中没有进一步后续计算的节点,通常是输入数据或模型的参数。
梯度累积:每次调用反向传播算法,梯度值会累加到叶节点的.grad
属性中。
批量梯度下降等优化算法有意义:可以在多个样本上累积梯度,从而更好地更新参数
不恰当的梯度累积
清除梯度累积的方法
optimizer.zero_grad() # 清零所有参数的梯度
leaf_tensor.grad = None # 将特定叶节点的梯度设置为None
叶节点和非叶节点
requires_grad = True
的节点.grad
属性可以直接访问# torch.no_grad()的上下文中执行的操作不会跟踪梯度
with torch.no_grad():
z = torch.matmul(x, w)+b
z = torch.matmul(x, w)+b
# z_det不会跟踪梯度, 但是z还会跟踪
z_det = z.detach()
禁用梯度跟踪与非叶节点
禁用梯度跟踪的情况
这是一张有向无环图(DAG),叶子节点是输入张量,根是输出张量。在这张图上做前向传递和后向传播两件事。
Forward Pass
Backward Pass
.backward()
.grad
属性中Note:
计算图是动态变化的,每次都在前向传递时生成。
每张计算图只能调用一次后向传播(.backward()
),计算完毕后该计算图会被自动清除。
如果想要在一张计算图上计算多次后向传播,需要在调用.backward()
时,使用参数retain_graph=True
。
需要在一张计算图上进行多次后向传播的情况: