Auto-sync: 2026-06-27 09:54:24
Browse files
dovla_cil/eval/maniskill_policy_rollout.py
CHANGED
|
@@ -292,6 +292,13 @@ def _evaluate_task_cases(
|
|
| 292 |
dtype=torch.float32,
|
| 293 |
device=device,
|
| 294 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 295 |
predicted, candidate_index = _select_action_chunk(
|
| 296 |
model,
|
| 297 |
observations,
|
|
@@ -301,9 +308,10 @@ def _evaluate_task_cases(
|
|
| 301 |
num_candidates=num_candidates,
|
| 302 |
candidate_sigma=candidate_sigma,
|
| 303 |
selection_seed=selection_seed + start,
|
|
|
|
|
|
|
| 304 |
)
|
| 305 |
predicted_np = predicted.detach().cpu().numpy().astype(np.float32)
|
| 306 |
-
env_dim = _env_action_dim(env)
|
| 307 |
adapted = _adapt_action_dim(predicted_np, env_dim)
|
| 308 |
adapted = _clip_to_action_space(adapted, env)
|
| 309 |
after_state, rewards, successes, restore_error = execute_grouped_action_lattice_batch(
|
|
@@ -365,6 +373,8 @@ def _select_action_chunk(
|
|
| 365 |
num_candidates: int,
|
| 366 |
candidate_sigma: float,
|
| 367 |
selection_seed: int,
|
|
|
|
|
|
|
| 368 |
) -> tuple[Any, np.ndarray]:
|
| 369 |
"""Return the executed action chunk per state and the chosen candidate index.
|
| 370 |
|
|
@@ -381,7 +391,7 @@ def _select_action_chunk(
|
|
| 381 |
|
| 382 |
generator = torch.Generator(device=policy_mean.device)
|
| 383 |
generator.manual_seed(int(selection_seed))
|
| 384 |
-
candidates = [policy_mean]
|
| 385 |
for _ in range(num_candidates - 1):
|
| 386 |
noise = torch.randn(
|
| 387 |
policy_mean.shape,
|
|
@@ -389,10 +399,16 @@ def _select_action_chunk(
|
|
| 389 |
device=policy_mean.device,
|
| 390 |
dtype=policy_mean.dtype,
|
| 391 |
)
|
| 392 |
-
candidates.append(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 393 |
|
| 394 |
best_potential = None
|
| 395 |
-
best_actions =
|
| 396 |
best_index = torch.zeros(batch_size, dtype=torch.long, device=policy_mean.device)
|
| 397 |
for cand_idx, candidate in enumerate(candidates):
|
| 398 |
field = model.forward_field(observations, instructions, candidate)
|
|
@@ -413,6 +429,39 @@ def _select_action_chunk(
|
|
| 413 |
return best_actions, best_index.detach().cpu().numpy()
|
| 414 |
|
| 415 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 416 |
def _source_dataset(record: CILRecord, fallback: Path) -> Path:
|
| 417 |
raw = record.metadata.get("source_dataset")
|
| 418 |
return Path(str(raw)).resolve() if raw else fallback.resolve()
|
|
|
|
| 292 |
dtype=torch.float32,
|
| 293 |
device=device,
|
| 294 |
)
|
| 295 |
+
env_dim = _env_action_dim(env)
|
| 296 |
+
action_low, action_high = _action_bounds_for_tensor(
|
| 297 |
+
env,
|
| 298 |
+
torch=torch,
|
| 299 |
+
device=device,
|
| 300 |
+
action_dim=model_config.action_dim,
|
| 301 |
+
)
|
| 302 |
predicted, candidate_index = _select_action_chunk(
|
| 303 |
model,
|
| 304 |
observations,
|
|
|
|
| 308 |
num_candidates=num_candidates,
|
| 309 |
candidate_sigma=candidate_sigma,
|
| 310 |
selection_seed=selection_seed + start,
|
| 311 |
+
action_low=action_low,
|
| 312 |
+
action_high=action_high,
|
| 313 |
)
|
| 314 |
predicted_np = predicted.detach().cpu().numpy().astype(np.float32)
|
|
|
|
| 315 |
adapted = _adapt_action_dim(predicted_np, env_dim)
|
| 316 |
adapted = _clip_to_action_space(adapted, env)
|
| 317 |
after_state, rewards, successes, restore_error = execute_grouped_action_lattice_batch(
|
|
|
|
| 373 |
num_candidates: int,
|
| 374 |
candidate_sigma: float,
|
| 375 |
selection_seed: int,
|
| 376 |
+
action_low: Any | None = None,
|
| 377 |
+
action_high: Any | None = None,
|
| 378 |
) -> tuple[Any, np.ndarray]:
|
| 379 |
"""Return the executed action chunk per state and the chosen candidate index.
|
| 380 |
|
|
|
|
| 391 |
|
| 392 |
generator = torch.Generator(device=policy_mean.device)
|
| 393 |
generator.manual_seed(int(selection_seed))
|
| 394 |
+
candidates = [_clamp_action_tensor(policy_mean, action_low=action_low, action_high=action_high)]
|
| 395 |
for _ in range(num_candidates - 1):
|
| 396 |
noise = torch.randn(
|
| 397 |
policy_mean.shape,
|
|
|
|
| 399 |
device=policy_mean.device,
|
| 400 |
dtype=policy_mean.dtype,
|
| 401 |
)
|
| 402 |
+
candidates.append(
|
| 403 |
+
_clamp_action_tensor(
|
| 404 |
+
policy_mean + candidate_sigma * noise,
|
| 405 |
+
action_low=action_low,
|
| 406 |
+
action_high=action_high,
|
| 407 |
+
)
|
| 408 |
+
)
|
| 409 |
|
| 410 |
best_potential = None
|
| 411 |
+
best_actions = candidates[0].clone()
|
| 412 |
best_index = torch.zeros(batch_size, dtype=torch.long, device=policy_mean.device)
|
| 413 |
for cand_idx, candidate in enumerate(candidates):
|
| 414 |
field = model.forward_field(observations, instructions, candidate)
|
|
|
|
| 429 |
return best_actions, best_index.detach().cpu().numpy()
|
| 430 |
|
| 431 |
|
| 432 |
+
def _action_bounds_for_tensor(
|
| 433 |
+
env: Any,
|
| 434 |
+
*,
|
| 435 |
+
torch: Any,
|
| 436 |
+
device: str,
|
| 437 |
+
action_dim: int,
|
| 438 |
+
) -> tuple[Any | None, Any | None]:
|
| 439 |
+
space = getattr(env, "single_action_space", None) or getattr(env, "action_space", None)
|
| 440 |
+
low = getattr(space, "low", None)
|
| 441 |
+
high = getattr(space, "high", None)
|
| 442 |
+
if low is None or high is None:
|
| 443 |
+
return None, None
|
| 444 |
+
low_arr = np.asarray(low, dtype=np.float32).reshape(-1)
|
| 445 |
+
high_arr = np.asarray(high, dtype=np.float32).reshape(-1)
|
| 446 |
+
if low_arr.size < action_dim or high_arr.size < action_dim:
|
| 447 |
+
return None, None
|
| 448 |
+
low_tensor = torch.as_tensor(low_arr[-action_dim:], dtype=torch.float32, device=device).reshape(
|
| 449 |
+
1, 1, action_dim
|
| 450 |
+
)
|
| 451 |
+
high_tensor = torch.as_tensor(
|
| 452 |
+
high_arr[-action_dim:], dtype=torch.float32, device=device
|
| 453 |
+
).reshape(1, 1, action_dim)
|
| 454 |
+
return low_tensor, high_tensor
|
| 455 |
+
|
| 456 |
+
|
| 457 |
+
def _clamp_action_tensor(action: Any, *, action_low: Any | None, action_high: Any | None) -> Any:
|
| 458 |
+
if action_low is not None:
|
| 459 |
+
action = action.clamp_min(action_low)
|
| 460 |
+
if action_high is not None:
|
| 461 |
+
action = action.clamp_max(action_high)
|
| 462 |
+
return action
|
| 463 |
+
|
| 464 |
+
|
| 465 |
def _source_dataset(record: CILRecord, fallback: Path) -> Path:
|
| 466 |
raw = record.metadata.get("source_dataset")
|
| 467 |
return Path(str(raw)).resolve() if raw else fallback.resolve()
|
dovla_cil/training/trainer.py
CHANGED
|
@@ -148,6 +148,7 @@ class DoVLATrainer:
|
|
| 148 |
)
|
| 149 |
self.wandb_run = self._maybe_init_wandb()
|
| 150 |
self.best_metric: float | None = None
|
|
|
|
| 151 |
|
| 152 |
def train(self) -> dict[str, Any]:
|
| 153 |
write_json(self._resolved_config(), self.output_dir / "resolved_config.json")
|
|
@@ -156,6 +157,7 @@ class DoVLATrainer:
|
|
| 156 |
|
| 157 |
history: list[dict[str, Any]] = []
|
| 158 |
best_metrics: dict[str, float] | None = None
|
|
|
|
| 159 |
for epoch in range(1, self.config.epochs + 1):
|
| 160 |
train_metrics = self._run_epoch(self.train_group_ids, train=True, epoch=epoch)
|
| 161 |
val_metrics = self._run_epoch(self.val_group_ids, train=False, epoch=epoch)
|
|
@@ -170,11 +172,23 @@ class DoVLATrainer:
|
|
| 170 |
if self._is_better(val_metrics):
|
| 171 |
best_metrics = val_metrics
|
| 172 |
self._save_checkpoint("best.pt", epoch=epoch, metrics=epoch_summary)
|
|
|
|
|
|
|
|
|
|
| 173 |
|
| 174 |
if best_metrics is None and history:
|
| 175 |
self._save_checkpoint("best.pt", epoch=history[-1]["epoch"], metrics=history[-1])
|
| 176 |
best_metrics = history[-1]["val"]
|
| 177 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 178 |
write_json(result, self.output_dir / "metrics.json")
|
| 179 |
if self.wandb_run is not None:
|
| 180 |
self.wandb_run.finish()
|
|
@@ -451,6 +465,13 @@ class DoVLATrainer:
|
|
| 451 |
return True
|
| 452 |
return False
|
| 453 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 454 |
def _resolve_device(self, device: str) -> str:
|
| 455 |
if torch is None:
|
| 456 |
return "cpu"
|
|
@@ -496,9 +517,15 @@ class DoVLATrainer:
|
|
| 496 |
train_metrics = _heuristic_metrics(self.dataset, self.train_group_ids)
|
| 497 |
val_metrics = _heuristic_metrics(self.dataset, self.val_group_ids)
|
| 498 |
history = [{"epoch": 1, "train": train_metrics, "val": val_metrics}]
|
| 499 |
-
summary = {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 500 |
self._save_checkpoint("latest.pt", epoch=1, metrics=history[0])
|
| 501 |
self._save_checkpoint("best.pt", epoch=1, metrics=history[0])
|
|
|
|
| 502 |
write_json(summary, self.output_dir / "metrics.json")
|
| 503 |
print(
|
| 504 |
"torch is not installed; wrote deterministic heuristic smoke checkpoints "
|
|
|
|
| 148 |
)
|
| 149 |
self.wandb_run = self._maybe_init_wandb()
|
| 150 |
self.best_metric: float | None = None
|
| 151 |
+
self.best_policy_metric: float | None = None
|
| 152 |
|
| 153 |
def train(self) -> dict[str, Any]:
|
| 154 |
write_json(self._resolved_config(), self.output_dir / "resolved_config.json")
|
|
|
|
| 157 |
|
| 158 |
history: list[dict[str, Any]] = []
|
| 159 |
best_metrics: dict[str, float] | None = None
|
| 160 |
+
best_policy_metrics: dict[str, float] | None = None
|
| 161 |
for epoch in range(1, self.config.epochs + 1):
|
| 162 |
train_metrics = self._run_epoch(self.train_group_ids, train=True, epoch=epoch)
|
| 163 |
val_metrics = self._run_epoch(self.val_group_ids, train=False, epoch=epoch)
|
|
|
|
| 172 |
if self._is_better(val_metrics):
|
| 173 |
best_metrics = val_metrics
|
| 174 |
self._save_checkpoint("best.pt", epoch=epoch, metrics=epoch_summary)
|
| 175 |
+
if self._is_better_policy(val_metrics):
|
| 176 |
+
best_policy_metrics = val_metrics
|
| 177 |
+
self._save_checkpoint("best_policy.pt", epoch=epoch, metrics=epoch_summary)
|
| 178 |
|
| 179 |
if best_metrics is None and history:
|
| 180 |
self._save_checkpoint("best.pt", epoch=history[-1]["epoch"], metrics=history[-1])
|
| 181 |
best_metrics = history[-1]["val"]
|
| 182 |
+
if best_policy_metrics is None and history:
|
| 183 |
+
self._save_checkpoint(
|
| 184 |
+
"best_policy.pt", epoch=history[-1]["epoch"], metrics=history[-1]
|
| 185 |
+
)
|
| 186 |
+
best_policy_metrics = history[-1]["val"]
|
| 187 |
+
result = {
|
| 188 |
+
"history": history,
|
| 189 |
+
"best": best_metrics or {},
|
| 190 |
+
"best_policy": best_policy_metrics or {},
|
| 191 |
+
}
|
| 192 |
write_json(result, self.output_dir / "metrics.json")
|
| 193 |
if self.wandb_run is not None:
|
| 194 |
self.wandb_run.finish()
|
|
|
|
| 465 |
return True
|
| 466 |
return False
|
| 467 |
|
| 468 |
+
def _is_better_policy(self, val_metrics: dict[str, float]) -> bool:
|
| 469 |
+
bc_loss = float(val_metrics.get("bc_loss", float("inf")))
|
| 470 |
+
if self.best_policy_metric is None or bc_loss < self.best_policy_metric:
|
| 471 |
+
self.best_policy_metric = bc_loss
|
| 472 |
+
return True
|
| 473 |
+
return False
|
| 474 |
+
|
| 475 |
def _resolve_device(self, device: str) -> str:
|
| 476 |
if torch is None:
|
| 477 |
return "cpu"
|
|
|
|
| 517 |
train_metrics = _heuristic_metrics(self.dataset, self.train_group_ids)
|
| 518 |
val_metrics = _heuristic_metrics(self.dataset, self.val_group_ids)
|
| 519 |
history = [{"epoch": 1, "train": train_metrics, "val": val_metrics}]
|
| 520 |
+
summary = {
|
| 521 |
+
"history": history,
|
| 522 |
+
"best": val_metrics,
|
| 523 |
+
"best_policy": val_metrics,
|
| 524 |
+
"torch_available": False,
|
| 525 |
+
}
|
| 526 |
self._save_checkpoint("latest.pt", epoch=1, metrics=history[0])
|
| 527 |
self._save_checkpoint("best.pt", epoch=1, metrics=history[0])
|
| 528 |
+
self._save_checkpoint("best_policy.pt", epoch=1, metrics=history[0])
|
| 529 |
write_json(summary, self.output_dir / "metrics.json")
|
| 530 |
print(
|
| 531 |
"torch is not installed; wrote deterministic heuristic smoke checkpoints "
|
logs/auto_sync_hf.log
CHANGED
|
@@ -130,3 +130,4 @@ No files have been modified since last commit. Skipping to prevent empty commit.
|
|
| 130 |
No files have been modified since last commit. Skipping to prevent empty commit.
|
| 131 |
No files have been modified since last commit. Skipping to prevent empty commit.
|
| 132 |
No files have been modified since last commit. Skipping to prevent empty commit.
|
|
|
|
|
|
| 130 |
No files have been modified since last commit. Skipping to prevent empty commit.
|
| 131 |
No files have been modified since last commit. Skipping to prevent empty commit.
|
| 132 |
No files have been modified since last commit. Skipping to prevent empty commit.
|
| 133 |
+
No files have been modified since last commit. Skipping to prevent empty commit.
|