PyTorch教程:理解自动微分机制torch.autograd
tutorials PyTorch tutorials. 项目地址: https://gitcode.com/gh_mirrors/tuto/tutorials
自动微分基础概念
在深度学习领域,反向传播算法是训练神经网络的核心。该算法通过计算损失函数相对于模型参数的梯度来调整权重。PyTorch提供了一个强大的内置微分引擎torch.autograd
,它能够自动计算任何计算图的梯度。
计算图与梯度追踪
让我们从一个简单的单层神经网络开始理解这个概念:
import torch
x = torch.ones(5) # 输入张量
y = torch.zeros(3) # 期望输出
w = torch.randn(5, 3, requires_grad=True) # 权重参数
b = torch.randn(3, requires_grad=True) # 偏置参数
z = torch.matmul(x, w) + b # 线性变换
loss = torch.nn.functional.binary_cross_entropy_with_logits(z, y) # 损失计算
这段代码构建了一个计算图,其中:
w
和b
是需要优化的参数requires_grad=True
表示需要计算这些张量的梯度- 每个操作都会记录在计算图中,为反向传播做准备
梯度计算机制
反向传播执行
要计算梯度,我们只需调用backward()
方法:
loss.backward() # 反向传播
print(w.grad) # 查看w的梯度
print(b.grad) # 查看b的梯度
关键点:
- 只有设置了
requires_grad=True
的叶节点才能获取梯度 - 默认情况下,每次
backward()
调用后计算图会被释放 - 如需多次反向传播,需设置
retain_graph=True
梯度函数属性
PyTorch中的每个操作都是一个Function
对象,它知道如何执行前向计算和反向传播:
print(f"z的梯度函数: {z.grad_fn}")
print(f"loss的梯度函数: {loss.grad_fn}")
梯度追踪控制
在某些场景下,我们不需要梯度计算:
禁用梯度追踪的方法
- 使用
torch.no_grad()
上下文管理器:
with torch.no_grad():
z = torch.matmul(x, w) + b
print(z.requires_grad) # 输出: False
- 使用
detach()
方法:
z_det = z.detach()
print(z_det.requires_grad) # 输出: False
禁用梯度追踪的典型场景:
- 模型推理阶段(仅需前向计算)
- 冻结部分网络参数
- 提高计算效率
计算图的动态特性
PyTorch的计算图是动态构建的:
- 每次
backward()
调用后,autograd会重新构建计算图 - 这使得我们可以在模型中使用控制流语句
- 允许在每次迭代中改变张量形状、大小和操作
进阶主题:雅可比积
对于向量函数输出,PyTorch计算的是雅可比积而非完整的雅可比矩阵:
inp = torch.eye(4, 5, requires_grad=True)
out = (inp+1).pow(2).t()
out.backward(torch.ones_like(out))
print(inp.grad)
重要特性:
- 梯度是累积的,多次反向传播会累加梯度
- 实际训练中,优化器会帮我们清零梯度
- 标量函数(如损失函数)的
backward()
等价于backward(torch.tensor(1.0))
最佳实践建议
- 训练阶段保持
requires_grad=True
以计算梯度 - 推理阶段使用
no_grad()
提高效率 - 注意梯度累积特性,适时清零梯度
- 利用动态图的优势构建灵活模型
理解autograd机制是掌握PyTorch的关键,它为神经网络训练提供了强大的自动微分能力,同时保持了高度的灵活性。
tutorials PyTorch tutorials. 项目地址: https://gitcode.com/gh_mirrors/tuto/tutorials
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考