Auto-sync: 2026-06-28 17:30:45
Browse files
dovla_cil/eval/maniskill_policy_rollout.py
CHANGED
|
@@ -69,6 +69,7 @@ def evaluate_maniskill_policy_rollout(
|
|
| 69 |
retrieval_residual_anchor: str = "expert",
|
| 70 |
retrieval_residual_reduce: str = "none",
|
| 71 |
lattice_exclude_types: tuple[str, ...] = (),
|
|
|
|
| 72 |
) -> dict[str, Any]:
|
| 73 |
"""Execute a checkpoint policy from restored ManiSkill CIL states.
|
| 74 |
|
|
@@ -106,6 +107,10 @@ def evaluate_maniskill_policy_rollout(
|
|
| 106 |
optional Gaussian multi-start proposals, performs projected gradient ascent on the learned
|
| 107 |
field potential in action space, and executes the best optimized chunk. This is still
|
| 108 |
deployment-clean: no dataset action candidates or rewards are consulted.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
"""
|
| 110 |
|
| 111 |
try:
|
|
@@ -160,6 +165,10 @@ def evaluate_maniskill_policy_rollout(
|
|
| 160 |
raise ValueError("retrieval_residual_scale must be non-negative")
|
| 161 |
if any(scale < 0 for scale in retrieval_residual_scales):
|
| 162 |
raise ValueError("retrieval_residual_scales must be non-negative")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 163 |
if selection_mode == "policy":
|
| 164 |
num_candidates = 1
|
| 165 |
checkpoint = torch.load(
|
|
@@ -255,6 +264,7 @@ def evaluate_maniskill_policy_rollout(
|
|
| 255 |
retrieval_residual_scale=retrieval_residual_scale,
|
| 256 |
retrieval_residual_scales=retrieval_residual_scales,
|
| 257 |
lattice_exclude_types=lattice_exclude_types,
|
|
|
|
| 258 |
)
|
| 259 |
rows.extend(task_rows)
|
| 260 |
task_summaries[task_id] = _summarize_rows(task_rows)
|
|
@@ -318,6 +328,7 @@ def evaluate_maniskill_policy_rollout(
|
|
| 318 |
if selection_mode == "retrieval_residual"
|
| 319 |
else "none",
|
| 320 |
"lattice_exclude_types": list(lattice_exclude_types),
|
|
|
|
| 321 |
"policy_rollout_success_rate": _mean([row["success"] for row in rows]),
|
| 322 |
"policy_rollout_progress": _mean([row["progress"] for row in rows]),
|
| 323 |
"oracle_success_rate": _mean([row["oracle_success"] for row in rows]),
|
|
@@ -678,6 +689,7 @@ def _evaluate_task_cases(
|
|
| 678 |
retrieval_residual_scale: float = 1.0,
|
| 679 |
retrieval_residual_scales: tuple[float, ...] = (),
|
| 680 |
lattice_exclude_types: tuple[str, ...] = (),
|
|
|
|
| 681 |
) -> list[dict[str, Any]]:
|
| 682 |
rows: list[dict[str, Any]] = []
|
| 683 |
for start in range(0, len(cases), group_batch_size):
|
|
@@ -767,6 +779,17 @@ def _evaluate_task_cases(
|
|
| 767 |
and lattice_exclude_types
|
| 768 |
else None
|
| 769 |
),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 770 |
)
|
| 771 |
predicted_np = predicted.detach().cpu().numpy().astype(np.float32)
|
| 772 |
adapted = _adapt_action_dim(predicted_np, env_dim)
|
|
@@ -864,6 +887,7 @@ def _select_action_chunk(
|
|
| 864 |
action_high: Any | None = None,
|
| 865 |
action_candidates: Any | None = None,
|
| 866 |
candidate_mask: Any | None = None,
|
|
|
|
| 867 |
) -> tuple[Any, np.ndarray]:
|
| 868 |
"""Return the executed action chunk per state and the chosen candidate index.
|
| 869 |
|
|
@@ -891,6 +915,7 @@ def _select_action_chunk(
|
|
| 891 |
action_low=action_low,
|
| 892 |
action_high=action_high,
|
| 893 |
candidate_mask=candidate_mask,
|
|
|
|
| 894 |
selection_margin=selection_margin,
|
| 895 |
baseline_action=policy_baseline,
|
| 896 |
)
|
|
@@ -910,6 +935,7 @@ def _select_action_chunk(
|
|
| 910 |
action_low=action_low,
|
| 911 |
action_high=action_high,
|
| 912 |
candidate_mask=candidate_mask,
|
|
|
|
| 913 |
residual_scale=retrieval_residual_scale,
|
| 914 |
residual_scales=retrieval_residual_scales,
|
| 915 |
num_gaussian_candidates=num_candidates,
|
|
@@ -1155,6 +1181,7 @@ def _select_lattice_action_chunk(
|
|
| 1155 |
action_low: Any | None,
|
| 1156 |
action_high: Any | None,
|
| 1157 |
candidate_mask: Any | None,
|
|
|
|
| 1158 |
selection_margin: float = 0.0,
|
| 1159 |
baseline_action: Any | None = None,
|
| 1160 |
) -> tuple[Any, np.ndarray]:
|
|
@@ -1175,6 +1202,14 @@ def _select_lattice_action_chunk(
|
|
| 1175 |
device=candidate_mask.device,
|
| 1176 |
)
|
| 1177 |
candidate_mask = torch.cat([baseline_mask, candidate_mask], dim=1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1178 |
batch_size, candidate_count = action_candidates.shape[:2]
|
| 1179 |
candidates = _clamp_action_tensor(
|
| 1180 |
action_candidates,
|
|
@@ -1194,6 +1229,13 @@ def _select_lattice_action_chunk(
|
|
| 1194 |
]
|
| 1195 |
field = model.forward_field(flat_observations, flat_instructions, flat_candidates)
|
| 1196 |
potentials = field["potential"].reshape(batch_size, candidate_count)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1197 |
if candidate_mask is not None:
|
| 1198 |
potentials = potentials.masked_fill(~candidate_mask, float("-inf"))
|
| 1199 |
best_index = torch.argmax(potentials, dim=1)
|
|
@@ -1220,6 +1262,7 @@ def _select_residual_lattice_action_chunk(
|
|
| 1220 |
action_low: Any | None,
|
| 1221 |
action_high: Any | None,
|
| 1222 |
candidate_mask: Any | None,
|
|
|
|
| 1223 |
residual_scale: float,
|
| 1224 |
num_gaussian_candidates: int,
|
| 1225 |
candidate_sigma: float,
|
|
@@ -1241,6 +1284,8 @@ def _select_residual_lattice_action_chunk(
|
|
| 1241 |
candidates = torch.cat(candidate_blocks, dim=1)
|
| 1242 |
if candidate_mask is not None and len(scales) > 1:
|
| 1243 |
candidate_mask = torch.cat([candidate_mask for _ in scales], dim=1)
|
|
|
|
|
|
|
| 1244 |
if num_gaussian_candidates > 1 and candidate_sigma > 0:
|
| 1245 |
generator = torch.Generator(device=policy_mean.device)
|
| 1246 |
generator.manual_seed(int(selection_seed))
|
|
@@ -1265,6 +1310,14 @@ def _select_residual_lattice_action_chunk(
|
|
| 1265 |
device=candidate_mask.device,
|
| 1266 |
)
|
| 1267 |
candidate_mask = torch.cat([candidate_mask, extra_mask], dim=1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1268 |
return _select_lattice_action_chunk(
|
| 1269 |
model,
|
| 1270 |
observations,
|
|
@@ -1282,6 +1335,7 @@ def _select_residual_lattice_action_chunk(
|
|
| 1282 |
else action_high
|
| 1283 |
),
|
| 1284 |
candidate_mask=candidate_mask,
|
|
|
|
| 1285 |
selection_margin=selection_margin,
|
| 1286 |
)
|
| 1287 |
|
|
@@ -1344,6 +1398,27 @@ def _lattice_candidate_mask(
|
|
| 1344 |
return torch.tensor(rows, dtype=torch.bool, device=device)
|
| 1345 |
|
| 1346 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1347 |
def _selected_candidate_type(
|
| 1348 |
case: _RolloutCase,
|
| 1349 |
*,
|
|
|
|
| 69 |
retrieval_residual_anchor: str = "expert",
|
| 70 |
retrieval_residual_reduce: str = "none",
|
| 71 |
lattice_exclude_types: tuple[str, ...] = (),
|
| 72 |
+
candidate_type_bonuses: dict[str, float] | None = None,
|
| 73 |
) -> dict[str, Any]:
|
| 74 |
"""Execute a checkpoint policy from restored ManiSkill CIL states.
|
| 75 |
|
|
|
|
| 107 |
optional Gaussian multi-start proposals, performs projected gradient ascent on the learned
|
| 108 |
field potential in action space, and executes the best optimized chunk. This is still
|
| 109 |
deployment-clean: no dataset action candidates or rewards are consulted.
|
| 110 |
+
|
| 111 |
+
``candidate_type_bonuses`` adds small type-specific priors to field potentials before
|
| 112 |
+
selection. The default empty mapping preserves previous behavior; non-empty values test
|
| 113 |
+
typed sparse-intervention hypotheses without reading validation rewards.
|
| 114 |
"""
|
| 115 |
|
| 116 |
try:
|
|
|
|
| 165 |
raise ValueError("retrieval_residual_scale must be non-negative")
|
| 166 |
if any(scale < 0 for scale in retrieval_residual_scales):
|
| 167 |
raise ValueError("retrieval_residual_scales must be non-negative")
|
| 168 |
+
candidate_type_bonuses = {
|
| 169 |
+
str(candidate_type): float(bonus)
|
| 170 |
+
for candidate_type, bonus in (candidate_type_bonuses or {}).items()
|
| 171 |
+
}
|
| 172 |
if selection_mode == "policy":
|
| 173 |
num_candidates = 1
|
| 174 |
checkpoint = torch.load(
|
|
|
|
| 264 |
retrieval_residual_scale=retrieval_residual_scale,
|
| 265 |
retrieval_residual_scales=retrieval_residual_scales,
|
| 266 |
lattice_exclude_types=lattice_exclude_types,
|
| 267 |
+
candidate_type_bonuses=candidate_type_bonuses,
|
| 268 |
)
|
| 269 |
rows.extend(task_rows)
|
| 270 |
task_summaries[task_id] = _summarize_rows(task_rows)
|
|
|
|
| 328 |
if selection_mode == "retrieval_residual"
|
| 329 |
else "none",
|
| 330 |
"lattice_exclude_types": list(lattice_exclude_types),
|
| 331 |
+
"candidate_type_bonuses": candidate_type_bonuses,
|
| 332 |
"policy_rollout_success_rate": _mean([row["success"] for row in rows]),
|
| 333 |
"policy_rollout_progress": _mean([row["progress"] for row in rows]),
|
| 334 |
"oracle_success_rate": _mean([row["oracle_success"] for row in rows]),
|
|
|
|
| 689 |
retrieval_residual_scale: float = 1.0,
|
| 690 |
retrieval_residual_scales: tuple[float, ...] = (),
|
| 691 |
lattice_exclude_types: tuple[str, ...] = (),
|
| 692 |
+
candidate_type_bonuses: dict[str, float] | None = None,
|
| 693 |
) -> list[dict[str, Any]]:
|
| 694 |
rows: list[dict[str, Any]] = []
|
| 695 |
for start in range(0, len(cases), group_batch_size):
|
|
|
|
| 779 |
and lattice_exclude_types
|
| 780 |
else None
|
| 781 |
),
|
| 782 |
+
candidate_type_bonus=(
|
| 783 |
+
_lattice_candidate_type_bonus(
|
| 784 |
+
batch,
|
| 785 |
+
torch=torch,
|
| 786 |
+
device=device,
|
| 787 |
+
candidate_type_bonuses=candidate_type_bonuses or {},
|
| 788 |
+
)
|
| 789 |
+
if selection_mode in {"lattice", "retrieval_lattice", "retrieval_residual"}
|
| 790 |
+
and candidate_type_bonuses
|
| 791 |
+
else None
|
| 792 |
+
),
|
| 793 |
)
|
| 794 |
predicted_np = predicted.detach().cpu().numpy().astype(np.float32)
|
| 795 |
adapted = _adapt_action_dim(predicted_np, env_dim)
|
|
|
|
| 887 |
action_high: Any | None = None,
|
| 888 |
action_candidates: Any | None = None,
|
| 889 |
candidate_mask: Any | None = None,
|
| 890 |
+
candidate_type_bonus: Any | None = None,
|
| 891 |
) -> tuple[Any, np.ndarray]:
|
| 892 |
"""Return the executed action chunk per state and the chosen candidate index.
|
| 893 |
|
|
|
|
| 915 |
action_low=action_low,
|
| 916 |
action_high=action_high,
|
| 917 |
candidate_mask=candidate_mask,
|
| 918 |
+
candidate_type_bonus=candidate_type_bonus,
|
| 919 |
selection_margin=selection_margin,
|
| 920 |
baseline_action=policy_baseline,
|
| 921 |
)
|
|
|
|
| 935 |
action_low=action_low,
|
| 936 |
action_high=action_high,
|
| 937 |
candidate_mask=candidate_mask,
|
| 938 |
+
candidate_type_bonus=candidate_type_bonus,
|
| 939 |
residual_scale=retrieval_residual_scale,
|
| 940 |
residual_scales=retrieval_residual_scales,
|
| 941 |
num_gaussian_candidates=num_candidates,
|
|
|
|
| 1181 |
action_low: Any | None,
|
| 1182 |
action_high: Any | None,
|
| 1183 |
candidate_mask: Any | None,
|
| 1184 |
+
candidate_type_bonus: Any | None = None,
|
| 1185 |
selection_margin: float = 0.0,
|
| 1186 |
baseline_action: Any | None = None,
|
| 1187 |
) -> tuple[Any, np.ndarray]:
|
|
|
|
| 1202 |
device=candidate_mask.device,
|
| 1203 |
)
|
| 1204 |
candidate_mask = torch.cat([baseline_mask, candidate_mask], dim=1)
|
| 1205 |
+
if candidate_type_bonus is not None:
|
| 1206 |
+
baseline_bonus = torch.zeros(
|
| 1207 |
+
candidate_type_bonus.shape[0],
|
| 1208 |
+
1,
|
| 1209 |
+
dtype=candidate_type_bonus.dtype,
|
| 1210 |
+
device=candidate_type_bonus.device,
|
| 1211 |
+
)
|
| 1212 |
+
candidate_type_bonus = torch.cat([baseline_bonus, candidate_type_bonus], dim=1)
|
| 1213 |
batch_size, candidate_count = action_candidates.shape[:2]
|
| 1214 |
candidates = _clamp_action_tensor(
|
| 1215 |
action_candidates,
|
|
|
|
| 1229 |
]
|
| 1230 |
field = model.forward_field(flat_observations, flat_instructions, flat_candidates)
|
| 1231 |
potentials = field["potential"].reshape(batch_size, candidate_count)
|
| 1232 |
+
if candidate_type_bonus is not None:
|
| 1233 |
+
if candidate_type_bonus.shape != potentials.shape:
|
| 1234 |
+
raise ValueError("candidate_type_bonus must have shape [B,K]")
|
| 1235 |
+
potentials = potentials + candidate_type_bonus.to(
|
| 1236 |
+
device=potentials.device,
|
| 1237 |
+
dtype=potentials.dtype,
|
| 1238 |
+
)
|
| 1239 |
if candidate_mask is not None:
|
| 1240 |
potentials = potentials.masked_fill(~candidate_mask, float("-inf"))
|
| 1241 |
best_index = torch.argmax(potentials, dim=1)
|
|
|
|
| 1262 |
action_low: Any | None,
|
| 1263 |
action_high: Any | None,
|
| 1264 |
candidate_mask: Any | None,
|
| 1265 |
+
candidate_type_bonus: Any | None = None,
|
| 1266 |
residual_scale: float,
|
| 1267 |
num_gaussian_candidates: int,
|
| 1268 |
candidate_sigma: float,
|
|
|
|
| 1284 |
candidates = torch.cat(candidate_blocks, dim=1)
|
| 1285 |
if candidate_mask is not None and len(scales) > 1:
|
| 1286 |
candidate_mask = torch.cat([candidate_mask for _ in scales], dim=1)
|
| 1287 |
+
if candidate_type_bonus is not None and len(scales) > 1:
|
| 1288 |
+
candidate_type_bonus = torch.cat([candidate_type_bonus for _ in scales], dim=1)
|
| 1289 |
if num_gaussian_candidates > 1 and candidate_sigma > 0:
|
| 1290 |
generator = torch.Generator(device=policy_mean.device)
|
| 1291 |
generator.manual_seed(int(selection_seed))
|
|
|
|
| 1310 |
device=candidate_mask.device,
|
| 1311 |
)
|
| 1312 |
candidate_mask = torch.cat([candidate_mask, extra_mask], dim=1)
|
| 1313 |
+
if candidate_type_bonus is not None:
|
| 1314 |
+
extra_bonus = torch.zeros(
|
| 1315 |
+
candidate_type_bonus.shape[0],
|
| 1316 |
+
num_gaussian_candidates - 1,
|
| 1317 |
+
dtype=candidate_type_bonus.dtype,
|
| 1318 |
+
device=candidate_type_bonus.device,
|
| 1319 |
+
)
|
| 1320 |
+
candidate_type_bonus = torch.cat([candidate_type_bonus, extra_bonus], dim=1)
|
| 1321 |
return _select_lattice_action_chunk(
|
| 1322 |
model,
|
| 1323 |
observations,
|
|
|
|
| 1335 |
else action_high
|
| 1336 |
),
|
| 1337 |
candidate_mask=candidate_mask,
|
| 1338 |
+
candidate_type_bonus=candidate_type_bonus,
|
| 1339 |
selection_margin=selection_margin,
|
| 1340 |
)
|
| 1341 |
|
|
|
|
| 1398 |
return torch.tensor(rows, dtype=torch.bool, device=device)
|
| 1399 |
|
| 1400 |
|
| 1401 |
+
def _lattice_candidate_type_bonus(
|
| 1402 |
+
batch: list[_RolloutCase],
|
| 1403 |
+
*,
|
| 1404 |
+
torch: Any,
|
| 1405 |
+
device: str,
|
| 1406 |
+
candidate_type_bonuses: dict[str, float],
|
| 1407 |
+
) -> Any:
|
| 1408 |
+
rows: list[list[float]] = []
|
| 1409 |
+
for case in batch:
|
| 1410 |
+
bonuses: list[float] = []
|
| 1411 |
+
for candidate_type in case.candidate_types:
|
| 1412 |
+
bonus = candidate_type_bonuses.get(candidate_type)
|
| 1413 |
+
if bonus is None:
|
| 1414 |
+
bonus = candidate_type_bonuses.get(f"retrieval_residual_{candidate_type}")
|
| 1415 |
+
if bonus is None:
|
| 1416 |
+
bonus = candidate_type_bonuses.get(f"lattice_{candidate_type}")
|
| 1417 |
+
bonuses.append(float(bonus or 0.0))
|
| 1418 |
+
rows.append(bonuses)
|
| 1419 |
+
return torch.tensor(rows, dtype=torch.float32, device=device)
|
| 1420 |
+
|
| 1421 |
+
|
| 1422 |
def _selected_candidate_type(
|
| 1423 |
case: _RolloutCase,
|
| 1424 |
*,
|
logs/auto_sync_hf.log
CHANGED
|
@@ -208,3 +208,4 @@ No files have been modified since last commit. Skipping to prevent empty commit.
|
|
| 208 |
No files have been modified since last commit. Skipping to prevent empty commit.
|
| 209 |
No files have been modified since last commit. Skipping to prevent empty commit.
|
| 210 |
No files have been modified since last commit. Skipping to prevent empty commit.
|
|
|
|
|
|
| 208 |
No files have been modified since last commit. Skipping to prevent empty commit.
|
| 209 |
No files have been modified since last commit. Skipping to prevent empty commit.
|
| 210 |
No files have been modified since last commit. Skipping to prevent empty commit.
|
| 211 |
+
No files have been modified since last commit. Skipping to prevent empty commit.
|