Add min and max LR or automagic to prefent runaway edge cases.
This commit is contained in:
@@ -93,8 +93,15 @@ class Automagic3(torch.optim.Optimizer):
|
|||||||
lr : float
|
lr : float
|
||||||
Starting learning rate for every group. The controller adapts away
|
Starting learning rate for every group. The controller adapts away
|
||||||
from this in whichever direction the pooled vote points, so it is a
|
from this in whichever direction the pooled vote points, so it is a
|
||||||
launch point, not a tuned target. There are no min/max lr clamps
|
launch point, not a tuned target.
|
||||||
(only a numerical overflow guard far outside the usable range).
|
min_lr : float
|
||||||
|
Lower bound on the adapted lr (default 1e-30). At the default this is
|
||||||
|
purely a numerical overflow guard far outside the usable range; set it
|
||||||
|
higher to put a hard floor under the controller.
|
||||||
|
max_lr : float
|
||||||
|
Upper bound on the adapted lr (default 1e3). At the default this is
|
||||||
|
purely a numerical overflow guard far outside the usable range; set it
|
||||||
|
lower to put a hard ceiling on the controller.
|
||||||
beta2 : float
|
beta2 : float
|
||||||
EMA decay for the second moment, as in Adam/Adafactor.
|
EMA decay for the second moment, as in Adam/Adafactor.
|
||||||
eps : float
|
eps : float
|
||||||
@@ -172,6 +179,8 @@ class Automagic3(torch.optim.Optimizer):
|
|||||||
self,
|
self,
|
||||||
params,
|
params,
|
||||||
lr: float = 1e-6,
|
lr: float = 1e-6,
|
||||||
|
min_lr: float = 1e-8,
|
||||||
|
max_lr: float = 1e3,
|
||||||
beta2: float = 0.999,
|
beta2: float = 0.999,
|
||||||
eps: float = 1e-30,
|
eps: float = 1e-30,
|
||||||
clip_threshold: float = 1.0,
|
clip_threshold: float = 1.0,
|
||||||
@@ -179,6 +188,10 @@ class Automagic3(torch.optim.Optimizer):
|
|||||||
polarity_history: int = 8, # sign-history window length (2-64)
|
polarity_history: int = 8, # sign-history window length (2-64)
|
||||||
fused: bool = True,
|
fused: bool = True,
|
||||||
):
|
):
|
||||||
|
if min_lr > max_lr:
|
||||||
|
raise ValueError(
|
||||||
|
f"min_lr ({min_lr}) must be <= max_lr ({max_lr})"
|
||||||
|
)
|
||||||
if lr > 1e-3:
|
if lr > 1e-3:
|
||||||
# No clamping: a too-high start just oscillates immediately and
|
# No clamping: a too-high start just oscillates immediately and
|
||||||
# the controller drives it down.
|
# the controller drives it down.
|
||||||
@@ -188,6 +201,8 @@ class Automagic3(torch.optim.Optimizer):
|
|||||||
)
|
)
|
||||||
defaults = dict(
|
defaults = dict(
|
||||||
lr=lr,
|
lr=lr,
|
||||||
|
min_lr=min_lr,
|
||||||
|
max_lr=max_lr,
|
||||||
beta2=beta2,
|
beta2=beta2,
|
||||||
eps=eps,
|
eps=eps,
|
||||||
clip_threshold=clip_threshold,
|
clip_threshold=clip_threshold,
|
||||||
@@ -358,7 +373,9 @@ class Automagic3(torch.optim.Optimizer):
|
|||||||
# param rides the normal state_dict machinery and tolerates
|
# param rides the normal state_dict machinery and tolerates
|
||||||
# multi-device groups).
|
# multi-device groups).
|
||||||
state["lr"] = torch.tensor(
|
state["lr"] = torch.tensor(
|
||||||
float(group["lr"]), dtype=torch.float32, device=p.device
|
min(max(float(group["lr"]), group["min_lr"]), group["max_lr"]),
|
||||||
|
dtype=torch.float32,
|
||||||
|
device=p.device,
|
||||||
)
|
)
|
||||||
# Ring buffer of per-element update sign bits, one 1-bit-packed
|
# Ring buffer of per-element update sign bits, one 1-bit-packed
|
||||||
# plane per step (H/8 bytes per element). Sums are recomputed from
|
# plane per step (H/8 bytes per element). Sums are recomputed from
|
||||||
@@ -592,9 +609,11 @@ class Automagic3(torch.optim.Optimizer):
|
|||||||
continue
|
continue
|
||||||
lr_t = st["lr"]
|
lr_t = st["lr"]
|
||||||
f = factor if factor.device == lr_t.device else factor.to(lr_t.device)
|
f = factor if factor.device == lr_t.device else factor.to(lr_t.device)
|
||||||
# Numerical overflow guard only -- NOT a control rail
|
# Keep the adapted lr inside [min_lr, max_lr]. At the defaults
|
||||||
# (decades outside the usable range).
|
# this is a numerical overflow guard only (decades outside the
|
||||||
lr_t.mul_(f).clamp_(min=1e-30, max=1e3)
|
# usable range); tighter user-set bounds act as hard rails on
|
||||||
|
# the controller.
|
||||||
|
lr_t.mul_(f).clamp_(min=group["min_lr"], max=group["max_lr"])
|
||||||
self._group_num[gi] = None
|
self._group_num[gi] = None
|
||||||
self._group_den[gi] = None
|
self._group_den[gi] = None
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user