BonanDing commited on
Commit
27f451f
·
1 Parent(s): 5095f17

Read DeMemWM training dynamic stream around revisit

Browse files
datasets/video/memory_selection.py CHANGED
@@ -606,6 +606,98 @@ def _nearest_unique_event_anchors(event_anchors: np.ndarray, reference_frames: n
606
  return np.sort(np.asarray(selected[:count], dtype=np.int64))
607
 
608
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
609
  def _select_event_triggered_dynamic(
610
  target_start: int,
611
  count: int,
@@ -724,6 +816,7 @@ def select_memory_indices(
724
  actions=None,
725
  anchor_candidate_start=None,
726
  anchor_candidate_stop=None,
 
727
  ):
728
  """Select causal memory indices and masks for [anchor][dynamic][revisit]."""
729
 
@@ -783,17 +876,24 @@ def select_memory_indices(
783
  )
784
 
785
  if policy == "event_triggered":
786
- dynamic = _select_dynamic_by_policy(
787
- target_start,
788
- counts["dynamic"],
789
- cfg,
790
- poses=poses,
791
- latents=latents,
792
- actions=actions,
793
- min_candidate_frame=min_candidate_frame,
794
- reference_frames=revisit if len(revisit) > 0 else None,
795
- excluded=np.concatenate([anchor, revisit]) if len(anchor) or len(revisit) else None,
796
- )
 
 
 
 
 
 
 
797
 
798
  _write_segment(indices, masks, "anchor", anchor)
799
  _write_segment(indices, masks, "dynamic", dynamic)
 
606
  return np.sort(np.asarray(selected[:count], dtype=np.int64))
607
 
608
 
609
+ def _build_dynamic_stream(
610
+ latents,
611
+ actions=None,
612
+ poses=None,
613
+ cfg=None,
614
+ min_candidate_frame: int = 0,
615
+ stop: int | None = None,
616
+ ) -> np.ndarray:
617
+ if latents is None:
618
+ return np.empty((0,), dtype=np.int64)
619
+
620
+ length = len(latents)
621
+ min_candidate_frame = max(0, int(min_candidate_frame))
622
+ target_stop = length if stop is None else max(0, min(int(stop), length))
623
+ if target_stop <= min_candidate_frame:
624
+ return np.empty((0,), dtype=np.int64)
625
+
626
+ event_anchors = _event_triggered_anchor_candidates(
627
+ target_stop,
628
+ cfg,
629
+ poses=poses,
630
+ latents=latents,
631
+ actions=actions,
632
+ min_candidate_frame=min_candidate_frame,
633
+ )
634
+ stream = np.concatenate([np.asarray([min_candidate_frame], dtype=np.int64), event_anchors.astype(np.int64, copy=False)])
635
+ stream = stream[(stream >= min_candidate_frame) & (stream < target_stop)]
636
+ return np.unique(np.sort(stream.astype(np.int64, copy=False)))
637
+
638
+
639
+ def _select_dynamic_from_stream(dynamic_stream, reference_frames, count: int) -> np.ndarray:
640
+ if count <= 0:
641
+ return np.empty((0,), dtype=np.int64)
642
+
643
+ stream = np.asarray(dynamic_stream, dtype=np.int64)
644
+ stream = np.unique(np.sort(stream[stream >= 0]))
645
+ if len(stream) == 0:
646
+ return np.empty((0,), dtype=np.int64)
647
+
648
+ references = np.asarray([] if reference_frames is None else reference_frames, dtype=np.int64)
649
+ references = np.unique(np.sort(references[references >= 0]))
650
+ if len(references) == 0:
651
+ return stream[-count:].astype(np.int64, copy=False)
652
+
653
+ selected = []
654
+ used = set()
655
+
656
+ def add_candidate(value) -> bool:
657
+ value = int(value)
658
+ if value in used:
659
+ return False
660
+ selected.append(value)
661
+ used.add(value)
662
+ return True
663
+
664
+ base_quota, extra = divmod(int(count), len(references))
665
+ for ref_idx, ref in enumerate(references):
666
+ quota = base_quota + (1 if ref_idx < extra else 0)
667
+ if quota <= 0:
668
+ continue
669
+ picked = 0
670
+ before = stream[stream <= int(ref)]
671
+ after = stream[stream >= int(ref)]
672
+ brackets = []
673
+ if len(before) > 0:
674
+ brackets.append(int(before[-1]))
675
+ if len(after) > 0:
676
+ brackets.append(int(after[0]))
677
+ for candidate in brackets:
678
+ picked += int(add_candidate(candidate))
679
+ if picked >= quota:
680
+ break
681
+ if picked >= quota:
682
+ continue
683
+
684
+ order = np.lexsort((stream, np.abs(stream - int(ref))))
685
+ for row in order:
686
+ picked += int(add_candidate(stream[row]))
687
+ if picked >= quota:
688
+ break
689
+
690
+ if len(selected) < count:
691
+ distance = np.min(np.abs(stream[:, None] - references[None, :]), axis=1)
692
+ order = np.lexsort((stream, distance))
693
+ for row in order:
694
+ add_candidate(stream[row])
695
+ if len(selected) >= count:
696
+ break
697
+
698
+ return np.sort(np.asarray(selected[:count], dtype=np.int64))
699
+
700
+
701
  def _select_event_triggered_dynamic(
702
  target_start: int,
703
  count: int,
 
816
  actions=None,
817
  anchor_candidate_start=None,
818
  anchor_candidate_stop=None,
819
+ dynamic_stream=None,
820
  ):
821
  """Select causal memory indices and masks for [anchor][dynamic][revisit]."""
822
 
 
876
  )
877
 
878
  if policy == "event_triggered":
879
+ if dynamic_stream is not None:
880
+ exclusion = max(0, int(cfg_get(cfg, "local_context_exclusion_frames", 8)))
881
+ causal_cutoff = max(min_candidate_frame, target_start - exclusion)
882
+ stream = np.asarray(dynamic_stream, dtype=np.int64)
883
+ eligible_stream = stream[(stream >= min_candidate_frame) & (stream < causal_cutoff)]
884
+ dynamic = _select_dynamic_from_stream(eligible_stream, revisit, counts["dynamic"])
885
+ else:
886
+ dynamic = _select_dynamic_by_policy(
887
+ target_start,
888
+ counts["dynamic"],
889
+ cfg,
890
+ poses=poses,
891
+ latents=latents,
892
+ actions=actions,
893
+ min_candidate_frame=min_candidate_frame,
894
+ reference_frames=revisit if len(revisit) > 0 else None,
895
+ excluded=np.concatenate([anchor, revisit]) if len(anchor) or len(revisit) else None,
896
+ )
897
 
898
  _write_segment(indices, masks, "anchor", anchor)
899
  _write_segment(indices, masks, "dynamic", dynamic)
datasets/video/minecraft_video_dememwm_latent_dataset.py CHANGED
@@ -10,7 +10,7 @@ import numpy as np
10
  import torch
11
  from omegaconf import DictConfig
12
 
13
- from .memory_selection import SEGMENT_KEYS, cfg_get, memory_segment_lengths, select_memory_indices
14
 
15
 
16
  ACTION_KEYS = [
@@ -210,6 +210,7 @@ class MinecraftVideoDeMemWMLatentDataset(torch.utils.data.Dataset):
210
  actions=actions,
211
  anchor_candidate_start=anchor_start,
212
  anchor_candidate_stop=anchor_stop,
 
213
  )
214
  ordered_memory = [memory_indices[key] for key in SEGMENT_KEYS]
215
  source_positions = np.concatenate([target_positions, *ordered_memory]).astype(np.int64)
@@ -292,10 +293,24 @@ class MinecraftVideoDeMemWMLatentDataset(torch.utils.data.Dataset):
292
  actions = self._normalize_actions(action_path, np.asarray(data["actions"]))
293
  poses = self._sanitize_poses(action_path, np.asarray(data["poses"], dtype=np.float32), len(actions))
294
 
 
 
 
 
 
 
 
 
 
 
 
 
 
295
  return {
296
  "latents": latents,
297
  "actions": actions,
298
  "poses": poses,
 
299
  "frame_indices": np.arange(len(latents), dtype=np.int64),
300
  "image_hw": self._feature_image_hw(meta_path),
301
  }
 
10
  import torch
11
  from omegaconf import DictConfig
12
 
13
+ from .memory_selection import SEGMENT_KEYS, _build_dynamic_stream, cfg_get, memory_segment_lengths, select_memory_indices
14
 
15
 
16
  ACTION_KEYS = [
 
210
  actions=actions,
211
  anchor_candidate_start=anchor_start,
212
  anchor_candidate_stop=anchor_stop,
213
+ dynamic_stream=arrays.get("dynamic_stream"),
214
  )
215
  ordered_memory = [memory_indices[key] for key in SEGMENT_KEYS]
216
  source_positions = np.concatenate([target_positions, *ordered_memory]).astype(np.int64)
 
293
  actions = self._normalize_actions(action_path, np.asarray(data["actions"]))
294
  poses = self._sanitize_poses(action_path, np.asarray(data["poses"], dtype=np.float32), len(actions))
295
 
296
+ dynamic_cfg = cfg_get(self.memory_selection, "dynamic", {})
297
+ dynamic_policy = str(cfg_get(dynamic_cfg, "selection_policy", "recent"))
298
+ if self.split == "training" and dynamic_policy == "event_triggered":
299
+ dynamic_stream = _build_dynamic_stream(
300
+ latents,
301
+ actions=actions,
302
+ poses=poses,
303
+ cfg=self.memory_selection,
304
+ min_candidate_frame=self.initial_frame_offset,
305
+ )
306
+ else:
307
+ dynamic_stream = np.empty((0,), dtype=np.int64)
308
+
309
  return {
310
  "latents": latents,
311
  "actions": actions,
312
  "poses": poses,
313
+ "dynamic_stream": dynamic_stream,
314
  "frame_indices": np.arange(len(latents), dtype=np.int64),
315
  "image_hw": self._feature_image_hw(meta_path),
316
  }