-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathhyperbolic_lr.py
124 lines (109 loc) · 3.54 KB
/
hyperbolic_lr.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import math
class HyperbolicLR:
"""
HyperbolicLR
Args:
optimizer: Optimizer
upper_bound: Upper bound on various max_iters
max_iter: Maximum number of iterations
infimum_lr: The infimum of the hyperbolic learning rate
"""
def __init__(self, optimizer, upper_bound=1000, max_iter=100, infimum_lr=1e-6):
init_lr = optimizer.param_groups[0]['lr']
if upper_bound < max_iter:
raise ValueError("upper_bound must be greater than max_iter")
elif infimum_lr >= init_lr:
raise ValueError("infimum_lr must be less than init_lr")
self._optimizer = optimizer
self.upper_bound = upper_bound
self.max_iter = max_iter
self.init_lr = init_lr
self.delta_lr = init_lr - infimum_lr
self.iter = 0
def step(self):
"""
Update the learning rate
"""
self._update_learning_rate()
def zero_grad(self):
"""
Zero out the gradients with the inner optimizer
"""
self._optimizer.zero_grad()
def get_last_lr(self):
"""
Get the last learning rates from the inner optimizer
"""
return [param_group['lr'] for param_group in self._optimizer.param_groups]
def _get_lr(self):
"""
Get the learning rate
"""
x = self.iter
N = self.max_iter
U = self.upper_bound
return self.init_lr + self.delta_lr * (
math.sqrt((N - x) / U * (2 - (N + x) / U)) - math.sqrt(N / U * (2 - N / U))
)
def _update_learning_rate(self):
"""
Update the learning rate
"""
self.iter += 1
lr = self._get_lr()
for param_group in self._optimizer.param_groups:
param_group['lr'] = lr
class ExpHyperbolicLR:
"""
ExpHyperbolicLR
Args:
optimizer: Optimizer
upper_bound: Upper bound on various max_iters
max_iter: Maximum number of iterations
infimum_lr: The infimum of the hyperbolic learning rate
"""
def __init__(self, optimizer, upper_bound=1000, max_iter=100, infimum_lr=1e-6):
init_lr = optimizer.param_groups[0]['lr']
if upper_bound < max_iter:
raise ValueError("upper_bound must be greater than max_iter")
elif infimum_lr >= init_lr:
raise ValueError("infimum_lr must be less than init_lr")
self._optimizer = optimizer
self.upper_bound = upper_bound
self.max_iter = max_iter
self.init_lr = init_lr
self.lr_ratio = init_lr / infimum_lr
self.iter = 0
def step(self):
"""
Update the learning rate
"""
self._update_learning_rate()
def zero_grad(self):
"""
Zero out the gradients with the inner optimizer
"""
self._optimizer.zero_grad()
def get_last_lr(self):
"""
Get the last learning rates from the inner optimizer
"""
return [param_group['lr'] for param_group in self._optimizer.param_groups]
def _get_lr(self):
"""
Get the learning rate
"""
x = self.iter
N = self.max_iter
U = self.upper_bound
return self.init_lr * self.lr_ratio ** (
math.sqrt((N - x) / U * (2 - (N + x) / U)) - math.sqrt(N / U * (2 - N / U))
)
def _update_learning_rate(self):
"""
Update the learning rate
"""
self.iter += 1
lr = self._get_lr()
for param_group in self._optimizer.param_groups:
param_group['lr'] = lr