yolov5中的优化器(optimizer)将模型可学习的参数分成了三个组,分别为pg0:BN参数,pg1:一般权重(weight)参数,pg2:偏置(biase)参数,通过param_group来管理3组参数。param_group的意义在于可以针对不同的参数组量身定制学习率(lr)、衰减(weight_decay)、动量(moment)等超参数。例如在某一模型中,希望特征提取部分的权值参数的学习率小一点,学习更新慢一点,这时可以把特征提取的参数设置为一组参数,而对于后面全连接分类层,希望其学习率大一点,学习快一点。这时,可以把整个模型参数设置为两组,一组为特征提取部分的参数,另一部分是全连接层的参数,对这两组设置不同的学习率或超参数。
def train(...):
#....省略.....
pg0, pg1, pg2 = [], [], [] # optimizer parameter groups
#将模型分成三组(weight,bn,bias,其它所有参数)优化
for k, v in model.named_modules():
if hasattr(v, 'bias') and isinstance(v.bias, nn.Parameter):
pg2.append(v.bias) # biases
if isinstance(v, nn.BatchNorm2d):
pg0.append(v.weight) # no decay
elif hasattr(v, 'weight') and isinstance(v.weight, nn.Parameter):
pg1.append(v.weight) # apply decay
if opt.adam:
optimizer = optim.Adam(pg0, lr=hyp['lr0'], betas=(hyp['momentum'], 0.999)) # adjust beta1 to momentum
else:
#nesterov梯度下降是继动量梯度下降之后的一种梯度下降的修正方法,也是继承了动量梯度的思想
optimizer = optim.SGD(pg0, lr=hyp['lr0'], momentum=hyp['momentum'], nesterov=True)
#添加参数组,设置weight,bias的优化方式
optimizer.add_param_group({'params': pg1, 'weight_decay': hyp['weight_decay']}) # add pg1 with weight_decay
optimizer.add_param_group({'params': pg2}) # add pg2 (biases)
logger.info('Optimizer groups: %g .bias, %g conv.weight, %g other' % (len(pg2), len(pg1), len(pg0)))
del pg0, pg1, pg2
#....省略....
学习率的调整yolov5使用pytorch已经封装好的torch.optim.lr_scheduler.LambdaLR方法,訪方法包含三个参数:
import math
import matplotlib.pyplot as plt
%matplotlib inline
def one_cycle(y1=0.0, y2=1.0, steps=100):
# lambda function for sinusoidal ramp from y1 to y2
return lambda x: ((1 - math.cos(x * math.pi / steps)) / 2) * (y2 - y1) + y1
lrf=0.2
epochs=300
lr_lambda=one_cycle(1,lrf,epochs)
lr_of_epoch = []
for last_epoch in range(epochs):
lr = lr_lambda(last_epoch)
lr_of_epoch.append(lr)
#s:点的面积
#c:颜色
plt.scatter(range(epochs),lr_of_epoch,s=1,c='green')
plt.title("yolov5 default lr_lambda")
base_lr = 0.01
lr_of_epoch = []
for last_epoch in range(epochs):
#lr=base_lr * lambda(last_epoch)
lr = base_lr * lr_lambda(last_epoch)
lr_of_epoch.append(lr)
#s:点的面积
#c:颜色
plt.scatter(range(epochs),lr_of_epoch,s=1,c='red')
plt.title("yolov5 default lr decay policy")