以SGD优化算法为例,初始学习率为0.001。
optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size = 20, gamma = 0.1, last_epoch=-1)
for epoch in range(60):
scheduler.step()
train()
其中gamma为调整倍数,20指的是调整的间隔,即0-20、21-40、41-60epoch内的学习率分别为0.001、0.0001、0.00001.
last_epoch为上一个epoch数,一般默认为-1初始值。如果需要断点续训,则将其改为续接的点的epoch。
optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones = [50, 80], gamma = 0.1, last_epoch=-1)
for epoch in range(100):
scheduler.step()
train()
0-50、51-80、81-100epochs的学习率分别为0.001、0.0001、0.00001.
其调整方式为学习率=上一epoch的学习率*gamma^epoch
optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
scheduler = torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma = 0.1, last_epoch=-1)
for epoch in range(100):
scheduler.step()
train()
以余弦函数的周期为周期,在每个周期的最大值时重新设置学习率,初始学习率为最大学习率,以2*T_max为周期,周期内先下降后上升。
公式为: η t = η m i n + 1 2 ( η m a x − η m i n ) ( 1 + cos ( T c u r T m a x π ) ) \eta_t = \eta_{min} + \frac{1}{2}(\eta_{max} - \eta_{min})(1 + \cos(\frac{T_{cur}}{T_{max}}\pi)) ηt=ηmin+21(ηmax−ηmin)(1+cos(TmaxTcurπ))
其中 η t \eta_t ηt为设定的最小的学习率, η m a x \eta_max ηmax为初始学习率
optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max = 10, eta_min=0, last_epoch=-1)
for epoch in range(100):
scheduler.step()
train()
T_max个epoch之后重新设置学习率
eta_min为最小学习率,即周期内学习率最小下降的下限,默认为0
余弦退火学习率衰减的损失函数曲线一般也是具有一定的周期性反复上下波动,例如:
为什么这种方法会有用呢?其实这种方式可以使用模型集成。每次收敛到极小值其实都算是一个局部最小值,在训练的最后阶段,选择其中若干个损失最小时的模型,也就是不同的局部最小值,对这几个模型进行集成便可以综合了这些局部最小值的优势。
optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=10, verbose=False, threshold=0.0001, threshold_mode='rel', cooldown=0, min_lr=0, eps=1e-08)
for epoch in range(100):
train()
val_loss = val()
scheduler.step(val_loss)
这种方式较为复杂,是当某些指标不再发生变化时使用的策略,如损失函数和精度等。
mode:模式,min:当指标(如损失)不再降低;
max:当指标(如精度)不再上升
factor:学习率调整倍数,相当于gamma
patience:当10个epoch后指标不再发生变化时,调整学习率
verbose:是否打印学习率信息
threshold_mode:判断指标是否达到最优的模式
rel:当mode=max,dynami_threshold=best*(1+threshold)
当mode=min,dynamic_threshold=best*(1-threshold)
abs:当mode=max,dynamic_threshold=best+threshold
当mode=min,dynamic_threshold=best-threshold
threshold:与threshold_mode相关
cooldown:调整学习率后,原来额学习率仍然保持cooldown个epoch后再调整学习率
min_lr:学习率降低的下限
eps:学习率变化小于该值时,不调整学习率
要注意的是,scheduler.step(val_loss)需要定义一个参数,即需要衡量的指标,一般选择验证集上的损失。
咋一看这种学习率下降的方式似乎是最好的,但是在实际应用中我发现存在很多问题,比如当patience太小的时候,学习率很快就下降到了最小值。这是因为就算是在合适的学习率时损失函数依然会存在一定时间的不下降的情况,不会一直下降的,所以patience的大小不应该太小。
optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda, last_epoch=-1)
for epoch in range(100):
scheduler.step()
train()
lr_lambda为函数,学习率=初始学习率*lr_lambda(last_epoch)