禁止以任何形式转载或抄袭!!
learning rate schedules主要就是对分子部分进行调整,采用learning rate schedules的时候多用于SGD这类非自适应的算法之中。
PyTorch提供的学习率调整策略分为三大类:
在PyTorch 1.1.0之前,学习率调度程序应该在优化器更新之前调用;1.1.0以后改变了这种方式。如果在优化器更新(调用optimizer.step())之前使用学习率调度程序(调用scheduler.step()),这将跳过学习率调度程序的第一个值。In PyTorch 1.1.0 and later, you should call them in the opposite order: optimizer.step()
before lr_scheduler.step()
.
model_param = [Parameter(torch.randn(2, 2, requires_grad=True))]
optimizer = SGD(model_param, 0.1)
scheduler = ExponentialLR(optimizer, gamma=0.9)
for epoch in range(20):
for input, target in dataset:
optimizer.zero_grad()
output = model(input)
loss = loss_fn(output, target)
loss.backward()
optimizer.step()
scheduler.step()
注意,一般都是在优化器进行调整之后,才应用学习率调整策略对学习率进行调整。
大多数学习率调整程序,都是可以根据前一个调整策略所获得的学习率再次进行调整的。
model = [Parameter(torch.randn(2, 2, requires_grad=True))]
optimizer = SGD(model, 0.1)
scheduler1 = ExponentialLR(optimizer, gamma=0.9)
scheduler2 = MultiStepLR(optimizer, milestones=[30,80], gamma=0.1)
for epoch in range(20):
for input, target in dataset:
optimizer.zero_grad()
output = model(input)
loss = loss_fn(output, target)
loss.backward()
optimizer.step()
scheduler1.step()
scheduler2.step()
等间隔调整
scheduler = lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1)
按需调整学习率
scheduler = lr_scheduler.MultiStepLR(optimizer, milestones=[40,70], gamma=0.1)
指数衰减,用得少
scheduler =lr_scheduler.ExponentialLR(optimizer, gamma=0.9)
scheduler =lr_scheduler.OneCycleLR(optimizer,max_lr=0.9,total_steps=1000, verbose=True)
注意:之前的几个学习率优化器是放在每个epoch,每个epoch更新一次,这个方法是每个step更新一次,应该放在step的循环中。
scheduler = lr_scheduler.CyclicLR(optimizer, base_lr=0.01, max_lr=0.1,step_size_up=150,step_size_down=250,mode='triangular')
scheduler = lr_scheduler.CyclicLR(optimizer, base_lr=0.01, max_lr=0.1,step_size_up=150,step_size_down=250,mode='exp_range',gamma=0.997)
与上一个函数所不同的是,这里使用余弦函数进行学习率的衰减,而且学习率是大学习率开始的。仍然是每个step更新。
T_max:Cosine是个周期函数,这里的T_max就是这个周期的一半,如果你将T_max设置为10,则学习率衰减的周期是20个epoch,其中前10个epoch从学习率的初值(也是最大值)下降到最低值,后10个epoch从学习率的最低值上升到最大值
eta_min:学习率衰减时的最小值,默认值为0
last_epoch:(上次训练)最后一个epoch的索引值,默认值为-1。如果你将其设置为20,那定义出来的scheduler的第一次step就会到第21个epoch对应的学习率。这里是为了resuming
optimizer = optim.SGD(params=model.parameters(), lr=0.05)
scheduler = lr_scheduler.CosineAnnealingLR(optimizer, T_max=200, eta_min=0.01, last_epoch=-1)
T_0 – 设定初次在哪里WarmRestarts
T_mult – 每次Restarts后周期扩展系数 默认为: 1.
eta_min–最小学习率,默认为0
scheduler = lr_scheduler.CosineAnnealingWarmRestarts(optimizer, T_0=300, T_mult=1, eta_min=0)
scheduler = lr_scheduler.CosineAnnealingWarmRestarts(optimizer, T_0=200, T_mult=2, eta_min=0)
这一个是用于自适应调整的学习率衰减函数。
功能:监控指标,当指标不再变化则调整(很实用)
比如监控Loss不再下降、或者分类准确率acc不再上升就进行学习率的调整。
optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9)
scheduler = ReduceLROnPlateau(optimizer, 'min')
for epoch in range(10):
train(...)
val_loss = validate(...)
# Note that step should be called after validate()
scheduler.step(val_loss)
自定义调整策略
这里主要是通过lr_lambda (function or list) 参数来设定学习率调整策略:
lambda1 = lambda epoch: 0.95 ** epoch
scheduler = LambdaLR(optimizer, lr_lambda=lambda1)
或者有多个学习率需要调整
#Assuming optimizer has two groups.
lambda1 = lambda epoch: epoch // 30
lambda2 = lambda epoch: 0.95 ** epoch
scheduler = LambdaLR(optimizer, lr_lambda=[lambda1, lambda2])
我这里来定义一个复杂一点的函数,
def lr_lambda(current_step: int,num_warmup_steps=280,num_training_steps=1000):
# 自定义函数
'''
num_warmup_steps (:obj:`int`):
The number of steps for the warmup phase.
num_training_steps (:obj:`int`):
The total number of training steps.
last_epoch (:obj:`int`, `optional`, defaults to -1):
The index of the last epoch when resuming training.
'''
if current_step < num_warmup_steps:
return float(current_step) / float(max(1, num_warmup_steps))
return max(
0.0, float(num_training_steps - current_step) / float(max(1, num_training_steps - num_warmup_steps))
)
scheduler = lr_scheduler.LambdaLR(optimizer, lr_lambda=lr_lambda)
将每个参数组的学习速率乘以指定函数中给定的因子。跟LambdaLR差不多,用得很少,就不画图了。
lambdaa = lambda epoch : 0.5
scheduler = optim.lr_scheduler.MultiplicativeLR(optimizer, lambdaa)
上一篇:深度学习Optimizer优化器小结