深度理解loss.backward()函数
是深度学习框架(如 PyTorch)中用于执行反向传播的函数。
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()
更多推荐


所有评论(0)