anhtld commited on
Commit
17a2884
·
verified ·
1 Parent(s): 56291e2

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(policy_mean + candidate_sigma * noise)
 
 
 
 
 
 
393
 
394
  best_potential = None
395
- best_actions = policy_mean.clone()
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
- result = {"history": history, "best": best_metrics or {}}
 
 
 
 
 
 
 
 
 
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 = {"history": history, "best": val_metrics, "torch_available": False}
 
 
 
 
 
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.