You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#3265 added a try/except around trainer.fit in src/gluonts/torch/model/estimator.py so that training can survive the StudentTOutput NaN ValueError described in the PR description. The current implementation (dev @ a0af774, lines 210-240) is:
try:
trainer.fit(
model=training_network,
train_dataloaders=training_data_loader,
val_dataloaders=validation_data_loader,
ckpt_path=ckpt_path,
)
exceptExceptionase:
ifcheckpoint.best_model_path=="":
logger.error("Training failed with no checkpoint available")
raiseelse:
logger.warning(
"Recovering from a checkpoint after training failed "f"with the following exception:\n{e}"
)
ifcheckpoint.best_model_path!="":
logger.info(f"Loading best model from {checkpoint.best_model_path}")
best_model=training_network.__class__.load_from_checkpoint(
checkpoint.best_model_path
)
else:
best_model=training_network
Observations
The catch is too wide.except Exception matches the targeted ValueError, but also CUDA OOM (torch.cuda.OutOfMemoryError), disk-full errors from dataloader checkpoints, shape mismatches from mis-configured user features, pickling failures, and Lightning's own MisconfigurationException. After any of these the training log shows a single WARNING and the function returns a stale checkpoint from a much earlier epoch, which users then evaluate and possibly promote to production. The failure signal that should have been a hard stop becomes a silent accuracy regression.
The original traceback is discarded.e is formatted with f\"{e}\", so only the exception's args are logged. Users lose the file/line/frames they need to decide whether the exception was NaN-loss (fine to recover from) or a real bug. logger.exception(...) or logger.warning(..., exc_info=True) both preserve the stack.
Recovery restores only model weights.training_network.__class__.load_from_checkpoint(...) rebuilds the module state dict; it does not restore the optimizer, LR scheduler, RNG, or dataloader iterator. For a short run that is fine — but the warning message does not say so, and users reading "recovering from a checkpoint" reasonably expect the full training state. A longer-running pipeline that wraps train(...) and then continues with additional gradient steps will silently diverge from a run that never hit the exception.
No retry / attempt counter. Nothing prevents a user from wrapping train(...) in their own retry loop and silently burning through N failed runs, each of which recovers from the very first checkpoint and reports success.
Suggested direction
Narrow the catch to the exceptions this code was designed to recover from. (ValueError, RuntimeError) covers both the NaN-loss ValueError described in Recover from a checkpoint if training failed with an exception #3265 and the "Expected parameter ... to satisfy the constraint" RuntimeError variant that PyTorch sometimes raises instead. Let torch.cuda.OutOfMemoryError, KeyboardInterrupt, SystemExit, and Lightning's MisconfigurationException propagate.
Log with logger.exception(...) / exc_info=True so the traceback lives in the log.
If full trainer state is worth restoring, Lightning already does it: instead of load_from_checkpoint after the catch, pass ckpt_path=checkpoint.best_model_path on a re-trainer.fit(...) call. If that is out of scope, at minimum document (in the warning message and the estimator docstring) that only weights are restored.
Consider an optional max_recoveries knob — default 1 — so a flapping training is surfaced to the user by the second failure instead of silently truncating every attempt.
I am happy to send a PR if the direction above is agreeable; I wanted to open the issue first since the trade-off around "narrow the catch vs. keep the safety net wide" is a design call for the maintainers.
Context
#3265 added a try/except around
trainer.fitinsrc/gluonts/torch/model/estimator.pyso that training can survive theStudentTOutputNaNValueErrordescribed in the PR description. The current implementation (dev @ a0af774, lines 210-240) is:Observations
The catch is too wide.
except Exceptionmatches the targetedValueError, but also CUDA OOM (torch.cuda.OutOfMemoryError), disk-full errors from dataloader checkpoints, shape mismatches from mis-configured user features, pickling failures, and Lightning's ownMisconfigurationException. After any of these the training log shows a single WARNING and the function returns a stale checkpoint from a much earlier epoch, which users then evaluate and possibly promote to production. The failure signal that should have been a hard stop becomes a silent accuracy regression.The original traceback is discarded.
eis formatted withf\"{e}\", so only the exception'sargsare logged. Users lose the file/line/frames they need to decide whether the exception was NaN-loss (fine to recover from) or a real bug.logger.exception(...)orlogger.warning(..., exc_info=True)both preserve the stack.Recovery restores only model weights.
training_network.__class__.load_from_checkpoint(...)rebuilds the module state dict; it does not restore the optimizer, LR scheduler, RNG, or dataloader iterator. For a short run that is fine — but the warning message does not say so, and users reading "recovering from a checkpoint" reasonably expect the full training state. A longer-running pipeline that wrapstrain(...)and then continues with additional gradient steps will silently diverge from a run that never hit the exception.No retry / attempt counter. Nothing prevents a user from wrapping
train(...)in their own retry loop and silently burning through N failed runs, each of which recovers from the very first checkpoint and reports success.Suggested direction
(ValueError, RuntimeError)covers both the NaN-lossValueErrordescribed in Recover from a checkpoint if training failed with an exception #3265 and the "Expected parameter ... to satisfy the constraint"RuntimeErrorvariant that PyTorch sometimes raises instead. Lettorch.cuda.OutOfMemoryError,KeyboardInterrupt,SystemExit, and Lightning'sMisconfigurationExceptionpropagate.logger.exception(...)/exc_info=Trueso the traceback lives in the log.load_from_checkpointafter the catch, passckpt_path=checkpoint.best_model_pathon a re-trainer.fit(...)call. If that is out of scope, at minimum document (in the warning message and the estimator docstring) that only weights are restored.max_recoveriesknob — default 1 — so a flapping training is surfaced to the user by the second failure instead of silently truncating every attempt.I am happy to send a PR if the direction above is agreeable; I wanted to open the issue first since the trade-off around "narrow the catch vs. keep the safety net wide" is a design call for the maintainers.