rethinking of lr scheduler

前言

复习一下基础工程问题。

torch.optim.LRScheduler

LRScheduler是一个模板类。具体的schedluer类型需要继承它。

每种LRScheduler的具体实现,都需要提供 get_lr() 无参方法的implementation。
所有需要的参数通过self传递。

默认情况使用无参 step() 进行 lr 的更新。(带参版本deprecated)。
简化逻辑如下:

def step(self, epoch=None):
	if epoch is None:
        self.last_epoch += 1
        values = self.get_lr()
    for i, data in enumerate(zip(self.optimizer.param_groups, values)):
        param_group, lr = data
        param_group['lr'] = lr
        self.print_lr(self.verbose, i, lr, epoch)

简单说就是通过get_lr() 拿到长度等于num_groups的list of values。

对group的管理

只使用optimizer的时候每个group只关心自己的group['lr']

在我们引入LRScheduler后,
会在init阶段,
默认情况下(即不给出last_epoch时),
group['lr'] 移植给 group['initial_lr']

而后scheduler 在 group['initial_lr'] 的基础上进行各种 lr 操作。
通常是linear变化。

last_epoch的心智模型

torch api存在一种隐形约定。

注意到step()时 先有 self.last_epoch += 1 ,再有 values = self.get_lr()
所以我们实现 get_lr() 时可以根据 self.last_epoch 去定位当前需要的epoch。

这样一来似乎有点奇怪,明明命名是last,使用时却变成了current。
所以需要对齐一下心智模型。

事实上,LRScheduler类在__init__()时会call一次_initial_step(),
这时候就会step()一次。
即初始化阶段,就会让 self.last_epoch从-1变成0。
然后根据self.last_epoch==0计算一次get_lr

所以last_epoch == 0的意思并非是我们已经完成了epoch0,即将开始epoch1。
而是指,已经完成的epoch的计数为0
我们即将开始0-th epoch
即事实上地,这个参数应该作为current_epoch来运用
但torch不知道为什么选了last这个名字。

作为例证,我们来看一下其他库的实现。
例如大名鼎鼎的 timm

# from timm.scheduler.cosine_lr
class CosineLRLambda:
    def __init__(self, scheduler_params):
        self.warmup_epochs = scheduler_params["warmup_epochs"]
        self.lr_warmup_factor = scheduler_params["warmup_factor"]
        self.max_epochs = scheduler_params["epochs"]
        self.lr_min_factor = scheduler_params["lr_min_factor"]

    def __call__(self, current_step):
        # `warmup_epochs` is already multiplied with the num of iterations
        if current_step < self.warmup_epochs:
            alpha = current_step / float(self.warmup_epochs)
            return self.lr_warmup_factor * (1.0 - alpha) + alpha
        else:
            if current_step >= self.max_epochs:
                return self.lr_min_factor
            lr_scale = self.lr_min_factor + 0.5 * (1 - self.lr_min_factor) * (
                1 + math.cos(math.pi * (current_step / self.max_epochs))
            )
            return lr_scale

注意到timm的上述实现中,唯一入参为 current_step
这样第一次调用时,父类torch.optim.LambdaLR会在get_lr()中调用lmbda(self.last_epoch)
这个self.last_epoch==0 传入到 CosineLRLambda.__call__()中就变成了current_step == 0

证明 last_epoch 确实是被作为 current用的。

小结

在这种心智模型下,
torch的隐形假设是,
我们总是在一个epoch的结尾才调用scheduler.step()

因为第0epoch一开始的那个step() 放在 init() 里面完成了。
下一个step()应该在0epoch的结尾处产生。

于是我们开发者在get_lr()的实现中,
应该把self.last_epoch 参数视作 current_epoch 的含义来使用。
或者更严谨地说,应该是next_epoch来使用,因为总是先 self.last_epoch +=1 get_lr()

选用last应该是一个torch的命名失误。

保存state_dict的顺序问题

考虑到上述last_epoch的心智模型。
在每个epoch结束后,有2种做法。

  1. 应该先进行scheduler.step(),切换到next_epoch and next lr,再保存scheduler.state_dict()。这样一来,下次直接 scheduler.load_state_dict()就能完成next_epoch的preparation。

  2. save(scheduler.state_dict()),再scheduler.step()。 如果这样做的话,恢复训练时,在scheduler.load_state_dict() 后,需要手动再 scheduler.step() 一次,进入到 next_epoch

第三种就是那种无状态的有closed form的 lrscheduler,step时只依赖epoch序号的。
这种只需要记录save时的epoch,然后重新赋值给 lrscheduler ,再step()一次进入next。

样例代码:

ckp_dict = load('...somefile')
epoch = ckp_dict['epoch']
lr_scheduler.last_epoch = epoch
lr_scheduler.step() # 进入next epoch

如果是有状态的lr_scheduler,例如ReduceLROnPlateau这种需要依赖metrics更新的,而不仅仅依赖epoch序号的。
你就得再读save时的metrics手动恢复。
感觉挺麻烦。
最简单的办法一定是save时,先step再save。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/603366.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue2 Avoided redundant navigation to current location

再次点击同一个链接会报错 每次使用 push 方法时带上两个回调函数 this.$router.push({name: item.name}, ()>{}, ()>{}) //第二、第三个参数分别为成功和失败的回调函数重写 Vue-router 原型对象上的 push 函数不行 https://blog.csdn.net/weixin_43615570/article/d…

python入门demo实例-个人信息收集页面实现

dd 今天是python入门day2&#xff0c;先看一下本案例demo的样子吧~ 一个简单得html页面&#xff0c;个人信息收集界面。 案例介绍常用得input 元素 文本框&#xff0c;密码&#xff0c;邮箱。文件上传等实现。 资源下载&#xff1a;python案例demo个人信息收集页面实现资源-…

微信公众号有哪些类型,微信服务号和订阅号有哪些区别

什么是微信公众号&#xff1f; 微信公众号是国内社交媒体平台微信上的公众账号。它们是允许公司发布内容&#xff0c;收集追随者并推广其产品或服务的商业帐户。微信公众号主要有两种类型&#xff1a;订阅账号和服务账号。 微信月活跃用户突破12亿 微信最近达到了平台上的月活…

jmeter利用自身代理录制脚本

在利用代理录制脚本时一定要安装java jdk&#xff0c;不然不能录制的。 没有安装过java jdk安装jmeter后打开时会提示安装jdk&#xff0c;但是mac系统中直接打开提示安装jdk页面后下载的java并不是jdk&#xff08;windows中没有试验过&#xff0c;笔者所说的基本全部指的是在ma…

区块链 | NFT 水印:Review on Watermarking Techniques(二)

&#x1f34d;原文&#xff1a;Review on Watermarking Techniques Aiming Authentication of Digital Image Artistic Works Minted as NFTs into Blockchains 1 半脆弱和可逆水印 鲁棒性好的水印技术通常会产生非常低透明度。正如前面所述&#xff0c;由于透明度在处理数字…

智慧公厕:一个让城市公共厕所更智能、更便利的信息化方案

公共厕所一直是城市管理中的一个难题。但是&#xff0c;随着科技的不断发展&#xff0c;智慧公厕正在成为解决这个问题的全新方案。智慧公厕不仅具备传统公厕的基本功能&#xff0c;更是通过信息化技术&#xff0c;实现了空余智能引导、环境监测、资源消耗监测、安全防范管理、…

【数据分析面试】38.更新图书馆数据(Python)

题目 作为一名精通Python的图书管理员&#xff0c;你正在搭建一个更高效地更新图书数据的系统。 编写一个名为 update_availability 的函数&#xff0c;用于更新数据表中特定 book_id 的 availability 值&#xff0c;并返回更新后的数据表。 注意: 如果找不到 book_id&#…

如何缩小图片大小kb?6个压缩图片大小的软件教你快速压缩

如何缩小图片大小kb&#xff1f;6个压缩图片大小的软件教你快速压缩 当需要缩小图片的大小&#xff08;KB&#xff09;时&#xff0c;可以利用一系列专门设计的工具和软件来帮助完成这一任务。这些工具可以有效地减小图片的文件大小&#xff0c;而又不会明显降低图片的质量。以…

小麦穗检测数据集VOC+YOLO格式6508张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;6508 标注数量(xml文件个数)&#xff1a;6508 标注数量(txt文件个数)&#xff1a;6508 标注…

MyBatis(XML映射器操作)

文章目录 XML映射器操作&#xff08;XxxMapper.xml&#xff09;文件目录1.基本介绍1.优点2.常用顶级元素 2.环境配置1.在原来的父模块下创建一个子模块2.删除没用的两个文件夹3.创建基本目录4.父模块的pom.xml5.jdbc.properties6.mybatis-config.xml7.测试使用MonsterMapperTes…

诛吕政变后,为何会是代王刘恒登上皇位?

公元前179年——这一年对于汉帝国而言是非常特殊的一年。在这一年&#xff0c;汉惠帝的所有儿子被秘密杀害。也就在这一年&#xff0c;远在北疆的诸侯王——代王刘恒在汉朝功臣周勃、丞相陈平等人的支持下在长安登基。 自此&#xff0c;汉朝皇位完成了一次“乾坤大挪移”——汉…

10、算数运算符(以 ‘/’、‘%’、‘++’为主去讲解)(Java超详细版本)

算数运算符 一、算数运算符二、“ / ”的使用三、“ % ”的使用四、“ ”的使用⭐ 一、算数运算符 算数运算符是对数值类型的变量进行运算的&#xff0c;在Java程序中使用的非常多的。 二、“ / ”的使用 1、Java中 “ / ” 的运算结果是省略小数部分的整数&#xff0c;不存…

2024年美国市场亚太游戏品牌数字广告洞察报告

来源&#xff1a;Sensor Tower 美国是全球最大的游戏市场之一&#xff0c;也是亚太游戏品牌出海的重要市场。2023年Q2至2024年Q1&#xff0c;美国市​场广告投放额排名前10的亚太游戏品牌&#xff0c;合计支出 超过7.5亿美元&#xff0c;环比上涨23%。 排名第一的米哈游(miHoY…

DES加密解密算法(简单、易懂、超级详细)

目录 一、基础补充 二、什么是DES算法 &#xff08;1&#xff09;对称加密算法 &#xff08;2&#xff09;非对称加密算法 &#xff08;3&#xff09;对称加密算法的应用 三、DES算法的基础操作步骤 1.明文的加密整体过程 2.F轮函数解析 3.密钥的形成过程 四、AC代码 五、D…

电脑怎么压缩视频?win端、Mac端压缩工具分享~

我们经常需要处理和分享视频文件。然而&#xff0c;视频文件往往会占用大量的存储空间&#xff0c;特别是高分辨率和高质量的视频。为了方便存储和分享&#xff0c;我们常常需要将视频文件进行压缩。本文将介绍如何使用电脑系统win端或Mac端自带的视频编辑器、以及常用的剪辑软…

Golang——IO操作

1. 输入输出的底层原理 终端其实是一个文件(Linux下一切皆文件)&#xff0c;相关实例如下&#xff1a; os.Stdin&#xff1a;标准输出的文件实例&#xff0c;类型为*Fileos.Stdout&#xff1a;标准输入的文件实例&#xff0c;类型为*Fileos.Stderr&#xff1a;标准错误输出的文…

元器件的检测及万用表的使用

实验目的&#xff1a; 1. 了解万用表的结构和原理&#xff1b; 2. 识别常用电子元器件&#xff0c;学习使用万用表测量电阻、电感、电容和二极管的方法&#xff1b; 3. 学习使用万用表测量直流电压和直流电流的方法&#xff1b; 4. 理解万用表内阻对测量结果的影响&#xf…

pythonnet调用dll提示DragDrop注册失败

问题描述 解决方案 在引入clr之前&#xff0c;引入pythoncom&#xff0c;并做初始化 # 注意这段代码必须在import clr之前否则无效 import pythoncom pythoncom.CoInitialize() import clr

【文献解析】3D高斯抛雪球是个什么玩意

论文地址&#xff1a;https://arxiv.org/abs/2308.04079 项目&#xff1a;3D Gaussian Splatting for Real-Time Radiance Field Rendering 代码&#xff1a;git clone https://github.com/graphdeco-inria/gaussian-splatting --recursive 一、文章概述 1.1问题导向 辐射…

【学习笔记】HarmonyOS 4.0 鸿蒙Next 应用开发--安装开发环境

开发前的准备 首先先到官网去下载Devco Studio 这个开发工具&#xff0c;https://developer.harmonyos.com/cn/develop/deveco-studio/#download 提供了WIndows和Mac的开发环境&#xff0c;我自己是Windows的开发环境。 所以下载之后直接点击exe进行安装即可。 如果之前安装过…
最新文章