trainloop 0.9.0__tar.gz → 0.11.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {trainloop-0.9.0 → trainloop-0.11.0}/PKG-INFO +1 -1
- {trainloop-0.9.0 → trainloop-0.11.0}/pyproject.toml +1 -1
- {trainloop-0.9.0 → trainloop-0.11.0}/pyproject.toml.orig +1 -1
- {trainloop-0.9.0 → trainloop-0.11.0}/src/trainloop/hooks.py +27 -10
- {trainloop-0.9.0 → trainloop-0.11.0}/src/trainloop/trainer.py +10 -5
- {trainloop-0.9.0 → trainloop-0.11.0}/README.md +0 -0
- {trainloop-0.9.0 → trainloop-0.11.0}/src/trainloop/__init__.py +0 -0
- {trainloop-0.9.0 → trainloop-0.11.0}/src/trainloop/py.typed +0 -0
- {trainloop-0.9.0 → trainloop-0.11.0}/src/trainloop/utils.py +0 -0
|
@@ -83,7 +83,9 @@ class BaseHook:
|
|
|
83
83
|
def on_after_train(self, trainer: BaseTrainer):
|
|
84
84
|
pass
|
|
85
85
|
|
|
86
|
-
def
|
|
86
|
+
def on_log_scalars(
|
|
87
|
+
self, trainer: BaseTrainer, records: dict, dry_run: bool = False
|
|
88
|
+
):
|
|
87
89
|
pass
|
|
88
90
|
|
|
89
91
|
def on_log_images(self, trainer: BaseTrainer, records: dict, dry_run: bool = False):
|
|
@@ -588,14 +590,18 @@ class EMAHook(BaseHook):
|
|
|
588
590
|
Args:
|
|
589
591
|
decay: EMA decay rate.
|
|
590
592
|
use_buffers: Whether to include model buffers in the EMA.
|
|
593
|
+
name: Name used for the EMA state in the trainer state dict.
|
|
591
594
|
"""
|
|
592
595
|
|
|
593
|
-
def __init__(
|
|
596
|
+
def __init__(
|
|
597
|
+
self, decay: float = 0.999, use_buffers: bool = False, name: str = "ema"
|
|
598
|
+
):
|
|
594
599
|
self.decay = decay
|
|
595
600
|
self.use_buffers = use_buffers
|
|
601
|
+
self.name = name
|
|
596
602
|
|
|
597
603
|
def on_before_train(self, trainer: BaseTrainer):
|
|
598
|
-
trainer.logger.info("=> Creating EMA model ...")
|
|
604
|
+
trainer.logger.info(f"=> Creating EMA model {self.name!r} ...")
|
|
599
605
|
# Note that AveragedModel does not seem to support FSDP. It will crash here.
|
|
600
606
|
self.ema_model = AveragedModel(
|
|
601
607
|
trainer.model,
|
|
@@ -608,10 +614,8 @@ class EMAHook(BaseHook):
|
|
|
608
614
|
self.ema_model.update_parameters(trainer.model)
|
|
609
615
|
|
|
610
616
|
def on_load_state_dict(self, trainer: BaseTrainer, state_dict: dict):
|
|
611
|
-
trainer.logger.info("=> Loading EMA model state ...")
|
|
612
|
-
incompatible_keys = set_model_state_dict(
|
|
613
|
-
self.ema_model, state_dict["ema_model"]
|
|
614
|
-
)
|
|
617
|
+
trainer.logger.info(f"=> Loading EMA model {self.name!r} state ...")
|
|
618
|
+
incompatible_keys = set_model_state_dict(self.ema_model, state_dict[self.name])
|
|
615
619
|
# This currently doesn't do anything because strict=True is implicit.
|
|
616
620
|
log_state_dict_incompatible_keys(
|
|
617
621
|
trainer.logger,
|
|
@@ -620,13 +624,18 @@ class EMAHook(BaseHook):
|
|
|
620
624
|
)
|
|
621
625
|
|
|
622
626
|
def on_state_dict(self, trainer: BaseTrainer, state_dict: dict):
|
|
627
|
+
if self.name in state_dict:
|
|
628
|
+
raise ValueError(f"State dict key {self.name!r} already exists")
|
|
623
629
|
# Note: sadly, we need to keep the AveragedModel wrapper, to save its n_averaged buffer
|
|
624
|
-
state_dict[
|
|
630
|
+
state_dict[self.name] = get_model_state_dict(self.ema_model)
|
|
625
631
|
|
|
626
632
|
|
|
627
633
|
class WandbHook(BaseHook):
|
|
628
634
|
"""Log metrics and images to Weights & Biases (rank 0 only).
|
|
629
635
|
|
|
636
|
+
Nested scalar key components are joined with ``/``. Avoid ``/`` within an
|
|
637
|
+
individual component because it is also W&B's panel namespace separator.
|
|
638
|
+
|
|
630
639
|
Args:
|
|
631
640
|
project: W&B project name.
|
|
632
641
|
config: Optional config dict or JSON file path to log.
|
|
@@ -678,7 +687,9 @@ class WandbHook(BaseHook):
|
|
|
678
687
|
if _dist_rank() == 0:
|
|
679
688
|
self.wandb.finish()
|
|
680
689
|
|
|
681
|
-
def
|
|
690
|
+
def on_log_scalars(
|
|
691
|
+
self, trainer: BaseTrainer, records: dict, dry_run: bool = False
|
|
692
|
+
):
|
|
682
693
|
if _dist_rank() == 0:
|
|
683
694
|
data = {"/".join(k): v for k, v in flatten_nested_dict(records).items()}
|
|
684
695
|
if not dry_run:
|
|
@@ -748,6 +759,10 @@ class WandbHook(BaseHook):
|
|
|
748
759
|
class TensorBoardHook(BaseHook):
|
|
749
760
|
"""Log metrics and images to TensorBoard (rank 0 only).
|
|
750
761
|
|
|
762
|
+
Nested namespace components are joined with ``namespace_separator`` and
|
|
763
|
+
the final name is separated with ``/``. Avoid these separators within
|
|
764
|
+
individual keys because TensorBoard uses them to organize tags.
|
|
765
|
+
|
|
751
766
|
Args:
|
|
752
767
|
texts: Optional text values to log when training starts.
|
|
753
768
|
namespace_separator: Separator for nested tag prefixes; the final TensorBoard
|
|
@@ -784,7 +799,9 @@ class TensorBoardHook(BaseHook):
|
|
|
784
799
|
self.writer.close()
|
|
785
800
|
self.writer = None
|
|
786
801
|
|
|
787
|
-
def
|
|
802
|
+
def on_log_scalars(
|
|
803
|
+
self, trainer: BaseTrainer, records: dict, dry_run: bool = False
|
|
804
|
+
):
|
|
788
805
|
if self.writer is None:
|
|
789
806
|
return
|
|
790
807
|
|
|
@@ -349,17 +349,22 @@ class BaseTrainer:
|
|
|
349
349
|
def unwrapped_model(self):
|
|
350
350
|
return self.unwrap(self.model)
|
|
351
351
|
|
|
352
|
-
def
|
|
352
|
+
def log_scalars(self, records: dict[str, Any], dry_run: bool = False):
|
|
353
353
|
"""
|
|
354
|
-
Dispatch
|
|
354
|
+
Dispatch nested scalar records to logging hooks.
|
|
355
|
+
|
|
356
|
+
Dictionary keys are treated as path components. Logging hooks may join
|
|
357
|
+
nested components with backend-specific namespace separators, such as
|
|
358
|
+
``/``. Avoid those separators within individual keys because distinct
|
|
359
|
+
nested paths may otherwise map to the same backend metric name.
|
|
355
360
|
|
|
356
361
|
Args:
|
|
357
|
-
records: Nested dict of
|
|
362
|
+
records: Nested dict of scalar metrics to log.
|
|
358
363
|
dry_run: If True, hooks should avoid side effects and only report intent.
|
|
359
364
|
"""
|
|
360
|
-
self.logger.debug("
|
|
365
|
+
self.logger.debug("log_scalars()")
|
|
361
366
|
for h in self.hooks:
|
|
362
|
-
h.
|
|
367
|
+
h.on_log_scalars(self, records, dry_run=dry_run)
|
|
363
368
|
|
|
364
369
|
def log_images(self, records: dict[str, Any], dry_run: bool = False):
|
|
365
370
|
"""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|