Linear Scale
随着Batch Size增大,学习率也需要增大
如何调整:Batch Size理解、如何调整batch size和学习率之间的关系?_batch size 比较大时,需要把learning rate也调大吗-CSDN博客
Warmup
在训练最开始,模型中绝大多数参数都是随机初始化的,与最终模型很远。一开始就使用一个很大的LR,会增加不确定性。所以在训练最开始,先使用一个较小的LR,训练几轮Epoch后,再使用较大的LR。
1.直观理解就是最开始的时候,loss大,如果学习率太大,gradient也就弄的很大,容易崩,结果什么都学不到。所以最开始步子小一些,等模型收敛到合适的位置,loss不再爆炸,再加大学习率开始快速学习。
和你说的sgd的用法也不矛盾,但是那个的前提是模型不容易跑崩。
2.有同感,实际跑起来的时候,一开始如果保证网络不崩掉,lr就得调小,直观上到平台期以后(实际上并没有到),再做decay,loss更降不动,倒是增大lr反而又能观察到loss的下降。随机权值并不见得是个好的初始化方式,warm-up倒也可以看做某种程度上的“预训练”
通俗的解释:
3.开车进入一个新城市的时候,一开始总是要小心翼翼驾驶的,否则容易出事故,过一会了大致了解了周边环境了才能提速。
Decay
一直使用较大的LR也有问题,在训练中后期,过大的LR可能导致模型在最优解附近震荡,无法快速收敛。
所以,在中后期,需要将LR进行一些衰减(Decay)。ResNet论文中最初使用的Step Decay:每训练30个Epoch,LR衰减为刚才的0.1倍。还有Cosine衰减
最好的学习率调整方案:
Linear + Warmup + Decay
将以上三种LR策略组合起来,可以形成一个完整的LR策略:
- 根据Batch Size大小,线性地缩放LR基准值,
- 前几个Epoch使用较小的LR先进行Warmup逐渐增大学习率,
- 之后逐渐对LR进行Decay衰减。
一般的学习率应该怎么选择?
batch-size用8-64
学习率10的-4到10的-2。
示例代码:
rcg用的就是这样的lr调整代码
此处给一个示例代码,到时候按需要调整即可
import math
import argparse
def adjust_learning_rate_cosine_epoch(optimizer, epoch, args):
"""Decay the learning rate with half-cycle cosine after warmup"""
if epoch < args.warmup_epochs:
lr = args.lr * epoch / args.warmup_epochs
else:
lr = args.min_lr + (args.lr - args.min_lr) * 0.5 * \
(1. + math.cos(math.pi * (epoch - args.warmup_epochs) / (args.epochs - args.warmup_epochs)))
for param_group in optimizer.param_groups:
if "lr_scale" in param_group:
param_group["lr"] = lr * param_group["lr_scale"]
else:
param_group["lr"] = lr
return lr
def adjust_learning_rate_cosine_step(optimizer, current_step, lr, **kwargs):
"""
Linear + Warmup + cosine-Decay
用于step为单位的程序
:param optimizer:
:param step:
:param kwargs:
:return:
"""
warmup_steps = kwargs['warmup_steps']
total_steps = kwargs['total_steps']
lr = lr
min_lr = kwargs['min_lr']
if current_step < warmup_steps:
lr = lr * current_step / warmup_steps
else:
lr = min_lr + (lr - min_lr) * 0.5 * (1. + math.cos(math.pi * (current_step - warmup_steps) / (total_steps - warmup_steps)))
for param_group in optimizer.param_groups:
if "lr_scale" in param_group:
param_group["lr"] = lr * param_group["lr_scale"]
else:
param_group["lr"] = lr
return lr
def adjust_learning_rate_const(optimizer, epoch, args):
"""Decay the learning rate with half-cycle cosine after warmup"""
if epoch < args.warmup_epochs:
lr = args.lr * epoch / args.warmup_epochs
else:
lr = args.lr
for param_group in optimizer.param_groups:
if "lr_scale" in param_group:
param_group["lr"] = lr * param_group["lr_scale"]
else:
param_group["lr"] = lr
return lr
def get_args_parser():
parser = argparse.ArgumentParser('RDM training', add_help=False)
parser.add_argument('--epochs', default=400, type=int)
parser.add_argument('--accum_iter', default=1, type=int, help='Accumulate gradient iterations (for increasing the effective batch size under memory constraints)')
# Optimizer parameters
parser.add_argument('--weight_decay', type=float, default=0.05, help='weight decay (default: 0.05)')
parser.add_argument('--lr', type=float, default=None, metavar='LR', help='learning rate (absolute lr)')
parser.add_argument('--blr', type=float, default=1e-3, metavar='LR', help='base learning rate: absolute_lr = base_lr * total_batch_size')
parser.add_argument('--min_lr', type=float, default=0., metavar='LR', help='decay lower lr bound for cyclic schedulers that hit 0')
parser.add_argument('--cosine_lr', action='store_true', help='Use cosine lr scheduling.')
parser.add_argument('--warmup_epochs', default=0, type=int)
# data_iter_step / len(data_loader) + epoch:是将学习率细致调整到了epoch中的step内,而不是简单的一个epoch用一个lr
adjust_learning_rate_cosine_step(optimizer, current_step, lr, **args)
# forward
# backward
# optimizer
# updata_lr
lr = optimizer.param_groups[0]["lr"]