我正在查看pytorch模型的示例:
https://pytorch.org/tutorials/beginner/blitz/cifar10_tutorial.html sphx-glr-beginner-blitz-cifar10-tutorial-py
for epoch in range(2): #在数据集上循环多次
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
# get the inputs; data is a list of [inputs, labels]
inputs, labels = data
# zero the parameter gradients
optimizer.zero_grad()
# forward + backward + optimize
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
# print statistics
running_loss += loss.item()
if i % 2000 == 1999: # print every 2000 mini-batches
print(f'[{epoch + 1}, {i + 1:5d}] loss: {running_loss / 2000:.3f}')
running_loss = 0.0
print('Finished Training')
我有一个非常基本的问题-优化器从未插入或定义到模型中(类似于keras
中的model.compile
)。它也没有收到最后一批或时代的损失或标签。它是如何"知道"的?执行优化步骤?
在优化器实例化时,传递一个模型参数:
optimizer = optim.Adam(model.parameters())
optimizer.step
更新这些参数
step
方法之前,在loss.backward()
步骤上计算梯度。
与其考虑损失和参数是如何关联的,不如将它们视为没有关联的独立事件。实际上,有两个不同的元素对参数及其缓存的梯度有影响。
-
自动光栅机制(负责执行梯度计算的过程)允许您在
torch.Tensor
(您的损失)上调用backward
,并且反过来将通过允许计算最终张量值的所有节点张量反向传播。这样做,它将浏览所谓的计算图,通过改变它们的grad
属性来更新每个参数的梯度。这意味着在backward
调用结束时,用于计算该输出的网络学习参数将具有包含相对于该参数的损失梯度的grad
属性。loss.backward()
-
优化器独立于向后传递,因为它不依赖于向后传递。您可以在您的图上向后调用一次,多次,或者根据您的用例在不同的损失项上调用。优化器的任务是独立地获取模型的参数(即不考虑网络架构或其计算图),并使用给定的优化例程(例如通过随机梯度下降,均方根传播等)更新它们。它遍历初始化时使用的所有参数,并使用它们各自的梯度值(应该通过至少一次反向传播存储在
grad
属性中)更新它们。optimizer.step()
重要提示:
-
请记住,向后进程和使用优化器的实际更新调用仅通过优化器将使用向后前面调用计算的结果这一事实隐式地联系在一起。
-
在PyTorch参数梯度保存在内存中,所以你必须在执行新的向后调用之前清除它们。这是使用优化器的
zero_grad
函数完成的。在实际操作中,它清除已注册为参数的张量的grad
属性。