TorchLean API

NN.Runtime.Autograd.Train.Optim

Optimizer integration for Runtime.Autograd #

This module is the training-loop side of autograd: it takes a gradient map produced by Runtime.Autograd and applies parameter updates.

PyTorch analogy:

All updates are shape checked and implemented using the pure Spec tensor operators, so they can be used in eager execution or lowered into a typed graph.

Formula ownership:

The important rule is: this file must not define a second public optimizer-formula surface. Each Optimizer.Internal.<algorithm> function below constructs the canonical optimizer state for one parameter, typed by that parameter's shape, and calls NN.Runtime.Optim.Optimizers directly. The only local algebra left here is training-loop glue that is not represented by the canonical pure states, such as coupled weight-decay preprocessing and PyTorch-style momentum dampening/Nesterov handling.

Per-parameter buffers are stored shape-erased (ParameterState) because the parameter table is heterogeneous; ParameterState.cast is the single place where the stored shape is checked against the live parameter shape.

Parameter table #

The declarations below provide the parameter registry used by the training loop.

Unlike PyTorch (where parameters are objects with identity), we use an explicit Nat id so that:

A single trainable parameter entry.

This is the Runtime.Autograd equivalent of a "parameter tensor" in PyTorch, except we make the identifier explicit (id : Nat) so we can key gradients and optimizer state in pure maps.

  • id :

    Stable identifier used to key gradients and optimizer state.

  • name : Option String

    Optional label, such as a module path; used only for reporting and debugging.

  • value : Spec.SomeTensor α

    The shape-erased parameter value.

Instances For
    @[reducible, inline]

    A flat runtime array of parameters used by the training loop.

    Instances For

      Constructors #

      Create a ParamEntry from a typed tensor.

      This is mostly a convenience for assembling a ParamTable from known-shaped tensors.

      Instances For

        Array of ids for membership checks.

        Instances For

          Find a parameter entry by id.

          Instances For

            Get a typed tensor from the table, with shape checking.

            Instances For

              Replace a parameter entry value by id.

              Instances For

                Build the set of parameter identifiers, rejecting duplicate ids.

                Optimizer buffers and gradients are keyed by id, so accepting two table entries with the same id would make both entries consume one gradient and mutate one shared optimizer state.

                Instances For

                  Scheduler wrapper #

                  Learning-rate scheduler wrapper used by the training loop.

                  PyTorch analogy: this plays the role of torch.optim.lr_scheduler.* objects, except we keep the state as an inductive value and expose a pure current/advance API.

                  The torch* constructors wrap the schedules from Optim.Scheduler.PyTorch, whose phase and step-count conventions follow PyTorch exactly where the native schedules deliberately differ.

                  Instances For

                    Read current learning rate from the scheduler state.

                    Instances For

                      Advance scheduler state by one step.

                      Instances For

                        Optimizer configuration #

                        Which optimizer update rule to apply.

                        PyTorch analogy: these correspond approximately to torch.optim.SGD, Adam, AdamW, etc.

                        Instances For

                          Optimizer hyperparameters for a subset of parameters.

                          PyTorch analogy: this is a single entry in the optimizer's param-group list (optimizer.param_groups).

                          • parameterIds : Array

                            Parameter ids that belong to this group.

                          • learningRate : α

                            Base learning rate (possibly overridden by scheduler on each step).

                          • weightDecay : α

                            $\ell_2$ regularization coefficient (behavior depends on the optimizer kind; see AdamW).

                          • momentum : α

                            Momentum factor (SGD with momentum).

                          • dampening : α

                            Dampening for momentum updates.

                          • nesterov : Bool

                            Use Nesterov variant for momentum updates.

                          • beta1 : α

                            Adam beta1 parameter (exponential decay for the first moment).

                          • beta2 : α

                            Adam beta2 parameter (exponential decay for the second moment).

                          • epsilon : α

                            Numerical stability term used by adaptive optimizers.

                          • rho : α

                            "Rho" decay parameter for RMSProp/AdaDelta style optimizers.

                          • scheduler : Option (LearningRateScheduler α)

                            Optional learning-rate scheduler for this group.

                          Instances For

                            Per-parameter optimizer buffers #

                            Optimizer buffers for one parameter of shape s.

                            Each constructor belongs to one algorithm family, so the buffers are typed by the parameter shape and there is no separate map per buffer kind. Buffers stored by a different family (for example after switching algorithm on a restored state) are treated as absent and re-initialised lazily, which is what the previous per-kind maps did implicitly.

                            Instances For

                              Shape-erased optimizer buffers for one parameter.

                              The parameter table is heterogeneous, so buffers are stored with their runtime shape and cast back to the live parameter shape by ParameterState.cast.

                              Instances For

                                Erase the shape of typed buffers.

                                Instances For

                                  Recover typed buffers for a parameter of shape s.

                                  This is the only shape cast on optimizer state. It fails when a checkpoint is reloaded into a model whose parameter id now has a different shape.

                                  Instances For

                                    Full optimizer state used by the training loop.

                                    This mirrors PyTorch's optimizer state:

                                    • a global optimizer-call counter,
                                    • hyperparameter groups, and
                                    • per-parameter buffers keyed by parameter id (Nat), including the parameter-local Adam step.
                                    • algorithm : OptimizerAlgorithm

                                      Which update rule to apply on step.

                                    • parameterGroups : Array (ParameterGroup α)

                                      Parameter groups (hyperparameters + membership).

                                    • stepCount :

                                      Global optimizer-call counter (increments once per step, including sparse steps).

                                    • parameterStates : Std.HashMap (ParameterState α)

                                      Per-parameter buffers keyed by parameter id.

                                      Adam bias correction is parameter-local: a parameter whose gradient is absent does not advance its moment step. The step lives inside ParameterBuffers.adam, so it cannot drift from the moments it corrects.

                                    Instances For

                                      A pure state snapshot for saving/restoring optimizer state.

                                      PyTorch analogy: this is the data carried by optimizer.state_dict() (modulo naming/layout). We use association lists instead of HashMap so the result is deterministic and easy to serialize.

                                      • algorithm : OptimizerAlgorithm

                                        Optimizer algorithm used to interpret the stored buffers.

                                      • stepCount :

                                        Global optimizer step at the time the snapshot was taken.

                                      • parameterGroups : Array (ParameterGroup α)

                                        Parameter groups, including scheduler state and hyperparameters.

                                      • parameterStates : Array ( × ParameterState α)

                                        Per-parameter buffers keyed by parameter id.

                                      Instances For

                                        Serialize optimizer state to a pure record.

                                        PyTorch analogy: this is the "export" step for state_dict().

                                        Instances For

                                          Restore optimizer state from a state dict.

                                          PyTorch analogy: this is the "import" step for load_state_dict(...).

                                          Instances For

                                            Number of Adam/AdamW updates applied to parameter id, if it has Adam-family buffers.

                                            Instances For

                                              Optimizer step #

                                              def Runtime.Autograd.Train.Optimizer.Internal.addWeightDecay {α : Type} [TorchLean.Storage α] [Context α] {s : Spec.Shape} (parameters gradients : TorchLean.Tensor α s) (weightDecay : α) :

                                              Add an $\ell_2$ regularization term to the gradient: $g+\operatorname{weightDecay}\,\operatorname{param}$.

                                              Note: this is the coupled weight decay used by classic SGD-style updates. For AdamW the integration step delegates to the canonical optimizer's decoupled update.

                                              Instances For

                                                Zero buffer used when a parameter has no stored state yet (PyTorch initialises lazily).

                                                Instances For
                                                  def Runtime.Autograd.Train.Optimizer.Internal.sgd {α : Type} [TorchLean.Storage α] [Context α] [DecidableRel fun (x1 x2 : α) => x1 > x2] {s : Spec.Shape} (group : ParameterGroup α) (parameters gradient : TorchLean.Tensor α s) :

                                                  Plain SGD: p - lr * (g + wd * p). Stateless.

                                                  Instances For
                                                    def Runtime.Autograd.Train.Optimizer.Internal.momentum {α : Type} [TorchLean.Storage α] [Context α] [DecidableRel fun (x1 x2 : α) => x1 > x2] {s : Spec.Shape} (group : ParameterGroup α) (buffers : Option (ParameterBuffers α s)) (parameters gradient : TorchLean.Tensor α s) :

                                                    SGD with momentum, PyTorch conventions.

                                                    The momentum buffer is initialised from the first raw (decayed) gradient; dampening is applied only once a buffer already exists. Nesterov uses g + momentum * buffer as the update direction.

                                                    Instances For

                                                      Squared-gradient accumulator shared by AdaGrad and RMSProp, or zeros when absent.

                                                      Instances For
                                                        def Runtime.Autograd.Train.Optimizer.Internal.adagrad {α : Type} [TorchLean.Storage α] [Context α] [DecidableRel fun (x1 x2 : α) => x1 > x2] {s : Spec.Shape} (group : ParameterGroup α) (buffers : Option (ParameterBuffers α s)) (parameters gradient : TorchLean.Tensor α s) :

                                                        AdaGrad with coupled weight decay.

                                                        Instances For
                                                          def Runtime.Autograd.Train.Optimizer.Internal.rmsprop {α : Type} [TorchLean.Storage α] [Context α] [DecidableRel fun (x1 x2 : α) => x1 > x2] {s : Spec.Shape} (group : ParameterGroup α) (buffers : Option (ParameterBuffers α s)) (parameters gradient : TorchLean.Tensor α s) :

                                                          RMSProp with coupled weight decay.

                                                          Instances For

                                                            Adam-family buffers (stepCount, firstMoment, secondMoment), zero-initialised when absent.

                                                            Instances For
                                                              def Runtime.Autograd.Train.Optimizer.Internal.adam {α : Type} [TorchLean.Storage α] [Context α] [DecidableRel fun (x1 x2 : α) => x1 > x2] {s : Spec.Shape} (group : ParameterGroup α) (buffers : Option (ParameterBuffers α s)) (parameters gradient : TorchLean.Tensor α s) :

                                                              Adam with coupled weight decay and parameter-local bias correction.

                                                              Instances For
                                                                def Runtime.Autograd.Train.Optimizer.Internal.adamw {α : Type} [TorchLean.Storage α] [Context α] [DecidableRel fun (x1 x2 : α) => x1 > x2] {s : Spec.Shape} (group : ParameterGroup α) (buffers : Option (ParameterBuffers α s)) (parameters gradient : TorchLean.Tensor α s) :

                                                                AdamW: decoupled weight decay handled by the canonical update, no gradient preprocessing.

                                                                Instances For
                                                                  def Runtime.Autograd.Train.Optimizer.Internal.adadelta {α : Type} [TorchLean.Storage α] [Context α] [DecidableRel fun (x1 x2 : α) => x1 > x2] {s : Spec.Shape} (group : ParameterGroup α) (buffers : Option (ParameterBuffers α s)) (parameters gradient : TorchLean.Tensor α s) :

                                                                  Adadelta with coupled weight decay.

                                                                  Instances For
                                                                    def Runtime.Autograd.Train.Optimizer.Internal.updateParameter {α : Type} [TorchLean.Storage α] [Context α] [DecidableRel fun (x1 x2 : α) => x1 > x2] {s : Spec.Shape} (algorithm : OptimizerAlgorithm) (group : ParameterGroup α) (buffers : Option (ParameterBuffers α s)) (parameters gradient : TorchLean.Tensor α s) :

                                                                    Apply the configured update rule to one parameter.

                                                                    Returns the new parameter value and the buffers to store for it (none for stateless SGD, which leaves any stored buffers untouched).

                                                                    Instances For

                                                                      Shape-check a gradient delivered as a shape-erased tensor against its parameter.

                                                                      Instances For
                                                                        def Runtime.Autograd.Train.Optimizer.Internal.advanceSchedulers {α : Type} [Context α] [DecidableRel fun (x1 x2 : α) => x1 > x2] (parameterGroups : Array (ParameterGroup α)) :

                                                                        Update each group's learning rate from its scheduler (if present) and advance the scheduler state.

                                                                        This matches the common training-loop pattern: "read LR, then call scheduler.step()".

                                                                        Instances For

                                                                          Build a map from parameter id to its ParameterGroup.

                                                                          Fails if an id appears in multiple groups (PyTorch also disallows overlapping param groups).

                                                                          Instances For

                                                                            Updated dynamic optimizer state and parameter table produced by one step.

                                                                            Instances For
                                                                              def Runtime.Autograd.Train.Optimizer.step {α : Type} [TorchLean.Storage α] [Context α] [DecidableRel fun (x1 x2 : α) => x1 > x2] (optimizerState : OptimizerState α) (parameters : ParameterTable α) (gradients : Std.HashMap (Spec.SomeTensor α)) :

                                                                              Apply one optimizer step to a parameter table.

                                                                              Inputs:

                                                                              • optimizerState is the current optimizer state (including per-parameter buffers),
                                                                              • parameters is the current parameter table,
                                                                              • gradients maps parameter ids to gradients (as produced by autograd).

                                                                              Behavior:

                                                                              • rejects duplicate parameter ids, overlapping groups, and group ids missing from the table,
                                                                              • applies learning-rate schedulers (if configured) per group,
                                                                              • shape-checks gradients and stored buffers against each parameter,
                                                                              • updates per-parameter buffers (momentum, Adam moments, and accumulators),
                                                                              • returns the updated optimizer state and an updated parameter table.

                                                                              Parameters without a gradient are left untouched, including their buffers.

                                                                              Instances For