loss.backward() 是深度学习框架(如 PyTorch)中用于执行反向传播的函数。以下是这行代码的主要功能和相关细节:

1. 核心功能:反向传播

  • 计算损失函数对模型参数的梯度。

  • 基于链式法则,从损失函数开始,逐层向前计算梯度。

2. 工作原理

  • 计算图构建:PyTorch 在前向传播时会构建动态计算图,记录张量操作。

  • 梯度计算loss.backward() 根据计算图和链式法则计算梯度。

  • 梯度存储:梯度存储在模型参数的 .grad 属性中。

3. 使用场景

  • 训练循环:通常在训练循环中,每次迭代都会调用 loss.backward()

  • 优化器配合:调用 loss.backward() 后,使用优化器(如 SGD 或 Adam)更新模型参数。

4. 注意事项

  • 梯度累积:默认情况下,梯度会累积。如果不想累积,需在每次反向传播前调用 optimizer.zero_grad()

  • 内存管理:计算图在反向传播后通常会被释放,除非指定 retain_graph=True

  • 非标量损失:如果损失不是标量(如多输出),需指定梯度张量。

5. 示例代码

import torch
import torch.nn as nn

# 定义模型、输入、目标和损失函数
model = nn.Linear(10, 1)
criterion = nn.MSELoss()
input_data = torch.randn(5, 10)
target = torch.randn(5, 1)

# 前向传播
output = model(input_data)
loss = criterion(output, target)

# 反向传播
loss.backward()  # 计算梯度

# 更新参数
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
optimizer.step()  # 更新权重
optimizer.zero_grad()  # 清空梯度

如果在调用 loss.backward() 计算梯度后不清空梯度(例如不调用 optimizer.zero_grad()),梯度将会被累积。以下是具体的影响和后果:

1. 梯度累积的原理

  • 每次调用 loss.backward() 计算得到的梯度会加到参数的 .grad 属性上,而不是覆盖之前的梯度。

  • 如果不清空梯度,下一次反向传播计算的梯度会与之前的梯度相加。

2. 后果

  • 梯度爆炸:累积的梯度可能导致梯度过大,从而使参数更新幅度过大,破坏模型的训练稳定性。

  • 训练不稳定:梯度累积可能导致优化方向失真,模型难以收敛或出现震荡。

  • 错误的优化方向:累积的梯度可能不符合当前批次数据的真实梯度方向,导致模型性能下

3. 示例代码(不清空梯度的影响)

import torch
import torch.nn as nn

# 定义一个简单的模型、损失函数和优化器
model = nn.Linear(1, 1)
criterion = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

# 输入和目标数据
x = torch.tensor([[1.0], [2.0], [3.0]])
y = torch.tensor([[2.0], [4.0], [6.0]])

# 第一次前向传播和反向传播
output = model(x)
loss = criterion(output, y)
loss.backward()  # 第一次计算梯度

# 第二次前向传播和反向传播(不清空梯度)
output = model(x)
loss = criterion(output, y)
loss.backward()  # 梯度被累积

# 查看参数梯度(可能已经变得非常大)
for param in model.parameters():
    print(param.grad)

# 更新参数(可能因为梯度过大导致更新幅度过大)
optimizer.step()

 

Logo

脑启社区是一个专注类脑智能领域的开发者社区。欢迎加入社区,共建类脑智能生态。社区为开发者提供了丰富的开源类脑工具软件、类脑算法模型及数据集、类脑知识库、类脑技术培训课程以及类脑应用案例等资源。

更多推荐