2学习率调整_学习率衰减

之前我们的优化,主要是聚焦于对梯度下降运动方向的调整,而在参数迭代更新的过程中,除了梯度,还有一个重要的参数是学习率α,对于学习率的调整也是优化的一个重要方面。

3a4b16727334d131400cc0477326ee3a.png

01

学习率衰减

首先我们以一个例子,来说明一下我们为什么需要学习率α衰减( learning rate decay )。如果学习率不衰减的话,如下图蓝线所示,由于噪音影响,代价函数更新路径相对不规则,但总体朝着最低点方向移动,但是移动到最低点附近时,由于学习率较大,每一次会移动相对较远的距离,容易直接跨过最低点,导致代价函数在更新完毕后距离最低点仍然相对较远;当我们随着迭代的次数逐渐降低学习率,那么便如绿线所示,一开始学习率较大,前进速度较快,到达最低点附近后,学习率降低到更小的值,于是最终更新完成后代价函数离最低点更近,也就是模型更加优化,预测值与实际值差距更小。

315c87570c823913ddb72fa05a5bc745.png

进行学习率衰减的一种方式如下所示,需要设置如下学习率更新规则:

d5eefa45499c7eb6da0e7fa6d4f014d2.png

1 个epoch 是指将所有mini-batch 全部迭代一遍,即遍历一遍。假设α 0=0.2 ,decay_rate=1 ,那么随着epoch 增加,学习率α会如下图变化:

7ad8684e8c18cf5cb1d3fec8498c7d48.png

在应用这个公式时,我们需要选择合适的超参数α 0 和decay_rate 。 除了这种学习率衰减方式,还有一些其他方式来进行学习率衰减:

21c6b610741c2bd926cbab1cdc02eb69.png

3afbf291b9a71e2a9d832672a747dc8f.png

此外还有离散衰减,经过一段时间衰减一半:

1cbacb2baa5d51af92c42ca7a4bb2e5e.png

02

学习率衰减的pytorch实现

指数衰减

我们首先需要确定需要针对哪个优化器执行学习率动态调整策略,也就是首先定义一个优化器:
optimizer_ExpLR = torch.optim.SGD(net.parameters(), lr=0.1)
定义好优化器以后,就可以给这个优化器绑定一个指数衰减学习率控制器:
ExpLR = torch.optim.lr_scheduler.ExponentialLR(optimizer_ExpLR, gamma=0.98)
参数gamma 表示衰减的底数,也就是decay_rate ,选择不同的gamma 值可以获得幅度不同的衰减曲线。

ce1b8775feda673a80af1632239792b7.png

固定步长衰减

即离散型衰减,学习率每隔一定步数(或者epoch )就减少为原来的gamma 分之一,使用固定步长衰减依旧先定义优化器,再给优化器绑定StepLR 对象:
optimizer_StepLR = torch.optim.SGD(net.parameters(), lr=0.1)StepLR = torch.optim.lr_scheduler.StepLR(optimizer_StepLR, step_size=step_size, gamma=0.65)
其中gamma 参数表示衰减的程度,step_size 参数表示每隔多少个step 进行一次学习率调整,下面对比了不同gamma 值下的学习率变化情况:

55bcba827dba94e404bb51e13cf04620.png

多步长衰减

有时我们希望不同的区间采用不同的更新频率,或者是有的区间更新学习率,有的区间不更新学习率,这就需要使用MultiStepLR 来实现动态区间长度控制:
optimizer_MultiStepLR = torch.optim.SGD(net.parameters(), lr=0.1)torch.optim.lr_scheduler.MultiStepLR(optimizer_MultiStepLR,\                milestones=[200, 300, 320, 340, 200], gamma=0.8)
其中milestones 参数为表示学习率更新的起止区间,在区间[0. 200] 内学习率不更新,而在[200, 300] 、[300, 320].....[340, 400] 的右侧值都进行一次更新;gamma 参数表示学习率衰减为上次的gamma 分之一。其图示如下:

91aaccc7315e1c13be18d784e8d3980e.png

从图中可以看出,学习率在区间[200 , 400] 内快速的下降,这就是milestones 参数所控制的,在milestones 以外的区间学习率始终保持不变。

余弦退火衰减

严格的说,余弦退火策略不应该算是学习率衰减策略,因为它使得学习率按照周期变化,其定义方式如下:
optimizer_CosineLR = torch.optim.SGD(net.parameters(), lr=0.1)CosineLR = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer_CosineLR, T_max=150, eta_min=0)
参数T_max 表示余弦函数周期;eta_min 表示学习率的最小值,默认它是0 表示学习率至少为正值。确定一个余弦函数需要知道最值和周期,其中周期就是T_max ,最值是初试学习率。下图展示了不同周期下的余弦学习率更新曲线:

117eecb78e2d4ef31906b3ea97864f2d.png

为网络的不同层设置不同的学习率

定义一个简单的网络结构:
class net(nn.Module):    def __init__(self):        super(net, self).__init__()        self.conv1 = nn.Conv2d(3, 64, 1)        self.conv2 = nn.Conv2d(64, 64, 1)        self.conv3 = nn.Conv2d(64, 64, 1)        self.conv4 = nn.Conv2d(64, 64, 1)        self.conv5 = nn.Conv2d(64, 64, 1)    def forward(self, x):        out = conv5(conv4(conv3(conv2(conv1(x)))))        return out
我们希望conv5 学习率是其他层的100 倍,我们可以:
net = net()lr = 0.001conv5_params = list(map(id, net.conv5.parameters())) # 1 base_params = filter(lambda p: id(p) not in conv5_params,                     net.parameters()) # 2,3optimizer = torch.optim.SGD([            {'params': base_params},            {'params': net.conv5.parameters(), 'lr': lr * 100}], lr=lr, momentum=0.9)
1. conv5_params = list(map(id,net.conv5.parameters())) 中id() 函数用于获取网络参数的内存地址,map() 函数用于将id() 函数作用于net.conv5.parameters() 得到的每个参数上。2.lambda p: id(p) 中lamda 表达式是python 中用于定义匿名函数的方式,其后面定义的是一个函数操作,冒号前的符号是函数的形式参数,用于接收参数,符合的个数表示需要接收的参数个数,冒号右边是具体的函数操作。3.filter() 函数的作用是过滤掉不符合条件(False) 的元素,返回一个迭代器对象。该函数接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判断,然后返回True 或False ,最后返回值为True 的元素

Reference

深度学习课程 --吴恩达

https://zhuanlan.zhihu.com/p/93624972

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值