项目地址https://github.com/Fafa-DL/Awesome-Backbones

项目说明:开箱即用,涵盖主流模型的图像分类|主干网络学习/对比/魔改项目

models下的配置文件中,学习率更新方式以及参数均在lr_config中,在上一期讲网络如何被搭建时说了type是我们所需的调用关键字。在core/optimizers/lr_update.py中可以看到目前所支持的学习率更新策略。

常用的为StepLrUpdaterCosineAnnealingLrUpdater,均继承了LrUpdater类,先来看看它

class LrUpdater(object):"""LR Scheduler in MMCV.Args:by_epoch (bool): LR changes epoch by epochwarmup (string): Type of warmup used. It can be None(use no warmup),'constant', 'linear' or 'exp'warmup_iters (int): The number of iterations or epochs that warmuplastswarmup_ratio (float): LR used at the beginning of warmup equals towarmup_ratio * initial_lrwarmup_by_epoch (bool): When warmup_by_epoch == True, warmup_itersmeans the number of epochs that warmup lasts, otherwise means thenumber of iteration that warmup lasts"""def __init__(self,by_epoch=True,warmup=None,warmup_iters=0,warmup_ratio=0.1,warmup_by_epoch=False):# validate the "warmup" argumentif warmup is not None:if warmup not in ['constant', 'linear', 'exp']:raise ValueError(f'"{warmup}" is not a supported type for warming up, valid'' types are "constant" and "linear"')if warmup is not None:assert warmup_iters > 0, \'"warmup_iters" must be a positive integer'assert 0 < warmup_ratio <= 1.0, \'"warmup_ratio" must be in range (0,1]'self.by_epoch = by_epochself.warmup = warmupself.warmup_iters = warmup_itersself.warmup_ratio = warmup_ratioself.warmup_by_epoch = warmup_by_epochif self.warmup_by_epoch:self.warmup_epochs = self.warmup_itersself.warmup_iters = Noneelse:self.warmup_epochs = Noneself.base_lr = []  # initial lr for all param groupsself.regular_lr = []  # expected lr if no warming up is performed# 给optimizer设置新lrdef _set_lr(self, runner, lr_groups):for param_group, lr in zip(runner.get("optimizer").param_groups,lr_groups):param_group['lr'] = lrdef get_lr(self, runner, base_lr):raise NotImplementedError# 获取新lrdef get_regular_lr(self, runner):return [self.get_lr(runner, _base_lr) for _base_lr in self.base_lr]# 获取warmup学习率更新策略的lrdef get_warmup_lr(self, cur_iters):def _get_warmup_lr(cur_iters, regular_lr):if self.warmup == 'constant':warmup_lr = [_lr * self.warmup_ratio for _lr in regular_lr]elif self.warmup == 'linear':k = (1 - cur_iters / self.warmup_iters) * (1 -self.warmup_ratio)warmup_lr = [_lr * (1 - k) for _lr in regular_lr]elif self.warmup == 'exp':k = self.warmup_ratio**(1 - cur_iters / self.warmup_iters)warmup_lr = [_lr * k for _lr in regular_lr]return warmup_lrif isinstance(self.regular_lr, dict):lr_groups = {}for key, regular_lr in self.regular_lr.items():lr_groups[key] = _get_warmup_lr(cur_iters, regular_lr)return lr_groupselse:return _get_warmup_lr(cur_iters, self.regular_lr)# 记录初始lrdef before_run(self, runner):# NOTE: when resuming from a checkpoint, if 'initial_lr' is not saved,# it will be set according to the optimizer paramsfor group in runner.get("optimizer").param_groups:group.setdefault('initial_lr', group['lr'])self.base_lr = [group['initial_lr'] for group in runner.get("optimizer").param_groups]# 在周期更新前获取新lr并在optimizer中更新它def before_train_epoch(self, runner):if self.warmup_iters is None: # 即self.warmup_by_epoch为True,warmup_epochs = warmup_itersepoch_len = len(runner.get("train_loader"))self.warmup_iters = self.warmup_epochs * epoch_len # 按周期更新则warmup iters = warmup_epochs * datasets//batch size# 不按周期更新则没必要在此进行lr更新,在下一步before_train_iter中更新if not self.by_epoch:returnself.regular_lr = self.get_regular_lr(runner)self._set_lr(runner, self.regular_lr)# 首先判断是否按周期更新lr,若按迭代次数更新即by_epoch为False,大于等于warmup_iters使用正常lr更新方式,小于则用warmup方式更新lrdef before_train_iter(self, runner):cur_iter = runner.get("iter")if not self.by_epoch:self.regular_lr = self.get_regular_lr(runner)if self.warmup is None or cur_iter >= self.warmup_iters:self._set_lr(runner, self.regular_lr)else:warmup_lr = self.get_warmup_lr(cur_iter)self._set_lr(runner, warmup_lr)elif self.by_epoch:# 按周期更新lr,若当前迭代步数大于warmup迭代步数阈值,直接返回,使用before_train_epoch中的lrif self.warmup is None or cur_iter > self.warmup_iters:returnelif cur_iter == self.warmup_iters: # 等于则用常规方式self._set_lr(runner, self.regular_lr)else:warmup_lr = self.get_warmup_lr(cur_iter) # 小于则用warmup方式self._set_lr(runner, warmup_lr)

LrUpdater执行的顺序为:

  1. __init__,初始化,主要针对warmup,需注意的是若warmup_by_epoch=Truewarmup_iters代表的是warmup作用的epoch数,若warmup_by_epoch=False,则warmup_iters代表的是warmup作用的iters数,1 epoch = total images // batch size iters
  2. before_run,在这里记录了初始学习率,通过获取配置文件optimizer_cfg中的lr定义初始学习率
  3. before_train_epoch,在每个epoch更新前获取新lr并在optimizer中更新学习率。若by_epoch=False,即按iter更新学习率,直接返回。否则大于等于warmup_iters存在周期时使用常规lr更新方式
    1. get_regular_lr,调用配置文件中type指定的学习率更新方式,如StepLrUpdaterCosineAnnealingLrUpdater,通过get_lr获取当前epoch/iter下的学习率
    2. _set_lr给优化器设置最新的学习率
  4. before_train_iter,在每个iter更新前获取新lr并在optimizer中更新学习率。首先判断是否按epoch更新lr
    1. by_epoch = False,即按iter更新,大于等于warmup_iters使用正常lr更新方式,小于则用warmup方式更新lr
    2. by_epoch = True,按epoch更新lr,若当前迭代步数大于warmup迭代步数阈值,直接返回,使用before_train_epoch中的lr,等于则用常规方式,小于则用warmup方式
    3. get_warmup_lr获取warmup学习率更新策略的lr

说完了核心LrUpdater类,再说说StepLrUpdaterCosineAnnealingLrUpdater,我们知道主要功能是根据当前iter或epoch计算最新学习率并返回,先看看StepLrUpdater

class StepLrUpdater(LrUpdater):"""Step LR scheduler with min_lr clipping.Args:step (int | list[int]): Step to decay the LR. If an int value is given,regard it as the decay interval. If a list is given, decay LR atthese steps.gamma (float, optional): Decay LR ratio. Default: 0.1.min_lr (float, optional): Minimum LR value to keep. If LR after decayis lower than `min_lr`, it will be clipped to this value. If Noneis given, we don't perform lr clipping. Default: None."""def __init__(self, step, gamma=0.1, min_lr=None, **kwargs):self.step = stepself.gamma = gammaself.min_lr = min_lrsuper(StepLrUpdater, self).__init__(**kwargs)def get_lr(self, runner, base_lr):progress = runner.get('epoch') if self.by_epoch else runner.get('iter')# calculate exponential termif isinstance(self.step, int):exp = progress // self.stepelse:exp = len(self.step)for i, s in enumerate(self.step):if progress < s:exp = ibreaklr = base_lr * (self.gamma**exp)if self.min_lr is not None:# clip to a minimum valuelr = max(lr, self.min_lr)return lr

step:步骤衰减LR,有两种形式,一是int,另一个是list。举例:

  • step=2,即每2个iter/epoch更新一次学习率
  • step=[20,60,80],即0-20,21-60,61-80,80-X间的iter/epoch更新一次学习率

gamma:学习率衰减比率,对应公式lr = base_lr * (self.gamma**exp)

min_lr:最小学习率,若设置了该值,则当学习率小于该值时使用min_lr

再看看CosineAnnealingLrUpdater

class CosineAnnealingLrUpdater(LrUpdater):def __init__(self, min_lr=None, min_lr_ratio=None, **kwargs):assert (min_lr is None) ^ (min_lr_ratio is None)self.min_lr = min_lrself.min_lr_ratio = min_lr_ratiosuper(CosineAnnealingLrUpdater, self).__init__(**kwargs)def get_lr(self, runner, base_lr):if self.by_epoch:progress = runner.get('epoch')max_progress = runner.get('max_epochs')else:progress = runner.get('iter')max_progress = runner.get('max_iters')if self.min_lr_ratio is not None:target_lr = base_lr * self.min_lr_ratioelse:target_lr = self.min_lrreturn annealing_cos(base_lr, target_lr, progress / max_progress)

min_lr:最小学习率

min_lr_ratio:最小学习率比率,min_lr_ratiomin_lr不能同时存在,因为这两个参数仅是用于计算最终学习率,当设置了min_lr,则最终学习率为min_lr;若设置了min_lr_ratio,则最终学习率为base_lr * min_lr_ratio

annealing_cos,学习率更新计算方法,具体如下

def annealing_cos(start, end, factor, weight=1):"""Calculate annealing cos learning rate.Cosine anneal from `weight * start + (1 - weight) * end` to `end` aspercentage goes from 0.0 to 1.0.Args:start (float): The starting learning rate of the cosine annealing.end (float): The ending learing rate of the cosine annealing.factor (float): The coefficient of `pi` when calculating the currentpercentage. Range from 0.0 to 1.0.weight (float, optional): The combination factor of `start` and `end`when calculating the actual starting learning rate. Default to 1."""cos_out = cos(pi * factor) + 1return end + 0.5 * weight * (start - end) * cos_out

至此学习率更新介绍完毕,最后说下优化器是如何调用,对应配置文件中的optimizer_cfg,在上一期讲网络如何被搭建时说了type是我们所需的调用关键字,此处type与torch.optim中的优化器一一对应,也就是不需要额外重写优化器类。

tools/train.py中可看到import torch.optim as optim,对应构建optimizer的语句为

optimizer = eval('optim.' + optimizer_cfg.pop('type'))(params=model.parameters(),**optimizer_cfg)

还是借助eval,所以如果有修改优化器的需要,大家可以查阅pytorch手册自行修改。

以上就是本次学习率更新策略/优化器的全部内容,在后续可视化教程中会绘制学习率曲线

【图像分类】学习率更新策略/优化器相关推荐

  1. 深度学习-图像处理之误差传播、权重更新及优化器

    以三层的BP神经网络为例: 输出如下:最后一层的激活函数统一用softmax,所以单独拎出来并没有写在里面.为什么要用softmax这个激活函数呢?因为输出的y1.y2并不属于任何一个分布,我们想让输 ...

  2. 【详解】模型优化技巧之优化器和学习率调整

    目录 PyTorch十大优化器 1 torch.optim.SGD 2 torch.optim.ASGD 3 torch.optim.Rprop 4 torch.optim.Adagrad 5 tor ...

  3. YOLOv5-优化器和学习率调整策略

    优化器和学习率调整策略 pytorch-优化器和学习率调整 这个链接关于优化器和学习率的一些基础讲得很细,还有相关实现代码 优化器 前向传播的过程,会得到模型输出与真实标签的差,我们称之为损失, 有了 ...

  4. 冻结训练优化器学习率

    1.冻结训练 为什么要冻结,a.因为加载的预训练模型参数一般是效果较好的,如果我们不冻结还是从头开始训练浪费资源(本来可以较快收敛的,结果从头开始训练浪费训练资源)甚至降低原模型精度:b.冻结训练需要 ...

  5. Pytorch模型训练实用教程学习笔记:四、优化器与学习率调整

    前言 最近在重温Pytorch基础,然而Pytorch官方文档的各种API是根据字母排列的,并不适合学习阅读. 于是在gayhub上找到了这样一份教程<Pytorch模型训练实用教程>,写 ...

  6. 图像语义分割实践(五)优化器与学习率

    概述 在数据制作环节中,提到minibatch思想用于数据批次量获取,是一种优化器思想,而该文则是对各种优化器进行介绍. 优化器:最小化损失函数算法,把深度学习当炼丹的话,优化器就是炉子,决定火候大小 ...

  7. 深度学习各类优化器详解(动量、NAG、adam、Adagrad、adadelta、RMSprop、adaMax、Nadam、AMSGrad)

    深度学习梯度更新各类优化器详细介绍 文章目录 <center>深度学习梯度更新各类优化器详细介绍 一.前言: 二.梯度下降变形形式 1.批量归一化(BGD) 2.随机梯度下降(SGD) 3 ...

  8. pytorch学习十 ---- 优化器

    1.什么是优化器? 首先我们回忆一下机器学习的五大模块:数据.模型.损失函数.优化器.迭代训练 在损失函数中我们会得到一个loss值,即真实标签与预测标签的差异值,对于loss我们通常会采用pytor ...

  9. 听六小桨讲AI | 第3期:优化器及其三种形式BGD、SGD以及MBGD

    点击左上方蓝字关注我们 本栏目由百度飞桨工程师联手精心打造,对深度学习的知识点进行由浅入深的剖析和讲解.大家可视它为深度学习百科(面试秘籍也是可以哒),当然也可收藏为深度学习查询手册~ 大家好,我是助 ...

  10. Pytorch框架中SGD&Adam优化器以及BP反向传播入门思想及实现

    因为这章内容比较多,分开来叙述,前面先讲理论后面是讲代码.最重要的是代码部分,结合代码去理解思想. SGD优化器 思想: 根据梯度,控制调整权重的幅度 公式: 权重(新) = 权重(旧) - 学习率 ...

最新文章

  1. Redis的API调用工具类
  2. java手机音乐_JAVA类(手机充电、放音乐示例)
  3. linux安装Python2.7
  4. python 元类的call_【原创】Python 对象创建过程中元类, __new__, __call__, __init__ 的处理...
  5. 计算机开不开机是什么原因是什么原因,电脑开不了机的原因,详细教您电脑开不了机怎么办...
  6. [导入]浅析.Net下的AppDomain编程
  7. 一个民工的数字化生活
  8. Python:Matplotlib 画曲线和柱状图(Code)
  9. fatal error C1083: 无法打开包括文件:dxtrans.h: No such file or directory
  10. email邮件中 内嵌iframe_Python+Selenium执行结果,封装函数,用Python自动发送SMTP邮件...
  11. Ubuntu 15 安装Chromium浏览器并添加Flash插件Pepper Flash Player
  12. Mysql笔记——DCL
  13. winform 可拖动的自定义Label控件
  14. kd树的根节点_多维空间分割树--KD树
  15. 文件怎么复制到虚拟机中的linux系统吗,Windows下的文件如何复制到虚拟机的Linux中...
  16. android音乐16bit,16bit音乐是无损吗
  17. 以贝叶斯思维看待世界
  18. TypeScript 简单使用
  19. Hive基础08、Hive引入Struct结构体
  20. 最简单可靠的机房温度电话报警

热门文章

  1. 机器学习 朴素贝叶斯之邮件分类
  2. ubuntu22.04 安装完后必做的事
  3. 奇舞周刊第 464 期:我被 pgx 及其背后的 Rust 美学征服
  4. [已解决]react异常:Can‘t perform a React state update on an unmounted component
  5. 数据类型的大小与编译器、cpu、操作系统的关系
  6. gotoblas2 安装编译方法
  7. 关于敏捷过程中的Stroy, Epic和Theme 的关系和区别(翻译)
  8. 航天器太阳能板的最大面积
  9. 湘潭大学计算机考研调剂,2017年湘潭大学考研调剂信息公告
  10. 什么是MQTT网关?与DTU终端有什么区别?