Optimizers¶
The batched optimizers of the candidate fit, selected by
train.optimizer.name and configured by train.optimizer.optimizer_params.
See Optimizers.
BaseOptimizer
¶
BaseOptimizer(shared_param_names: Iterable[str], lr: LRLike, clip_value: float | None = None, clip_norm: float | None = None, shared_param_lr_multiplier: float = 1.0)
Bases: ABC
Base class of the ensemble-batched optimizers.
Every parameter tensor carries the candidate ensemble on its leading
dimension, one row per candidate neuron, and a subclass's step updates
all rows at once. Parameters named in shared_param_names have no
ensemble dimension; the subclasses update them once per step from the
gradient averaged over the active members, at the mean of those members'
learning rates times shared_param_lr_multiplier.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
shared_param_names
|
iterable of str
|
Names of the parameters shared by every ensemble member. |
required |
lr
|
float or (ensemble_size,) tensor
|
Learning rate, one per member when a tensor. |
required |
clip_value
|
float
|
Clamp every gradient element to [-clip_value, clip_value]. |
None
|
clip_norm
|
float
|
Rescale each member's gradient to at most this L2 norm. |
None
|
shared_param_lr_multiplier
|
float
|
Factor on the learning rate of the shared parameters. Default 1.0. |
1.0
|
state_dict
¶
Return the optimizer state as a dict; implemented by subclasses.
load_state_dict
¶
Restore the state written by state_dict; implemented by subclasses.
gradient_clipping
¶
Clip a batched gradient by value, then by per-member norm.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
g
|
(B, ...) tensor
|
Gradient with the ensemble on the leading dimension. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
g |
(B, ...) tensor
|
|
BatchedLBFGS
¶
BatchedLBFGS(params: dict[str, Tensor], shared_param_names: Iterable[str], lr: LRLike, history_size: int = 10, clip_value: float | None = None, clip_norm: float | None = None, shared_param_lr_multiplier: float = 1.0, max_step: float | None = 1.0, curvature_eps: float | None = 1e-08)
Bases: BaseOptimizer
Limited-memory BFGS, batched over the candidate ensemble.
Each member keeps its own history of the last history_size correction
pairs s = delta theta, y = delta g per parameter tensor. The two-loop
recursion turns the clipped gradient into a quasi-Newton direction
d ~ H^-1 g, and the step is
theta = theta - lr*d
with no line search. A pair is stored only if it passes the curvature
condition (curvature_eps), and each member's update of a parameter
tensor is capped at norm max_step. Members with active_mask False in
step keep their parameters and store no pair. Shared parameters keep
one history, driven by the gradient averaged over the active members.
stats counts steps, pairs, rejected pairs, updates and capped updates
for the trainer's log.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
params
|
dict of str -> (B, ...) tensor
|
Initial parameters. |
required |
shared_param_names
|
iterable of str
|
See |
required |
lr
|
float or (B,) tensor
|
See |
required |
clip_value
|
float or None
|
See |
None
|
clip_norm
|
float or None
|
See |
None
|
shared_param_lr_multiplier
|
float
|
See |
1.0
|
history_size
|
int
|
Correction pairs kept per member. Default 10. |
10
|
max_step
|
float or None
|
Cap on the norm of one member's update of one parameter tensor, in parameter units (a crude trust region); None for no cap. Default 1.0. |
1.0
|
curvature_eps
|
float or None
|
Store a pair only if y.s > curvature_eps|s||y| (the BFGS curvature condition, with the standard skipping rule); None stores every pair with s != 0. Default 1e-8. |
1e-08
|
Notes
Why the two guards. The two-loop recursion scales its direction by s.y / y.y and takes a fixed step. On a direction whose gradient and curvature vanish together (an RBF bump losing its mass) that scale is a ratio of two vanishing numbers and the step does not shrink with the gradient: one step can throw centres tens of standard units off the data. A pair with y.s <= 0 makes the inverse-Hessian estimate indefinite and the direction can point uphill. The cap bounds the damage of any single step; the curvature test keeps the estimate positive definite. Neither changes a well-conditioned convex fit (the polynomial families) beyond its first steps.
Storage. For the batched (per-member) parameters the correction
history is a pair of tensors s_hist[k], y_hist[k] of shape
(B, history_size, P) plus a per-member fill count hist_count[k]; the
newest pair sits in the last slot and the valid slots are the last
hist_count ones. The two-loop recursion runs as history_size
batched operations over the whole ensemble instead of a Python loop
over its members. Shared parameters keep a single deque history and
the single-vector recursion.
step
¶
step(params: dict[str, Tensor], grads: dict[str, Tensor], active_mask: Tensor | None = None) -> dict[str, torch.Tensor]
Take one optimizer step for every active member.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
params
|
dict of str -> (B, ...) tensor
|
Current parameters, with the members on the leading dimension. |
required |
grads
|
dict of str -> (B, ...) tensor
|
Their gradients, with the same keys and shapes. |
required |
active_mask
|
(B,) bool tensor
|
True for the members that step; None steps every member. |
None
|
Returns:
| Type | Description |
|---|---|
dict of str -> (B, ...) tensor
|
The new parameters, with the same keys and shapes. |
state_dict
¶
Snapshot of curvature history + prev params/grads + lr so a resumed run keeps the L-BFGS approximation rather than starting from identity.
load_state_dict
¶
Restore the state written by state_dict; every field must be present.
Shared parameters get their single deque history back; batched ones
their (B, history_size, P) correction tensors and per-member fill
counts.
BatchedAdam
¶
BatchedAdam(params: dict[str, Tensor], shared_param_names: Iterable[str], lr: LRLike, betas: tuple[float, float] = (0.9, 0.999), eps: float = 1e-08, clip_value: float | None = None, clip_norm: float | None = None, shared_param_lr_multiplier: float = 1.0)
Bases: BaseOptimizer
Adam, batched over the candidate ensemble.
Per member and parameter tensor, with g the clipped gradient and t the step count (shared by all members):
m = b1*m + (1 - b1)*g, v = b2*v + (1 - b2)*g^2
theta = theta - lr * m_hat / (sqrt(v_hat) + eps)
m_hat = m / (1 - b1^t), v_hat = v / (1 - b2^t)
Members with active_mask False in step keep their parameters; their
moment buffers still advance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
params
|
dict of str -> (B, ...) tensor
|
Initial parameters; they set the shapes of the moment buffers. |
required |
shared_param_names
|
iterable of str
|
See |
required |
lr
|
float or (B,) tensor
|
See |
required |
clip_value
|
float or None
|
See |
None
|
clip_norm
|
float or None
|
See |
None
|
shared_param_lr_multiplier
|
float
|
See |
1.0
|
betas
|
(float, float)
|
Decay rates b1, b2 of the moment estimates. Default (0.9, 0.999). |
(0.9, 0.999)
|
eps
|
float
|
Added to sqrt(v_hat) in the denominator. Default 1e-8. |
1e-08
|
step
¶
step(params: dict[str, Tensor], grads: dict[str, Tensor], active_mask: Tensor | None = None, b: Any = None) -> dict[str, torch.Tensor]
Take one optimizer step for every active member.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
params
|
dict of str -> (B, ...) tensor
|
Current parameters, with the members on the leading dimension. |
required |
grads
|
dict of str -> (B, ...) tensor
|
Their gradients, with the same keys and shapes. |
required |
active_mask
|
(B,) bool tensor
|
True for the members that step; None steps every member. |
None
|
b
|
any
|
Not used. |
None
|
Returns:
| Type | Description |
|---|---|
dict of str -> (B, ...) tensor
|
The new parameters, with the same keys and shapes. |
state_dict
¶
Return lr, betas, eps, the moment buffers, the step count and the shared-parameter settings.
load_state_dict
¶
Restore the state written by state_dict; every field must be present.
BatchedSGD
¶
BatchedSGD(params: dict[str, Tensor], shared_param_names: Iterable[str], lr: LRLike, momentum: float = 0.9, weight_decay: float = 0.0, nesterov: bool = True, clip_value: float | None = None, clip_norm: float | None = None, shared_param_lr_multiplier: float = 1.0)
Bases: BaseOptimizer
SGD with momentum, batched over the candidate ensemble.
Per member and parameter tensor, with g the gradient plus
weight_decay*theta, then clipped:
v = momentum*v + g
theta = theta - lr*(momentum*v + g) (nesterov=True)
theta = theta - lr*v (nesterov=False)
Members with active_mask False in step keep their parameters; their
momentum buffer still advances.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
params
|
dict of str -> (B, ...) tensor
|
Initial parameters; they set the shapes of the momentum buffers. |
required |
shared_param_names
|
iterable of str
|
See |
required |
lr
|
float or (B,) tensor
|
See |
required |
clip_value
|
float or None
|
See |
None
|
clip_norm
|
float or None
|
See |
None
|
shared_param_lr_multiplier
|
float
|
See |
1.0
|
momentum
|
float
|
Momentum coefficient. Default 0.9. |
0.9
|
weight_decay
|
float
|
L2 penalty added to the gradient (coupled, not decoupled). Default 0.0. |
0.0
|
nesterov
|
bool
|
Use the Nesterov form of the update. Default True. |
True
|
step
¶
step(params: dict[str, Tensor], grads: dict[str, Tensor], active_mask: Tensor | None = None) -> dict[str, torch.Tensor]
Take one optimizer step for every active member.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
params
|
dict of str -> (B, ...) tensor
|
Current parameters, with the members on the leading dimension. |
required |
grads
|
dict of str -> (B, ...) tensor
|
Their gradients, with the same keys and shapes. |
required |
active_mask
|
(B,) bool tensor
|
True for the members that step; None steps every member. |
None
|
Returns:
| Type | Description |
|---|---|
dict of str -> (B, ...) tensor
|
The new parameters, with the same keys and shapes. |
state_dict
¶
Return lr, weight decay, the momentum settings and buffers, and the shared-parameter settings.
load_state_dict
¶
Restore the state written by state_dict; every field must be present.