optimizer.zero_grad()、loss.backward()、optimizer.step()

 1、Theory

loss.backward() computes dloss/dx for every parameter x which has requires_grad=True. These are accumulated into x.grad for every parameter x. In pseudo-code:

x.grad += dloss/dx

optimizer.step updates the value of x using the gradient x.grad. For example, the SGD optimizer performs:

x += -lr * x.grad

optimizer.zero_grad() clears x.grad for every parameter x in the optimizer. It’s important to call this before loss.backward(), otherwise you’ll accumulate the gradients from multiple passes.

If you have multiple losses (loss1, loss2) you can sum them and then call backwards once:

loss3 = loss1 + loss2
loss3.backward()

2、Example 

if you have “net2” which is a pretrained network and you want to backprop the gradients of the loss of “net2” into “net1”. In pseudo-code: 

import torch
from torch import optim


def train(n_epoch):
    net1 = model1()
    net2 = model2(pretrained=True)
    optim1 = optim.SGD(net1.parameters(), lr=0.1)

    for epoch in range(n_epoch):
        for data in dataloader:
            net2.eval()
            with torch.no_grad():
                loss2 = net2(data)

            net1.train()
            optim1.zero_grad()
            loss1 = net1(data)
            total_loss = loss1 + loss2
            total_loss.backward()
            optim1.step()

 

参考: What does the backward() function do? - autograd - PyTorch Forums

在 PyTorch 中,`optimizer.zero_grad()` 是一个关键操作,通常在训练模型的每个迭代步骤中调用。它的主要作用是清空模型参数的梯度缓冲区,以防止梯度在多次反向传播之间累积。 在每次训练迭代中,模型会计算损失函数相对于其参数的梯度,并通过反向传播更新这些梯度。如果不调用 `optimizer.zero_grad()`,梯度将在多个批次之间累积,这可能导致参数更新方向错误,影响模型的收敛性和性能。因此,在每次迭代开始时调用 `optimizer.zero_grad()` 是标准做法,确保每次更新仅基于当前批次的数据。 例如,在一个典型的训练循环中,代码可能如下所示: ```python for data, target in dataloader: optimizer.zero_grad() output = model(data) loss = loss_function(output, target) loss.backward() optimizer.step() ``` 在此代码段中,`optimizer.zero_grad()` 确保了每次迭代开始时梯度缓冲区是干净的,从而保证了梯度计算的准确性[^2]。 此外,需要注意的是,某些情况下可能需要手动管理梯度,例如在累积多个小批次的梯度后再进行一次更新。这时,可以暂时省略 `optimizer.zero_grad()` 直到累积完成后再调用,以确保梯度正确累积[^1]。 ### 示例代码 以下是一个简单的训练循环示例,展示了 `optimizer.zero_grad()` 的使用: ```python import torch from torch import nn, optim # 假设的模型 model = nn.Linear(10, 2) # 损失函数和优化器 criterion = nn.MSELoss() optimizer = optim.SGD(model.parameters(), lr=0.01) # 假设的数据 inputs = torch.randn(3, 10) targets = torch.randn(3, 2) # 训练循环 for epoch in range(100): optimizer.zero_grad() # 清空之前的梯度 outputs = model(inputs) loss = criterion(outputs, targets) loss.backward() # 计算梯度 optimizer.step() # 更新参数 ``` ### 注意事项 - **梯度累积**:在某些情况下,为了节省内存或提高训练效率,可能会选择累积多个批次的梯度后再进行一次参数更新。此时,`optimizer.zero_grad()` 应该在累积周期结束后调用,而不是在每个批次开始时[^1]。 - **调试和性能优化**:在调试过程中,确保每次迭代都正确清空梯度可以帮助识别和解决梯度消失或爆炸的问题。同时,合理的梯度管理可以提高训练效率和模型性能[^2]。 ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值