Auto-sync: 2026-06-27 18:32:13 (part 2)
Browse files- results/nonexpert_proposal_target_census.md +38 -0
- results/paper_story_memo.md +103 -0
- scripts/__pycache__/eval_maniskill_policy_rollout.cpython-311.pyc.139951570731952 +0 -0
- scripts/build_paper_table_status.py +321 -0
- scripts/slurm/build_paper_table_status.sbatch +18 -0
- scripts/slurm/eval_maniskill_policy_rollout_cpu_smoke.sbatch +99 -0
- scripts/slurm/smoke_field_optim_unit.sbatch +104 -0
- scripts/slurm/smoke_retrieval_residual_unit.sbatch +128 -0
results/nonexpert_proposal_target_census.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Non-Expert Proposal Target Census
|
| 2 |
+
|
| 3 |
+
Dataset: `/scratch/knguy52/dovla/experiments/six_task_h16_collection`
|
| 4 |
+
|
| 5 |
+
This census uses the per-task `record_index.jsonl` files and defines score as
|
| 6 |
+
`reward_progress + 1(success)`, matching the trainer's reward score convention.
|
| 7 |
+
|
| 8 |
+
## Candidate Counts
|
| 9 |
+
|
| 10 |
+
| candidate type | records |
|
| 11 |
+
|---|---:|
|
| 12 |
+
| expert | 2,873 |
|
| 13 |
+
| near_miss | 5,746 |
|
| 14 |
+
| wrong_direction | 2,873 |
|
| 15 |
+
| no_op | 2,873 |
|
| 16 |
+
| wrong_gripper | 2,873 |
|
| 17 |
+
| random_negative | 28,730 |
|
| 18 |
+
|
| 19 |
+
## Best Candidate Per State
|
| 20 |
+
|
| 21 |
+
| selection rule | expert | near_miss | wrong_direction | wrong_gripper | random_negative | no_op |
|
| 22 |
+
|---|---:|---:|---:|---:|---:|---:|
|
| 23 |
+
| best any | 1,244 | 988 | 134 | 97 | 258 | 152 |
|
| 24 |
+
| best non-expert | 0 | 1,985 | 186 | 140 | 312 | 250 |
|
| 25 |
+
| best non-expert and successful | 0 | 1,401 | 152 | 117 | 181 | 202 |
|
| 26 |
+
|
| 27 |
+
## Experiment Implication
|
| 28 |
+
|
| 29 |
+
The previous near-miss policy target covers the dominant useful non-expert
|
| 30 |
+
proposal family, but the best non-expert action is not a `near_miss` in 888 of
|
| 31 |
+
2,873 states. Job `14842574` trains `nonexpert_policy_bc5` to imitate the best
|
| 32 |
+
non-expert local intervention using:
|
| 33 |
+
|
| 34 |
+
`POLICY_TARGET_TYPES=near_miss,wrong_direction,wrong_gripper,random_negative,no_op`
|
| 35 |
+
|
| 36 |
+
with `--loss-weight bc=5.0`. Jobs `14842575`/`14842576` evaluate and summarize
|
| 37 |
+
direct `best_policy.pt` rollout, while `14842577`/`14842578` evaluate and
|
| 38 |
+
summarize Gaussian field selection around `best.pt`.
|
results/paper_story_memo.md
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# DoVLA-CIL Paper Story Memo
|
| 2 |
+
|
| 3 |
+
## One-Sentence Thesis
|
| 4 |
+
|
| 5 |
+
DoVLA-CIL is a counterfactual action-selection framework: same-state intervention
|
| 6 |
+
lattices expose a learnable local utility field, and the field only becomes useful
|
| 7 |
+
when queried on proposal geometry that matches those local counterfactuals.
|
| 8 |
+
|
| 9 |
+
## What The Current Evidence Supports
|
| 10 |
+
|
| 11 |
+
| Claim | Evidence | Status |
|
| 12 |
+
|---|---|---|
|
| 13 |
+
| Longer horizon behavior cloning is not enough | h=16 direct policy is 29.74%, essentially h=4 baseline | Supported |
|
| 14 |
+
| The learned field is not a generic off-manifold optimizer | Gaussian field search is 29.10% | Supported |
|
| 15 |
+
| Generic action libraries do not explain the gain | nearest train-state retrieval lattice is 28.93%, no-expert retrieval is 27.13% | Supported |
|
| 16 |
+
| Same-state local counterfactual proposals are the mechanism | near-miss-only lattice is 55.94%; removing expert+near_miss drops to 25.57% | Strongly supported |
|
| 17 |
+
| Conservative same-state result is large | no-expert lattice is 56.99% vs 29.74% policy | Main result |
|
| 18 |
+
| Full lattice gives upper result | full lattice is 69.33%, oracle is 86.78% | Strong but label expert proposal clearly |
|
| 19 |
+
| Deployment-clean proposal is currently a bottleneck | best clean proposal+field sweep is 32.93%, far below 56.99% | Supported |
|
| 20 |
+
| Gradient-based field optimization can solve the clean proposal gap | `field_optim` jobs are pending | Not yet known |
|
| 21 |
+
| A broader non-expert proposal target can reduce the proposal gap | `nonexpert_policy_bc5` jobs are pending; target census shows 888/2873 states have best non-expert action outside `near_miss` | Not yet known |
|
| 22 |
+
| Counterfactual residuals transfer better than absolute retrieved actions | `retrieval_residual` jobs are pending; absolute retrieval was 28.93% | Not yet known |
|
| 23 |
+
|
| 24 |
+
## Main Table Candidate
|
| 25 |
+
|
| 26 |
+
Use `scripts/build_paper_table_status.py` to regenerate
|
| 27 |
+
`results/paper_table_status.md` after jobs finish. Until later jobs improve the
|
| 28 |
+
clean proposal result, the intended main rows are:
|
| 29 |
+
|
| 30 |
+
1. Direct h=16 policy: 29.74%
|
| 31 |
+
2. Gaussian field search: 29.10%
|
| 32 |
+
3. Retrieval lattice, no expert: 27.13%
|
| 33 |
+
4. Near-miss proposal + field, BC x5 field checkpoint: 32.93%
|
| 34 |
+
5. Lattice, near-miss only: 55.94%
|
| 35 |
+
6. Lattice, no expert: 56.99%
|
| 36 |
+
7. Lattice, full: 69.33%
|
| 37 |
+
8. Oracle ceiling: 86.78%
|
| 38 |
+
|
| 39 |
+
## Novelty Framing
|
| 40 |
+
|
| 41 |
+
The novelty should not be framed as combining imitation learning, retrieval, and
|
| 42 |
+
test-time search. The cleaner novelty is:
|
| 43 |
+
|
| 44 |
+
- a data engine that measures many counterfactual interventions from the exact same
|
| 45 |
+
simulator state;
|
| 46 |
+
- a path-independent field that scores action outcomes rather than imitating one
|
| 47 |
+
expert action;
|
| 48 |
+
- a mechanism result showing that near-miss local counterfactuals are the minimal
|
| 49 |
+
proposal family that carries the rollout gain;
|
| 50 |
+
- a proposal-bottleneck story: the learned field is strong, but only on local
|
| 51 |
+
intervention geometry.
|
| 52 |
+
|
| 53 |
+
## Reviewer Risks
|
| 54 |
+
|
| 55 |
+
| Risk | Current answer | Remaining work |
|
| 56 |
+
|---|---|---|
|
| 57 |
+
| Same-state lattice is not deployment-clean | show no-expert lattice and near-miss-only mechanism; show retrieval/Gaussian failures | improve clean proposal route |
|
| 58 |
+
| Full lattice includes expert proposal | label as upper deployment/ceiling, not main conservative result | keep no-expert row as main |
|
| 59 |
+
| Gains are from candidate leakage, not learning | selection never reads candidate rewards; no-expert and near-miss-only isolate mechanism | add field_optim/proposal model evidence |
|
| 60 |
+
| Method is just a bundle of tricks | use mechanism ablations to show one central idea: local counterfactual field | avoid presenting unrelated variants as core |
|
| 61 |
+
| Not SOTA enough | current clean deploy result is modest | need external baselines and stronger proposal generator before claiming SOTA |
|
| 62 |
+
|
| 63 |
+
## Active Jobs
|
| 64 |
+
|
| 65 |
+
Last checked: `2026-06-27 21:12 UTC`.
|
| 66 |
+
|
| 67 |
+
- `14842523`: GPU smoke for `selection_mode=field_optim`.
|
| 68 |
+
- `14842557`: low-resource CPU unit smoke for the pure action-optimization helper.
|
| 69 |
+
- `14842528`: 4-config x 3-seed `field_optim` sweep, dependent on `14842523`.
|
| 70 |
+
- `14842529`: sweep summary, dependent on `14842528`.
|
| 71 |
+
- `14842551`: after-any fallback summary for partial sweep results.
|
| 72 |
+
- `14842574`: train `nonexpert_policy_bc5` on best non-expert local interventions.
|
| 73 |
+
- `14842575`: direct rollout eval for `nonexpert_policy_bc5`.
|
| 74 |
+
- `14842616`: direct rollout summary.
|
| 75 |
+
- `14842577`: field-selection sweep for `nonexpert_policy_bc5`.
|
| 76 |
+
- `14842617`: field-selection summary.
|
| 77 |
+
- `14842596`: smoke-test `retrieval_residual`, which translates nearest
|
| 78 |
+
train-state counterfactual residuals around the policy mean.
|
| 79 |
+
- `14842597`: full `retrieval_residual` rollout after smoke.
|
| 80 |
+
- `14842618`: `retrieval_residual` summary.
|
| 81 |
+
- `14842609`: smoke-test `retrieval_residual` with `RETRIEVAL_NEIGHBORS=4`.
|
| 82 |
+
- `14842610`: full KNN4 `retrieval_residual` rollout after smoke.
|
| 83 |
+
- `14842619`: KNN4 `retrieval_residual` summary.
|
| 84 |
+
- `14842646`: CPU unit smoke for the KNN residual helper.
|
| 85 |
+
|
| 86 |
+
Current scheduler state: `14842523` is waiting on priority, and `14842557` is
|
| 87 |
+
waiting for CPU nodes that are not down, drained, or reserved. The
|
| 88 |
+
`nonexpert_policy_bc5` train array `14842574` is waiting on unavailable GPU
|
| 89 |
+
nodes, and downstream jobs are waiting on dependencies.
|
| 90 |
+
`14842596` is also waiting on currently unavailable GPU nodes; `14842597` and
|
| 91 |
+
`14842618` are dependency-held.
|
| 92 |
+
`14842609` is waiting on the same unavailable GPU nodes; `14842610` and
|
| 93 |
+
`14842619` are dependency-held.
|
| 94 |
+
`14842646` is waiting on unavailable CPU nodes.
|
| 95 |
+
|
| 96 |
+
## Decision Rule For Field Optim Jobs
|
| 97 |
+
|
| 98 |
+
- If `field_optim` beats 32.93% but remains below 40%, keep it as a better
|
| 99 |
+
deployment-clean positive control, not the main result.
|
| 100 |
+
- If `field_optim` reaches 40-50%, promote it to the main clean-deployment bridge
|
| 101 |
+
and frame same-state lattice as mechanistic supervision/upper bound.
|
| 102 |
+
- If `field_optim` fails or stays near 30%, keep it as a negative ablation and
|
| 103 |
+
prioritize training a proposal model on successful non-expert lattice candidates.
|
scripts/__pycache__/eval_maniskill_policy_rollout.cpython-311.pyc.139951570731952
ADDED
|
File without changes
|
scripts/build_paper_table_status.py
ADDED
|
@@ -0,0 +1,321 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python
|
| 2 |
+
from __future__ import annotations
|
| 3 |
+
|
| 4 |
+
import json
|
| 5 |
+
from dataclasses import asdict, dataclass
|
| 6 |
+
from pathlib import Path
|
| 7 |
+
from typing import Any
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
RESULTS_DIR = Path("results")
|
| 11 |
+
BASELINE_H16_POLICY = 0.29739130434782607
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
@dataclass(frozen=True)
|
| 15 |
+
class ResultSpec:
|
| 16 |
+
key: str
|
| 17 |
+
label: str
|
| 18 |
+
path: str
|
| 19 |
+
clean_deployment: str
|
| 20 |
+
same_state_proposals: str
|
| 21 |
+
expert_proposal: str
|
| 22 |
+
story_role: str
|
| 23 |
+
fallback_success: float | None = None
|
| 24 |
+
pending_job: str = ""
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
SPECS = [
|
| 28 |
+
ResultSpec(
|
| 29 |
+
key="h16_policy",
|
| 30 |
+
label="Direct h=16 policy",
|
| 31 |
+
path="h16_policy_ckpt_summary.json",
|
| 32 |
+
clean_deployment="yes",
|
| 33 |
+
same_state_proposals="no",
|
| 34 |
+
expert_proposal="no",
|
| 35 |
+
story_role="behavior-cloning baseline",
|
| 36 |
+
fallback_success=0.29739130434782607,
|
| 37 |
+
),
|
| 38 |
+
ResultSpec(
|
| 39 |
+
key="gaussian_field",
|
| 40 |
+
label="Gaussian field search",
|
| 41 |
+
path="h16_field_sweep_summary.json",
|
| 42 |
+
clean_deployment="yes",
|
| 43 |
+
same_state_proposals="no",
|
| 44 |
+
expert_proposal="no",
|
| 45 |
+
story_role="negative off-manifold field ablation",
|
| 46 |
+
fallback_success=0.2910,
|
| 47 |
+
),
|
| 48 |
+
ResultSpec(
|
| 49 |
+
key="retrieval_lattice_no_expert",
|
| 50 |
+
label="Nearest train-state lattice, no expert",
|
| 51 |
+
path="h16_retrieval_lattice_no_expert_summary.json",
|
| 52 |
+
clean_deployment="yes",
|
| 53 |
+
same_state_proposals="no",
|
| 54 |
+
expert_proposal="no",
|
| 55 |
+
story_role="negative generic action-library ablation",
|
| 56 |
+
fallback_success=0.2713,
|
| 57 |
+
),
|
| 58 |
+
ResultSpec(
|
| 59 |
+
key="near_miss_policy_bc5_field",
|
| 60 |
+
label="Near-miss proposal policy + field",
|
| 61 |
+
path="h16_policy_ckpt_near_miss_policy_bc5_bestpt_field_sweep_summary.json",
|
| 62 |
+
clean_deployment="yes",
|
| 63 |
+
same_state_proposals="no",
|
| 64 |
+
expert_proposal="no",
|
| 65 |
+
story_role="current best clean deployment bridge",
|
| 66 |
+
fallback_success=0.3293,
|
| 67 |
+
),
|
| 68 |
+
ResultSpec(
|
| 69 |
+
key="field_optim",
|
| 70 |
+
label="Trust-region field optimization",
|
| 71 |
+
path="h16_field_optim_near_miss_policy_bc5_bestpt_s4_trust05_summary.json",
|
| 72 |
+
clean_deployment="yes",
|
| 73 |
+
same_state_proposals="no",
|
| 74 |
+
expert_proposal="no",
|
| 75 |
+
story_role="pending differentiable field-ascent bridge",
|
| 76 |
+
pending_job="14842528/14842551",
|
| 77 |
+
),
|
| 78 |
+
ResultSpec(
|
| 79 |
+
key="nonexpert_policy_bc5",
|
| 80 |
+
label="Best non-expert proposal policy",
|
| 81 |
+
path="h16_policy_ckpt_nonexpert_policy_bc5_summary.json",
|
| 82 |
+
clean_deployment="yes",
|
| 83 |
+
same_state_proposals="no",
|
| 84 |
+
expert_proposal="no",
|
| 85 |
+
story_role="pending broader non-expert proposal model",
|
| 86 |
+
pending_job="14842574/14842575/14842616",
|
| 87 |
+
),
|
| 88 |
+
ResultSpec(
|
| 89 |
+
key="nonexpert_policy_bc5_field",
|
| 90 |
+
label="Best non-expert proposal policy + field",
|
| 91 |
+
path="h16_policy_ckpt_nonexpert_policy_bc5_bestpt_field_sweep_summary.json",
|
| 92 |
+
clean_deployment="yes",
|
| 93 |
+
same_state_proposals="no",
|
| 94 |
+
expert_proposal="no",
|
| 95 |
+
story_role="pending broader proposal-field bridge",
|
| 96 |
+
pending_job="14842574/14842577/14842617",
|
| 97 |
+
),
|
| 98 |
+
ResultSpec(
|
| 99 |
+
key="retrieval_residual",
|
| 100 |
+
label="Train-state counterfactual residual retrieval",
|
| 101 |
+
path="h16_policy_ckpt_near_miss_policy_bc5_bestpt_retrieval_residual_summary.json",
|
| 102 |
+
clean_deployment="yes",
|
| 103 |
+
same_state_proposals="no",
|
| 104 |
+
expert_proposal="no",
|
| 105 |
+
story_role="pending transferable local tangent proposal",
|
| 106 |
+
pending_job="14842596/14842597/14842618",
|
| 107 |
+
),
|
| 108 |
+
ResultSpec(
|
| 109 |
+
key="retrieval_residual_knn4",
|
| 110 |
+
label="KNN counterfactual residual retrieval",
|
| 111 |
+
path="h16_policy_ckpt_near_miss_policy_bc5_bestpt_retrieval_residual_knn4_summary.json",
|
| 112 |
+
clean_deployment="yes",
|
| 113 |
+
same_state_proposals="no",
|
| 114 |
+
expert_proposal="no",
|
| 115 |
+
story_role="pending KNN tangent proposal",
|
| 116 |
+
pending_job="14842609/14842610/14842619",
|
| 117 |
+
),
|
| 118 |
+
ResultSpec(
|
| 119 |
+
key="near_miss_only_lattice",
|
| 120 |
+
label="Same-state lattice, near-miss only",
|
| 121 |
+
path="h16_lattice_near_miss_only_v2_summary.json",
|
| 122 |
+
clean_deployment="no",
|
| 123 |
+
same_state_proposals="yes",
|
| 124 |
+
expert_proposal="no",
|
| 125 |
+
story_role="minimal mechanism result",
|
| 126 |
+
fallback_success=0.5594,
|
| 127 |
+
),
|
| 128 |
+
ResultSpec(
|
| 129 |
+
key="no_expert_lattice",
|
| 130 |
+
label="Same-state lattice, no expert",
|
| 131 |
+
path="h16_lattice_no_expert_summary.json",
|
| 132 |
+
clean_deployment="no",
|
| 133 |
+
same_state_proposals="yes",
|
| 134 |
+
expert_proposal="no",
|
| 135 |
+
story_role="main conservative mechanism result",
|
| 136 |
+
fallback_success=0.5699,
|
| 137 |
+
),
|
| 138 |
+
ResultSpec(
|
| 139 |
+
key="no_near_miss_no_expert_lattice",
|
| 140 |
+
label="Same-state lattice, no expert/no near-miss",
|
| 141 |
+
path="h16_lattice_no_near_miss_no_expert_v2_summary.json",
|
| 142 |
+
clean_deployment="no",
|
| 143 |
+
same_state_proposals="yes",
|
| 144 |
+
expert_proposal="no",
|
| 145 |
+
story_role="mechanism knockout",
|
| 146 |
+
fallback_success=0.2557,
|
| 147 |
+
),
|
| 148 |
+
ResultSpec(
|
| 149 |
+
key="full_lattice",
|
| 150 |
+
label="Same-state lattice, full",
|
| 151 |
+
path="h16_lattice_summary.json",
|
| 152 |
+
clean_deployment="no",
|
| 153 |
+
same_state_proposals="yes",
|
| 154 |
+
expert_proposal="yes",
|
| 155 |
+
story_role="upper result with expert proposal",
|
| 156 |
+
fallback_success=0.6933,
|
| 157 |
+
),
|
| 158 |
+
]
|
| 159 |
+
|
| 160 |
+
|
| 161 |
+
def main() -> int:
|
| 162 |
+
RESULTS_DIR.mkdir(exist_ok=True)
|
| 163 |
+
rows = [_row_for_spec(spec) for spec in SPECS]
|
| 164 |
+
payload = {
|
| 165 |
+
"baseline_h16_policy_success": BASELINE_H16_POLICY,
|
| 166 |
+
"rows": rows,
|
| 167 |
+
"best_clean": _best_row(rows, clean="yes"),
|
| 168 |
+
"best_mechanism_no_expert": _best_mechanism_row(rows),
|
| 169 |
+
"decision_notes": _decision_notes(rows),
|
| 170 |
+
}
|
| 171 |
+
json_path = RESULTS_DIR / "paper_table_status.json"
|
| 172 |
+
md_path = RESULTS_DIR / "paper_table_status.md"
|
| 173 |
+
json_path.write_text(json.dumps(payload, indent=2) + "\n")
|
| 174 |
+
md_path.write_text(_render_markdown(payload) + "\n")
|
| 175 |
+
print(f"Wrote {json_path}")
|
| 176 |
+
print(f"Wrote {md_path}")
|
| 177 |
+
return 0
|
| 178 |
+
|
| 179 |
+
|
| 180 |
+
def _row_for_spec(spec: ResultSpec) -> dict[str, Any]:
|
| 181 |
+
path = RESULTS_DIR / spec.path
|
| 182 |
+
extracted = _extract_result(path) if path.exists() else {}
|
| 183 |
+
success = extracted.get("success", spec.fallback_success)
|
| 184 |
+
status = "complete" if path.exists() else ("fallback" if success is not None else "pending")
|
| 185 |
+
return {
|
| 186 |
+
**asdict(spec),
|
| 187 |
+
"path_exists": path.exists(),
|
| 188 |
+
"status": status,
|
| 189 |
+
"success": success,
|
| 190 |
+
"std_success": extracted.get("std_success"),
|
| 191 |
+
"completed_seeds": extracted.get("completed_seeds"),
|
| 192 |
+
"num_completed": extracted.get("num_completed"),
|
| 193 |
+
"best_config": extracted.get("best_config"),
|
| 194 |
+
"gain_vs_h16_policy": (success - BASELINE_H16_POLICY) if success is not None else None,
|
| 195 |
+
}
|
| 196 |
+
|
| 197 |
+
|
| 198 |
+
def _extract_result(path: Path) -> dict[str, Any]:
|
| 199 |
+
data = json.loads(path.read_text())
|
| 200 |
+
output: dict[str, Any] = {}
|
| 201 |
+
if "mean_success" in data:
|
| 202 |
+
output["success"] = _float_or_none(data.get("mean_success"))
|
| 203 |
+
output["std_success"] = _float_or_none(data.get("std_success"))
|
| 204 |
+
output["num_completed"] = data.get("num_completed")
|
| 205 |
+
elif isinstance(data.get("best"), dict):
|
| 206 |
+
best = data["best"]
|
| 207 |
+
output["success"] = _float_or_none(best.get("mean_success"))
|
| 208 |
+
output["std_success"] = _float_or_none(best.get("std_success"))
|
| 209 |
+
output["completed_seeds"] = best.get("completed_seeds")
|
| 210 |
+
output["num_completed"] = best.get("num_completed")
|
| 211 |
+
output["best_config"] = best.get("config")
|
| 212 |
+
elif "policy_rollout_success_rate" in data:
|
| 213 |
+
output["success"] = _float_or_none(data.get("policy_rollout_success_rate"))
|
| 214 |
+
output["num_completed"] = data.get("num_groups")
|
| 215 |
+
return output
|
| 216 |
+
|
| 217 |
+
|
| 218 |
+
def _float_or_none(value: Any) -> float | None:
|
| 219 |
+
if value is None:
|
| 220 |
+
return None
|
| 221 |
+
try:
|
| 222 |
+
return float(value)
|
| 223 |
+
except (TypeError, ValueError):
|
| 224 |
+
return None
|
| 225 |
+
|
| 226 |
+
|
| 227 |
+
def _best_row(rows: list[dict[str, Any]], *, clean: str) -> dict[str, Any] | None:
|
| 228 |
+
completed = [
|
| 229 |
+
row
|
| 230 |
+
for row in rows
|
| 231 |
+
if row["clean_deployment"] == clean and row["success"] is not None
|
| 232 |
+
]
|
| 233 |
+
return max(completed, key=lambda row: row["success"]) if completed else None
|
| 234 |
+
|
| 235 |
+
|
| 236 |
+
def _best_mechanism_row(rows: list[dict[str, Any]]) -> dict[str, Any] | None:
|
| 237 |
+
candidates = [
|
| 238 |
+
row
|
| 239 |
+
for row in rows
|
| 240 |
+
if row["same_state_proposals"] == "yes"
|
| 241 |
+
and row["expert_proposal"] == "no"
|
| 242 |
+
and row["success"] is not None
|
| 243 |
+
]
|
| 244 |
+
return max(candidates, key=lambda row: row["success"]) if candidates else None
|
| 245 |
+
|
| 246 |
+
|
| 247 |
+
def _decision_notes(rows: list[dict[str, Any]]) -> list[str]:
|
| 248 |
+
by_key = {row["key"]: row for row in rows}
|
| 249 |
+
notes = [
|
| 250 |
+
"Use no-expert same-state lattice as the conservative mechanism result, not as deployment-clean inference.",
|
| 251 |
+
"Use full lattice only as an upper result because it includes expert proposals.",
|
| 252 |
+
"Do not claim external SOTA from this table alone; add current external baselines separately.",
|
| 253 |
+
]
|
| 254 |
+
clean_best = _best_row(rows, clean="yes")
|
| 255 |
+
if clean_best is not None:
|
| 256 |
+
notes.append(
|
| 257 |
+
"Current best clean deployment row is "
|
| 258 |
+
f"{clean_best['label']} at {_fmt_percent(clean_best['success'])}."
|
| 259 |
+
)
|
| 260 |
+
for key in ("field_optim", "retrieval_residual", "retrieval_residual_knn4"):
|
| 261 |
+
row = by_key[key]
|
| 262 |
+
if row["success"] is None:
|
| 263 |
+
notes.append(f"{row['label']} is pending ({row['pending_job']}).")
|
| 264 |
+
elif row["success"] >= 0.40:
|
| 265 |
+
notes.append(f"{row['label']} is strong enough to promote as a clean bridge.")
|
| 266 |
+
elif row["success"] > 0.3293:
|
| 267 |
+
notes.append(f"{row['label']} improves the clean bridge but is not yet the main result.")
|
| 268 |
+
else:
|
| 269 |
+
notes.append(f"{row['label']} should be framed as a negative/diagnostic ablation.")
|
| 270 |
+
return notes
|
| 271 |
+
|
| 272 |
+
|
| 273 |
+
def _render_markdown(payload: dict[str, Any]) -> str:
|
| 274 |
+
lines = [
|
| 275 |
+
"# Paper Table Status",
|
| 276 |
+
"",
|
| 277 |
+
f"Baseline h=16 policy: {_fmt_percent(payload['baseline_h16_policy_success'])}",
|
| 278 |
+
"",
|
| 279 |
+
"| key | method | status | success | gain vs h16 | clean | same-state props | expert prop | role |",
|
| 280 |
+
"|---|---|---|---:|---:|---|---|---|---|",
|
| 281 |
+
]
|
| 282 |
+
for row in payload["rows"]:
|
| 283 |
+
lines.append(
|
| 284 |
+
"| {key} | {label} | {status} | {success} | {gain} | {clean} | {same} | {expert} | {role} |".format(
|
| 285 |
+
key=row["key"],
|
| 286 |
+
label=row["label"],
|
| 287 |
+
status=_status_text(row),
|
| 288 |
+
success=_fmt_percent(row["success"]),
|
| 289 |
+
gain=_fmt_signed_percent(row["gain_vs_h16_policy"]),
|
| 290 |
+
clean=row["clean_deployment"],
|
| 291 |
+
same=row["same_state_proposals"],
|
| 292 |
+
expert=row["expert_proposal"],
|
| 293 |
+
role=row["story_role"],
|
| 294 |
+
)
|
| 295 |
+
)
|
| 296 |
+
lines.extend(["", "## Decision Notes", ""])
|
| 297 |
+
for note in payload["decision_notes"]:
|
| 298 |
+
lines.append(f"- {note}")
|
| 299 |
+
return "\n".join(lines)
|
| 300 |
+
|
| 301 |
+
|
| 302 |
+
def _status_text(row: dict[str, Any]) -> str:
|
| 303 |
+
if row["status"] == "pending":
|
| 304 |
+
return f"pending {row['pending_job']}".strip()
|
| 305 |
+
if row["status"] == "fallback":
|
| 306 |
+
return "fallback canonical"
|
| 307 |
+
if row.get("best_config"):
|
| 308 |
+
return f"complete {row['best_config']}"
|
| 309 |
+
return "complete"
|
| 310 |
+
|
| 311 |
+
|
| 312 |
+
def _fmt_percent(value: float | None) -> str:
|
| 313 |
+
return "pending" if value is None else f"{100.0 * value:.2f}%"
|
| 314 |
+
|
| 315 |
+
|
| 316 |
+
def _fmt_signed_percent(value: float | None) -> str:
|
| 317 |
+
return "pending" if value is None else f"{100.0 * value:+.2f} pp"
|
| 318 |
+
|
| 319 |
+
|
| 320 |
+
if __name__ == "__main__":
|
| 321 |
+
raise SystemExit(main())
|
scripts/slurm/build_paper_table_status.sbatch
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
#SBATCH --job-name=build_paper_table
|
| 3 |
+
#SBATCH --account=def-yalda
|
| 4 |
+
#SBATCH --time=00:05:00
|
| 5 |
+
#SBATCH --cpus-per-task=1
|
| 6 |
+
#SBATCH --mem=1G
|
| 7 |
+
#SBATCH --output=outputs/hpc/logs/%x_%j.out
|
| 8 |
+
#SBATCH --error=outputs/hpc/logs/%x_%j.err
|
| 9 |
+
|
| 10 |
+
set -euo pipefail
|
| 11 |
+
|
| 12 |
+
PROJECT_DIR="${PROJECT_DIR:-$SLURM_SUBMIT_DIR}"
|
| 13 |
+
PYTHON="${PYTHON:-python3}"
|
| 14 |
+
|
| 15 |
+
cd "$PROJECT_DIR"
|
| 16 |
+
mkdir -p outputs/hpc/logs results
|
| 17 |
+
|
| 18 |
+
"$PYTHON" scripts/build_paper_table_status.py
|
scripts/slurm/eval_maniskill_policy_rollout_cpu_smoke.sbatch
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
#SBATCH --job-name=dovla_ms_cpu_smoke
|
| 3 |
+
#SBATCH --account=def-yalda
|
| 4 |
+
#SBATCH --nodes=1
|
| 5 |
+
#SBATCH --ntasks=1
|
| 6 |
+
#SBATCH --cpus-per-task=4
|
| 7 |
+
#SBATCH --mem=16G
|
| 8 |
+
#SBATCH --time=00:30:00
|
| 9 |
+
#SBATCH --array=0-0
|
| 10 |
+
#SBATCH --output=outputs/hpc/logs/%x_%A_%a.out
|
| 11 |
+
#SBATCH --error=outputs/hpc/logs/%x_%A_%a.err
|
| 12 |
+
|
| 13 |
+
set -euo pipefail
|
| 14 |
+
|
| 15 |
+
PROJECT_DIR="${PROJECT_DIR:-$SLURM_SUBMIT_DIR}"
|
| 16 |
+
DATASET="${DATASET:?Set DATASET to a ManiSkill CIL dataset or collection}"
|
| 17 |
+
SEED="${SLURM_ARRAY_TASK_ID:-0}"
|
| 18 |
+
RUN_ROOT="${RUN_ROOT:-}"
|
| 19 |
+
OBJECTIVE="${OBJECTIVE:-lattice_field}"
|
| 20 |
+
CHECKPOINT_NAME="${CHECKPOINT_NAME:-best.pt}"
|
| 21 |
+
OUT_NAME="${OUT_NAME:-policy_rollout_cpu_smoke.json}"
|
| 22 |
+
if [[ -n "$RUN_ROOT" ]]; then
|
| 23 |
+
CHECKPOINT="${CHECKPOINT:-$RUN_ROOT/$OBJECTIVE/seed_$SEED/$CHECKPOINT_NAME}"
|
| 24 |
+
OUT="${OUT:-$RUN_ROOT/$OBJECTIVE/seed_$SEED/$OUT_NAME}"
|
| 25 |
+
else
|
| 26 |
+
CHECKPOINT="${CHECKPOINT:?Set CHECKPOINT, or RUN_ROOT for seed-indexed array runs}"
|
| 27 |
+
OUT="${OUT:?Set OUT, or RUN_ROOT for seed-indexed array runs}"
|
| 28 |
+
fi
|
| 29 |
+
|
| 30 |
+
SCRATCH_ROOT="/scratch/$USER/dovla"
|
| 31 |
+
SIF="${SIF:-$SCRATCH_ROOT/containers/pytorch_2.7.1_cuda12.8.sif}"
|
| 32 |
+
PYTHON="${PYTHON:-$SCRATCH_ROOT/envs/maniskill/bin/python}"
|
| 33 |
+
NATIVE_LIBS="$SCRATCH_ROOT/native_libs/lib"
|
| 34 |
+
CPU_RENDER_LIBS="$SCRATCH_ROOT/cpu_render_libs"
|
| 35 |
+
CA_BUNDLE="$SCRATCH_ROOT/ca-bundle.crt"
|
| 36 |
+
VULKAN_ICD="$CPU_RENDER_LIBS/share/vulkan/icd.d/lvp_icd.x86_64.json"
|
| 37 |
+
MAX_GROUPS="${MAX_GROUPS:-8}"
|
| 38 |
+
GROUP_BATCH_SIZE="${GROUP_BATCH_SIZE:-2}"
|
| 39 |
+
SIM_BACKEND="${SIM_BACKEND:-physx_cpu}"
|
| 40 |
+
RENDER_BACKEND="${RENDER_BACKEND:-cpu}"
|
| 41 |
+
ALL_GROUPS="${ALL_GROUPS:-0}"
|
| 42 |
+
DEVICE="${DEVICE:-cpu}"
|
| 43 |
+
SELECTION_MODE="${SELECTION_MODE:-field_optim}"
|
| 44 |
+
NUM_CANDIDATES="${NUM_CANDIDATES:-4}"
|
| 45 |
+
CANDIDATE_SIGMA="${CANDIDATE_SIGMA:-0.2}"
|
| 46 |
+
SELECTION_SEED="${SELECTION_SEED:-0}"
|
| 47 |
+
FIELD_OPTIM_STEPS="${FIELD_OPTIM_STEPS:-2}"
|
| 48 |
+
FIELD_OPTIM_STEP_SIZE="${FIELD_OPTIM_STEP_SIZE:-0.05}"
|
| 49 |
+
FIELD_OPTIM_TRUST_RADIUS="${FIELD_OPTIM_TRUST_RADIUS:-0.5}"
|
| 50 |
+
FIELD_OPTIM_L2_PENALTY="${FIELD_OPTIM_L2_PENALTY:-0.02}"
|
| 51 |
+
LATTICE_EXCLUDE_TYPES="${LATTICE_EXCLUDE_TYPES:-}"
|
| 52 |
+
if [[ -n "${LATTICE_EXCLUDE_TYPES_COLON:-}" ]]; then
|
| 53 |
+
LATTICE_EXCLUDE_TYPES="${LATTICE_EXCLUDE_TYPES_COLON//:/,}"
|
| 54 |
+
fi
|
| 55 |
+
|
| 56 |
+
module load StdEnv/2023 apptainer/1.4.5
|
| 57 |
+
cd "$PROJECT_DIR"
|
| 58 |
+
mkdir -p outputs/hpc/logs "$(dirname "$OUT")"
|
| 59 |
+
|
| 60 |
+
RUNTIME_DIR="/tmp/$USER/dovla-policy-rollout-cpu-$SLURM_JOB_ID-${SLURM_ARRAY_TASK_ID:-0}"
|
| 61 |
+
CACHE_DIR="/tmp/$USER/dovla-policy-rollout-cpu-mesa-$SLURM_JOB_ID-${SLURM_ARRAY_TASK_ID:-0}"
|
| 62 |
+
mkdir -p "$RUNTIME_DIR" "$CACHE_DIR"
|
| 63 |
+
chmod 700 "$RUNTIME_DIR"
|
| 64 |
+
|
| 65 |
+
export OMP_NUM_THREADS=1
|
| 66 |
+
export OPENBLAS_NUM_THREADS=1
|
| 67 |
+
export MKL_NUM_THREADS=1
|
| 68 |
+
export DOVLA_TORCH_THREADS=1
|
| 69 |
+
|
| 70 |
+
EXTRA_ARGS=()
|
| 71 |
+
if [[ "$ALL_GROUPS" == "1" ]]; then
|
| 72 |
+
EXTRA_ARGS+=(--all-groups)
|
| 73 |
+
fi
|
| 74 |
+
if [[ "$MAX_GROUPS" != "all" ]]; then
|
| 75 |
+
EXTRA_ARGS+=(--max-groups "$MAX_GROUPS")
|
| 76 |
+
fi
|
| 77 |
+
|
| 78 |
+
apptainer exec \
|
| 79 |
+
--env "LD_LIBRARY_PATH=$CPU_RENDER_LIBS/lib:$NATIVE_LIBS,VK_ICD_FILENAMES=$VULKAN_ICD,VK_DRIVER_FILES=$VULKAN_ICD,XDG_RUNTIME_DIR=$RUNTIME_DIR,MESA_SHADER_CACHE_DIR=$CACHE_DIR,LIBGL_ALWAYS_SOFTWARE=1,LP_NUM_THREADS=1,SSL_CERT_FILE=$CA_BUNDLE,REQUESTS_CA_BUNDLE=$CA_BUNDLE,OMP_NUM_THREADS=1,OPENBLAS_NUM_THREADS=1,MKL_NUM_THREADS=1,DOVLA_TORCH_THREADS=1,MPLBACKEND=Agg,PYTHONDONTWRITEBYTECODE=1" \
|
| 80 |
+
-B "$PROJECT_DIR:$PROJECT_DIR" \
|
| 81 |
+
-B "/scratch/$USER:/scratch/$USER" \
|
| 82 |
+
"$SIF" "$PYTHON" scripts/eval_maniskill_policy_rollout.py \
|
| 83 |
+
--checkpoint "$CHECKPOINT" \
|
| 84 |
+
--dataset "$DATASET" \
|
| 85 |
+
--out "$OUT" \
|
| 86 |
+
--device "$DEVICE" \
|
| 87 |
+
--group-batch-size "$GROUP_BATCH_SIZE" \
|
| 88 |
+
--sim-backend "$SIM_BACKEND" \
|
| 89 |
+
--render-backend "$RENDER_BACKEND" \
|
| 90 |
+
--selection-mode "$SELECTION_MODE" \
|
| 91 |
+
--num-candidates "$NUM_CANDIDATES" \
|
| 92 |
+
--candidate-sigma "$CANDIDATE_SIGMA" \
|
| 93 |
+
--selection-seed "$SELECTION_SEED" \
|
| 94 |
+
--field-optim-steps "$FIELD_OPTIM_STEPS" \
|
| 95 |
+
--field-optim-step-size "$FIELD_OPTIM_STEP_SIZE" \
|
| 96 |
+
--field-optim-trust-radius "$FIELD_OPTIM_TRUST_RADIUS" \
|
| 97 |
+
--field-optim-l2-penalty "$FIELD_OPTIM_L2_PENALTY" \
|
| 98 |
+
--lattice-exclude-types "$LATTICE_EXCLUDE_TYPES" \
|
| 99 |
+
"${EXTRA_ARGS[@]}"
|
scripts/slurm/smoke_field_optim_unit.sbatch
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
#SBATCH --job-name=smoke_field_optim
|
| 3 |
+
#SBATCH --account=def-yalda
|
| 4 |
+
#SBATCH --nodes=1
|
| 5 |
+
#SBATCH --ntasks=1
|
| 6 |
+
#SBATCH --cpus-per-task=1
|
| 7 |
+
#SBATCH --mem=1G
|
| 8 |
+
#SBATCH --time=00:05:00
|
| 9 |
+
#SBATCH --output=outputs/hpc/logs/%x_%j.out
|
| 10 |
+
#SBATCH --error=outputs/hpc/logs/%x_%j.err
|
| 11 |
+
|
| 12 |
+
set -euo pipefail
|
| 13 |
+
|
| 14 |
+
PROJECT_DIR="${PROJECT_DIR:-$SLURM_SUBMIT_DIR}"
|
| 15 |
+
SCRATCH_ROOT="/scratch/$USER/dovla"
|
| 16 |
+
SIF="${SIF:-$SCRATCH_ROOT/containers/pytorch_2.7.1_cuda12.8.sif}"
|
| 17 |
+
PYTHON="${PYTHON:-$SCRATCH_ROOT/envs/maniskill/bin/python}"
|
| 18 |
+
|
| 19 |
+
module load StdEnv/2023 apptainer/1.4.5
|
| 20 |
+
cd "$PROJECT_DIR"
|
| 21 |
+
mkdir -p outputs/hpc/logs
|
| 22 |
+
|
| 23 |
+
export OMP_NUM_THREADS=1
|
| 24 |
+
export OPENBLAS_NUM_THREADS=1
|
| 25 |
+
export MKL_NUM_THREADS=1
|
| 26 |
+
export DOVLA_TORCH_THREADS=1
|
| 27 |
+
|
| 28 |
+
apptainer exec \
|
| 29 |
+
--env "OMP_NUM_THREADS=1,OPENBLAS_NUM_THREADS=1,MKL_NUM_THREADS=1,DOVLA_TORCH_THREADS=1,PYTHONDONTWRITEBYTECODE=1" \
|
| 30 |
+
-B "$PROJECT_DIR:$PROJECT_DIR" \
|
| 31 |
+
-B "/scratch/$USER:/scratch/$USER" \
|
| 32 |
+
"$SIF" "$PYTHON" - <<'PY'
|
| 33 |
+
import torch
|
| 34 |
+
|
| 35 |
+
from dovla_cil.eval.maniskill_policy_rollout import _select_action_chunk
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
class StubModel:
|
| 39 |
+
def __init__(self, mean, target):
|
| 40 |
+
self.mean = mean
|
| 41 |
+
self.target = target
|
| 42 |
+
|
| 43 |
+
def forward_policy(self, observation, instruction):
|
| 44 |
+
del observation, instruction
|
| 45 |
+
return self.mean
|
| 46 |
+
|
| 47 |
+
def forward_field(self, observation, instruction, action):
|
| 48 |
+
del observation, instruction
|
| 49 |
+
distance = ((action - self.target) ** 2).reshape(action.shape[0], -1).sum(dim=1)
|
| 50 |
+
return {"potential": -distance}
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
mean = torch.zeros(1, 1, 3)
|
| 54 |
+
target = torch.full_like(mean, 0.4)
|
| 55 |
+
model = StubModel(mean, target)
|
| 56 |
+
actions, index = _select_action_chunk(
|
| 57 |
+
model,
|
| 58 |
+
observations=torch.zeros(1, 3),
|
| 59 |
+
instructions=["smoke"],
|
| 60 |
+
torch=torch,
|
| 61 |
+
selection_mode="field_optim",
|
| 62 |
+
num_candidates=4,
|
| 63 |
+
candidate_sigma=0.2,
|
| 64 |
+
selection_seed=7,
|
| 65 |
+
field_optim_steps=6,
|
| 66 |
+
field_optim_step_size=0.1,
|
| 67 |
+
field_optim_trust_radius=0.5,
|
| 68 |
+
field_optim_l2_penalty=0.0,
|
| 69 |
+
)
|
| 70 |
+
before = float(((mean - target) ** 2).sum())
|
| 71 |
+
after = float(((actions - target) ** 2).sum())
|
| 72 |
+
assert after < before, (before, after, actions)
|
| 73 |
+
assert index.shape == (1,)
|
| 74 |
+
|
| 75 |
+
bounded_actions, _ = _select_action_chunk(
|
| 76 |
+
model,
|
| 77 |
+
observations=torch.zeros(1, 3),
|
| 78 |
+
instructions=["smoke"],
|
| 79 |
+
torch=torch,
|
| 80 |
+
selection_mode="field_optim",
|
| 81 |
+
num_candidates=4,
|
| 82 |
+
candidate_sigma=1.0,
|
| 83 |
+
selection_seed=11,
|
| 84 |
+
field_optim_steps=6,
|
| 85 |
+
field_optim_step_size=0.2,
|
| 86 |
+
field_optim_trust_radius=0.25,
|
| 87 |
+
field_optim_l2_penalty=0.0,
|
| 88 |
+
action_low=torch.full_like(mean, -0.5),
|
| 89 |
+
action_high=torch.full_like(mean, 0.5),
|
| 90 |
+
)
|
| 91 |
+
assert float(bounded_actions.max()) <= 0.250001, bounded_actions
|
| 92 |
+
assert float(bounded_actions.min()) >= -0.250001, bounded_actions
|
| 93 |
+
|
| 94 |
+
print(
|
| 95 |
+
{
|
| 96 |
+
"status": "ok",
|
| 97 |
+
"before": before,
|
| 98 |
+
"after": after,
|
| 99 |
+
"selected_index": index.tolist(),
|
| 100 |
+
"bounded_max": float(bounded_actions.max()),
|
| 101 |
+
"bounded_min": float(bounded_actions.min()),
|
| 102 |
+
}
|
| 103 |
+
)
|
| 104 |
+
PY
|
scripts/slurm/smoke_retrieval_residual_unit.sbatch
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
#SBATCH --job-name=smoke_retrieval_residual
|
| 3 |
+
#SBATCH --account=def-yalda
|
| 4 |
+
#SBATCH --nodes=1
|
| 5 |
+
#SBATCH --ntasks=1
|
| 6 |
+
#SBATCH --cpus-per-task=1
|
| 7 |
+
#SBATCH --mem=1G
|
| 8 |
+
#SBATCH --time=00:05:00
|
| 9 |
+
#SBATCH --output=outputs/hpc/logs/%x_%j.out
|
| 10 |
+
#SBATCH --error=outputs/hpc/logs/%x_%j.err
|
| 11 |
+
|
| 12 |
+
set -euo pipefail
|
| 13 |
+
|
| 14 |
+
PROJECT_DIR="${PROJECT_DIR:-$SLURM_SUBMIT_DIR}"
|
| 15 |
+
SCRATCH_ROOT="/scratch/$USER/dovla"
|
| 16 |
+
SIF="${SIF:-$SCRATCH_ROOT/containers/pytorch_2.7.1_cuda12.8.sif}"
|
| 17 |
+
PYTHON="${PYTHON:-$SCRATCH_ROOT/envs/maniskill/bin/python}"
|
| 18 |
+
|
| 19 |
+
module load StdEnv/2023 apptainer/1.4.5
|
| 20 |
+
cd "$PROJECT_DIR"
|
| 21 |
+
mkdir -p outputs/hpc/logs
|
| 22 |
+
|
| 23 |
+
export OMP_NUM_THREADS=1
|
| 24 |
+
export OPENBLAS_NUM_THREADS=1
|
| 25 |
+
export MKL_NUM_THREADS=1
|
| 26 |
+
export DOVLA_TORCH_THREADS=1
|
| 27 |
+
|
| 28 |
+
apptainer exec \
|
| 29 |
+
--env "OMP_NUM_THREADS=1,OPENBLAS_NUM_THREADS=1,MKL_NUM_THREADS=1,DOVLA_TORCH_THREADS=1,PYTHONDONTWRITEBYTECODE=1" \
|
| 30 |
+
-B "$PROJECT_DIR:$PROJECT_DIR" \
|
| 31 |
+
-B "/scratch/$USER:/scratch/$USER" \
|
| 32 |
+
"$SIF" "$PYTHON" - <<'PY'
|
| 33 |
+
from pathlib import Path
|
| 34 |
+
from types import SimpleNamespace
|
| 35 |
+
|
| 36 |
+
import numpy as np
|
| 37 |
+
|
| 38 |
+
from dovla_cil.data.schema import ActionChunk
|
| 39 |
+
from dovla_cil.eval.maniskill_policy_rollout import (
|
| 40 |
+
_RolloutCase,
|
| 41 |
+
_attach_retrieved_residual_candidates,
|
| 42 |
+
_selected_candidate_type,
|
| 43 |
+
)
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def record(group_id: str, candidate_type: str, action_value: float, feature: float):
|
| 47 |
+
return SimpleNamespace(
|
| 48 |
+
group_id=group_id,
|
| 49 |
+
task_id="PickCube-v1",
|
| 50 |
+
candidate_type=candidate_type,
|
| 51 |
+
record_id=f"{group_id}-{candidate_type}-{action_value}",
|
| 52 |
+
observation_inline={"features": [feature, 0.0]},
|
| 53 |
+
action_chunk=ActionChunk(
|
| 54 |
+
representation="continuous",
|
| 55 |
+
horizon=1,
|
| 56 |
+
values=[[action_value, 0.0]],
|
| 57 |
+
),
|
| 58 |
+
)
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
dataset = SimpleNamespace(
|
| 62 |
+
group_ids=["train_a", "train_b", "heldout"],
|
| 63 |
+
get_group=lambda group_id: {
|
| 64 |
+
"train_a": [
|
| 65 |
+
record("train_a", "expert", 1.0, 0.0),
|
| 66 |
+
record("train_a", "near_miss", 1.2, 0.0),
|
| 67 |
+
],
|
| 68 |
+
"train_b": [
|
| 69 |
+
record("train_b", "expert", -1.0, 0.4),
|
| 70 |
+
record("train_b", "wrong_direction", -1.3, 0.4),
|
| 71 |
+
],
|
| 72 |
+
"heldout": [
|
| 73 |
+
record("heldout", "expert", 9.0, 0.1),
|
| 74 |
+
record("heldout", "near_miss", 9.9, 0.1),
|
| 75 |
+
],
|
| 76 |
+
}[group_id],
|
| 77 |
+
)
|
| 78 |
+
case = _RolloutCase(
|
| 79 |
+
group_id="heldout",
|
| 80 |
+
task_id="PickCube-v1",
|
| 81 |
+
source_dataset=Path("."),
|
| 82 |
+
state={},
|
| 83 |
+
observation={"features": [0.1, 0.0]},
|
| 84 |
+
instruction="pick",
|
| 85 |
+
oracle_score=1.0,
|
| 86 |
+
oracle_success=True,
|
| 87 |
+
expert_score=1.0,
|
| 88 |
+
expert_success=True,
|
| 89 |
+
best_action_values=[[9.9, 0.0]],
|
| 90 |
+
candidate_action_values=[],
|
| 91 |
+
candidate_types=[],
|
| 92 |
+
)
|
| 93 |
+
|
| 94 |
+
[attached] = _attach_retrieved_residual_candidates(
|
| 95 |
+
dataset,
|
| 96 |
+
[case],
|
| 97 |
+
heldout_group_ids=["heldout"],
|
| 98 |
+
obs_dim=2,
|
| 99 |
+
observation_mode="state",
|
| 100 |
+
retrieval_neighbors=2,
|
| 101 |
+
)
|
| 102 |
+
|
| 103 |
+
expected_values = np.asarray(
|
| 104 |
+
[[[0.0, 0.0]], [[0.2, 0.0]], [[0.0, 0.0]], [[-0.3, 0.0]]],
|
| 105 |
+
dtype=np.float32,
|
| 106 |
+
)
|
| 107 |
+
actual_values = np.asarray(attached.candidate_action_values, dtype=np.float32)
|
| 108 |
+
assert attached.candidate_source_group_id == "train_a;train_b"
|
| 109 |
+
assert attached.candidate_types == [
|
| 110 |
+
"policy_residual",
|
| 111 |
+
"residual_near_miss",
|
| 112 |
+
"policy_residual",
|
| 113 |
+
"residual_wrong_direction",
|
| 114 |
+
]
|
| 115 |
+
assert np.allclose(actual_values, expected_values), actual_values
|
| 116 |
+
assert (
|
| 117 |
+
_selected_candidate_type(attached, selected_index=3, selection_mode="retrieval_residual")
|
| 118 |
+
== "retrieval_residual_residual_wrong_direction"
|
| 119 |
+
)
|
| 120 |
+
print(
|
| 121 |
+
{
|
| 122 |
+
"status": "ok",
|
| 123 |
+
"candidate_source_group_id": attached.candidate_source_group_id,
|
| 124 |
+
"candidate_types": attached.candidate_types,
|
| 125 |
+
"candidate_values": actual_values.tolist(),
|
| 126 |
+
}
|
| 127 |
+
)
|
| 128 |
+
PY
|