- Momentum & Nesterov Momentum
- AdaGrad & Adadelta
- RMSprop
- Adam
Pytorch优化器基类:Optimizer
优化器有个参数组的概念,可以定制不同层的优化。其表现结构为list[dict]:
[
{'params':[tensor([[ 0.7182, -1.6116],
[-1.6995, 1.2277]], requires_grad=True), tensor([[-0.4665, -1.3747],
[ 0.5758, -0.4772]], requires_grad=True)], 'lr': 0.1, 'momentum': 0, 'dampening': 0, 'weight_decay': 0, 'nesterov': False},
{'params':[tensor([[-0.0233, -0.3799],
[ 0.5708, -0.1617]], requires_grad=True)], 'lr': 0.001, 'momentum': 0.8, 'dampening': 0, 'weight_decay': 0, 'nesterov': False}
]
基本方法:
- zero_grad(): 将梯度置为0
- state_dict():获取模型当前的参数
- load_state_dict(state_dict):将state_dict的的参数加载到当前网络
- add_param_group():增加一组参数,可为该组参数定制 lr,momentum, weight_decay 等,在 finetune 中常用
- step(closure):执行一步权值更新, 其中可传入参数 closure(一个闭包)。如,当采用 LBFGS优化方法时,需要多次计算,因此需要传入一个闭包去允许它们重新计算 loss。
优化器子类(10个),需要重要掌握的为粗体:
- torch.optim.SGD
- torch.optim.ASGD
- torch.optim.Rprop
- torch.optim.Adagrad
- torch.optim.Adadelta
- torch.optim.RMSprop
- torch.optim.Adam
- torch.optim.Adamax
- torch.optim.SparseAdam
- torch.optim.LBFGS
1、torch.optim.SGD
torch.optim.SGD(params, lr=required, momentum=0, dampening=0, weight_decay=0, nesterov=False)
可实现 SGD 优化算法,带动量 SGD 优化算法,带 NAG(Nesterov accelerated gradient)动量 SGD 优化算法,并且均可拥有 weight_decay 项。
注意事项:
pytroch 中使用 SGD 十分需要注意的是,更新公式与其他框架略有不同!
PyTorch 中是这样的:
v=ρ ?v+g
p=p-lr?v=p - lr?ρ ?v - lr?g
其他框架:
v=ρ ?v+lr?g
p=p-v=p - ρ ?v - lr?g
ρ 是动量, v 是速率, g 是梯度, p 是参数,其实差别就是在 ρ ?v 这一项, PyTorch 中将此项也乘了一个学习率。
指数加权平均:
其中,
- :为第 t 天的实际观察值,
- : 是要代替 的估计值,也就是第 t 天的指数加权平均值,
- : 为 的权重,是可调节的超参。( )
模型在训练优化的时候肯定是按照最优化的方向收敛,如果在某个batch里遇到异常点,异常点的影响也会很大。
momentum是降低每个batch对模型优化方向的影响,试想100个batch就1个batch是异常的,但是这1个batch的影响微乎其微,基本不改变w和b的大小,而其他99个batch虽然影响比较小,但是积少成多,使得模型在案最优的方案拟合。
若上图,
纵轴方向,平均过程中正负摆动相互抵消,平均值接近于零,摆动变小,学习放慢。
横轴方向,因为所有的微分都指向横轴方向,因此平均值仍然较大,向最小值运动更快了。
在抵达最小值的路上减少了摆动,加快了训练速度。
迭代公式:
Momentum其实也使盲目的,根据数据自动往相关的方向调整,因为数据大多是好的,所以最后是往最优化的方向拟合。
nesterov accelerated gradient:http://www.360doc.com/content/16/1010/08/36492363_597225745.shtml
2、torch.optim.ASGD
torch.optim.ASGD(params, lr=0.01, lambd=0.0001, alpha=0.75, t0=1000000.0, weight_decay=0)
ASGD 也成为 SAG,均表示随机平均梯度下降(Averaged Stochastic Gradient Descent),简单地说 ASGD 就是用空间换时间的一种 SGD
3、torch.optim.Rprop
torch.optim.Rprop(params, lr=0.01, etas=(0.5, 1.2), step_sizes=(1e-06, 50))
实现 Rprop 优化方法(弹性反向传播),该优化方法适用于 full-batch,不适用于 mini-batch,因而在 mini-batch 大行其道的时代里,很少见到
4、torch.optim.Adagrad
torch.optim.Adagrad(params, lr=0.01, lr_decay=0, weight_decay=0, initial_accumulator_value=0)
实现 Adagrad 优化方法(Adaptive Gradient), Adagrad 是一种自适应优化方法,是自适应的为各个参数分配不同的学习率。
这个学习率的变化,会受到梯度的大小和迭代次数的影响。梯度越大,学习率越小;梯度越小,学习率越大。
缺点是训练后期,学习率过小,因为 Adagrad 累加之前所有的梯度平方作为分母。
5、torch.optim.Adadelta
torch.optim.Adadelta(params, lr=1.0, rho=0.9, eps=1e-06, weight_decay=0)
Adadelta 是 Adagrad 的改进。 Adadelta 分母中采用距离当前时间点比较近的累计项,这可以避免在训练后期,学习率过小。
6、torch.optim.RMSprop
torch.optim.RMSprop(params, lr=0.01, alpha=0.99, eps=1e-08, weight_decay=0, momentum=0, centered=False)
实现 RMSprop 优化方法( Hinton 提出), RMS 是均方根( root meam square)的意思。
RMSprop 和 Adadelta 一样,也是对 Adagrad 的一种改进。
RMSprop 采用均方根作为分母,可缓解 Adagrad 学习率下降较快的问题, 并且引入均方根,可以减少摆动,
7、torch.optim.Adam(AMSGrad)
torch.optim.Adam(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0, amsgrad=False)
实现 Adam(Adaptive Moment Estimation))优化方法。 Adam 是一种自适应学习率的优化方法,
Adam 利用梯度的一阶矩估计和二阶矩估计动态的调整学习率。吴老师课上说过,Adam 是结合了 Momentum 和 RMSprop,并进行了偏差修正
8、torch.optim.Adamax
torch.optim.Adamax(params, lr=0.002, betas=(0.9, 0.999), eps=1e-08, weight_decay=0)
实现 Adamax 优化方法。 Adamax 是对 Adam 增加了一个学习率上限的概念,所以也称之为 Adamax
9、torch.optim.SparseAdam
torch.optim.SparseAdam(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08)
针对稀疏张量的一种“ 阉割版”Adam 优化方法。
10、torch.optim.LBFGS
torch.optim.LBFGS(params, lr=1, max_iter=20, max_eval=None, tolerance_grad=1e-05, tolerance_change=1e-09, history_size=100, line_search_fn=None)
实现 L-BFGS( Limited-memory Broyden– Fletcher– Goldfarb– Shanno)优化方法。L-BFGS 属于拟牛顿算法。 L-BFGS 是对 BFGS 的改进,特点就是节省内存
配合优化器,六个学习率调整方法(有序调整、自适应调整、自定义调整):
- lr_scheduler.StepLR
- lr_scheduler.MultiStepLR
- lr_scheduler.ExponentialLR
- lr_scheduler.CosineAnnealingLR
- lr_scheduler.ReduceLROnPlateau
- lr_scheduler.LambdaLR
按调整策略分:
- 有序调整
- 依一定规律有序进行调整,人为可控
- eg:
- lr_scheduler.MultiStepLR:按需设定下降间隔
- lr_scheduler.ExponentialLR:指数下降
- lr_scheduler.CosineAnnealingLR
- 自适应调整‘
- 依训练状况伺机调整,该法通过监测某一指标的变化情况,当该指标不再怎么变化的时候,就是调整学习率的时机,因而属于自适应的调整
- eg:
- lr_scheduler.ReduceLROnPlateau
- 自定义调整:
- 不仅可为不同的层设定不同的学习率,还可以为其设定不同的学习率调整策略,在 fine-tune 中十分有用。
- eg:
- lr_scheduler.LambdaLR
1、torch.optim.lr_scheduler.StepLR
torch.optim.lr_scheduler.StepLR(optimizer, step_size, gamma=0.1, last_epoch=-1)
等间隔调整学习率,调整倍数为 gamma 倍,调整间隔为 step_size。间隔单位是step。需要注意的是, step 通常是指 epoch,不要弄成 iteration 了
2、torch.optim.lr_scheduler.MultiStepLR
torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones, gamma=0.1, last_epoch=-1)
按设定的间隔调整学习率。这个方法适合后期调试使用,观察 loss 曲线,为每个实验定制学习率调整时机
3、torch.optim.lr_scheduler.ExponentialLR
torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma, last_epoch=-1)
按指数衰减调整学习率,调整公式: lr=lr * gamma**epoch
4、torch.optim.lr_scheduler.CosineAnnealingLR
torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max, eta_min=0, last_epoch=-1)
以余弦函数为周期,并在每个周期最大值时重新设置学习率
5、torch.optim.lr_scheduler.ReduceLROnPlateau
torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min',factor=0.1, patience=10, verbose=False,
threshold=0.0001, threshold_mode='rel', cooldown=0, min_lr=0, eps=1e-08)
当某指标不再变化(下降或升高),调整学习率,这是非常实用的学习率调整策略。
例如,当验证集的 loss 不再下降时,进行学习率调整;或者监测验证集的 accuracy,当accuracy 不再上升时,则调整学习率。
6、torch.optim.lr_scheduler.LambdaLR
torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda, last_epoch=-1)
为不同参数组设定不同学习率调整策略。调整规则为, lr=base_lr * lmbda(self.last_epoch)
参考:
https://www.jianshu.com/p/41218cb5e099?utm_source=oschina-app