nemo_automodel.components.optim.optimizer
nemo_automodel.components.optim.optimizer
Typed optimizer + LR scheduler configs (TorchTitan-style).
Each optimizer config is a plain dataclass exposing the full parameter surface
as named fields (no opaque **kwargs). Reading the dataclass tells you
exactly what you can configure.
Every config owns its own construction via config.build(model, ...), which
loops over model.parts and applies the per-part concerns (TP foreach,
Megatron-FSDP sharding). Subclasses only implement the small
_build_optimizer(params) hook; configs with bespoke construction needs
(e.g. MuonConfig’s Dion parameter grouping) override build directly.
build_optimizer is a thin dispatcher: it normalizes its
optimizer_config argument to an OptimizerConfig and returns
config.build(model, ...). The argument is either:
- a typed
OptimizerConfiginstance — the Automodel-native path; or - a
(name_or_path, kwargs)tuple, wherename_or_pathis a short registry name ("adam","adamw","muon", …) or a dotted import path ("torch.optim.AdamW"). It is resolved and constructed withkwargs: a typed config from its fields, or — for any other callable — the escape hatch for external integrations (e.g. veRL) viaOptimizerFromFactoryConfig.
Module Contents
Classes
Functions
Data
API
Bases: _DionConfigBase
dion.Dion2 — recommended successor to the legacy Dion optimizer.
Bases: _DionConfigBase
dion.Dion — legacy low-rank optimizer (prefer Dion2Config).
Legacy Dion takes separate replicate/outer/inner shard meshes; for FSDP2 the
resolved 1-D shard submesh maps to outer_shard_mesh.
Bases: OptimizerConfig
transformer_engine.pytorch.optimizers.FusedAdam.
LR scheduler configuration. None fields are computed by
build from the training schedule (total steps, optimizer base LR/WD).
Build one LR scheduler per optimizer.
None fields are filled from the training schedule and each
optimizer’s base LR/WD.
Parameters:
The optimizer(s) to schedule.
The step scheduler, used to derive total steps.
Returns: list[OptimizerParamScheduler]
class:OptimizerParamScheduler per optimizer.
Bases: _DionConfigBase
dion.Muon — matrix-aware update for 2D+ params, scalar fallback for 1D.
Grouped MoE experts are trained as batches of matrices. Their [expert, in, out]
storage is orthogonalized as is (Newton–Schulz is transpose-equivariant), but
dion.Muon’s spectral-norm LR scale reads the last two dims as [out, in], so
_make_optimizer folds the correct per-shape scale into those groups.
Route 3D+ weights to Muon unless flatten would merge their batch axis into each matrix.
Split a transposed [..., in, out] matrix group by shape and fold the spectral-norm scale into its LR.
dion.Muon would scale by sqrt(shape[-2] / shape[-1]), the inverse of the correct sqrt(out / in) for
this layout. Each shape gets adjust_lr=None with lr (and any lr_mult) multiplied by the correct
scale; weight_decay (and any wd_mult) is divided by it because Muon decays with lr * weight_decay.
Parameters:
Dion param group. When matrix_transposed is set, params are tensors of shape
[..., in, out] with arbitrary leading batch (expert) dimensions; DTensor shapes are global.
Returns: list[_DionParamGroup]
[group] unchanged when it is not a transposed matrix group, otherwise one group per distinct
Build dion.Muon per model part and reject batched matrices it cannot update.
dion.Muon gathers sharded matrix axes only over its own data-parallel mesh. A 3D+ weight (for example grouped
experts with 1 < ep_size < dp_size) whose matrix axis is sharded over another mesh fails at the first
step, so this raises at build time instead.
Raises:
ValueError: If a Muon-updated 3D+ DTensor has a matrix axis sharded over a mesh other than Muon’s.
Bases: _DionConfigBase
Muown: per-neuron Adam magnitudes and Dion Muon directions, including MoE.
Muown updates every expert of a grouped weight as its own matrix.
Construct Muown using the tensor-layout contract documented on Muown.
Bases: _DionConfigBase
dion.NorMuon — Muon variant with neuron-wise normalization.
Base optimizer config.
Subclasses expose their full field surface and implement
_build_optimizer, the per-part hook that constructs a single
optimizer from a list of parameters. build owns the shared
orchestration (per-part loop, TP foreach, per-group LR overrides) and is
rarely overridden — only by configs whose construction does not fit the
parameters -> optimizer shape (e.g. MuonConfig). Megatron-FSDP
optimizer sharding is no longer applied here; the recipe layer re-applies it
via shard_optimizers_for_megatron_fsdp(...).
Construct a single optimizer for params (one model part).
asdict(self) with non-constructor (grouping) fields removed.
Build one optimizer per model.parts (or [model]).
Applies the shared per-part concerns (TP foreach disabling, per-group
LR/WD overrides) and delegates the actual optimizer instantiation to
_build_optimizer. Megatron-FSDP optimizer sharding is applied by
the recipe layer, not here.
Parameters:
Model (or model with .parts) to optimize.
Device mesh used for tensor/data parallelism.
Whether the model is being trained with PEFT (suppresses the bf16 torch-Adam precision warning).
Returns: list[torch.optim.Optimizer]
One optimizer per model part.
Build one optimizer from caller-defined parameter groups.
Bases: OptimizerConfig
Build an optimizer from an arbitrary factory callable plus kwargs.
The integration escape hatch (e.g. veRL): rather than exposing typed fields,
it wraps an optimizer class/callable and the **kwargs to construct it.
This keeps the factory path on the same config.build(model, ...) contract
as the typed configs, so build_optimizer never has to special-case it.
Hyperparameters live in kwargs; the inherited lr/weight_decay
fields are unused. The factory is called as factory(params=..., **kwargs);
Dion-family optimizers (which need parameter grouping) should use the typed
MuonConfig instead. A param_group_overrides entry in
kwargs is consumed here (not forwarded to the factory) to drive
per-group LR/WD, matching the typed-config behavior.
Per-parameter-group learning-rate and weight-decay override.
Parameters whose (module-qualified) name matches pattern are placed
in their own optimizer parameter group carrying lr_mult /
wd_mult, which the LR scheduler multiplies into the group’s learning
rate and weight decay every step (see
OptimizerParamScheduler.step). This mirrors Megatron-LM’s per-group
lr_mult scaling of max_lr / min_lr.
Multiplier applied to this group’s learning rate.
Python regular expression matched against each parameter name
with re.search (so a plain substring like "router" also
works).
Multiplier applied to this group’s weight decay.
Bases: OptimizerConfig
Shared base for the dion-family typed configs (Muon / Muown / NorMuon / Dion2 / Dion).
Dion optimizers need Dion’s parameter grouping (built from the model) and the
device mesh rather than a flat parameter list, so build runs grouping
per model part. Grouping-only fields (scalar_* / *_lr and
adamw_param_patterns) are stripped from the constructor kwargs.
adamw_param_patterns selects trainable parameters for auxiliary AdamW
by regex on canonical parameter names; an empty list keeps default routing.
LR/WD overrides apply after this selection.
Dion is incompatible with Megatron-FSDP optimizer sharding; this is
enforced at the recipe layer (supports_megatron_fsdp_sharding = False
drives an allow=False sharding call that asserts rather than silently
returning an unsharded optimizer).
Whether 3D+ weights go to the matrix optimizer; Dion treats them as scalars.
Route matching trainable parameters to Dion’s auxiliary AdamW.
Parameters:
Model whose canonical parameter names are matched by regex.
Dion parameter-group dictionaries. Each params list
contains parameters of arbitrary shape, including DTensors whose
global shapes and placements are preserved.
Returns: list[dict[str, Any]]
Split parameter-group dictionaries containing the original parameters,
Split Dion’s layout groups by the first matching parameter-name rule.
Multipliers apply to the selected algorithm’s base LR/WD, including without a scheduler. Store their ratio to the matrix base for the shared scheduler, which otherwise overwrites auxiliary learning rates. Empty groups are omitted so flattened DCP loads never need to index a missing first parameter. Scheduler construction uses optimizer defaults for the matrix base LR/WD even when all matrices are overridden.
Instantiate the concrete dion optimizer from grouped params + filtered kwargs.
Bases: typing.TypedDict
Parameter group handed to a Dion-family optimizer.
params is always present. Layout groups built by
_separate_param_groups carry matrix_transposed; scalar groups
carry algorithm with their own lr, weight_decay and Adam/Lion hyperparameters.
_DionConfigBase._apply_param_group_overrides adds lr_mult / wd_mult and
MuonConfig._spectral_norm_groups sets adjust_lr.
Partition named_params into optimizer groups by name-pattern overrides.
Each parameter joins the group of the first override whose pattern matches
its name; unmatched parameters form the default group. Override groups carry
only lr_mult / wd_mult (read by OptimizerParamScheduler.step),
not a pre-scaled lr / weight_decay: every group therefore inherits the
optimizer’s base lr / weight_decay at construction, and the scheduler
(which calls step(0) on init) applies the multipliers. Keeping the stored
lr unscaled is what lets LRSchedulerConfig.build read an accurate base
LR from param_groups[0] even when the default group is empty. Empty groups
(a pattern matching nothing) are dropped with a warning.
Parameters:
(name, parameter) pairs for the trainable params of one
model part.
The per-group overrides to apply, in priority order.
Returns: list[dict[str, Any]]
A list of parameter-group dicts suitable for a torch optimizer, default
Coerce a list of dicts (as delivered by YAML) or objects into ParamGroupOverride.
Drop parameters whose rank-local shard holds zero elements.
FSDP2 shards every parameter along dim-0 across the shard group, so any
parameter with dim-0 smaller than the group — e.g. the biases, norm
weights, or class/position embeddings of a small dense vision tower
sharded over a wide mesh — leaves zero-numel local shards on the tail
ranks. TransformerEngine FusedAdam’s multi_tensor_apply kernel has no
empty-tensor guard and faults (CUDA misaligned address / illegal memory
access) at the first optimizer step. Dropping locally-empty shards is
exact, not an approximation: every element of those parameters lives on
other ranks, whose optimizers update them; this rank has nothing to do.
Parameters:
Flat list of parameters, or list of param-group dicts with a
"params" list. Parameters are plain tensors or DTensors;
a DTensor parameter carries a non-empty global shape whose
dim-0-sharded local shard may be empty on this rank.
Returns: list[Any]
params with zero-numel local shards removed. Param groups keep
Raises:
ValueError: If every parameter of the flat list — or of any single param group — is locally empty on this rank. Neither outcome has a safe representation: dropping a whole group makesoptimizer.param_groupsrank-asymmetric (LR/WD schedulers address groups positionally, e.g.param_groups[0], so ranks would silently schedule different lr/wd for shards other ranks own), while keeping an empty group breaks torch DCP’s flattened optimizer-state load, which indexes the first param of each group.
Return True if factory accepts a foreach kwarg.
torch.optim optimizers take foreach; external factories such as TE
FusedAdam do not, so passing it would raise TypeError.
Return False when TP > 1 (foreach is unsupported), else None.
Import an object from a dotted path, e.g. "torch.optim.AdamW".
Return True if factory is TransformerEngine’s FusedAdam (or a subclass).
functools.partial wrappers are unwrapped (iteratively, for nested
partials) before the identity check, so partial(FusedAdam, ...)
factories are recognized. Other wrapper callables (closures, custom
factory functions) are opaque and are NOT recognized; such factories must
guard against zero-numel local shards themselves.
Identity-based and import-free: TE is an optional dependency, so this never
imports it. If TE has not been imported yet, factory cannot be TE’s
FusedAdam class and the check is trivially False.
Number of elements of param owned by this rank.
Parameters:
Parameter tensor of arbitrary shape. For a DTensor (e.g. an
FSDP2 parameter with a dim-0 Shard placement), the global shape
may be non-empty while this rank’s local shard holds zero elements;
the local (to_local()) element count is returned. For a plain
tensor, local and global element counts coincide (numel()).
Returns: int
Element count of the rank-local shard; 0 when this rank owns no slice.
Return one model part’s trainable params, grouped by overrides when set.
Without overrides this is the flat trainable-parameter list (unchanged
behavior); with overrides it is the list of parameter-group dicts from
_build_param_groups.
Build one optimizer per model.parts (or [model]).
Thin dispatcher: it normalizes config to an OptimizerConfig and
returns config.build(model, ...). Per-part concerns (TP foreach,
Dion param grouping) live on the config. Megatron-FSDP optimizer sharding is
re-applied separately by the recipe layer.
config is one of:
- a typed
OptimizerConfiginstance — the Automodel-native path. - a
(name_or_path, kwargs)tuple, wherename_or_pathis a short registry name (seeOPTIMIZER_CONFIG_REGISTRY, e.g."adamw") or a dotted import path (e.g."torch.optim.AdamW"), andkwargsare the constructor arguments. A registry/import-path that resolves to anOptimizerConfigsubclass is built from its typed fields; any other callable is wrapped in anOptimizerFromFactoryConfig(the escape hatch for external integrations, e.g. veRL).
Parameters:
Model (or model with .parts) to optimize.
An OptimizerConfig instance or a (name_or_path, kwargs) tuple.
Device mesh used for tensor/data parallelism.
Returns: list[torch.optim.Optimizer]
One optimizer per model part.
Normalize an optimizer target plus kwargs into an OptimizerConfig.
This is the single normalization entry point shared by the recipe layer
(which resolves a YAML _target_ to a Python object) and
build_optimizer (which accepts (name_or_path, kwargs) tuples).
target is one of:
- an
OptimizerConfiginstance — returned as-is (kwargsignored, since the instance already carries its typed fields). - an
OptimizerConfigsubclass — instantiated from its typed fields with**kwargs. - a string — a registry short name (see
OPTIMIZER_CONFIG_REGISTRY, e.g."adamw") or a dotted import path (e.g."torch.optim.AdamW"); it is resolved and then handled as a subclass or callable. - any other optimizer callable/class — wrapped in an
OptimizerFromFactoryConfig(the escape hatch for external integrations, e.g. veRL).
Parameters:
The optimizer config instance/subclass, registry name or import path, or optimizer callable to normalize.
Constructor arguments for the resolved config/callable.
Returns: OptimizerConfig
class:OptimizerConfig ready to build(...).