Callbacks¤
substrax.callbacks holds the training-callback protocol and metric-driven early
stopping, in two shapes:
EarlyStoppingfor a loop that feeds it one validation value per epoch and asksshould_stop;EarlyStoppingCallbackfor a trainer that drivesTrainingCallbackhooks and reads the metric from the epoch's logs.
EarlyStopping keeps its counters in a BestMetricTracker; EarlyStoppingCallback applies
an EarlyStopping to the logged metric and adds the goal and divergence thresholds and the
non-finite check. patience is at least 1: patience counts epochs without improvement, so an
improving epoch never stops training.
from substrax.callbacks import EarlyStopping, EarlyStoppingCallback, EarlyStoppingConfig
stopper = EarlyStopping(patience=3, min_delta=1e-3)
for epoch in range(epochs):
stopper.update(validate())
if stopper.should_stop:
break
callback = EarlyStoppingCallback(EarlyStoppingConfig(monitor="val_loss", patience=10))
Learning-rate decay on a plateau is not here: use optax.contrib.reduce_on_plateau.
Resuming a run¤
BestMetricTracker, EarlyStopping, EarlyStoppingCallback and CallbackList satisfy
substrax.typing.Checkpointable: get_state() returns their bookkeeping as a dictionary a
checkpoint store writes, and set_state() on objects built the same way continues where the
saved ones stood, so a resumed run stops at the epoch the uninterrupted run would have.
CallbackList keeps each stateful callback's state under its position, skips callbacks without
state, and refuses a state saved from a list whose stateful callbacks stood elsewhere.
from substrax.callbacks import CallbackList
from substrax.checkpoint import OrbaxCheckpointStore
callbacks = CallbackList([EarlyStoppingCallback(EarlyStoppingConfig(patience=10))])
with OrbaxCheckpointStore(directory) as store:
store.save(step, {"extensions": {"callbacks": callbacks.get_state()}})
callbacks.set_state(store.restore(step).items["extensions"]["callbacks"])
substrax.callbacks
¤
Training callbacks, best-metric tracking and early stopping.
BaseCallback
¤
No-op implementation of every hook; subclasses override what they need.
on_train_begin(_trainer)
¤
Called once before the first epoch.
on_train_end(_trainer)
¤
Called once after the last epoch.
on_epoch_begin(_trainer, _epoch)
¤
Called before each epoch.
on_epoch_end(_trainer, _epoch, _logs)
¤
Called after each epoch with that epoch's metrics.
on_batch_begin(_trainer, _batch)
¤
Called before each batch.
on_batch_end(_trainer, _batch, _logs)
¤
Called after each batch with that batch's metrics.
on_validation_begin(_trainer)
¤
Called before a validation pass.
on_validation_end(_trainer, _logs)
¤
Called after a validation pass with its metrics.
CallbackList(callbacks=None)
¤
Dispatches every hook to its callbacks in registration order.
Wrap an initial set of callbacks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
callbacks
|
Iterable[TrainingCallback] | None
|
The callbacks to start with; each receives every hook, in this order. |
None
|
add(callback)
¤
Append a callback.
remove(callback)
¤
Remove a callback; raises ValueError if it was never added.
__len__()
¤
The number of callbacks.
__iter__()
¤
Iterate over the callbacks in dispatch order.
get_state()
¤
Every stateful callback's state, for a checkpoint.
Returns:
| Name | Type | Description |
|---|---|---|
Each |
CheckpointState
|
class: |
CheckpointState
|
in dispatch order; callbacks without state are skipped. |
set_state(state)
¤
Take back a state :meth:get_state returned, into a list built the same way.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
state
|
CheckpointState
|
Each stateful callback's saved state, by position. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the stateful callbacks do not stand at the saved positions. |
on_train_begin(trainer)
¤
Dispatch on_train_begin.
on_train_end(trainer)
¤
Dispatch on_train_end.
on_epoch_begin(trainer, epoch)
¤
Dispatch on_epoch_begin.
on_epoch_end(trainer, epoch, logs)
¤
Dispatch on_epoch_end.
on_batch_begin(trainer, batch)
¤
Dispatch on_batch_begin.
on_batch_end(trainer, batch, logs)
¤
Dispatch on_batch_end.
on_validation_begin(trainer)
¤
Dispatch on_validation_begin.
on_validation_end(trainer, logs)
¤
Dispatch on_validation_end.
TrainerLike
¤
Bases: Protocol
What a callback may ask of the trainer that drives it.
model
property
¤
The model being trained.
TrainingCallback
¤
Bases: Protocol
Lifecycle hooks a training loop fires; implement any subset via BaseCallback.
Parameters are positional-only so implementations may name them as they like.
on_train_begin(trainer)
¤
Called once before the first epoch.
on_train_end(trainer)
¤
Called once after the last epoch.
on_epoch_begin(trainer, epoch)
¤
Called before each epoch.
on_epoch_end(trainer, epoch, logs)
¤
Called after each epoch with that epoch's metrics.
on_batch_begin(trainer, batch)
¤
Called before each batch.
on_batch_end(trainer, batch, logs)
¤
Called after each batch with that batch's metrics.
on_validation_begin(trainer)
¤
Called before a validation pass.
on_validation_end(trainer, logs)
¤
Called after a validation pass with its metrics.
EarlyStoppingCallback(config)
¤
Bases: BaseCallback
Stop training when a monitored metric stops improving.
Initialize early stopping callback.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
EarlyStoppingConfig
|
Early stopping configuration. |
required |
wait_count
property
¤
Epochs since the last improvement.
best_score
property
¤
The best monitored value so far, or None before the metric first appears.
stopped_epoch
property
¤
The epoch at which stopping was decided, if it has been.
should_stop
property
¤
Whether training should stop.
on_epoch_end(_trainer, epoch, logs)
¤
Read the monitored metric, if present, and decide whether to stop.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
_trainer
|
TrainerLike
|
The trainer instance (unused). |
required |
epoch
|
int
|
Current epoch number. |
required |
logs
|
dict[str, Any]
|
Dictionary of metrics from this epoch. |
required |
get_state()
¤
The stopper's state and the stopping epoch, for a checkpoint.
Returns:
| Type | Description |
|---|---|
CheckpointState
|
|
CheckpointState
|
( |
set_state(state)
¤
Take back a state :meth:get_state returned.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
state
|
CheckpointState
|
The saved stopper state and stopping epoch. |
required |
EarlyStoppingConfig(*, monitor='val_loss', min_delta=0.0, patience=10, mode='min', check_finite=True, stopping_threshold=None, divergence_threshold=None)
dataclass
¤
Configuration for early stopping.
Attributes:
| Name | Type | Description |
|---|---|---|
monitor |
str
|
Metric name to monitor (e.g., "val_loss", "accuracy"). |
min_delta |
float
|
Minimum change to qualify as an improvement. |
patience |
int
|
Number of epochs with no improvement before stopping. |
mode |
Literal['min', 'max']
|
"min" if lower is better, "max" if higher is better. |
check_finite |
bool
|
If True, stop when metric becomes NaN or Inf. |
stopping_threshold |
float | None
|
Stop immediately when metric reaches this value. |
divergence_threshold |
float | None
|
Stop if metric exceeds this value (min mode only). |
__post_init__()
¤
Refuse a patience below one, which would stop on an improving epoch.
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
BestMetricTracker(*, mode, min_delta)
¤
Shared best-so-far + stagnation bookkeeping for the plateau callbacks.
Tracks the best monitored value and the number of consecutive updates without
a min_delta improvement, in either "min" or "max" mode.
Initialise the tracker.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mode
|
PlateauMode | str
|
|
required |
min_delta
|
float
|
Minimum absolute change counted as an improvement. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
mode
property
¤
The improvement direction.
best
property
¤
The best monitored value seen so far.
num_bad_epochs
property
¤
Consecutive updates without a min_delta improvement.
register(value)
¤
Record value; return True if it improves on the best so far.
Updates the best value and resets the stagnation counter on an improvement; otherwise increments the stagnation counter.
get_state()
¤
The best value and the stagnation count, for a checkpoint.
Returns:
| Type | Description |
|---|---|
CheckpointState
|
|
set_state(state)
¤
Take back a state :meth:get_state returned.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
state
|
CheckpointState
|
The saved best value and stagnation count. |
required |
EarlyStopping(*, patience, min_delta=0.0, mode=PlateauMode.MIN)
¤
Bases: BestMetricTracker
Signal to stop once a monitored metric stops improving.
Initialise the stopper.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
patience
|
int
|
Epochs without a |
required |
min_delta
|
float
|
Minimum absolute change counted as an improvement. |
0.0
|
mode
|
PlateauMode | str
|
|
MIN
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
PlateauMode
¤
Bases: StrEnum
Whether a monitored metric improves by decreasing or increasing.