PyTorch训练循环中zero_grad()的正确调用位置详解
在PyTorch中,optimizer.zero_grad()必须在loss.backward()之前执行,且绝不能位于backward()与step()之间;其具体位置(循环开头或backward()前一刻)不影响梯度计算逻辑,但影响代码可读性与多优化器场景下的正确性。 在pytorch中,`optimizer.zero_grad()`必须在`loss.backward()`之前执行,且绝不能位于`backward()`与`step()`之间;其具体位置(循环开头或`backward()`前一刻)不影响梯度计算逻辑,但影响代码可读性与多优化器场景下的正确性。zero_grad()的核心作用是清空优化器所管理参数的累积梯度(即param.grad张量)。PyTorch默认采用梯度累加机制——每次调用backward()时,新梯度会以加法方式累加到现有grad上,而非覆盖。因此,若不显式清零,历史批次的梯度将持续叠加,导致错误的参数更新方向和幅度。? 正确时机:必须在 loss.backward() 之前、且在 optimizer.step() 之后的任意位置均可,只要不夹在 backward() 和 step() 中间。例如以下两种写法完全等价且均正确:# ? 方式1:循环起始处清零(推荐,简洁清晰)for epoch in range(num_epochs): for batch in dataloader: optimizer.zero_grad() # ← 清零在此处 outputs = model(batch.x) loss = criterion(outputs, batch.y) loss.backward() # ← 梯度计算 optimizer.step() # ← 参数更新# ? 方式2:backward前一刻清零(语义更显式)for epoch in range(num_epochs): for batch in dataloader: outputs = model(batch.x) loss = criterion(outputs, batch.y) optimizer.zero_grad() # ← 清零在此处(仍早于backward) loss.backward() optimizer.step()?? 绝对禁止的写法:loss.backward()optimizer.zero_grad() # ? 错误!此时梯度已计算但未更新,清零将丢失本次梯度optimizer.step()对于含多个子网络与独立优化器的复杂模型(如VAE、GAN、编码器-解码器),应为每个优化器单独、就近调用zero_grad(),确保职责明确、避免干扰: Cleanup.pictures 智能移除图片中的物体、文本、污迹、人物或任何不想要的东西
