nvalchemi.training.hooks.TrainingUpdateHook#
- class nvalchemi.training.hooks.TrainingUpdateHook[source]#
Base class for hooks that customize training-update phases.
Subclasses override
__call__()and dispatch onstageto handle one or more claimed stages:BEFORE_BATCH,DO_BACKWARD,DO_OPTIMIZER_STEP,AFTER_OPTIMIZER_STEP. Compose via+to build aTrainingUpdateOrchestrator. See Training update hooks for the stage contract and restrictions each update hook must follow.- priority#
Dispatch order within an orchestrator; lower runs first. Canonical buckets: 10 = gradient accumulation, 20 = mixed precision, 30 = gradient clipping, 40 = spike skipping. Default 50.
- Type:
int
- _exclusive_update_key#
Optional key for hook families that must appear at most once inside an orchestrator.
- Type:
str | None
Notes
TrainingUpdateHookis NOT directly compatible with the standardHookProtocol – its__call__signature includes awill_skipargument and returns(bool, torch.Tensor | None)rather than the Protocol’s__call__(ctx, stage) -> None. This is intentional:Hookis a structural Protocol so domain-specific hook families can use signatures suited to their semantics. Bare instances must be composed via+or wrapped by aTrainingUpdateOrchestrator(the strategy auto-wraps lone hooks); the orchestrator owns Protocol compliance.will_skipis a stage-local cumulative veto signal. It isTruewhen an earlier, higher-priority hook has already requested that the current stage’s gated operation be skipped. The orchestrator still calls later hooks after a veto so they can observe the decision, update bookkeeping, or emit diagnostics, but those hooks should avoid side effects that assume the gated operation will run. A hook may also returnFalseto veto the operation for lower-priority hooks.This signal is intended for composable pipeline behavior. For example, a gradient-accumulation hook can veto
DO_OPTIMIZER_STEPon non-step microbatches; later hooks then receivewill_skip=Trueand can skip work such as gradient clipping, scaler updates, or expensive parameter scans.will_skipis reset for each stage dispatch and should not be interpreted as a global training-step status unless the orchestrator also records that state onctx.Each
__call__returns(proceed, loss):proceedis a strictbool(int/NoneraiseTypeError). OnBEFORE_BATCHandDO_OPTIMIZER_STEPthe orchestrator applies any-veto-wins composition: if any hook returnsFalsethe gated operation (zero_gradientsoroptimizer/scheduler.step) is skipped. OnDO_BACKWARDandAFTER_OPTIMIZER_STEPthe value is unused; returnTrue.lossis the loss tensor the hook would use, transformed or not. Default isctx.lossunchanged. The orchestrator threads it through hooks in priority order duringDO_BACKWARDso each hook sees its predecessor’s transform;backward()runs once on the final loss. Hooks that run on stages other thanDO_BACKWARDmay returnNoneforlossbecause the orchestrator ignores it there.
Examples
>>> import torch >>> from nvalchemi.training._stages import TrainingStage >>> class ClipGrads(TrainingUpdateHook): ... priority = 30 ... def __init__(self, max_norm): ... self.max_norm = max_norm ... def __call__(self, ctx, stage, will_skip): ... match stage: ... case TrainingStage.DO_OPTIMIZER_STEP: ... if not will_skip: ... for opt in ctx.optimizers: ... params = (p for g in opt.param_groups for p in g["params"]) ... torch.nn.utils.clip_grad_norm_(params, self.max_norm) ... return True, ctx.loss ... case _: ... return True, ctx.loss