模型在刚开始训练的时候比较不稳定的,刚开始的学习率应当设置得很低很低,这样可以保证网络能够具有良好的收敛性。但是较低的学习率会使得训练过程变得非常缓慢,因此采用较低学习率逐渐增大至较高学习率的方式实现网络训练的“热身”阶段,称为 warmup stage。
但是如果要使得网络训练的 loss 最小,那么一直使用较高学习率是不合适的,因为它会使得权重的梯度一直来回震荡,很难使训练的损失值达到全局最低谷。因此需要在经过一些steps之后学习率再慢慢变小。
之前训练模型很不容易收敛,模型总是有很大的震荡,各种调参都不太好使,后来用warm-up试了一下,收敛得很好,所以在这边记录一下。模型比较大、数据集比较小、不易训练的都可以尝试一下。
if p['scheduler'] == 'warm_up':
warmup_epoch = 5
if warmup_epoch and epoch<warmup_epoch:
warmup_percent_done = epoch / warmup_epoch
# gradual warmup_lr
warmup_learning_rate = init_lr * warmup_percent_done
lr = warmup_learning_rate
else:
lambd = pow(1 - (epoch / p['epochs']), 0.9)
lr = lr * lambd
直接加入这一段即可,然后在配置中选择‘warm-up’策略。
其他策略也使用过,但模型震荡比较厉害。
if p['scheduler'] == 'step':
steps = np.sum(epoch > np.array(p['scheduler_kwargs']['lr_decay_epochs']))
if steps > 0:
lr = lr * (p['scheduler_kwargs']['lr_decay_rate'] ** steps)
elif p['scheduler'] == 'poly':
lambd = pow(1-(epoch/p['epochs']), 0.9)
lr = lr * lambd