Skip to content

Commit fbe27d6

Browse files
committed
Remove some changes to existing behaviour and small correctness issues with optimizer. tensor step/LR support.
1 parent 29993ff commit fbe27d6

7 files changed

Lines changed: 33 additions & 25 deletions

File tree

timm/optim/_helpers.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Small optimizer helpers shared by timm optimizer implementations."""
22

3-
from typing import List, Optional, Sequence
3+
from typing import List, Optional, Sequence, Union
44

55
import torch
66
from torch import Tensor
@@ -10,12 +10,22 @@ def _get_scalar_dtype() -> torch.dtype:
1010
return torch.float64 if torch.get_default_dtype() == torch.float64 else torch.float32
1111

1212

13-
def _init_scalar(value: float = 0.0, device=None) -> Tensor:
14-
return torch.tensor(value, dtype=_get_scalar_dtype(), device=device)
13+
def _init_scalar(
14+
value: Union[float, Tensor] = 0.0,
15+
device=None,
16+
dtype: Optional[torch.dtype] = None,
17+
) -> Tensor:
18+
if isinstance(value, Tensor):
19+
dtype = dtype or value.dtype
20+
device = value.device if device is None else torch.device(device)
21+
if value.device == device and value.dtype == dtype:
22+
return value
23+
return value.to(device=device, dtype=dtype)
24+
return torch.tensor(value, dtype=dtype or _get_scalar_dtype(), device=device)
1525

1626

17-
def _zeros_scalar(device=None) -> Tensor:
18-
return torch.zeros((), dtype=_get_scalar_dtype(), device=device)
27+
def _zeros_scalar(device=None, dtype: Optional[torch.dtype] = None) -> Tensor:
28+
return torch.zeros((), dtype=dtype or _get_scalar_dtype(), device=device)
1929

2030

2131
def _is_compiling() -> bool:

timm/optim/adafactor_bv.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from torch import Tensor
1717
from torch.optim import Optimizer
1818

19-
from ._helpers import _get_scalar_dtype, _get_value, _init_scalar, _validate_scalar
19+
from ._helpers import _get_value, _init_scalar, _validate_scalar
2020
from ._types import ParamsT
2121

2222

@@ -111,7 +111,7 @@ def __setstate__(self, state):
111111
for p in group['params']:
112112
p_state = self.state.get(p, {})
113113
if len(p_state) != 0 and 'step' in p_state:
114-
p_state['step'] = _init_scalar(float(p_state['step']), device='cpu')
114+
p_state['step'] = _init_scalar(p_state['step'], device='cpu', dtype=torch.float64)
115115

116116
if 'exp_avg' in p_state and torch.is_tensor(p_state['exp_avg']):
117117
# FIXME this is a bit of a hack, optimizer.load_state_dict appears to upcast
@@ -148,7 +148,7 @@ def step(self, closure=None):
148148
state = self.state[p]
149149

150150
if len(state) == 0:
151-
state['step'] = _init_scalar(device='cpu')
151+
state['step'] = _init_scalar(device='cpu', dtype=torch.float64)
152152

153153
shape = p.grad.shape
154154
factored_dims = _factored_dims(

timm/optim/adamw.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ def __setstate__(self, state):
9595
p_state = self.state.get(p, {})
9696
if p_state and 'step' in p_state:
9797
p_state['step'] = _init_scalar(
98-
float(p_state['step']),
98+
p_state['step'],
9999
device=p.device if group['capturable'] else 'cpu',
100100
)
101101

timm/optim/lamb.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ def __setstate__(self, state):
129129
group.setdefault('decoupled_decay', False)
130130
group.setdefault('corrected_weight_decay', False)
131131
if 'step' in group:
132-
group['step'] = _init_scalar(float(group['step']), device='cpu')
132+
group['step'] = _init_scalar(group['step'], device='cpu')
133133

134134
def _get_clip_grad_norm(self):
135135
max_grad_norm = self.defaults['max_grad_norm']
@@ -169,14 +169,15 @@ def step(self, closure=None):
169169
grad_averaging = 1 if group['grad_averaging'] else 0
170170
beta3 = 1 - beta1 if grad_averaging else 1.0
171171

172-
if not any(p.grad is not None for p in group['params']):
173-
continue
174-
175172
# assume same step across group now to simplify things
176173
# per parameter step can be easily support by making it tensor, or pass list into kernel
177174
if 'step' not in group:
178175
group['step'] = _init_scalar(device='cpu')
179176
group['step'].add_(1)
177+
178+
if not any(p.grad is not None for p in group['params']):
179+
continue
180+
180181
step = _get_value(group['step'])
181182

182183
if bias_correction:

timm/optim/laprop.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,19 +66,15 @@ def __setstate__(self, state):
6666
if not p_state:
6767
continue
6868
if 'step' in p_state:
69-
p_state['step'] = _init_scalar(float(p_state['step']), device='cpu')
70-
if (
71-
'exp_avg_lr_1' in p_state
72-
and torch.is_tensor(group['lr'])
73-
and not torch.is_tensor(p_state['exp_avg_lr_1'])
74-
):
75-
p_state['exp_avg_lr_1'] = torch.tensor(
76-
float(p_state['exp_avg_lr_1']),
69+
p_state['step'] = _init_scalar(p_state['step'], device='cpu')
70+
if 'exp_avg_lr_1' in p_state and torch.is_tensor(group['lr']):
71+
p_state['exp_avg_lr_1'] = _init_scalar(
72+
p_state['exp_avg_lr_1'],
7773
dtype=group['lr'].dtype,
7874
device=group['lr'].device,
7975
)
8076
if 'exp_avg_lr_2' in p_state:
81-
p_state['exp_avg_lr_2'] = _init_scalar(float(p_state['exp_avg_lr_2']), device='cpu')
77+
p_state['exp_avg_lr_2'] = _init_scalar(p_state['exp_avg_lr_2'], device='cpu')
8278

8379
@torch.no_grad()
8480
def step(self, closure=None):
@@ -129,9 +125,10 @@ def step(self, closure=None):
129125

130126
# 1 - beta1 ** state['step']
131127
if torch.is_tensor(group['lr']):
128+
lr_safe = torch.where(group['lr'] != 0., group['lr'], torch.ones_like(group['lr']))
132129
bias_correction1 = torch.where(
133130
group['lr'] != 0.,
134-
state['exp_avg_lr_1'] / group['lr'],
131+
state['exp_avg_lr_1'] / lr_safe,
135132
torch.ones_like(group['lr']),
136133
)
137134
else:

timm/optim/nadamw.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ def __setstate__(self, state):
8787
p_state = self.state.get(p, {})
8888
if p_state and 'step' in p_state:
8989
p_state['step'] = _init_scalar(
90-
float(p_state['step']),
90+
p_state['step'],
9191
device=p.device if group['capturable'] else 'cpu',
9292
)
9393

timm/optim/rmsprop_tf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ def __setstate__(self, state):
9494
for p in group['params']:
9595
p_state = self.state.get(p, {})
9696
if p_state and 'step' in p_state:
97-
p_state['step'] = _init_scalar(float(p_state['step']), device='cpu')
97+
p_state['step'] = _init_scalar(p_state['step'], device='cpu')
9898

9999
@torch.no_grad()
100100
def step(self, closure=None):

0 commit comments

Comments
 (0)