optimizer.zero_grad()是什么?
optimizer.zero_grad()
是PyTorch中的一个操作,它用于清零所有被优化变量(通常是模型的参数)的梯度。
在PyTorch中,当你计算某个张量的梯度时(比如通过调用.backward()
函数),这个梯度会被累积到.grad
属性中,而不是被替换掉。这意味着,每次计算梯度,新的梯度值会被加上旧的梯度值。
如果在反向传播前不将梯度清零,那么梯度值将会在每次.backward()
传播时不断累积,这往往不是我们希望看到的。为了确保正确的计算,我们需要在每次进行权重更新之前,用optimizer.zero_grad()
将梯度信息清零。
以下是一个例子,用于更好地展示optimizer.zero_grad()
的作用。考虑一个简单的线性模型:
model = nn.Linear(2, 2)
optimizer = torch.optim.SGD(model.parameters(), lr=0.1)
# 第一次反向传播
loss1 = model(torch.randn(1, 2)).sum()
loss1.backward()
print(model.weight.grad) # 输出:tensor([[ 0.1734, -0.3710], ...])
optimizer.step() # 更新权重
# 第二次反向传播,没有清空梯度
loss2 = model(torch.randn(1, 2)).sum()
loss2.backward()
print(model.weight.grad) # 输出:tensor([[ 0.2811, -0.5524], ...])
optimizer.step()
# 这一次我们清空了梯度
optimizer.zero_grad()
loss3 = model(torch.randn(1, 2)).sum()
loss3.backward()
print(model.weight.grad) # 输出:tensor([[ 0.1077, -0.1814], ...])
optimizer.step()
可以看到,如果不使用optimizer.zero_grad()
,得到的梯度值是累积的结果,这在大多数优化场景中是不正确的。而使用了optimizer.zero_grad()
后,每次计算后得到的是当前情况下的准确梯度。
所有优化器都实现了一个step()方法,用于更新参数:optimizer.step()
这是大多数优化器支持的简化版本。一旦使用backward()计算出梯度,就可以调用该函数。