更新时间:2024-07-08
本文作者:小新
发布于公众号“NLP情报局”
身为一名深度学习炼丹师,我们知道学习率对于模型训练效果来说相当重要。
然鹅,学习率过低会导致学习速度太慢,学习率过高又容易导致难以收敛。
因此,很多炼丹师都会采用动态调整学习率的方法。刚开始训练时,学习率大一点,以加快学习速度;之后逐渐减小来寻找最优解。
那么在Pytorch中,如何在训练过程里动态调整学习率呢?本文将带你深入理解优化器和学习率调整策略。
在介绍学习率调整方法之前,先带你了解一下Pytorch中的优化器Optimizer机制,模型训练时的固定搭配如下:
loss.backward()
optimizer.step()
optimizer.zero_grad()
简单来说,loss.backward()就是反向计算出各参数的梯度,然后optimizer.step()更新网络中的参数,optimizer.zero_grad()将这一轮的梯度清零,防止其影响下一轮的更新。
常用优化器都在torch.optim包中,因此需要先导入包:
import torch.optim.Adamimport torch.optim.SGD
这里以Adam和SGD优化器为例,介绍一下Pytorch中的优化器使用方法。假设我们有一个网络,下面的例子都以此网络展开:
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.layer1=nn.Linear(10, 2)
self.layer2=nn.Linear(2, 10)
def forward(self, input):
return self.layer1(input)
所有Optimizer公有的一些基本属性:
每个Optimizer都维护一个param_groups的list,该list中维护需要优化的参数以及对应的属性设置。
我们在构造优化器时,最简单的方法通常如下:
model=Net()
optimizer_Adam=torch.optim.Adam(model.parameters(), lr=0.1)
model.parameters()返回模型的全部参数,并将它们传入Adam函数构造出一个Adam优化器,并设置 learning rate=0.1。
因此该 Adam 优化器的 param_groups 维护的就是模型 model 的全部参数,并且学习率为0.1,这样在调用optimizer_Adam.step()时,就会对model的全部参数进行更新。
Optimizer的param_groups是一个list,其中的每个元素都是一组独立的参数,以dict的方式存储。结构如下:
-param_groups
-0(dict) # 第一组参数
params: # 维护要更新的参数
lr: # 该组参数的学习率
betas:
eps: # 该组参数的学习率最小值
weight_decay: # 该组参数的权重衰减系数
amsgrad:
-1(dict) # 第二组参数
-2(dict) # 第三组参数
...
这样可以实现很多灵活的操作,比如:
例如,只想训练上面的model中的layer1参数,而保持layer2的参数不动。可以如下设置Optimizer:
model=Net()
# 只传入layer层的参数,就可以只更新layer层的参数而不影响其他参数。
optimizer_Adam=torch.optim.Adam(model.layer1.parameters(), lr=0.1)
例如,要想使model的layer1参数学习率为0.1,layer2的参数学习率为0.2,可以如下设置Optimizer:
model=Net()
params_dict=[{'params': model.layer.parameters(), 'lr': 0.1},
{'params': model.layer2.parameters(), 'lr': 0.2}]
optimizer_Adam=torch.optim.Adam(params_dict)
这种方法更为灵活,手动构造一个params_dict列表来初始化Optimizer。注意,字典中的参数部分的 key 必须为‘params’。
了解了Optimizer的基本结构和使用方法,接下来将向你介绍如何在训练过程中动态更新 learning rate。
前文提到Optimizer的每一组参数维护一个lr,因此最直接的方法就是在训练过程中手动修改Optimizer中对应的lr值。
model=Net() # 生成网络
optimizer_Adam=torch.optim.Adam(model.parameters(), lr=0.1) # 生成优化器
for epoch in range(100): # 假设迭代100个epoch
if epoch % 5==0: # 每迭代5次,更新一次学习率
for params in optimizer_Adam.param_groups:
# 遍历Optimizer中的每一组参数,将该组参数的学习率 * 0.9
params['lr']*=0.9
# params['weight_decay']=0.5 # 当然也可以修改其他属性
torch.optim.lr_scheduler包中提供了一些类,用于动态修改lr。
pytorch 1.1.0版本之后,在创建了lr_scheduler对象之后,会自动执行第一次lr更新(可以理解为执行一次scheduler.step())。
因此在使用的时候,需要先调用optimizer.step(),再调用scheduler.step()。
如果创建了lr_scheduler对象之后,先调用scheduler.step(),再调用optimizer.step(),则会跳过了第一个学习率的值。
# 调用顺序
loss.backward()
optimizer.step()
scheduler.step()...
具体使用方法由于篇幅有限不在此阐述了,感兴趣的伙伴可以去torch官网查看文档。
学习率对于深度学习炼丹来说尤为重要,一个合适的学习率不仅能加速训练的拟合,还能更好地逼近最优解。
固定的学习率随着深度学习模型逐渐上升的复杂性已不太适用,动态调整学习率或者对模型不同部分设置不同的学习率已成为一种炼丹趋势。
最后和你正式介绍一下自己哈:
我是叶琛,一个爱旅行,懂养生的算法工程师兼干货答主,也是个喜欢用接地气的文风为年轻朋友分享职场经验和算法知识的人。希望我的文字可以为你提供帮助!
总结不易,如有帮助请给 @Giant点个赞哟,谢谢啦!
关于腾越娱乐
腾越最安全、信誉、快捷的娱乐【skype:zhumeng1688】,是亚洲极具公信力的娱乐游戏公司,以互联网技术为基础,引进海外高科技人才,腾越公司自主研发了基于playcraft引擎的H5网页版游戏,致力于带给腾越平台玩家最新颖、最高效的服务与娱乐体验。...联系我们
电话:400-123-4657
邮箱:admin@youweb.com
地址:广东省广州市天河区88号
传真:+86-123-4567