Safemotion Lib
Loading...
Searching...
No Matches
lr_scheduler.py
Go to the documentation of this file.
1# encoding: utf-8
2"""
3@author: liaoxingyu
4@contact: sherlockliao01@gmail.com
5"""
6
7import math
8from bisect import bisect_right
9from typing import List
10
11import torch
12from torch.optim.lr_scheduler import _LRScheduler
13
14__all__ = ["WarmupMultiStepLR", "WarmupCosineAnnealingLR"]
15
16
17class WarmupMultiStepLR(_LRScheduler):
19 self,
20 optimizer: torch.optim.Optimizer,
21 milestones: List[int],
22 gamma: float = 0.1,
23 warmup_factor: float = 0.001,
24 warmup_iters: int = 1000,
25 warmup_method: str = "linear",
26 last_epoch: int = -1,
27 **kwargs,
28 ):
29 if not list(milestones) == sorted(milestones):
30 raise ValueError(
31 "Milestones should be a list of" " increasing integers. Got {}", milestones
32 )
33 self.milestones = milestones
34 self.gamma = gamma
35 self.warmup_factor = warmup_factor
36 self.warmup_iters = warmup_iters
37 self.warmup_method = warmup_method
38 super().__init__(optimizer, last_epoch)
39
40 def get_lr(self) -> List[float]:
41 warmup_factor = _get_warmup_factor_at_iter(
43 )
44 return [
45 base_lr * warmup_factor * self.gamma ** bisect_right(self.milestones, self.last_epoch)
46 for base_lr in self.base_lrs
47 ]
48
49 def _compute_values(self) -> List[float]:
50 # The new interface
51 return self.get_lr()
52
53
54class WarmupCosineAnnealingLR(_LRScheduler):
55 r"""Set the learning rate of each parameter group using a cosine annealing
56 schedule, where :math:`\eta_{max}` is set to the initial lr and
57 :math:`T_{cur}` is the number of epochs since the last restart in SGDR:
58
59 .. math::
60 \eta_t = \eta_{min} + \frac{1}{2}(\eta_{max} - \eta_{min})(1 +
61 \cos(\frac{T_{cur}}{T_{max}}\pi))
62
63 When last_epoch=-1, sets initial lr as lr.
64
65 It has been proposed in
66 `SGDR: Stochastic Gradient Descent with Warm Restarts`_. Note that this only
67 implements the cosine annealing part of SGDR, and not the restarts.
68
69 Args:
70 optimizer (Optimizer): Wrapped optimizer.
71 T_max (int): Maximum number of iterations.
72 eta_min (float): Minimum learning rate. Default: 0.
73 last_epoch (int): The index of last epoch. Default: -1.
74
75 .. _SGDR\: Stochastic Gradient Descent with Warm Restarts:
76 https://arxiv.org/abs/1608.03983
77 """
78
80 self,
81 optimizer: torch.optim.Optimizer,
82 max_iters: int,
83 delay_iters: int = 0,
84 eta_min_lr: int = 0,
85 warmup_factor: float = 0.001,
86 warmup_iters: int = 1000,
87 warmup_method: str = "linear",
88 last_epoch=-1,
89 **kwargs
90 ):
91 self.max_iters = max_iters
92 self.delay_iters = delay_iters
93 self.eta_min_lr = eta_min_lr
94 self.warmup_factor = warmup_factor
95 self.warmup_iters = warmup_iters
96 self.warmup_method = warmup_method
97 assert self.delay_iters >= self.warmup_iters, "Scheduler delay iters must be larger than warmup iters"
98 super(WarmupCosineAnnealingLR, self).__init__(optimizer, last_epoch)
99
100 def get_lr(self) -> List[float]:
101 if self.last_epoch <= self.warmup_iters:
102 warmup_factor = _get_warmup_factor_at_iter(
104 )
105 return [
106 base_lr * warmup_factor for base_lr in self.base_lrs
107 ]
108 elif self.last_epoch <= self.delay_iters:
109 return self.base_lrs
110
111 else:
112 return [
113 self.eta_min_lr + (base_lr - self.eta_min_lr) *
114 (1 + math.cos(
115 math.pi * (self.last_epoch - self.delay_iters) / (self.max_iters - self.delay_iters))) / 2
116 for base_lr in self.base_lrs]
117
118
120 method: str, iter: int, warmup_iters: int, warmup_factor: float
121) -> float:
122 """
123 Return the learning rate warmup factor at a specific iteration.
124 See https://arxiv.org/abs/1706.02677 for more details.
125 Args:
126 method (str): warmup method; either "constant" or "linear".
127 iter (int): iteration at which to calculate the warmup factor.
128 warmup_iters (int): the number of warmup iterations.
129 warmup_factor (float): the base warmup factor (the meaning changes according
130 to the method used).
131 Returns:
132 float: the effective warmup factor at the given iteration.
133 """
134 if iter >= warmup_iters:
135 return 1.0
136
137 if method == "constant":
138 return warmup_factor
139 elif method == "linear":
140 alpha = iter / warmup_iters
141 return warmup_factor * (1 - alpha) + alpha
142 else:
143 raise ValueError("Unknown warmup method: {}".format(method))
__init__(self, torch.optim.Optimizer optimizer, int max_iters, int delay_iters=0, int eta_min_lr=0, float warmup_factor=0.001, int warmup_iters=1000, str warmup_method="linear", last_epoch=-1, **kwargs)
__init__(self, torch.optim.Optimizer optimizer, List[int] milestones, float gamma=0.1, float warmup_factor=0.001, int warmup_iters=1000, str warmup_method="linear", int last_epoch=-1, **kwargs)
float _get_warmup_factor_at_iter(str method, int iter, int warmup_iters, float warmup_factor)