网站改版设计要多久,网站域名过期,好的网站建设案例,只买域名可以做自己的网站嘛文章目录 1. torch.optim.lr_scheduler.StepLR 官方文档详解2. 使用示例2.1 官方提供使用示例2.2 自己写代码测试方法2.2.1 get_last_lr() 方法2.2.2 state_dict() 方法2.2.3 load_state_dict() 保存和加载调度器 3. 思考3.1 为什么需要state_dict()3.2 get_lr() 与 get_last_l… 文章目录 1. torch.optim.lr_scheduler.StepLR 官方文档详解2. 使用示例2.1 官方提供使用示例2.2 自己写代码测试方法2.2.1 get_last_lr() 方法2.2.2 state_dict() 方法2.2.3 load_state_dict() 保存和加载调度器 3. 思考3.1 为什么需要state_dict()3.2 get_lr() 与 get_last_lr() 的输出不一致问题 在深度学习中学习率调度器Learning Rate Scheduler 是用来动态调整学习率的工具。它的主要目的是在训练过程中自动调整学习率以提高训练的效率和效果。之所以称其为“调度器”是因为它控制着学习率的调整和更新类似于调度一个过程或者任务它按照某种策略和规则来“调度”学习率本文将详细介绍pytorch中动态调整学习率方法之一 torch.optim.lr_scheduler.StepLR 官方文档链接 https://pytorch.ac.cn/docs/stable/generated/torch.optim.lr_scheduler.StepLR.html#torch.optim.lr_scheduler.StepLR
1. torch.optim.lr_scheduler.StepLR 官方文档详解
官方文档定义:
class torch.optim.lr_scheduler.StepLR(optimizer, step_size, gamma0.1, last_epoch-1, verbosedeprecated)每隔 step_size 个 epochs 将每个参数组的学习率衰减 gamma 倍。 请注意这种衰减可能与来自此调度程序外部的学习率的其他更改同时发生。当 last_epoch-1 时将初始 lr 设置为 lr。
参数 o p t i m i z e r optimizer optimizer (优化器) : 包装的优化器 s t e p _ s i z e ( i n t ) step\_size(int) step_size(int) : 学习率衰减周期 g a m m a ( f l o a t ) gamma (float) gamma(float) : 学习率衰减的乘法因子, 默认值0.1 l a s t _ e p o c h ( i n t ) last\_epoch (int) last_epoch(int) : 最后一个 epoch 的索引, 默认值-1 表示从头开始 v e r b o s e ( b o o l ∣ s t r ) verbose (bool | str) verbose(bool∣str): 如果为 True则为每次更新打印一条消息到标准输出, 默认值False。
注意
自版本 2.2 起不推荐使用 v e r b o s e verbose verbose 已弃用。请使用 g e t _ l a s t _ l r ( ) get\_last\_lr() get_last_lr()访问学习率
其它 g e t _ l a s t _ l r ( ) get\_last\_lr() get_last_lr() : 返回当前调度程序计算的最后一个学习率, 返回类型 L i s t [ f l o a t ] List[float] List[float] g e t _ l r ( ) get\_lr() get_lr() : 计算每个组的学习率 l o a d _ s t a t e _ d i c t ( s t a t e _ d i c t ) load\_state\_dict(state\_dict) load_state_dict(state_dict) : 加载调度程序的状态参数 s t a t e _ d i c t ( d i c t ) state\_dict (dict) state_dict(dict) 调度程序状态应为 s t a t e _ d i c t ( ) state\_dict() state_dict() 调用返回的对象。 p r i n t _ l r ( i s _ v e r b o s e , g r o u p , l r , e p o c h N o n e ) print\_lr(is\_verbose, group, lr, epochNone) print_lr(is_verbose,group,lr,epochNone) : 显示当前学习率。 s t a t e _ d i c t ( ) state\_dict() state_dict() : 将调度程序的状态作为 d i c t dict dict 返回,它包含 s e l f . _ _ d i c t _ _ self.\_\_dict\_\_ self.__dict__ 中每个变量的条目这些变量不是优化器。 s t e p ( e p o c h N o n e ) step(epochNone) step(epochNone) : 执行一步操作即更新一次学习率
注意
自版本 2.4 起不推荐使用 p r i n t _ l r ( ) print\_lr() print_lr() 已弃用。请使用 g e t _ l a s t _ l r ( ) get\_last\_lr() get_last_lr() 访问学习率。
2. 使用示例
2.1 官方提供使用示例
假设初始 l r 0.05 lr 0.05 lr0.05 s t e p _ s i z e 30 step\_size30 step_size30 g a m m a 0.1 gamma0.1 gamma0.1即每 30 个 epoch后将学习率乘以 0.1当 e p o c h 30 epoch 30 epoch30 时 l r 0.05 lr 0.05 lr0.05 即 l r l r lrlr lrlr当 30 e p o c h 60 30 epoch 60 30epoch60 l r 0.005 lr 0.005 lr0.005即 l r n e w l r o l d ∗ g a m m a 0.05 ∗ 0.1 0.005 lr_{new}lr_{old}*gamma0.05*0.10.005 lrnewlrold∗gamma0.05∗0.10.005当 60 e p o c h 90 60 epoch 90 60epoch90 l r 0.0005 lr 0.0005 lr0.0005即 l r n e w l r o l d ∗ g a m m a 0.005 ∗ 0.1 0.0005 lr_{new}lr_{old}*gamma0.005*0.10.0005 lrnewlrold∗gamma0.005∗0.10.0005
# Assuming optimizer uses lr 0.05 for all groups
# lr 0.05 if epoch 30
# lr 0.005 if 30 epoch 60
# lr 0.0005 if 60 epoch 90
# ...
scheduler StepLR(optimizer, step_size30, gamma0.1)
for epoch in range(100):train(...)validate(...)scheduler.step()2.2 自己写代码测试方法
2.2.1 get_last_lr() 方法
用于返回调度器计算的 最后一个学习率。这个学习率是在调度器scheduler调整之后的当前学习率如果优化器中有多个参数组 g e t _ l a s t _ l r ( ) get\_last\_lr() get_last_lr() 返回的是一个列表每个元素对应一个参数组的学习率如果优化器中只有一个参数组 g e t _ l a s t _ l r ( ) get\_last\_lr() get_last_lr() 返回一个只有一个元素的列表
import torch
from torch import nn
from torch import optim
net nn.Linear(3,4)
def train():optimizer optim.Adam(net.parameters(), lr0.1)scheduler optim.lr_scheduler.StepLR(optimizer, step_size 1, gamma0.1)for epoch in range(0, 10):print(epoch, scheduler.get_last_lr())optimizer.step()scheduler.step()
if __name__ __main__:train()代码输出
0 [0.1]
1 [0.010000000000000002]
2 [0.0010000000000000002]
3 [0.00010000000000000003]
4 [1.0000000000000004e-05]
5 [1.0000000000000004e-06]
6 [1.0000000000000005e-07]
7 [1.0000000000000005e-08]
8 [1.0000000000000005e-09]
9 [1.0000000000000006e-10]2.2.2 state_dict() 方法 s t a t e _ d i c t ( ) state\_dict() state_dict() 是一个非常重要的函数它能够返回一个包含模型或优化器状态的字典dict。对于学习率调度器来说 s t a t e _ d i c t ( ) state\_dict() state_dict() 返回调度器的状态包括它的参数和变量用于保存和恢复调度器的状态等
代码示例
import torch
from torch import nn
from torch import optimnet nn.Linear(3,4)def train():optimizer optim.Adam(net.parameters(), lr0.1)scheduler optim.lr_scheduler.StepLR(optimizer, step_size 1, gamma0.1)for epoch in range(10):print(epoch, scheduler.state_dict())optimizer.step()scheduler.step()if __name__ __main__:train()
代码输出
0 {step_size: 1, gamma: 0.1, base_lrs: [0.1], last_epoch: 0, verbose: False, _step_count: 1, _get_lr_called_within_step: False, _last_lr: [0.1]}
1 {step_size: 1, gamma: 0.1, base_lrs: [0.1], last_epoch: 1, verbose: False, _step_count: 2, _get_lr_called_within_step: False, _last_lr: [0.010000000000000002]}
2 {step_size: 1, gamma: 0.1, base_lrs: [0.1], last_epoch: 2, verbose: False, _step_count: 3, _get_lr_called_within_step: False, _last_lr: [0.0010000000000000002]}
3 {step_size: 1, gamma: 0.1, base_lrs: [0.1], last_epoch: 3, verbose: False, _step_count: 4, _get_lr_called_within_step: False, _last_lr: [0.00010000000000000003]}
4 {step_size: 1, gamma: 0.1, base_lrs: [0.1], last_epoch: 4, verbose: False, _step_count: 5, _get_lr_called_within_step: False, _last_lr: [1.0000000000000004e-05]}
5 {step_size: 1, gamma: 0.1, base_lrs: [0.1], last_epoch: 5, verbose: False, _step_count: 6, _get_lr_called_within_step: False, _last_lr: [1.0000000000000004e-06]}
6 {step_size: 1, gamma: 0.1, base_lrs: [0.1], last_epoch: 6, verbose: False, _step_count: 7, _get_lr_called_within_step: False, _last_lr: [1.0000000000000005e-07]}
7 {step_size: 1, gamma: 0.1, base_lrs: [0.1], last_epoch: 7, verbose: False, _step_count: 8, _get_lr_called_within_step: False, _last_lr: [1.0000000000000005e-08]}
8 {step_size: 1, gamma: 0.1, base_lrs: [0.1], last_epoch: 8, verbose: False, _step_count: 9, _get_lr_called_within_step: False, _last_lr: [1.0000000000000005e-09]}
9 {step_size: 1, gamma: 0.1, base_lrs: [0.1], last_epoch: 9, verbose: False, _step_count: 10, _get_lr_called_within_step: False, _last_lr: [1.0000000000000006e-10]}输出详解
step_size: 该值表示每隔多少个 epoch 学习率就会发生变化。在例子中 s t e p _ s i z e 1 step\_size 1 step_size1意味着每经过 1 个 epoch学习率都会更新一次gamma: 这是学习率更新的衰减因子。每次调用 s c h e d u l e r . s t e p ( ) scheduler.step() scheduler.step() 时当前的学习率将会乘以 g a m m a gamma gamma。例子中 g a m m a 0.1 gamma 0.1 gamma0.1意味着每次更新学习率时学习率将减少为原来的 10%base_lrs: 这是每个参数组的初始学习率在调度器调整之前的学习率。这里的 [ 0.1 ] [0.1] [0.1]表示模型的初始学习率是 0.1。如果有多个参数组这里会是一个列表列出每个参数组的初始学习率last_epoch: 这是上一个 epoch 的编号用来确定学习率更新时的参考点。 l a s t _ e p o c h 0 last\_epoch 0 last_epoch0 表示调度器刚刚初始化学习率还没有更新过。通常last_epoch 用来恢复训练时从哪个 epoch 开始更新学习率verbose: 该参数控制调度器是否在学习率更新时打印详细信息。 v e r b o s e F a l s e verbose False verboseFalse 表示调度器在更新学习率时不会打印信息。如果设置为 T r u e True True则每次更新学习率时都会打印一条日志。_step_count: 这个内部变量跟踪调度器已经调用了多少次 step()。在例子中 _ s t e p _ c o u n t 1 \_step\_count 1 _step_count1表示调度器已经调用过一次 s t e p ( ) step() step()即更新过一次学习率_get_lr_called_within_step: 是一个内部标志表示是否在 step() 方法内部调用了 get_lr()。通常不需要关注这个值它帮助调度器管理内部逻辑_last_lr: 这是调度器最近一次计算的学习率。这个列表保存了每个参数组的学习率。在你的例子中 _ l a s t _ l r [ 0.1 ] \_last\_lr [0.1] _last_lr[0.1]表示当前学习率是 0.1。这会在 scheduler.step() 后更新为新的学习率。
2.2.3 load_state_dict() 保存和加载调度器
可以将 state_dict() 保存到文件中然后在以后恢复。如下是一个保存和加载学习率调度器状态的例子
保存调度器状态
# 保存调度器的 state_dict
torch.save(scheduler.state_dict(), scheduler_state.pth)加载调度器状态
# 加载调度器的 state_dict
scheduler.load_state_dict(torch.load(scheduler_state.pth))通过这种方式可以在训练中断后恢复学习率调度器的状态并继续进行训练。
保存调度器状态示例
当 epoch 5 时保存调度器状态
import torch
from torch import nn
from torch import optim
net nn.Linear(3,4)
def train():optimizer optim.Adam(net.parameters(), lr0.1)scheduler optim.lr_scheduler.StepLR(optimizer, step_size 1, gamma0.1)for epoch in range(10):if epoch 5:torch.save(scheduler.state_dict(), scheduler_state.pth)breakoptimizer.step()scheduler.step()if __name__ __main__:train()加载调度器状态示例
import torch
from torch import nn
from torch import optimnet nn.Linear(3,4)def train():optimizer optim.Adam(net.parameters(), lr0.1)scheduler optim.lr_scheduler.StepLR(optimizer, step_size 1, gamma0.1)scheduler.load_state_dict(torch.load(scheduler_state.pth))for epoch in range(3):print(epoch, scheduler.state_dict())optimizer.step()scheduler.step()if __name__ __main__:train()
代码输出
0 {step_size: 1, gamma: 0.1, base_lrs: [0.1], last_epoch: 5, verbose: False, _step_count: 6, _get_lr_called_within_step: False, _last_lr: [1.0000000000000004e-06]}
1 {step_size: 1, gamma: 0.1, base_lrs: [0.1], last_epoch: 6, verbose: False, _step_count: 7, _get_lr_called_within_step: False, _last_lr: [0.010000000000000002]}
2 {step_size: 1, gamma: 0.1, base_lrs: [0.1], last_epoch: 7, verbose: False, _step_count: 8, _get_lr_called_within_step: False, _last_lr: [0.0010000000000000002]}可以看到
last_epoch 从 5 开始_step_count 从6 开始_last_lr 从 1e-6 开始
说明是从上次终断的状态继续运行
3. 思考
3.1 为什么需要state_dict()
保存和恢复训练 当你希望在训练中断后恢复训练时你可以保存模型和调度器的 state_dict()然后在恢复时加载它们确保学习率调度器从上次停止的地方继续工作而不是从头开始。调试和分析通过 state_dict() 可以查看学习率的变化帮助你调试和分析训练过程中调度器的行为。
3.2 get_lr() 与 get_last_lr() 的输出不一致问题
测试代码
import torch
from torch import nn
from torch import optimnet nn.Linear(3,4)def train():optimizer optim.Adam(net.parameters(), lr0.1)scheduler optim.lr_scheduler.StepLR(optimizer, step_size 1, gamma0.1)for epoch in range(3):print(epoch, scheduler.get_lr())print(epoch, scheduler.get_last_lr())print([group[lr] for group in optimizer.param_groups])print()optimizer.step()scheduler.step()if __name__ __main__:train()代码输出
0 [0.1]
0 [0.1]
[0.1]1 [0.0010000000000000002]
1 [0.010000000000000002]
[0.010000000000000002]2 [0.00010000000000000003]
2 [0.0010000000000000002]
[0.0010000000000000002]不知道为什么从 epoch 0 之后get_lr() 每次都比 get_last_lr() 提前一步更新但是通过查看 optimizer.param_groups 的学习率与 get_last_lr() 一致。
get_lr()函数源码
def get_lr(self):if not self._get_lr_called_within_step:warnings.warn(To get the last learning rate computed by the scheduler, please use get_last_lr()., UserWarning)if (self.last_epoch 0) or (self.last_epoch % self.step_size ! 0):return [group[lr] for group in self.optimizer.param_groups]return [group[lr] * self.gammafor group in self.optimizer.param_groups]我们可以看到在源码中当if (self.last_epoch 0) or (self.last_epoch % self.step_size ! 0)返回值为[group[lr] for group in self.optimizer.param_groups], 否则的话返回值为[group[lr] * self.gamma for group in self.optimizer.param_groups]因此可以很好的解释上面的现象但是Pytorch为什么要这样做呢目前没有找到相关资料可以评论区留言讨论
get_last_lr() 函数源码:
def get_last_lr(self): Return last computed learning rate by current scheduler.return self._last_lr