anhtld commited on
Commit
811688f
·
verified ·
1 Parent(s): d688d49

Auto-sync: 2026-06-28 22:04:20

Browse files
dovla_cil/eval/maniskill_policy_rollout.py CHANGED
@@ -27,6 +27,15 @@ _FIELD_CONDITIONED_RESIDUAL_REDUCERS = {"field_softmax"}
27
  _RESIDUAL_REDUCERS = (
28
  {"none"} | _NUMPY_RESIDUAL_REDUCERS | _FIELD_CONDITIONED_RESIDUAL_REDUCERS
29
  )
 
 
 
 
 
 
 
 
 
30
 
31
 
32
  @dataclass(frozen=True)
@@ -101,7 +110,8 @@ def evaluate_maniskill_policy_rollout(
101
  training-split state with the same task rather than the evaluated state's own lattice. This
102
  tests whether the field can use reusable intervention proposals without same-state proposal
103
  leakage. ``retrieval_metric='zscore'`` standardizes state features by the train-bank
104
- statistics for each task before nearest-neighbor lookup; the default ``raw`` metric
 
105
  preserves earlier results exactly.
106
 
107
  When ``selection_mode == 'retrieval_residual'`` the evaluator retrieves counterfactual
@@ -159,8 +169,8 @@ def evaluate_maniskill_policy_rollout(
159
  raise ValueError("selection_margin must be non-negative")
160
  if retrieval_neighbors <= 0:
161
  raise ValueError("retrieval_neighbors must be positive")
162
- if retrieval_metric not in {"raw", "zscore"}:
163
- raise ValueError("retrieval_metric must be 'raw' or 'zscore'")
164
  if retrieval_residual_anchor not in {"expert", "policy"}:
165
  raise ValueError("retrieval_residual_anchor must be 'expert' or 'policy'")
166
  if retrieval_residual_reduce not in _RESIDUAL_REDUCERS:
@@ -476,6 +486,7 @@ def _attach_retrieved_lattice_candidates(
476
  query,
477
  retrieval_neighbors=retrieval_neighbors,
478
  retrieval_metric=retrieval_metric,
 
479
  )
480
  source_group_ids: list[str] = []
481
  actions: list[list[list[float]]] = []
@@ -571,6 +582,7 @@ def _attach_retrieved_residual_candidates(
571
  query,
572
  retrieval_neighbors=retrieval_neighbors,
573
  retrieval_metric=retrieval_metric,
 
574
  )
575
  source_group_ids: list[str] = []
576
  residuals: list[list[list[float]]] = []
@@ -684,6 +696,7 @@ def _nearest_retrieval_entries(
684
  *,
685
  retrieval_neighbors: int,
686
  retrieval_metric: str,
 
687
  ) -> list[tuple[Any, np.ndarray, Any, Any]]:
688
  return [
689
  entry
@@ -692,6 +705,7 @@ def _nearest_retrieval_entries(
692
  query,
693
  retrieval_neighbors=retrieval_neighbors,
694
  retrieval_metric=retrieval_metric,
 
695
  )
696
  ]
697
 
@@ -702,6 +716,7 @@ def _nearest_retrieval_entries_with_distances(
702
  *,
703
  retrieval_neighbors: int,
704
  retrieval_metric: str,
 
705
  ) -> list[tuple[tuple[Any, np.ndarray, Any, Any], float]]:
706
  if retrieval_metric == "raw":
707
  scored = [
@@ -709,8 +724,26 @@ def _nearest_retrieval_entries_with_distances(
709
  for item in candidates
710
  ]
711
  return sorted(scored, key=lambda item: item[1])[:retrieval_neighbors]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
712
  if retrieval_metric != "zscore":
713
- raise ValueError("retrieval_metric must be 'raw' or 'zscore'")
714
  features = np.stack([np.asarray(item[1], dtype=np.float32) for item in candidates], axis=0)
715
  mean = features.mean(axis=0, dtype=np.float64).astype(np.float32)
716
  std = features.std(axis=0, dtype=np.float64).astype(np.float32)
@@ -725,6 +758,38 @@ def _nearest_retrieval_entries_with_distances(
725
  ]
726
 
727
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
728
  def _kernel_weights_from_distances(distances: list[float]) -> list[float]:
729
  if not distances:
730
  return []
 
27
  _RESIDUAL_REDUCERS = (
28
  {"none"} | _NUMPY_RESIDUAL_REDUCERS | _FIELD_CONDITIONED_RESIDUAL_REDUCERS
29
  )
30
+ _RETRIEVAL_METRICS = {"raw", "zscore", "task_relative"}
31
+ _MANISKILL_ACTOR_STATE_DIM = 13
32
+ _TASKS_WITH_REFERENCE_ACTOR = {
33
+ "PickCube-v1",
34
+ "PushCube-v1",
35
+ "PullCube-v1",
36
+ "StackCube-v1",
37
+ "PegInsertionSide-v1",
38
+ }
39
 
40
 
41
  @dataclass(frozen=True)
 
110
  training-split state with the same task rather than the evaluated state's own lattice. This
111
  tests whether the field can use reusable intervention proposals without same-state proposal
112
  leakage. ``retrieval_metric='zscore'`` standardizes state features by the train-bank
113
+ statistics for each task before nearest-neighbor lookup; ``task_relative`` retrieves by
114
+ target/reference actor pose blocks rather than full robot state. The default ``raw`` metric
115
  preserves earlier results exactly.
116
 
117
  When ``selection_mode == 'retrieval_residual'`` the evaluator retrieves counterfactual
 
169
  raise ValueError("selection_margin must be non-negative")
170
  if retrieval_neighbors <= 0:
171
  raise ValueError("retrieval_neighbors must be positive")
172
+ if retrieval_metric not in _RETRIEVAL_METRICS:
173
+ raise ValueError("retrieval_metric must be 'raw', 'zscore', or 'task_relative'")
174
  if retrieval_residual_anchor not in {"expert", "policy"}:
175
  raise ValueError("retrieval_residual_anchor must be 'expert' or 'policy'")
176
  if retrieval_residual_reduce not in _RESIDUAL_REDUCERS:
 
486
  query,
487
  retrieval_neighbors=retrieval_neighbors,
488
  retrieval_metric=retrieval_metric,
489
+ task_id=case.task_id,
490
  )
491
  source_group_ids: list[str] = []
492
  actions: list[list[list[float]]] = []
 
582
  query,
583
  retrieval_neighbors=retrieval_neighbors,
584
  retrieval_metric=retrieval_metric,
585
+ task_id=case.task_id,
586
  )
587
  source_group_ids: list[str] = []
588
  residuals: list[list[list[float]]] = []
 
696
  *,
697
  retrieval_neighbors: int,
698
  retrieval_metric: str,
699
+ task_id: str | None = None,
700
  ) -> list[tuple[Any, np.ndarray, Any, Any]]:
701
  return [
702
  entry
 
705
  query,
706
  retrieval_neighbors=retrieval_neighbors,
707
  retrieval_metric=retrieval_metric,
708
+ task_id=task_id,
709
  )
710
  ]
711
 
 
716
  *,
717
  retrieval_neighbors: int,
718
  retrieval_metric: str,
719
+ task_id: str | None = None,
720
  ) -> list[tuple[tuple[Any, np.ndarray, Any, Any], float]]:
721
  if retrieval_metric == "raw":
722
  scored = [
 
724
  for item in candidates
725
  ]
726
  return sorted(scored, key=lambda item: item[1])[:retrieval_neighbors]
727
+ if retrieval_metric == "task_relative":
728
+ normalized_query = _task_relative_retrieval_feature(query, task_id=task_id)
729
+ scored = [
730
+ (
731
+ item,
732
+ float(
733
+ np.mean(
734
+ (
735
+ _task_relative_retrieval_feature(item[1], task_id=task_id)
736
+ - normalized_query
737
+ )
738
+ ** 2
739
+ )
740
+ ),
741
+ )
742
+ for item in candidates
743
+ ]
744
+ return sorted(scored, key=lambda item: item[1])[:retrieval_neighbors]
745
  if retrieval_metric != "zscore":
746
+ raise ValueError("retrieval_metric must be 'raw', 'zscore', or 'task_relative'")
747
  features = np.stack([np.asarray(item[1], dtype=np.float32) for item in candidates], axis=0)
748
  mean = features.mean(axis=0, dtype=np.float64).astype(np.float32)
749
  std = features.std(axis=0, dtype=np.float64).astype(np.float32)
 
758
  ]
759
 
760
 
761
+ def _task_relative_retrieval_feature(
762
+ feature: np.ndarray,
763
+ *,
764
+ task_id: str | None,
765
+ ) -> np.ndarray:
766
+ values = np.asarray(feature, dtype=np.float32).reshape(-1)
767
+ if values.size < _MANISKILL_ACTOR_STATE_DIM:
768
+ return values
769
+ target = values[:_MANISKILL_ACTOR_STATE_DIM]
770
+ parts = [
771
+ 4.0 * target[:3],
772
+ target[3:7],
773
+ ]
774
+ has_reference = (
775
+ task_id in _TASKS_WITH_REFERENCE_ACTOR
776
+ and values.size >= 2 * _MANISKILL_ACTOR_STATE_DIM
777
+ )
778
+ if has_reference:
779
+ start = _MANISKILL_ACTOR_STATE_DIM
780
+ reference = values[start : start + _MANISKILL_ACTOR_STATE_DIM]
781
+ parts.extend(
782
+ [
783
+ 2.0 * reference[:3],
784
+ 4.0 * (target[:3] - reference[:3]),
785
+ reference[3:7],
786
+ ]
787
+ )
788
+ if task_id in {"LiftPegUpright-v1", "PegInsertionSide-v1"}:
789
+ parts.append(2.0 * target[3:7])
790
+ return np.concatenate(parts).astype(np.float32)
791
+
792
+
793
  def _kernel_weights_from_distances(distances: list[float]) -> list[float]:
794
  if not distances:
795
  return []