Note that this isn't triggered in our usual Trainer.train_one_epoch pipeline, but could be encountered during direct use of TrainStepper.train_on_batch.
When a TimeLengthSchedule has no milestones (e.g., created via from_constant(n)), calling init_for_epoch(None) fails to initialize the sampler because self._epoch starts as None and the cache check self._epoch == epoch short-circuits. sample() then returns n_data_steps instead of the configured constant, silently ignoring the user's n_forward_steps setting.
A secondary consequence: after a successful init_for_epoch(k) with a valid integer epoch, a subsequent init_for_epoch(None) crashes with AssertionError because the cache check no longer short-circuits but the code unconditionally asserts epoch is not None.
Note that this isn't triggered in our usual
Trainer.train_one_epochpipeline, but could be encountered during direct use ofTrainStepper.train_on_batch.When a
TimeLengthSchedulehas no milestones (e.g., created viafrom_constant(n)), callinginit_for_epoch(None)fails to initialize the sampler becauseself._epochstarts asNoneand the cache checkself._epoch == epochshort-circuits.sample()then returnsn_data_stepsinstead of the configured constant, silently ignoring the user'sn_forward_stepssetting.A secondary consequence: after a successful
init_for_epoch(k)with a valid integer epoch, a subsequentinit_for_epoch(None)crashes withAssertionErrorbecause the cache check no longer short-circuits but the code unconditionally assertsepoch is not None.