BonanDing commited on
Commit
894c19c
·
1 Parent(s): 2c06b7e

Allow noncausal DeMemWM dynamic events

Browse files
.exp_artifact/dememwm_future_memory_selection_plan.md CHANGED
@@ -274,7 +274,7 @@ Allow noncausal DeMemWM revisit selection
274
 
275
  ## Substep 3: Enable Future Event-Triggered Dynamic Selection
276
 
277
- Status: `[ ]`
278
 
279
  Goal:
280
 
 
274
 
275
  ## Substep 3: Enable Future Event-Triggered Dynamic Selection
276
 
277
+ Status: `[x]`
278
 
279
  Goal:
280
 
datasets/video/memory_selection.py CHANGED
@@ -883,12 +883,21 @@ def select_memory_indices(
883
  )
884
 
885
  if policy == "event_triggered":
 
886
  if dynamic_stream is not None:
887
- exclusion = max(0, int(cfg_get(cfg, "local_context_exclusion_frames", 8)))
888
- causal_cutoff = max(min_candidate_frame, target_start - exclusion)
 
 
 
 
 
889
  stream = np.asarray(dynamic_stream, dtype=np.int64)
890
- eligible_stream = stream[(stream >= min_candidate_frame) & (stream < causal_cutoff)]
891
- dynamic = _select_dynamic_from_stream(eligible_stream, revisit, counts["dynamic"])
 
 
 
892
  else:
893
  dynamic = _select_dynamic_by_policy(
894
  target_start,
@@ -898,8 +907,7 @@ def select_memory_indices(
898
  latents=latents,
899
  actions=actions,
900
  min_candidate_frame=min_candidate_frame,
901
- reference_frames=revisit if len(revisit) > 0 else None,
902
- excluded=np.concatenate([anchor, revisit]) if len(anchor) or len(revisit) else None,
903
  )
904
 
905
  _write_segment(indices, masks, "anchor", anchor)
 
883
  )
884
 
885
  if policy == "event_triggered":
886
+ dynamic_references = revisit if len(revisit) > 0 else target_positions
887
  if dynamic_stream is not None:
888
+ candidates = _memory_candidate_frames(
889
+ len(poses),
890
+ target_positions,
891
+ cfg,
892
+ split,
893
+ min_candidate_frame=min_candidate_frame,
894
+ )
895
  stream = np.asarray(dynamic_stream, dtype=np.int64)
896
+ if len(candidates) > 0:
897
+ eligible_stream = stream[np.isin(stream, candidates)]
898
+ else:
899
+ eligible_stream = np.empty((0,), dtype=np.int64)
900
+ dynamic = _select_dynamic_from_stream(eligible_stream, dynamic_references, counts["dynamic"])
901
  else:
902
  dynamic = _select_dynamic_by_policy(
903
  target_start,
 
907
  latents=latents,
908
  actions=actions,
909
  min_candidate_frame=min_candidate_frame,
910
+ reference_frames=dynamic_references,
 
911
  )
912
 
913
  _write_segment(indices, masks, "anchor", anchor)
tests/test_dememwm_latent_dataset.py CHANGED
@@ -384,6 +384,120 @@ class MemorySelectionTests(unittest.TestCase):
384
  self.assertEqual(indices["anchor"].tolist(), [2, 5])
385
  self.assertEqual(masks["anchor"].tolist(), [True, True])
386
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
387
 
388
  def test_event_triggered_dynamic_selects_first_stable_post_event_frame(self):
389
  poses = np.zeros((10, 5), dtype=np.float32)
 
384
  self.assertEqual(indices["anchor"].tolist(), [2, 5])
385
  self.assertEqual(masks["anchor"].tolist(), [True, True])
386
 
387
+ def test_event_triggered_dynamic_causal_stream_stays_before_target(self):
388
+ poses = _poses(12)
389
+ cfg = _selection_cfg(
390
+ max_anchor_frames=0,
391
+ max_dynamic_frames=3,
392
+ max_revisit_frames=0,
393
+ dynamic=_dynamic_cfg("event_triggered"),
394
+ )
395
+
396
+ indices, masks = select_memory_indices(
397
+ poses,
398
+ np.array([5]),
399
+ cfg,
400
+ split="training",
401
+ dynamic_stream=np.asarray([1, 4, 5, 7, 9], dtype=np.int64),
402
+ )
403
+
404
+ selected = indices["dynamic"][masks["dynamic"]]
405
+ self.assertEqual(selected.tolist(), [1, 4])
406
+ self.assertTrue(np.all(selected < 5))
407
+
408
+ def test_event_triggered_dynamic_noncausal_stream_can_select_future(self):
409
+ poses = _poses(12)
410
+ cfg = _selection_cfg(
411
+ causal=False,
412
+ max_anchor_frames=0,
413
+ max_dynamic_frames=3,
414
+ max_revisit_frames=0,
415
+ dynamic=_dynamic_cfg("event_triggered"),
416
+ )
417
+
418
+ indices, masks = select_memory_indices(
419
+ poses,
420
+ np.array([5]),
421
+ cfg,
422
+ split="training",
423
+ dynamic_stream=np.asarray([1, 4, 5, 7, 9], dtype=np.int64),
424
+ )
425
+
426
+ selected = indices["dynamic"][masks["dynamic"]]
427
+ self.assertEqual(selected.tolist(), [4, 5, 7])
428
+ self.assertTrue(np.any(selected > 5))
429
+
430
+ def test_event_triggered_dynamic_eval_stream_stays_past_when_noncausal(self):
431
+ poses = _poses(12)
432
+ cfg = _selection_cfg(
433
+ causal=False,
434
+ max_anchor_frames=0,
435
+ max_dynamic_frames=3,
436
+ max_revisit_frames=0,
437
+ dynamic=_dynamic_cfg("event_triggered"),
438
+ )
439
+
440
+ for split in ("validation", "test"):
441
+ with self.subTest(split=split):
442
+ indices, masks = select_memory_indices(
443
+ poses,
444
+ np.array([5]),
445
+ cfg,
446
+ split=split,
447
+ dynamic_stream=np.asarray([1, 4, 5, 7, 9], dtype=np.int64),
448
+ )
449
+
450
+ selected = indices["dynamic"][masks["dynamic"]]
451
+ self.assertEqual(selected.tolist(), [1, 4])
452
+ self.assertTrue(np.all(selected < 5))
453
+
454
+ def test_event_triggered_dynamic_can_duplicate_anchor_and_revisit(self):
455
+ import datasets.video.memory_selection as memory_selection
456
+
457
+ poses = _poses(8)
458
+ cfg = _selection_cfg(
459
+ max_anchor_frames=1,
460
+ max_dynamic_frames=2,
461
+ max_revisit_frames=2,
462
+ anchor_diverse_selection=False,
463
+ dynamic=_dynamic_cfg("event_triggered"),
464
+ )
465
+
466
+ with mock.patch.object(memory_selection, "_select_revisit", return_value=np.asarray([0, 5], dtype=np.int64)):
467
+ indices, masks = select_memory_indices(
468
+ poses,
469
+ np.array([6]),
470
+ cfg,
471
+ split="training",
472
+ dynamic_stream=np.asarray([0, 5], dtype=np.int64),
473
+ )
474
+
475
+ self.assertEqual(indices["anchor"].tolist(), [0])
476
+ self.assertEqual(indices["revisit"].tolist(), [0, 5])
477
+ self.assertEqual(indices["dynamic"].tolist(), [0, 5])
478
+ self.assertTrue(masks["dynamic"].all())
479
+
480
+ def test_recent_dynamic_remains_past_only_when_memory_selection_is_noncausal(self):
481
+ poses = _poses(10)
482
+ cfg = _selection_cfg(
483
+ causal=False,
484
+ max_anchor_frames=0,
485
+ max_dynamic_frames=2,
486
+ max_revisit_frames=0,
487
+ dynamic=_dynamic_cfg("recent"),
488
+ )
489
+
490
+ indices, masks = select_memory_indices(
491
+ poses,
492
+ np.array([6]),
493
+ cfg,
494
+ split="training",
495
+ dynamic_stream=np.asarray([6, 7, 8, 9], dtype=np.int64),
496
+ )
497
+
498
+ self.assertEqual(indices["dynamic"].tolist(), [4, 5])
499
+ self.assertEqual(masks["dynamic"].tolist(), [True, True])
500
+ self.assertTrue(np.all(indices["dynamic"][masks["dynamic"]] < 6))
501
 
502
  def test_event_triggered_dynamic_selects_first_stable_post_event_frame(self):
503
  poses = np.zeros((10, 5), dtype=np.float32)