文章目录
optimizer.zero_grad()
一、功能
梯度初始化为零,把loss关于weight的导数变成0
二、为什么每一轮batch都需要设置optimizer.zero_grad
根据pytorch中的backward()函数的计算,当网络参量进行反馈时,梯度是被积累的而不是被替换掉。
但是在每一个batch时毫无疑问并不需要将两个batch的梯度混合起来累积,因此这里就需要每个batch设置一遍zero_grad。
三、每个batch必定执行的操作步骤
optimizer.zero_grad() # 梯度初始化为零,把loss关于weight的导数变成0
output = model(data) # forward:将数据传入模型,前向传播求出预测的值
loss = F.cross_entropy(output, target) # 求loss
loss.backward() # backward:反向传播求梯度
optimizer.step() # optimizer:更新所有参数
三个函数的作用是先将梯度归零optimizer.zero_grad()
,然后反向传播计算得到每个参数的梯度值loss.backward()
,最后通过梯度下降执行一步参数更新optimizer.step()
step()函数的作用是执行一次优化步骤,通过梯度下降法来更新参数的值。因为梯度下降是基于梯度的,所以在执行optimizer.step()函数前应先执行loss.backward()函数来计算梯度。
注意:optimizer只负责通过梯度下降进行优化,而不负责产生梯度,梯度是tensor.backward()方法产生的。
四、优化器定义
SGD优化器
optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9, weight_decay=1e-4)
4.1 优化器参数
参考资料:理解optimizer.zero_grad(), loss.backward(), optimizer.step()的作用及原理
讲解非常细致,带有代码讲解,强烈建议看原文!!
param_groups
Optimizer类在实例化时会在构造函数中创建一个param_groups列表,列表中有num_groups个长度为6的param_group字典(num_groups取决于你定义optimizer时传入了几组参数),每个param_group包含了 ['params', 'lr', 'momentum', 'dampening', 'weight_decay', 'nesterov']
这6组键值对。
param_group[‘params’]
由传入的模型参数组成的列表,即实例化Optimizer类时传入该group的参数,如果参数没有分组,则为整个模型的参数 model.parameters() ,每个参数是一个torch.nn.parameter.Parameter对象(没看懂)
。
# 改优化器的学习率
for param_group in optimizer.param_groups:
param_group['lr'] = lr
代码实例
举例一
if (model.hyperparams['optimizer'] in [None, "adam"]):
optimizer = optim.Adam(
params,
lr=model.hyperparams['learning_rate'],
weight_decay=model.hyperparams['decay'],
)
elif (model.hyperparams['optimizer'] == "sgd"):
optimizer = optim.SGD(
params,
lr=model.hyperparams['learning_rate'],
weight_decay=model.hyperparams['decay'],
momentum=model.hyperparams['momentum'])
else:
print("Unknown optimizer. Please choose between (adam, sgd).")
optimizer.zero_grad() # Reset gradients
optimizer.step() # Run optimizer
举例二:R-CenterNet
learning_rate = 1.25e-4
params=[]
params_dict = dict(model.named_parameters())
for key,value in params_dict.items():
params += [{'params':[value],'lr':learning_rate}]
optimizer = torch.optim.Adam(params, lr=learning_rate, weight_decay=1e-4)
for epoch in range(num_epochs):
model.train()
if epoch == 90:
learning_rate= learning_rate * 0.1
if epoch == 120:
learning_rate= learning_rate * (0.1 ** 2)
for param_group in optimizer.param_groups:
param_group['lr'] = learning_rate