Skip to content

Commit a4e9c9a

Browse files
RecML authorsrecml authors
authored andcommitted
Internal change
PiperOrigin-RevId: 940694716
1 parent 8e8b05b commit a4e9c9a

4 files changed

Lines changed: 1252 additions & 69 deletions

File tree

recml/core/training/keras_trainer.py

Lines changed: 63 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,32 @@ def __init__(
122122
max_checkpoints_to_keep: int = 5,
123123
checkpoint_save_interval_epochs: int = 1,
124124
rng_seed: int = core.DEFAULT_RNG_SEED,
125-
legacy_checkpoint_format: bool = True,
125+
checkpoint_version: keras_utils.CheckpointVersion | str = "v2",
126+
legacy_checkpoint_format: bool | None = None,
126127
):
127-
"""Initializes the instance."""
128+
"""Initializes the instance.
129+
130+
Args:
131+
distribution: The distribution strategy to use.
132+
model_dir: The directory to save checkpoints and logs.
133+
train_steps: Total number of training steps.
134+
steps_per_eval: Number of steps between evaluations.
135+
continuous_eval_timeout: Timeout for continuous evaluation.
136+
steps_per_loop: Number of steps per training loop.
137+
max_checkpoints_to_keep: Maximum number of checkpoints to keep.
138+
checkpoint_save_interval_epochs: Interval in epochs to save checkpoints.
139+
rng_seed: Random seed.
140+
checkpoint_version: The checkpoint version to use. Supported versions:
141+
"v1" (legacy V1), "v2" (V2, default), "v3" (V3).
142+
legacy_checkpoint_format: Deprecated. Use checkpoint_version instead. If
143+
set, True maps to V1, and False maps to V2. TODO(b/542602169): Remove
144+
this in v2.
145+
resume_training_launcher: Launcher to resume training.
146+
enable_xmanager_measurements: Whether to enable XManager measurements.
147+
enable_autoxprof: Whether to enable AutoXprof.
148+
autoxprof_settings: Settings for AutoXprof.
149+
s2_logging_settings: Settings for S2 logging.
150+
"""
128151

129152
keras.utils.set_random_seed(rng_seed)
130153

@@ -153,25 +176,42 @@ def __init__(
153176
self._checkpoint_dir = os.path.join(model_dir, core.CHECKPOINT_DIR)
154177
self._max_checkpoints_to_keep = max_checkpoints_to_keep
155178
self._checkpoint_save_interval_epochs = checkpoint_save_interval_epochs
156-
self._legacy_checkpoint_format = legacy_checkpoint_format
179+
if legacy_checkpoint_format is not None:
180+
logging.warning(
181+
"legacy_checkpoint_format is deprecated, use checkpoint_version"
182+
" instead."
183+
)
184+
self._checkpoint_version = (
185+
keras_utils.CheckpointVersion.V1
186+
if legacy_checkpoint_format
187+
else keras_utils.CheckpointVersion.V2
188+
)
189+
else:
190+
self._checkpoint_version = keras_utils.CheckpointVersion(
191+
checkpoint_version
192+
)
157193

158194
@functools.cached_property
159195
def train_callbacks(self) -> list[keras.callbacks.Callback]:
160196
"""Returns the training callbacks."""
161197
if keras.backend.backend() == "jax":
162-
if self._legacy_checkpoint_format:
163-
checkpoint_manager = keras_utils.KerasOrbaxCheckpointManager(
164-
checkpoint_dir=self._checkpoint_dir,
165-
max_to_keep=self._max_checkpoints_to_keep,
166-
save_interval_epochs=self._checkpoint_save_interval_epochs,
167-
)
198+
if self._checkpoint_version == keras_utils.CheckpointVersion.V1:
199+
manager_cls = keras_utils.KerasOrbaxCheckpointManager
200+
elif self._checkpoint_version == keras_utils.CheckpointVersion.V2:
201+
manager_cls = keras_utils.KerasOrbaxCheckpointManagerV2
202+
elif self._checkpoint_version == keras_utils.CheckpointVersion.V3:
203+
manager_cls = keras_utils.KerasOrbaxCheckpointManagerV3
168204
else:
169-
checkpoint_manager = keras_utils.KerasOrbaxCheckpointManagerV2(
170-
checkpoint_dir=self._checkpoint_dir,
171-
max_to_keep=self._max_checkpoints_to_keep,
172-
save_interval_epochs=self._checkpoint_save_interval_epochs,
205+
raise ValueError(
206+
f"Unsupported checkpoint version: {self._checkpoint_version}"
173207
)
174208

209+
checkpoint_manager = manager_cls(
210+
checkpoint_dir=self._checkpoint_dir,
211+
max_to_keep=self._max_checkpoints_to_keep,
212+
save_interval_epochs=self._checkpoint_save_interval_epochs,
213+
)
214+
175215
callbacks = [
176216
keras_utils.EpochSummaryCallback(
177217
log_dir=os.path.join(self._model_dir, core.LOG_DIR),
@@ -379,7 +419,7 @@ def timeout_fn() -> bool:
379419
else:
380420
steps_msg = "running complete evaluation..."
381421

382-
use_legacy_checkpoint_format = self._legacy_checkpoint_format
422+
checkpoint_version = self._checkpoint_version
383423

384424
class _RestoreCallback(keras.callbacks.Callback):
385425
"""Callback for restoring the model from the latest checkpoint."""
@@ -393,14 +433,21 @@ def __init__(
393433
self._epoch = epoch
394434

395435
def on_test_begin(self, logs: Mapping[str, Any] | None = None):
396-
if use_legacy_checkpoint_format:
436+
if checkpoint_version == keras_utils.CheckpointVersion.V1:
397437
keras_utils.restore_keras_model(
398438
model, self._checkpoint_dir, step=self._epoch
399439
)
400-
else:
440+
elif checkpoint_version in (
441+
keras_utils.CheckpointVersion.V2,
442+
keras_utils.CheckpointVersion.V3,
443+
):
401444
keras_utils.restore_keras_checkpoint(
402445
self._checkpoint_dir, model=model, epoch=self._epoch
403446
)
447+
else:
448+
raise ValueError(
449+
f"Unsupported checkpoint version: {checkpoint_version}"
450+
)
404451

405452
history = None
406453
for epoch in ocp.checkpoint_utils.checkpoints_iterator(

recml/core/training/keras_trainer_test.py

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class KerasTrainerTest(parameterized.TestCase):
5555

5656
def setUp(self):
5757
super().setUp()
58+
keras.backend.clear_session()
5859
# Workaround to make `create_tempdir` work with pytest.
5960
if not flags.FLAGS.is_parsed():
6061
flags.FLAGS.mark_as_parsed()
@@ -63,26 +64,38 @@ def setUp(self):
6364
{"testcase_name": "train", "mode": core.Trainer.Mode.TRAIN},
6465
{"testcase_name": "eval", "mode": core.Trainer.Mode.EVAL},
6566
{
66-
"testcase_name": "train_and_eval",
67+
"testcase_name": "train_and_eval_v3",
6768
"mode": core.Trainer.Mode.TRAIN_AND_EVAL,
69+
"checkpoint_version": "v3",
6870
},
6971
{
70-
"testcase_name": "continuous_eval_",
71-
"mode": core.Trainer.Mode.CONTINUOUS_EVAL,
72+
"testcase_name": "train_and_eval_v2",
73+
"mode": core.Trainer.Mode.TRAIN_AND_EVAL,
74+
"checkpoint_version": "v2",
7275
},
7376
{
74-
"testcase_name": "train_and_eval_legacy_checkpoint_format",
77+
"testcase_name": "train_and_eval_v1",
7578
"mode": core.Trainer.Mode.TRAIN_AND_EVAL,
76-
"legacy_checkpoint_format": True,
79+
"checkpoint_version": "v1",
80+
},
81+
{
82+
"testcase_name": "continuous_eval_v3",
83+
"mode": core.Trainer.Mode.CONTINUOUS_EVAL,
84+
"checkpoint_version": "v3",
85+
},
86+
{
87+
"testcase_name": "continuous_eval_v2",
88+
"mode": core.Trainer.Mode.CONTINUOUS_EVAL,
89+
"checkpoint_version": "v2",
7790
},
7891
{
79-
"testcase_name": "continuous_eval_legacy_checkpoint_format",
92+
"testcase_name": "continuous_eval_v1",
8093
"mode": core.Trainer.Mode.CONTINUOUS_EVAL,
81-
"legacy_checkpoint_format": True,
94+
"checkpoint_version": "v1",
8295
},
8396
)
8497
def test_keras_task_and_trainer(
85-
self, mode: str, legacy_checkpoint_format: bool = False
98+
self, mode: str, checkpoint_version: str = "v3"
8699
):
87100
if keras.backend.backend() == "jax":
88101
distribution = keras.distribution.DataParallel()
@@ -98,13 +111,14 @@ def test_keras_task_and_trainer(
98111
steps_per_loop=2,
99112
model_dir=self.create_tempdir().full_path,
100113
continuous_eval_timeout=5,
101-
legacy_checkpoint_format=legacy_checkpoint_format,
114+
checkpoint_version=checkpoint_version,
102115
)
103116
experiment = core.Experiment(_KerasTask(), trainer)
104117

105118
if mode == core.Trainer.Mode.CONTINUOUS_EVAL:
106119
# Produce one checkpoint so there is something to evaluate.
107120
core.run_experiment(experiment, core.Trainer.Mode.TRAIN)
121+
keras.backend.clear_session()
108122

109123
history = core.run_experiment(experiment, mode)
110124

0 commit comments

Comments
 (0)