学习率调整(二): warm up

@TOC

pytorch的优化器和如何调整学习率都可以在这个链接中找到torch.optim

这里我们不介绍优化器,介绍一些调整学习率的方法,通过pytorch的库就不需要我们手动设置adjust learning rate函数了

LambdaLR

pytorch官方文档: LambdaLR

torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda, last_epoch=-1, verbose=False)

Sets the learning rate of each parameter group to the initial lr times a given function. When last_epoch=-1, sets initial lr as lr.

将params中的学习率设置为学习率乘上一个给定的函数

  • optimizer: 优化器
  • lr_lambda: 一个关于epoch的函数,用来计算学习率要乘的那个数字
  • last_epoch: 最后一个迭代的索引,默认-1
  • verbose: 没啥用

lambdalr学习率的调整非常的简单,我们只需要在optimizer的基础上加上一个调整学习率的函数以及lambdalr即可,当需要更新学习率时,使用scheduler.step()

这里我们将optimizer用scheduler进行包装scheduler = lr_scheduler.LambdaLR(optimizer, lr_lambda=lambda1),命名为scheduler,之后的操作都是对scheduler操作的

同上一篇博客一样,我们依然用linear举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class linear(nn.Module):
def __init__(self):
super(linear, self).__init__()
self.linear1 = nn.Linear(2, 3)
self.linear2 = nn.Linear(3, 4)

def forward(self, x):
x = self.linear1(x)
y = self.linear2(x)
return y

net = linear()
optimizer = optim.SGD(params=net.parameters(), lr=0.05)
lambda1 = lambda epoch: 0.2**epoch # add
scheduler = lr_scheduler.LambdaLR(optimizer, lr_lambda=lambda1) # add
plt.figure()
x = list(range(40))
y = []
for epoch in range(40):
print(epoch, scheduler.get_last_lr()[0])
y.append(scheduler.get_last_lr()[0])
scheduler.step() # add
plt.plot(x,y)

'''
0 0.05
1 0.010000000000000002
2 0.0020000000000000005
3 0.00040000000000000013
4 8.000000000000002e-05
5 1.6000000000000006e-05
...
38 1.3743895347200028e-28
39 2.748779069440006e-29
'''

如果我们对linear1和linear2的学习率调整方法不一样怎么办?这里lr_scheduler库也提供了解决办法

首先将传入optimizer的参数分开,假设有两组参数,然后在lambdalr的学习率函数调整部分设置两个函数即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
net = linear()
params = [{"params": net.linear1.parameters(), "lr":0.05}, # 设置两组函数
{"params": net.linear2.parameters(), "lr":0.05}]
optimizer = optim.SGD(params=params, lr=10)

lambda1 = lambda epoch: 0.5**epoch # 这里用了两个学习率调整函数
lambda2 = lambda epoch: 0.2**epoch

scheduler = lr_scheduler.LambdaLR(optimizer, lr_lambda=[lambda1, lambda2]) # 设置两个函数
plt.figure()
x = list(range(40))
y1 = []
y2 = []

for epoch in range(40):
print(epoch, scheduler.get_last_lr()[0], scheduler.get_last_lr()[1])
y1.append(scheduler.get_last_lr()[0])
y2.append(scheduler.get_last_lr()[1])
scheduler.step() # 更新学习率
plt.plot(x, y1)
plt.plot(x, y2)
plt.legend(['linear1', 'linear2'], loc='upper left')
plt.show()

'''
0 0.05 0.05
1 0.025 0.010000000000000002
2 0.0125 0.0020000000000000005
3 0.00625 0.00040000000000000013
4 0.003125 8.000000000000002e-05
5 0.0015625 1.6000000000000006e-05
...
38 1.8189894035458566e-13 1.3743895347200028e-28
39 9.094947017729283e-14 2.748779069440006e-29
'''

scheduler还有几个方法,下面简单介绍

  • get_last_lr: 上面也有例子,是获取当前的学习率
  • state_dict: 获取当前scheduler状态
  • load_state_dict: 加载模型,保存之后加载