有一些论文对warmup进行了讨论,使用 SGD 训练神经网络时,在初始使用较大学习率而后期改为较小学习率在各种任务场景下都是一种广为使用的做法,在实践中效果好且最近也有若干文章尝试对其进行了理论解释。例如《On Layer Normalization in the Transformer Architecture》等,论文中作者发现Post-LN Transformer在训练的初始阶段,输出层附近的期望梯度非常大,所以没有warm-up的话模型优化过程就会非常不稳定。

虽然在实践中效果好且最近也有若干文章尝试对其进行了理论解释,但到底为何有效,目前还没有被充分证明。

Transformer中的warm-up可以看作学习率 lr 随迭代数 t 的函数:

学习率 lr 会以某种方式递减,学习率从0开始增长,经过 Twarmup 次迭代达到最大。论文中对Adam,SGD等有无warmup做了实验,

可以看到,warmup增加了训练时间,同时在最初阶段使用较大的学习率会导致Loss偏大,对模型的训练的影响是巨大的。warmup在这里对SGD是非常重要的。

Rectified Adam针对warmup前期数据样本不足导致的biased variance的问题提出了解决方案,论文中实验结果看到还是有一定效果的。RAdam 由随机初始化带来的 Variance 比较小。即使隔离掉 warmup 部分的影响后Variance 也是要比 Adam 小的。

class AdamWarmup(Optimizer):# DOTAdef __init__(self, params, lr=1e-3, betas=(0.9, 0.999), eps=1e-8, weight_decay=0, warmup = 0):if not 0.0 <= lr:raise ValueError("Invalid learning rate: {}".format(lr))if not 0.0 <= eps:raise ValueError("Invalid epsilon value: {}".format(eps))if not 0.0 <= betas[0] < 1.0:raise ValueError("Invalid beta parameter at index 0: {}".format(betas[0]))if not 0.0 <= betas[1] < 1.0:raise ValueError("Invalid beta parameter at index 1: {}".format(betas[1]))defaults = dict(lr=lr, betas=betas, eps=eps,weight_decay=weight_decay, warmup = warmup)super(AdamW, self).__init__(params, defaults)def __setstate__(self, state):super(AdamW, self).__setstate__(state)def step(self, closure=None):loss = Noneif closure is not None:loss = closure()for group in self.param_groups:for p in group['params']:if p.grad is None:continuegrad = p.grad.data.float()if grad.is_sparse:raise RuntimeError('Adam does not support sparse gradients, please consider SparseAdam instead')p_data_fp32 = p.data.float()state = self.state[p]if len(state) == 0:state['step'] = 0state['exp_avg'] = torch.zeros_like(p_data_fp32)state['exp_avg_sq'] = torch.zeros_like(p_data_fp32)else:state['exp_avg'] = state['exp_avg'].type_as(p_data_fp32)state['exp_avg_sq'] = state['exp_avg_sq'].type_as(p_data_fp32)exp_avg, exp_avg_sq = state['exp_avg'], state['exp_avg_sq']beta1, beta2 = group['betas']state['step'] += 1exp_avg_sq.mul_(beta2).addcmul_(1 - beta2, grad, grad)exp_avg.mul_(beta1).add_(1 - beta1, grad)denom = exp_avg_sq.sqrt().add_(group['eps'])bias_correction1 = 1 - beta1 ** state['step']bias_correction2 = 1 - beta2 ** state['step']if group['warmup'] > state['step']:scheduled_lr = 1e-8 + state['step'] * group['lr'] / group['warmup']else:scheduled_lr = group['lr']step_size = scheduled_lr * math.sqrt(bias_correction2) / bias_correction1if group['weight_decay'] != 0:p_data_fp32.add_(-group['weight_decay'] * scheduled_lr, p_data_fp32)p_data_fp32.addcdiv_(-step_size, exp_avg, denom)p.data.copy_(p_data_fp32)return loss

class RAdam(Optimizer):def __init__(self, params, lr=1e-3, betas=(0.9, 0.999), eps=1e-8, weight_decay=0, degenerated_to_sgd=False):if not 0.0 <= lr:raise ValueError("Invalid learning rate: {}".format(lr))if not 0.0 <= eps:raise ValueError("Invalid epsilon value: {}".format(eps))if not 0.0 <= betas[0] < 1.0:raise ValueError("Invalid beta parameter at index 0: {}".format(betas[0]))if not 0.0 <= betas[1] < 1.0:raise ValueError("Invalid beta parameter at index 1: {}".format(betas[1]))self.degenerated_to_sgd = degenerated_to_sgdif isinstance(params, (list, tuple)) and len(params) > 0 and isinstance(params[0], dict):for param in params:if 'betas' in param and (param['betas'][0] != betas[0] or param['betas'][1] != betas[1]):param['buffer'] = [[None, None, None] for _ in range(10)]defaults = dict(lr=lr, betas=betas, eps=eps, weight_decay=weight_decay, buffer=[[None, None, None] for _ in range(10)])super(RAdam, self).__init__(params, defaults)def __setstate__(self, state):super(RAdam, self).__setstate__(state)def step(self, closure=None):loss = Noneif closure is not None:loss = closure()for group in self.param_groups:for p in group['params']:if p.grad is None:continuegrad = p.grad.data.float()if grad.is_sparse:raise RuntimeError('RAdam does not support sparse gradients')p_data_fp32 = p.data.float()state = self.state[p]if len(state) == 0:state['step'] = 0state['exp_avg'] = torch.zeros_like(p_data_fp32)state['exp_avg_sq'] = torch.zeros_like(p_data_fp32)else:state['exp_avg'] = state['exp_avg'].type_as(p_data_fp32)state['exp_avg_sq'] = state['exp_avg_sq'].type_as(p_data_fp32)exp_avg, exp_avg_sq = state['exp_avg'], state['exp_avg_sq']beta1, beta2 = group['betas']exp_avg_sq.mul_(beta2).addcmul_(1 - beta2, grad, grad)exp_avg.mul_(beta1).add_(1 - beta1, grad)state['step'] += 1buffered = group['buffer'][int(state['step'] % 10)]if state['step'] == buffered[0]:N_sma, step_size = buffered[1], buffered[2]else:buffered[0] = state['step']beta2_t = beta2 ** state['step']N_sma_max = 2 / (1 - beta2) - 1N_sma = N_sma_max - 2 * state['step'] * beta2_t / (1 - beta2_t)buffered[1] = N_sma# more conservative since it's an approximated valueif N_sma >= 5:step_size = math.sqrt((1 - beta2_t) * (N_sma - 4) / (N_sma_max - 4) * (N_sma - 2) / N_sma * N_sma_max / (N_sma_max - 2)) / (1 - beta1 ** state['step'])elif self.degenerated_to_sgd:step_size = 1.0 / (1 - beta1 ** state['step'])else:step_size = -1buffered[2] = step_size# more conservative since it's an approximated valueif N_sma >= 5:if group['weight_decay'] != 0:p_data_fp32.add_(-group['weight_decay'] * group['lr'], p_data_fp32)denom = exp_avg_sq.sqrt().add_(group['eps'])p_data_fp32.addcdiv_(-step_size * group['lr'], exp_avg, denom)p.data.copy_(p_data_fp32)elif step_size > 0:if group['weight_decay'] != 0:p_data_fp32.add_(-group['weight_decay'] * group['lr'], p_data_fp32)p_data_fp32.add_(-step_size * group['lr'], exp_avg)p.data.copy_(p_data_fp32)return loss

神经网络调参技巧:warmup策略相关推荐

  1. loss 曲线 神经网络_总结李飞飞教授讲义中的神经网络调参技巧

    总结了李飞飞教授的讲义,稍微结合自己的一些经验(也就是厚着脸皮说一下结合了自己的经验了,其实自己的那些经验,都在教授的讲义中了....). 数据预处理:零均值(zero-centered),将数据的均 ...

  2. 卷积神经网络调参技巧(2)--过拟合(Dropout)

    Dropout(丢弃) 首先需要讲一下过拟合,训练一个大型网络时,因为训练数据有限,很容易出现过拟合.过拟合是指模型的泛化能力差,网络对训练数据集的拟合能力很好,但是换了其他的数据集,拟合能力就变差了 ...

  3. 神经网络调参-warmup and decay

    欢迎大家访问个人博客:https://jmxgodlz.xyz 前言 本文将介绍神经网络调参技巧:warmup,decay.反向传播主要完成参数更新:θt=θt−1−α∗gt\theta_t=\the ...

  4. 深度卷积神经网络(CNN tricks)调参技巧

    (53条消息) 深度卷积神经网络(CNN tricks)调参技巧(一)学习率调节_踏雪飞鸿的博客-CSDN博客https://blog.csdn.net/weixin_38957591/article ...

  5. 深度学习这么调参训练_聊一聊深度学习中的调参技巧?

    本期问题能否聊一聊深度学习中的调参技巧? 我们主要从以下几个方面来讲.1. 深度学习中有哪些参数需要调? 2. 深度学习在什么时候需要动用调参技巧?又如何调参? 3. 训练网络的一般过程是什么? 1. ...

  6. step-by-step: 夕小瑶版神经网络调参指南(上)

    距离上一篇文章已经过去好久好久好久啦.闭关几个月后,其实早有继续码文章的打算,先后写了一下核函数与神经网络的一些思考.文本预处理tricks.不均衡文本分类问题.多标签分类问题.tensorflow常 ...

  7. 深度学习网络调参技巧

    深度学习网络调参技巧 本文转载自[炼丹实验室],讲了一些深度学习训练的技巧,其中包含了部分调参心得:深度学习训练心得.不过由于一般深度学习实验,相比普通机器学习任务,时间较长,因此调参技巧就显得尤为重 ...

  8. 天下苦深度强化学习久矣,这有一份训练与调参技巧手册

    ©作者 | 申岳 单位 | 北京邮电大学 研究方向 | 机器人学习 天下苦 RL 久矣,其中最苦的地方莫过于训练和调参了,人人欲"调"之而后快. 在此为 RL 社区贡献一点绵薄之力 ...

  9. 深度学习调参技巧总结

    深度学习调参技巧总结 做dl也有一段时间了,积累了一些经验,也在网上看到一些别人的经验.  为了面试,结合知乎上面的问答,我也总结了一下,欢迎大家补充. 知乎 深度学习调参有哪些技巧? 一. 初始化  ...

最新文章

  1. Linux上跑程序加大内存
  2. 商城报表系统html5,关于html5:推荐这几款主流报表产品
  3. 进程间通信-Queue(python版)
  4. Linux管道的原子性,管道的原子性 linux写操作原子性
  5. windows 批处理脚本(batch scripting)
  6. linux firefox 解雇ie,Fire IE
  7. android 创建线程的三种方式
  8. 网约车定价策略:手机越贵打车越贵?
  9. Python数据分析与挖掘实战学习12
  10. C语言 neutralize函数,因子中性化
  11. 人生算法第一天心得总结(A)九段进阶(3-6)
  12. python二进制转中文_python3 二进制转中文
  13. 鲜为人知的“水”凶猛
  14. Pulmonary--Detection5
  15. MongoDB文档翻译-聚集-对邮编数据集进行聚集
  16. c#通过POST方式读取HTTP数据(包括使用Postman软件对比)
  17. 软考中级到高级我都是怎么考的
  18. 开发Unity3D空战类插件 战机游戏模板
  19. 【BUG】Swagger2 与通用的 Spring MVC Controller 冲突
  20. 豆瓣Top250电影信息海报爬虫

热门文章

  1. AbpZero之企业微信---登录(拓展第三方auth授权登录)---第一步:查看AbpZero的auth第三方登录的底层机制...
  2. UVA - 12166 Equilibrium Mobile
  3. getdc 与getwindowDc的区别,loadbitmap 与loadimage的区别
  4. 一个简单的epoll测试例子
  5. 数字编码电位器c语言,单片机小白学习之路(三十八)---AD转换电位器编码
  6. qgridlayout 滚动时固定第一行_滚动直线导轨副的安装技术
  7. 新手小白零基础搭建个人博客(一)服务器篇
  8. linux sql failed,Cacti SQL Failed! Error:’1062′故障排除
  9. SQLite学习手册(在线备份)
  10. python读取ttf_python解析字体反爬