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 |
-
|
| 787 |
-
|
| 788 |
-
|
| 789 |
-
|
| 790 |
-
|
| 791 |
-
|
| 792 |
-
|
| 793 |
-
|
| 794 |
-
|
| 795 |
-
|
| 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 |
}
|