BonanDing commited on
Commit
7aed17d
·
1 Parent(s): 1be60e5

Fix DeMemWM checkpoint load priority

Browse files
configurations/training.yaml CHANGED
@@ -12,7 +12,7 @@ wandb:
12
  project: worldmem # wandb project name; if not provided, defaults to root folder name [fixme]
13
  mode: online # set wandb logging to online, offline or dryrun
14
 
15
- resume: null # wandb run id to resume logging and loading checkpoint from
16
  load: null # wandb run id containing checkpoint or a path to a checkpoint file
17
  auto_resume: true # automatically resume training from output_dir/checkpoints when available
18
  resume_ckpt_path: null # explicit full Lightning checkpoint path for deterministic training resume
 
12
  project: worldmem # wandb project name; if not provided, defaults to root folder name [fixme]
13
  mode: online # set wandb logging to online, offline or dryrun
14
 
15
+ resume: null # wandb run id to resume logging
16
  load: null # wandb run id containing checkpoint or a path to a checkpoint file
17
  auto_resume: true # automatically resume training from output_dir/checkpoints when available
18
  resume_ckpt_path: null # explicit full Lightning checkpoint path for deterministic training resume
experiments/exp_base.py CHANGED
@@ -65,6 +65,8 @@ _DEMEMWM_FRAME_MEMORY_MARKERS = (
65
  "r_attn_anchor",
66
  "r_attn_dynamic",
67
  "r_attn_revisit",
 
 
68
  "frame_memory",
69
  "memory_adapter",
70
  )
@@ -308,6 +310,19 @@ class BaseExperiment(ABC):
308
  self.diffusion_model_path = getattr(root_cfg, "diffusion_model_path", None)
309
  self.vae_path = getattr(root_cfg, "vae_path", None)
310
  self.pose_predictor_path = getattr(root_cfg, "pose_predictor_path", None)
 
 
 
 
 
 
 
 
 
 
 
 
 
311
 
312
  def _build_algo(self):
313
  """
@@ -466,15 +481,15 @@ class BaseLightningExperiment(BaseExperiment):
466
  )
467
 
468
 
469
- if self.customized_load:
470
- if self.seperate_load:
471
- if 'oasis500m' in self.diffusion_model_path:
472
- load_custom_checkpoint(algo=self.algo.diffusion_model.model,checkpoint_path=self.diffusion_model_path)
473
- else:
474
- load_custom_checkpoint(algo=self.algo.diffusion_model,checkpoint_path=self.diffusion_model_path)
475
- load_custom_checkpoint(algo=self.algo.vae,checkpoint_path=self.vae_path)
476
- else:
477
- load_custom_checkpoint(algo=self.algo,checkpoint_path=self.ckpt_path)
478
 
479
  if self.zero_init_gate:
480
  for name, para in self.algo.diffusion_model.named_parameters():
@@ -536,14 +551,7 @@ class BaseLightningExperiment(BaseExperiment):
536
  )
537
 
538
  if self.customized_load:
539
- if self.seperate_load:
540
- if 'oasis500m' in self.diffusion_model_path:
541
- load_custom_checkpoint(algo=self.algo.diffusion_model.model,checkpoint_path=self.diffusion_model_path)
542
- else:
543
- load_custom_checkpoint(algo=self.algo.diffusion_model,checkpoint_path=self.diffusion_model_path)
544
- load_custom_checkpoint(algo=self.algo.vae,checkpoint_path=self.vae_path)
545
- else:
546
- load_custom_checkpoint(algo=self.algo,checkpoint_path=self.ckpt_path)
547
 
548
  if self.zero_init_gate:
549
  for name, para in self.algo.diffusion_model.named_parameters():
@@ -590,14 +598,7 @@ class BaseLightningExperiment(BaseExperiment):
590
  )
591
 
592
  if self.customized_load:
593
- if self.seperate_load:
594
- if 'oasis500m' in self.diffusion_model_path:
595
- load_custom_checkpoint(algo=self.algo.diffusion_model.model,checkpoint_path=self.diffusion_model_path)
596
- else:
597
- load_custom_checkpoint(algo=self.algo.diffusion_model,checkpoint_path=self.diffusion_model_path)
598
- load_custom_checkpoint(algo=self.algo.vae,checkpoint_path=self.vae_path)
599
- else:
600
- load_custom_checkpoint(algo=self.algo,checkpoint_path=self.ckpt_path)
601
 
602
  if self.zero_init_gate:
603
  for name, para in self.algo.diffusion_model.named_parameters():
 
65
  "r_attn_anchor",
66
  "r_attn_dynamic",
67
  "r_attn_revisit",
68
+ "r_adaLN_modulation",
69
+ "r_mlp",
70
  "frame_memory",
71
  "memory_adapter",
72
  )
 
310
  self.diffusion_model_path = getattr(root_cfg, "diffusion_model_path", None)
311
  self.vae_path = getattr(root_cfg, "vae_path", None)
312
  self.pose_predictor_path = getattr(root_cfg, "pose_predictor_path", None)
313
+ self.auto_resuming = getattr(root_cfg, "_auto_resuming", False)
314
+
315
+ def _load_custom_checkpoint_for_task(self) -> None:
316
+ if self.ckpt_path:
317
+ load_custom_checkpoint(algo=self.algo, checkpoint_path=self.ckpt_path)
318
+ elif self.seperate_load:
319
+ if 'oasis500m' in self.diffusion_model_path:
320
+ load_custom_checkpoint(algo=self.algo.diffusion_model.model, checkpoint_path=self.diffusion_model_path)
321
+ else:
322
+ load_custom_checkpoint(algo=self.algo.diffusion_model, checkpoint_path=self.diffusion_model_path)
323
+ load_custom_checkpoint(algo=self.algo.vae, checkpoint_path=self.vae_path)
324
+ else:
325
+ load_custom_checkpoint(algo=self.algo, checkpoint_path=self.ckpt_path)
326
 
327
  def _build_algo(self):
328
  """
 
481
  )
482
 
483
 
484
+ if self.auto_resuming:
485
+ trainer.fit(
486
+ self.algo,
487
+ train_dataloaders=self._build_training_loader(),
488
+ val_dataloaders=self._build_validation_loader(),
489
+ ckpt_path=self.ckpt_path,
490
+ )
491
+ elif self.customized_load:
492
+ self._load_custom_checkpoint_for_task()
493
 
494
  if self.zero_init_gate:
495
  for name, para in self.algo.diffusion_model.named_parameters():
 
551
  )
552
 
553
  if self.customized_load:
554
+ self._load_custom_checkpoint_for_task()
 
 
 
 
 
 
 
555
 
556
  if self.zero_init_gate:
557
  for name, para in self.algo.diffusion_model.named_parameters():
 
598
  )
599
 
600
  if self.customized_load:
601
+ self._load_custom_checkpoint_for_task()
 
 
 
 
 
 
 
602
 
603
  if self.zero_init_gate:
604
  for name, para in self.algo.diffusion_model.named_parameters():
tests/test_checkpoint_loading.py CHANGED
@@ -18,6 +18,7 @@ class DummyFrameMemoryBlock(nn.Module):
18
  def __init__(self, hidden_size=2):
19
  super().__init__()
20
  self.r_adaLN_modulation = nn.Sequential(nn.SiLU(), nn.Linear(hidden_size, 6 * hidden_size))
 
21
  self.r_attn_anchor = nn.Linear(hidden_size, hidden_size, bias=False)
22
  self.r_attn_dynamic = nn.Linear(hidden_size, hidden_size, bias=False)
23
  self.r_attn_revisit = nn.Linear(hidden_size, hidden_size, bias=False)
@@ -32,8 +33,15 @@ class DummyDeMemWM(nn.Module):
32
 
33
  def _ones_state(module, skip_frame_memory=False):
34
  state = {}
 
 
 
 
 
 
 
35
  for key, value in module.state_dict().items():
36
- if skip_frame_memory and any(marker in key for marker in ("r_attn_anchor", "r_attn_dynamic", "r_attn_revisit")):
37
  continue
38
  state[key] = torch.ones_like(value)
39
  return state
@@ -107,7 +115,7 @@ class CheckpointLoadingTests(unittest.TestCase):
107
  target = DummyDeMemWM()
108
  state = _ones_state(target, skip_frame_memory=True)
109
  for key, value in target.state_dict().items():
110
- if "r_attn_anchor" in key:
111
  state[key] = torch.ones_like(value)
112
 
113
  with tempfile.TemporaryDirectory() as tmpdir:
@@ -116,6 +124,32 @@ class CheckpointLoadingTests(unittest.TestCase):
116
  with self.assertRaisesRegex(RuntimeError, "Incomplete DeMemWM checkpoint.*r_attn_dynamic"):
117
  load_custom_checkpoint(target, ckpt_path)
118
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  def test_directory_load_skips_unreadable_latest_checkpoint(self):
120
  target = nn.Linear(2, 2)
121
  state = {key: torch.full_like(value, 3.0) for key, value in target.state_dict().items()}
 
18
  def __init__(self, hidden_size=2):
19
  super().__init__()
20
  self.r_adaLN_modulation = nn.Sequential(nn.SiLU(), nn.Linear(hidden_size, 6 * hidden_size))
21
+ self.r_mlp = nn.Linear(hidden_size, hidden_size)
22
  self.r_attn_anchor = nn.Linear(hidden_size, hidden_size, bias=False)
23
  self.r_attn_dynamic = nn.Linear(hidden_size, hidden_size, bias=False)
24
  self.r_attn_revisit = nn.Linear(hidden_size, hidden_size, bias=False)
 
33
 
34
  def _ones_state(module, skip_frame_memory=False):
35
  state = {}
36
+ memory_markers = (
37
+ "r_attn_anchor",
38
+ "r_attn_dynamic",
39
+ "r_attn_revisit",
40
+ "r_adaLN_modulation",
41
+ "r_mlp",
42
+ )
43
  for key, value in module.state_dict().items():
44
+ if skip_frame_memory and any(marker in key for marker in memory_markers):
45
  continue
46
  state[key] = torch.ones_like(value)
47
  return state
 
115
  target = DummyDeMemWM()
116
  state = _ones_state(target, skip_frame_memory=True)
117
  for key, value in target.state_dict().items():
118
+ if "r_attn_anchor" in key or "r_adaLN_modulation" in key or "r_mlp" in key:
119
  state[key] = torch.ones_like(value)
120
 
121
  with tempfile.TemporaryDirectory() as tmpdir:
 
124
  with self.assertRaisesRegex(RuntimeError, "Incomplete DeMemWM checkpoint.*r_attn_dynamic"):
125
  load_custom_checkpoint(target, ckpt_path)
126
 
127
+ def test_incomplete_dememwm_checkpoint_missing_adaln_mlp_fails(self):
128
+ target = DummyDeMemWM()
129
+ state = _ones_state(target, skip_frame_memory=True)
130
+ for key, value in target.state_dict().items():
131
+ if "r_attn_" in key:
132
+ state[key] = torch.ones_like(value)
133
+
134
+ with tempfile.TemporaryDirectory() as tmpdir:
135
+ ckpt_path = Path(tmpdir) / "incomplete_dememwm_missing_adaln_mlp.ckpt"
136
+ torch.save({"state_dict": state}, ckpt_path)
137
+ with self.assertRaisesRegex(RuntimeError, "Incomplete DeMemWM checkpoint.*r_adaLN_modulation"):
138
+ load_custom_checkpoint(target, ckpt_path)
139
+
140
+ def test_incomplete_dememwm_checkpoint_missing_r_mlp_fails(self):
141
+ target = DummyDeMemWM()
142
+ state = _ones_state(target, skip_frame_memory=True)
143
+ for key, value in target.state_dict().items():
144
+ if "r_attn_" in key or "r_adaLN_modulation" in key:
145
+ state[key] = torch.ones_like(value)
146
+
147
+ with tempfile.TemporaryDirectory() as tmpdir:
148
+ ckpt_path = Path(tmpdir) / "incomplete_dememwm_missing_r_mlp.ckpt"
149
+ torch.save({"state_dict": state}, ckpt_path)
150
+ with self.assertRaisesRegex(RuntimeError, "Incomplete DeMemWM checkpoint.*r_mlp"):
151
+ load_custom_checkpoint(target, ckpt_path)
152
+
153
  def test_directory_load_skips_unreadable_latest_checkpoint(self):
154
  target = nn.Linear(2, 2)
155
  state = {key: torch.full_like(value, 3.0) for key, value in target.state_dict().items()}
tests/test_resume_checkpoint_logic.py ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import unittest
2
+ from unittest.mock import patch
3
+
4
+ from omegaconf import OmegaConf
5
+
6
+ from experiments import exp_base
7
+
8
+
9
+ class DummyExperiment(exp_base.BaseLightningExperiment):
10
+ compatible_algorithms = {}
11
+ compatible_datasets = {}
12
+
13
+ def _build_training_loader(self):
14
+ return None
15
+
16
+ def _build_validation_loader(self):
17
+ return None
18
+
19
+ def _build_test_loader(self):
20
+ return None
21
+
22
+
23
+ class DummyTrainer:
24
+ fit_calls = []
25
+ validate_calls = []
26
+ test_calls = []
27
+
28
+ def __init__(self, *args, **kwargs):
29
+ pass
30
+
31
+ def fit(self, *args, **kwargs):
32
+ self.fit_calls.append({"args": args, "kwargs": kwargs})
33
+
34
+ def validate(self, *args, **kwargs):
35
+ self.validate_calls.append({"args": args, "kwargs": kwargs})
36
+
37
+ def test(self, *args, **kwargs):
38
+ self.test_calls.append({"args": args, "kwargs": kwargs})
39
+
40
+
41
+ def _root_cfg(auto_resuming=True):
42
+ return OmegaConf.create(
43
+ {
44
+ "debug": False,
45
+ "_auto_resuming": auto_resuming,
46
+ "customized_load": True,
47
+ "seperate_load": True,
48
+ "diffusion_model_path": "oasis500m.safetensors",
49
+ "vae_path": "vit-l-20.safetensors",
50
+ "algorithm": {"_name": "dummy"},
51
+ "dataset": {"_name": "dummy"},
52
+ "experiment": {
53
+ "debug": False,
54
+ "num_nodes": 1,
55
+ "tasks": ["training"],
56
+ "training": {
57
+ "compile": False,
58
+ "precision": 32,
59
+ "batch_size": 1,
60
+ "max_epochs": 1,
61
+ "max_steps": 1,
62
+ "max_time": None,
63
+ "data": {"shuffle": False, "num_workers": 0},
64
+ "optim": {"gradient_clip_val": 0, "accumulate_grad_batches": 1},
65
+ },
66
+ "validation": {
67
+ "compile": False,
68
+ "precision": 32,
69
+ "inference_mode": True,
70
+ "val_every_n_step": None,
71
+ "val_every_n_epoch": None,
72
+ "limit_batch": 0,
73
+ "batch_size": 1,
74
+ "data": {"shuffle": False, "num_workers": 0},
75
+ },
76
+ "test": {
77
+ "compile": False,
78
+ "precision": 32,
79
+ "inference_mode": True,
80
+ "limit_batch": 0,
81
+ "batch_size": 1,
82
+ "data": {"shuffle": False, "num_workers": 0},
83
+ },
84
+ },
85
+ }
86
+ )
87
+
88
+
89
+ class ResumeCheckpointLogicTests(unittest.TestCase):
90
+ def test_auto_resume_takes_priority_over_custom_separate_load(self):
91
+ DummyTrainer.fit_calls = []
92
+ experiment = DummyExperiment(_root_cfg(auto_resuming=True), logger=None, ckpt_path="/tmp/last.ckpt")
93
+ experiment.algo = object()
94
+
95
+ with patch.object(exp_base.pl, "Trainer", DummyTrainer), patch.object(
96
+ exp_base,
97
+ "load_custom_checkpoint",
98
+ side_effect=AssertionError("custom load should not run during auto-resume"),
99
+ ):
100
+ experiment.training()
101
+
102
+ self.assertEqual(DummyTrainer.fit_calls[0]["kwargs"]["ckpt_path"], "/tmp/last.ckpt")
103
+
104
+ def test_validation_load_checkpoint_takes_priority_over_separate_load(self):
105
+ DummyTrainer.validate_calls = []
106
+ experiment = DummyExperiment(_root_cfg(auto_resuming=False), logger=None, ckpt_path="/tmp/trained.ckpt")
107
+ experiment.algo = object()
108
+
109
+ with patch.object(exp_base.pl, "Trainer", DummyTrainer), patch.object(exp_base, "load_custom_checkpoint") as load_mock:
110
+ experiment.validation()
111
+
112
+ load_mock.assert_called_once_with(algo=experiment.algo, checkpoint_path="/tmp/trained.ckpt")
113
+ self.assertIsNone(DummyTrainer.validate_calls[0]["kwargs"]["ckpt_path"])
114
+
115
+ def test_test_load_checkpoint_takes_priority_over_separate_load(self):
116
+ DummyTrainer.test_calls = []
117
+ experiment = DummyExperiment(_root_cfg(auto_resuming=False), logger=None, ckpt_path="/tmp/trained.ckpt")
118
+ experiment.algo = object()
119
+
120
+ with patch.object(exp_base.pl, "Trainer", DummyTrainer), patch.object(exp_base, "load_custom_checkpoint") as load_mock:
121
+ experiment.test()
122
+
123
+ load_mock.assert_called_once_with(algo=experiment.algo, checkpoint_path="/tmp/trained.ckpt")
124
+ self.assertIsNone(DummyTrainer.test_calls[0]["kwargs"]["ckpt_path"])
125
+
126
+
127
+ if __name__ == "__main__":
128
+ unittest.main()
utils/wandb_utils.py CHANGED
@@ -40,22 +40,6 @@ class SpaceEfficientWandbLogger(WandbLogger):
40
  expiration_days: Optional[int] = 5,
41
  **kwargs: Any,
42
  ) -> None:
43
- super().__init__(
44
- name=name,
45
- save_dir=save_dir,
46
- version=version,
47
- offline=False,
48
- dir=dir,
49
- id=id,
50
- anonymous=anonymous,
51
- project=project,
52
- log_model=log_model,
53
- experiment=experiment,
54
- prefix=prefix,
55
- checkpoint_name=checkpoint_name,
56
- **kwargs,
57
- )
58
-
59
  super().__init__(
60
  name=name,
61
  save_dir=save_dir,
 
40
  expiration_days: Optional[int] = 5,
41
  **kwargs: Any,
42
  ) -> None:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  super().__init__(
44
  name=name,
45
  save_dir=save_dir,