Instructions to use aabyaneh/fasterwam with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Diffusers
How to use aabyaneh/fasterwam with Diffusers:
pip install -U diffusers transformers accelerate
import torch from diffusers import DiffusionPipeline # switch to "mps" for apple devices pipe = DiffusionPipeline.from_pretrained("aabyaneh/fasterwam", dtype=torch.bfloat16, device_map="cuda") prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k" image = pipe(prompt).images[0] - Notebooks
- Google Colab
- Kaggle
Make corrected-data epoch-30 FasterWAM current; move previous run under old
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- LATEST_RESULTS.md +10 -0
- README.md +6 -0
- hf_local_checkpoint_runs.json +76 -0
- joint/fasterwam/README.md +4 -4
- joint/fasterwam/old/ARCHIVE_PROVENANCE.json +724 -0
- joint/fasterwam/old/README.md +5 -0
- joint/fasterwam/train90_joint_job4247/README.md +0 -9
- joint/fasterwam/train90_joint_job4247/checkpoints/weights/step_029310.pt +0 -3
- joint/fasterwam/train90_joint_job4247/checkpoints/weights/step_058620.pt +0 -3
- joint/fasterwam/train90_joint_job4247/checkpoints/weights/step_087930.pt +0 -3
- joint/fasterwam/train90_joint_job4247/conditioning/dish_utensil/tasks.jsonl +0 -1
- joint/fasterwam/train90_joint_job4247/conditioning/fruit_pick/tasks.jsonl +0 -1
- joint/fasterwam/train90_joint_job4247/conditioning/index.json +0 -22
- joint/fasterwam/train90_joint_job4247/conditioning/place_cube/tasks.jsonl +0 -1
- joint/fasterwam/train90_joint_job4247/conditioning/prompts.json +0 -6
- joint/fasterwam/train90_joint_job4247/conditioning/push_t/tasks.jsonl +0 -1
- joint/fasterwam/train90_joint_job4247/conditioning/text_embeds_cache/3331746089cf26d56af486af1ef7035e746c2e823cc957e2e3b7a0c3baf347ef.t5_len128.wan22ti2v5b.pt +0 -3
- joint/fasterwam/train90_joint_job4247/conditioning/text_embeds_cache/531e2910f4efdc285bcefbeca24a8a1ff789d6c4365dfd7c15de4eda9eb89f6b.t5_len128.wan22ti2v5b.pt +0 -3
- joint/fasterwam/train90_joint_job4247/conditioning/text_embeds_cache/6bbe3e745d0bcd06a540d3d895af431a769ae466d0cf1102bcee7979ba41e95b.t5_len128.wan22ti2v5b.pt +0 -3
- joint/fasterwam/train90_joint_job4247/conditioning/text_embeds_cache/71cb088954da46da4e3cb6c6f73ac812690e9bccf886c7858377c61918b4e3e8.t5_len128.wan22ti2v5b.pt +0 -3
- joint/fasterwam/train90_joint_job4247/config.yaml +0 -344
- joint/fasterwam/train90_joint_job4247/dataset_stats.json +0 -1938
- joint/fasterwam/train90_joint_job4247/manifest.json +0 -45
- joint/fasterwam/train90_joint_job4247/provenance/code.json +0 -22
- joint/fasterwam/train90_joint_job4247/provenance/implementation.json +0 -364
- joint/fasterwam/train90_joint_job4247/provenance/training.log +0 -0
- joint/fasterwam/train90_joint_job4247/provenance/training_summary.json +0 -3
- joint/fasterwam/train90_joint_job4247/requirements.txt +0 -226
- joint/fasterwam/train90_joint_job4247/splits/dish_utensil_lerobot_v21.json +0 -118
- joint/fasterwam/train90_joint_job4247/splits/fruit_pick_lerobot_v21.json +0 -118
- joint/fasterwam/train90_joint_job4247/splits/place_cube_lerobot_v21.json +0 -118
- joint/fasterwam/train90_joint_job4247/splits/push_t_lerobot_v21.json +0 -118
- joint/fasterwam/train90_joint_job4247/training_code/fastwam/LICENSE +0 -24
- joint/fasterwam/train90_joint_job4247/training_code/fastwam/pyproject.toml +0 -53
- joint/fasterwam/train90_joint_job4247/training_code/fastwam/scripts/train.py +0 -24
- joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/__init__.py +0 -1
- joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/__init__.py +0 -0
- joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/aligned_3dpft.py +0 -91
- joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/dataset_utils.py +0 -109
- joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/eef_anchors.py +0 -310
- joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/base_lerobot_dataset.py +0 -517
- joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/constants.py +0 -54
- joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/lerobot/datasets/compute_stats.py +0 -179
- joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/lerobot/datasets/utils.py +0 -965
- joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/lerobot/datasets/video_utils.py +0 -527
- joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/lerobot/lerobot_dataset.py +0 -1404
- joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/processors/base_processor.py +0 -263
- joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/processors/fastwam_processor.py +0 -362
- joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/robot_video_dataset.py +0 -446
- joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/transforms/action_state_merger.py +0 -78
LATEST_RESULTS.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
# Latest completed training results — September 16, 2026
|
| 2 |
|
| 3 |
These five runs completed on the canonical 90/10 episode split. Each was trained on four H200 GPUs with global batch 32. This update publishes three inference checkpoints spread across each run, including the final checkpoint. Optimizer state remains local; the tables below report the final checkpoint metrics.
|
|
|
|
| 1 |
+
# Latest publication — September 19, 2026
|
| 2 |
+
|
| 3 |
+
Current joint FasterWAM: [job 4414, epoch 30](joint/fasterwam/train90_joint_job4414/README.md), native step 87,930, trained jointly on fruit_pick, dish_utensil, place_cube and push_t. Dataset revision `4ad42310b4408ff08370124e680e3a20ad267b1e` contains the validated corrected place_cube spatial crops. All four task embeddings and joint normalization are included. Sampled validation: loss 0.2390, action L1 0.0042, action L2/MSE 0.0017, PSNR 30.0401, SSIM 0.8902 (rounded log values, not robot success measurements).
|
| 4 |
+
|
| 5 |
+
This checkpoint was saved before the user-requested time limit. The run was configured for 50 epochs but stopped later at that limit; this publication contains epoch 30 only. The previous job 4247 run is archived under [joint/fasterwam/old/](joint/fasterwam/old/README.md), with its original files preserved.
|
| 6 |
+
|
| 7 |
+
The following September 16 results are historical and predate the place_cube correction.
|
| 8 |
+
|
| 9 |
+
---
|
| 10 |
+
|
| 11 |
# Latest completed training results — September 16, 2026
|
| 12 |
|
| 13 |
These five runs completed on the canonical 90/10 episode split. Each was trained on four H200 GPUs with global batch 32. This update publishes three inference checkpoints spread across each run, including the final checkpoint. Optimizer state remains local; the tables below report the final checkpoint metrics.
|
README.md
CHANGED
|
@@ -20,6 +20,12 @@ Each run includes its original checkpoint format and inference/training metadata
|
|
| 20 |
|
| 21 |
See [CHECKPOINT_UPLOADS.md](CHECKPOINT_UPLOADS.md) for the upload contract and commands, [checkpoint_layout.json](checkpoint_layout.json) for the path schema, and [hf_checkpoint_imports.json](hf_checkpoint_imports.json) for pinned source revisions and file hashes. Imported run READMEs retain their original training and evaluation limitations; these historical runs are not asserted to use the current benchmark split.
|
| 22 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
## Imported archives
|
| 24 |
|
| 25 |
| Source | Run folder |
|
|
|
|
| 20 |
|
| 21 |
See [CHECKPOINT_UPLOADS.md](CHECKPOINT_UPLOADS.md) for the upload contract and commands, [checkpoint_layout.json](checkpoint_layout.json) for the path schema, and [hf_checkpoint_imports.json](hf_checkpoint_imports.json) for pinned source revisions and file hashes. Imported run READMEs retain their original training and evaluation limitations; these historical runs are not asserted to use the current benchmark split.
|
| 22 |
|
| 23 |
+
## Current joint FasterWAM — September 19, 2026
|
| 24 |
+
|
| 25 |
+
[Job 4414, epoch 30](joint/fasterwam/train90_joint_job4414/README.md) is the current joint FasterWAM checkpoint, trained on all four datasets with corrected place_cube crops (dataset revision `4ad42310b4408ff08370124e680e3a20ad267b1e`). Native checkpoint: `step_087930.pt`; 8 H200 GPUs; 360 train / 40 held-out episodes. Inference weights and matching config, normalization, task embeddings, source and validation provenance are included. The run stopped at its requested time limit after saving epoch 30; it did not complete the planned 50 epochs.
|
| 26 |
+
|
| 27 |
+
The previous joint FasterWAM run, job 4247, is preserved under [joint/fasterwam/old/](joint/fasterwam/old/README.md). Its place_cube crops were invalid and it is superseded by job 4414.
|
| 28 |
+
|
| 29 |
## Imported archives
|
| 30 |
|
| 31 |
| Source | Run folder |
|
hf_local_checkpoint_runs.json
CHANGED
|
@@ -116,6 +116,82 @@
|
|
| 116 |
"task": "place_cube",
|
| 117 |
"training_status": "complete",
|
| 118 |
"wandb_run": "https://wandb.ai/aabyaneh/fasterwam-real/runs/ilkye0g0"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 119 |
}
|
| 120 |
]
|
| 121 |
}
|
|
|
|
| 116 |
"task": "place_cube",
|
| 117 |
"training_status": "complete",
|
| 118 |
"wandb_run": "https://wandb.ai/aabyaneh/fasterwam-real/runs/ilkye0g0"
|
| 119 |
+
},
|
| 120 |
+
{
|
| 121 |
+
"bytes": 31086341628,
|
| 122 |
+
"checkpoint_contents": "three inference checkpoints and matching metadata",
|
| 123 |
+
"checkpoint_epochs": [
|
| 124 |
+
10,
|
| 125 |
+
20,
|
| 126 |
+
30
|
| 127 |
+
],
|
| 128 |
+
"completed_updates": 94160,
|
| 129 |
+
"ended_utc": "2026-09-17T15:38:29Z",
|
| 130 |
+
"final_checkpoint_step": 87930,
|
| 131 |
+
"final_metrics": {},
|
| 132 |
+
"includes_training_state": false,
|
| 133 |
+
"last_logged_training_step": 94160,
|
| 134 |
+
"model": "fasterwam",
|
| 135 |
+
"native_checkpoint_steps": [
|
| 136 |
+
29310,
|
| 137 |
+
58620,
|
| 138 |
+
87930
|
| 139 |
+
],
|
| 140 |
+
"planned_epochs": 50,
|
| 141 |
+
"prepared_bundle": "train_out/hf_uploads/fasterwam_joint_train90_joint_job4247",
|
| 142 |
+
"run_id": "train90_joint_job4247",
|
| 143 |
+
"source_dir": "fastwam_train/runs/joint_all4_fasterwam/2026-09-17_04-15-26_job4247",
|
| 144 |
+
"task": "joint",
|
| 145 |
+
"training_status": "cancelled_by_user",
|
| 146 |
+
"wandb_run": "https://wandb.ai/aabyaneh/fasterwam-real/runs/pp7o49m6",
|
| 147 |
+
"verified_commit": "68669a419e3ab75fe9841daebb8642c31ce9ba06",
|
| 148 |
+
"publication_status": "archived",
|
| 149 |
+
"repo_prefix": "joint/fasterwam/old/train90_joint_job4247",
|
| 150 |
+
"archive_reason": "Superseded: trained with invalid place_cube spatial crops",
|
| 151 |
+
"superseded_by": "joint/fasterwam/train90_joint_job4414"
|
| 152 |
+
},
|
| 153 |
+
{
|
| 154 |
+
"schema_version": 1,
|
| 155 |
+
"task": "joint",
|
| 156 |
+
"model": "fasterwam",
|
| 157 |
+
"run_id": "train90_joint_job4414",
|
| 158 |
+
"slurm_job": 4414,
|
| 159 |
+
"native_checkpoint_steps": [
|
| 160 |
+
87930
|
| 161 |
+
],
|
| 162 |
+
"checkpoint_epochs": [
|
| 163 |
+
30
|
| 164 |
+
],
|
| 165 |
+
"final_checkpoint_step": 87930,
|
| 166 |
+
"published_checkpoint_updates": 87930,
|
| 167 |
+
"last_logged_training_step": 100800,
|
| 168 |
+
"planned_epochs": 50,
|
| 169 |
+
"training_status": "time_limit_at_user_requested_deadline",
|
| 170 |
+
"ended_utc": "2026-09-19T12:01:03Z",
|
| 171 |
+
"checkpoint_saved_utc": "2026-09-19T10:26:15Z",
|
| 172 |
+
"includes_training_state": false,
|
| 173 |
+
"training_gpus": 8,
|
| 174 |
+
"global_batch_size": 32,
|
| 175 |
+
"train_episodes": 360,
|
| 176 |
+
"validation_episodes": 40,
|
| 177 |
+
"dataset_revision": "4ad42310b4408ff08370124e680e3a20ad267b1e",
|
| 178 |
+
"code_revision": "19483b8b1b6a72e697091a07e7df7777aa09fd85",
|
| 179 |
+
"base_model": "Wan-AI/Wan2.2-TI2V-5B",
|
| 180 |
+
"prompts": {
|
| 181 |
+
"fruit_pick": "Lift the lid, put it aside, and pick the black plum.",
|
| 182 |
+
"dish_utensil": "pick the dishes out of the rack and place them on the table, then pick and place the spoon to the gray dish and fork to the pink dish",
|
| 183 |
+
"place_cube": "place the cube in the bowl",
|
| 184 |
+
"push_t": "push the T block to the target outline"
|
| 185 |
+
},
|
| 186 |
+
"source_dir": "fastwam_train/runs/joint_all4_fasterwam/2026-09-18_23-28-49_job4414",
|
| 187 |
+
"wandb_run": "https://wandb.ai/aabyaneh/fasterwam-real/runs/bct4y3en",
|
| 188 |
+
"integrity_inventory": "upload_manifest.json",
|
| 189 |
+
"robot_evaluation": "not performed",
|
| 190 |
+
"repo_prefix": "joint/fasterwam/train90_joint_job4414",
|
| 191 |
+
"publication_status": "published_verified",
|
| 192 |
+
"prepared_bundle": "train_out/hf_uploads/fasterwam_joint_train90_joint_job4414",
|
| 193 |
+
"checkpoint_contents": "epoch-30 inference weights, config, normalization, all four task embeddings, code and corrected-data provenance",
|
| 194 |
+
"verified_upload_commit": "870cf97d4d8ca9bf5c9c6a71eb7f903559617cb6"
|
| 195 |
}
|
| 196 |
]
|
| 197 |
}
|
joint/fasterwam/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
-
#
|
| 2 |
|
| 3 |
-
|
| 4 |
|
| 5 |
-
|
| 6 |
|
| 7 |
-
|
|
|
|
| 1 |
+
# Joint FasterWAM
|
| 2 |
|
| 3 |
+
Current: [train90_joint_job4414 — epoch 30](train90_joint_job4414/README.md).
|
| 4 |
|
| 5 |
+
Native weights: [step_087930.pt](train90_joint_job4414/checkpoints/weights/step_087930.pt). Trained jointly on fruit_pick, dish_utensil, place_cube and push_t, with the corrected and validated place_cube dataset revision `4ad42310b4408ff08370124e680e3a20ad267b1e`.
|
| 6 |
|
| 7 |
+
[Old runs](old/README.md) preserve the previous job 4247 weights and metadata. Those weights used invalid place_cube crops and are superseded.
|
joint/fasterwam/old/ARCHIVE_PROVENANCE.json
ADDED
|
@@ -0,0 +1,724 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"commit": "e73433f58cd3b4e2266fc6b759ca0f54ceae1af7",
|
| 3 |
+
"source_revision": "a99226d389334830c413f8a419dff39560ee8b89",
|
| 4 |
+
"source_prefix": "joint/fasterwam/train90_joint_job4247/",
|
| 5 |
+
"archive_prefix": "joint/fasterwam/old/train90_joint_job4247/",
|
| 6 |
+
"verified_files": 119,
|
| 7 |
+
"reason": "Invalid place_cube spatial crops; superseded by job4414",
|
| 8 |
+
"files": [
|
| 9 |
+
{
|
| 10 |
+
"path": "joint/fasterwam/train90_joint_job4247/README.md",
|
| 11 |
+
"size": 1082,
|
| 12 |
+
"sha256": null,
|
| 13 |
+
"blob_id": "e8ea7671120730ba22d5c4fa1ddc6f137546bdc1"
|
| 14 |
+
},
|
| 15 |
+
{
|
| 16 |
+
"path": "joint/fasterwam/train90_joint_job4247/checkpoints/weights/step_029310.pt",
|
| 17 |
+
"size": 10360250873,
|
| 18 |
+
"sha256": "714b360d124faa1eccef880ef97916250bf9b267f84276f9c5235f239fb55ab3",
|
| 19 |
+
"blob_id": "7bc1b60d59bd1830ae034645b582de3cf16a5e7c"
|
| 20 |
+
},
|
| 21 |
+
{
|
| 22 |
+
"path": "joint/fasterwam/train90_joint_job4247/checkpoints/weights/step_058620.pt",
|
| 23 |
+
"size": 10360250873,
|
| 24 |
+
"sha256": "229abf320895323b87f42dae740a0b7c9cd8d03860b3a313d3d7e7c9a98fba91",
|
| 25 |
+
"blob_id": "7f32e0496b6e7f64c32fc8af496e9cf3c12f013e"
|
| 26 |
+
},
|
| 27 |
+
{
|
| 28 |
+
"path": "joint/fasterwam/train90_joint_job4247/checkpoints/weights/step_087930.pt",
|
| 29 |
+
"size": 10360250873,
|
| 30 |
+
"sha256": "0a2e5a3592cfb6d02682183b746e6009300e080d753d22b400b08820d4e1d8c4",
|
| 31 |
+
"blob_id": "284bfd8f838ae78a8fe25071ed6dfcb84212e709"
|
| 32 |
+
},
|
| 33 |
+
{
|
| 34 |
+
"path": "joint/fasterwam/train90_joint_job4247/conditioning/dish_utensil/tasks.jsonl",
|
| 35 |
+
"size": 163,
|
| 36 |
+
"sha256": null,
|
| 37 |
+
"blob_id": "4889ce572a4fba78e9b0c0db49e2e3139895057e"
|
| 38 |
+
},
|
| 39 |
+
{
|
| 40 |
+
"path": "joint/fasterwam/train90_joint_job4247/conditioning/fruit_pick/tasks.jsonl",
|
| 41 |
+
"size": 82,
|
| 42 |
+
"sha256": null,
|
| 43 |
+
"blob_id": "1cf9cc95bcf3b7cd93dd6c318c9e5266df517aee"
|
| 44 |
+
},
|
| 45 |
+
{
|
| 46 |
+
"path": "joint/fasterwam/train90_joint_job4247/conditioning/index.json",
|
| 47 |
+
"size": 1651,
|
| 48 |
+
"sha256": null,
|
| 49 |
+
"blob_id": "a08f8e4eb5d5765b5ffa7fb33d11180b0e366121"
|
| 50 |
+
},
|
| 51 |
+
{
|
| 52 |
+
"path": "joint/fasterwam/train90_joint_job4247/conditioning/place_cube/tasks.jsonl",
|
| 53 |
+
"size": 56,
|
| 54 |
+
"sha256": null,
|
| 55 |
+
"blob_id": "2f1a8277b173ab2a3a0e7321a424921f32b5ee5c"
|
| 56 |
+
},
|
| 57 |
+
{
|
| 58 |
+
"path": "joint/fasterwam/train90_joint_job4247/conditioning/prompts.json",
|
| 59 |
+
"size": 330,
|
| 60 |
+
"sha256": null,
|
| 61 |
+
"blob_id": "c4d04fa855239969c2853d2a54ed4188d1549db9"
|
| 62 |
+
},
|
| 63 |
+
{
|
| 64 |
+
"path": "joint/fasterwam/train90_joint_job4247/conditioning/push_t/tasks.jsonl",
|
| 65 |
+
"size": 68,
|
| 66 |
+
"sha256": null,
|
| 67 |
+
"blob_id": "1dedddb57ce3fb271987779e8b688f196a06ffd8"
|
| 68 |
+
},
|
| 69 |
+
{
|
| 70 |
+
"path": "joint/fasterwam/train90_joint_job4247/conditioning/text_embeds_cache/3331746089cf26d56af486af1ef7035e746c2e823cc957e2e3b7a0c3baf347ef.t5_len128.wan22ti2v5b.pt",
|
| 71 |
+
"size": 1051869,
|
| 72 |
+
"sha256": "7ddfc1a78ca521bc8793e4a58e8c1f4fa55d83274ae0026483888d21521e5855",
|
| 73 |
+
"blob_id": "ff38e930fb2171e06a66a825b02c59071a9d5991"
|
| 74 |
+
},
|
| 75 |
+
{
|
| 76 |
+
"path": "joint/fasterwam/train90_joint_job4247/conditioning/text_embeds_cache/531e2910f4efdc285bcefbeca24a8a1ff789d6c4365dfd7c15de4eda9eb89f6b.t5_len128.wan22ti2v5b.pt",
|
| 77 |
+
"size": 1051869,
|
| 78 |
+
"sha256": "c676ff34af5f0fd05efa441912d0b94569a824caafa5778847b9a885a79c1e23",
|
| 79 |
+
"blob_id": "40c9e1771938248f3a82f545d8a212f501372235"
|
| 80 |
+
},
|
| 81 |
+
{
|
| 82 |
+
"path": "joint/fasterwam/train90_joint_job4247/conditioning/text_embeds_cache/6bbe3e745d0bcd06a540d3d895af431a769ae466d0cf1102bcee7979ba41e95b.t5_len128.wan22ti2v5b.pt",
|
| 83 |
+
"size": 1051869,
|
| 84 |
+
"sha256": "f4d0befa15744dccbba163d380fd62e8c0ca8bffc6b5271f200d527abc23d200",
|
| 85 |
+
"blob_id": "b2aab59f6efd38faebc888e4561bebabf897c2f5"
|
| 86 |
+
},
|
| 87 |
+
{
|
| 88 |
+
"path": "joint/fasterwam/train90_joint_job4247/conditioning/text_embeds_cache/71cb088954da46da4e3cb6c6f73ac812690e9bccf886c7858377c61918b4e3e8.t5_len128.wan22ti2v5b.pt",
|
| 89 |
+
"size": 1051869,
|
| 90 |
+
"sha256": "85b8468de72c7e7c481fe968d6ab5164d3b3c694f64b7037ec2d05fa706c73c6",
|
| 91 |
+
"blob_id": "897035aef7e7c67b5888ba6ac7e4bc7f3db82f60"
|
| 92 |
+
},
|
| 93 |
+
{
|
| 94 |
+
"path": "joint/fasterwam/train90_joint_job4247/config.yaml",
|
| 95 |
+
"size": 8668,
|
| 96 |
+
"sha256": null,
|
| 97 |
+
"blob_id": "7c71304ca5cdeb48c17118080c7c6719b1819a2e"
|
| 98 |
+
},
|
| 99 |
+
{
|
| 100 |
+
"path": "joint/fasterwam/train90_joint_job4247/dataset_stats.json",
|
| 101 |
+
"size": 40087,
|
| 102 |
+
"sha256": null,
|
| 103 |
+
"blob_id": "700f9c798742497fbe3b831a5e7f708234f22961"
|
| 104 |
+
},
|
| 105 |
+
{
|
| 106 |
+
"path": "joint/fasterwam/train90_joint_job4247/manifest.json",
|
| 107 |
+
"size": 1737,
|
| 108 |
+
"sha256": null,
|
| 109 |
+
"blob_id": "385eea812f62fc92e0b89255c4a6ead3770a491b"
|
| 110 |
+
},
|
| 111 |
+
{
|
| 112 |
+
"path": "joint/fasterwam/train90_joint_job4247/provenance/code.json",
|
| 113 |
+
"size": 814,
|
| 114 |
+
"sha256": null,
|
| 115 |
+
"blob_id": "0f4e4c5550b1c1efeeaa760d3b7e6b87ad87f5e2"
|
| 116 |
+
},
|
| 117 |
+
{
|
| 118 |
+
"path": "joint/fasterwam/train90_joint_job4247/provenance/implementation.json",
|
| 119 |
+
"size": 42911,
|
| 120 |
+
"sha256": null,
|
| 121 |
+
"blob_id": "8c655b29d8501a4ad76f034bc66d1c2b7711f6bb"
|
| 122 |
+
},
|
| 123 |
+
{
|
| 124 |
+
"path": "joint/fasterwam/train90_joint_job4247/provenance/training.log",
|
| 125 |
+
"size": 4024180,
|
| 126 |
+
"sha256": null,
|
| 127 |
+
"blob_id": "6aa04b0e02ac670b53ddadfcde85e16fd38bdce3"
|
| 128 |
+
},
|
| 129 |
+
{
|
| 130 |
+
"path": "joint/fasterwam/train90_joint_job4247/provenance/training_summary.json",
|
| 131 |
+
"size": 66,
|
| 132 |
+
"sha256": null,
|
| 133 |
+
"blob_id": "89dc1ccdf4dd67a320bba366f9805bd86f9d4519"
|
| 134 |
+
},
|
| 135 |
+
{
|
| 136 |
+
"path": "joint/fasterwam/train90_joint_job4247/requirements.txt",
|
| 137 |
+
"size": 4136,
|
| 138 |
+
"sha256": null,
|
| 139 |
+
"blob_id": "9170e47ace8e1b0b2c76374d13fdb864e9a5825b"
|
| 140 |
+
},
|
| 141 |
+
{
|
| 142 |
+
"path": "joint/fasterwam/train90_joint_job4247/splits/dish_utensil_lerobot_v21.json",
|
| 143 |
+
"size": 1340,
|
| 144 |
+
"sha256": null,
|
| 145 |
+
"blob_id": "dceff5f8f43f54d6fe4f011848210a0c01276820"
|
| 146 |
+
},
|
| 147 |
+
{
|
| 148 |
+
"path": "joint/fasterwam/train90_joint_job4247/splits/fruit_pick_lerobot_v21.json",
|
| 149 |
+
"size": 1336,
|
| 150 |
+
"sha256": null,
|
| 151 |
+
"blob_id": "c079faa8f98ae706d44fe91c105a24a88f320eec"
|
| 152 |
+
},
|
| 153 |
+
{
|
| 154 |
+
"path": "joint/fasterwam/train90_joint_job4247/splits/place_cube_lerobot_v21.json",
|
| 155 |
+
"size": 1333,
|
| 156 |
+
"sha256": null,
|
| 157 |
+
"blob_id": "50da50bfb6f4e1bf0a0a68313388c91e59ac140f"
|
| 158 |
+
},
|
| 159 |
+
{
|
| 160 |
+
"path": "joint/fasterwam/train90_joint_job4247/splits/push_t_lerobot_v21.json",
|
| 161 |
+
"size": 1328,
|
| 162 |
+
"sha256": null,
|
| 163 |
+
"blob_id": "521fe4a4f96b004d0ddc54c1b8340fc5e8955319"
|
| 164 |
+
},
|
| 165 |
+
{
|
| 166 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/LICENSE",
|
| 167 |
+
"size": 1210,
|
| 168 |
+
"sha256": null,
|
| 169 |
+
"blob_id": "90124d129334cd5de11aa0fd606182b3ffd442cb"
|
| 170 |
+
},
|
| 171 |
+
{
|
| 172 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/pyproject.toml",
|
| 173 |
+
"size": 1152,
|
| 174 |
+
"sha256": null,
|
| 175 |
+
"blob_id": "853bc3e032f6cc85ff20f2338f8418976b69a615"
|
| 176 |
+
},
|
| 177 |
+
{
|
| 178 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/scripts/train.py",
|
| 179 |
+
"size": 543,
|
| 180 |
+
"sha256": null,
|
| 181 |
+
"blob_id": "f0a3b5e2467eef86eb7deac5305a33d1cc00bcf7"
|
| 182 |
+
},
|
| 183 |
+
{
|
| 184 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/__init__.py",
|
| 185 |
+
"size": 23,
|
| 186 |
+
"sha256": null,
|
| 187 |
+
"blob_id": "f40dcb36ffb7cb5999600c8d9520cd72e3f60af0"
|
| 188 |
+
},
|
| 189 |
+
{
|
| 190 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/__init__.py",
|
| 191 |
+
"size": 0,
|
| 192 |
+
"sha256": null,
|
| 193 |
+
"blob_id": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"
|
| 194 |
+
},
|
| 195 |
+
{
|
| 196 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/aligned_3dpft.py",
|
| 197 |
+
"size": 4311,
|
| 198 |
+
"sha256": null,
|
| 199 |
+
"blob_id": "e18d746558f8cda87966946151f5a425d47d6363"
|
| 200 |
+
},
|
| 201 |
+
{
|
| 202 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/dataset_utils.py",
|
| 203 |
+
"size": 3735,
|
| 204 |
+
"sha256": null,
|
| 205 |
+
"blob_id": "e7d5830119dd42c492ec3ba5c01081c26b836d71"
|
| 206 |
+
},
|
| 207 |
+
{
|
| 208 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/eef_anchors.py",
|
| 209 |
+
"size": 12039,
|
| 210 |
+
"sha256": null,
|
| 211 |
+
"blob_id": "d1a2b97271c6c10a9514430605fdac99315d5dea"
|
| 212 |
+
},
|
| 213 |
+
{
|
| 214 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/base_lerobot_dataset.py",
|
| 215 |
+
"size": 23105,
|
| 216 |
+
"sha256": null,
|
| 217 |
+
"blob_id": "227fb9ee707369162bc1cc2c16fa1b96a1729a7a"
|
| 218 |
+
},
|
| 219 |
+
{
|
| 220 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/constants.py",
|
| 221 |
+
"size": 1915,
|
| 222 |
+
"sha256": null,
|
| 223 |
+
"blob_id": "30777239efdfa096bfefbc0f2d729e8f36da90ca"
|
| 224 |
+
},
|
| 225 |
+
{
|
| 226 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/lerobot/datasets/compute_stats.py",
|
| 227 |
+
"size": 7067,
|
| 228 |
+
"sha256": null,
|
| 229 |
+
"blob_id": "df26818f654de1410ccdab2306a85ca4070b761b"
|
| 230 |
+
},
|
| 231 |
+
{
|
| 232 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/lerobot/datasets/utils.py",
|
| 233 |
+
"size": 36236,
|
| 234 |
+
"sha256": null,
|
| 235 |
+
"blob_id": "dd382df529058e4edcf202cde1eef54170e21863"
|
| 236 |
+
},
|
| 237 |
+
{
|
| 238 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/lerobot/datasets/video_utils.py",
|
| 239 |
+
"size": 19421,
|
| 240 |
+
"sha256": null,
|
| 241 |
+
"blob_id": "9dd6fee91c9d867d5a0f4540e5ae0713b7f753dc"
|
| 242 |
+
},
|
| 243 |
+
{
|
| 244 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/lerobot/lerobot_dataset.py",
|
| 245 |
+
"size": 60778,
|
| 246 |
+
"sha256": null,
|
| 247 |
+
"blob_id": "ef5d5e50235f051c8919c9a635c25a3289215c02"
|
| 248 |
+
},
|
| 249 |
+
{
|
| 250 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/processors/base_processor.py",
|
| 251 |
+
"size": 10811,
|
| 252 |
+
"sha256": null,
|
| 253 |
+
"blob_id": "39d1665b6f0da68060fad7a120241577301a6139"
|
| 254 |
+
},
|
| 255 |
+
{
|
| 256 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/processors/fastwam_processor.py",
|
| 257 |
+
"size": 15064,
|
| 258 |
+
"sha256": null,
|
| 259 |
+
"blob_id": "e06eb0246a6443f7dcd1052582f3cad41dd05f37"
|
| 260 |
+
},
|
| 261 |
+
{
|
| 262 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/robot_video_dataset.py",
|
| 263 |
+
"size": 20540,
|
| 264 |
+
"sha256": null,
|
| 265 |
+
"blob_id": "b7b682a760a2671104c5cbcae7e63e077a68a249"
|
| 266 |
+
},
|
| 267 |
+
{
|
| 268 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/transforms/action_state_merger.py",
|
| 269 |
+
"size": 2522,
|
| 270 |
+
"sha256": null,
|
| 271 |
+
"blob_id": "0a35644a4fbc65a5cb6abe3f642f4af35a4e438b"
|
| 272 |
+
},
|
| 273 |
+
{
|
| 274 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/transforms/image.py",
|
| 275 |
+
"size": 725,
|
| 276 |
+
"sha256": null,
|
| 277 |
+
"blob_id": "8dbeda01c09dd57bc772ad4d53cf8b49586a2d06"
|
| 278 |
+
},
|
| 279 |
+
{
|
| 280 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/transforms/misc.py",
|
| 281 |
+
"size": 422,
|
| 282 |
+
"sha256": null,
|
| 283 |
+
"blob_id": "49279d6888f565078aafbcc3a830584bb34515a5"
|
| 284 |
+
},
|
| 285 |
+
{
|
| 286 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/transforms/relative_action.py",
|
| 287 |
+
"size": 5423,
|
| 288 |
+
"sha256": null,
|
| 289 |
+
"blob_id": "5e4df6dbf0e131e9093ae7e2e149dcdc9823801f"
|
| 290 |
+
},
|
| 291 |
+
{
|
| 292 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/transforms/rotation.py",
|
| 293 |
+
"size": 5603,
|
| 294 |
+
"sha256": null,
|
| 295 |
+
"blob_id": "4f19924703f4274401f01537180aae11f9bc84c7"
|
| 296 |
+
},
|
| 297 |
+
{
|
| 298 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/utils/normalizer.py",
|
| 299 |
+
"size": 11274,
|
| 300 |
+
"sha256": null,
|
| 301 |
+
"blob_id": "1c674b0234bcf3cf1a1bef0f8fc0523020449b4a"
|
| 302 |
+
},
|
| 303 |
+
{
|
| 304 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/utils/rotation.py",
|
| 305 |
+
"size": 21110,
|
| 306 |
+
"sha256": null,
|
| 307 |
+
"blob_id": "f468cd4f24092bfe8a601a85e2cb8e5e6b84cbbb"
|
| 308 |
+
},
|
| 309 |
+
{
|
| 310 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/robotwin_aligned_3dpft.py",
|
| 311 |
+
"size": 4506,
|
| 312 |
+
"sha256": null,
|
| 313 |
+
"blob_id": "e601786919c6f4723924c6ef0bc16984348a3c7e"
|
| 314 |
+
},
|
| 315 |
+
{
|
| 316 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/video_latent_cache.py",
|
| 317 |
+
"size": 19138,
|
| 318 |
+
"sha256": null,
|
| 319 |
+
"blob_id": "ce28d1193029023b115d3a63b8cd4480c3f1b7a0"
|
| 320 |
+
},
|
| 321 |
+
{
|
| 322 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/geometry/__init__.py",
|
| 323 |
+
"size": 3140,
|
| 324 |
+
"sha256": null,
|
| 325 |
+
"blob_id": "a710f4c422f5b6c459c1404112b173f60569dc20"
|
| 326 |
+
},
|
| 327 |
+
{
|
| 328 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/geometry/bearing.py",
|
| 329 |
+
"size": 7646,
|
| 330 |
+
"sha256": null,
|
| 331 |
+
"blob_id": "3491b9a307ab752fe0005e6daa3410f4eeb9ca2e"
|
| 332 |
+
},
|
| 333 |
+
{
|
| 334 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/geometry/calibration.py",
|
| 335 |
+
"size": 15987,
|
| 336 |
+
"sha256": null,
|
| 337 |
+
"blob_id": "177eac6a5383929a16be17ccfb8283512c270992"
|
| 338 |
+
},
|
| 339 |
+
{
|
| 340 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/geometry/camera_source.py",
|
| 341 |
+
"size": 5050,
|
| 342 |
+
"sha256": null,
|
| 343 |
+
"blob_id": "9cab1f86c82968633b4efef4df5ce001c7808f60"
|
| 344 |
+
},
|
| 345 |
+
{
|
| 346 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/geometry/control_rope.py",
|
| 347 |
+
"size": 4168,
|
| 348 |
+
"sha256": null,
|
| 349 |
+
"blob_id": "6bb696b07899fcd4c0b49771be8aca39b9c726ac"
|
| 350 |
+
},
|
| 351 |
+
{
|
| 352 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/geometry/eef_projector.py",
|
| 353 |
+
"size": 41068,
|
| 354 |
+
"sha256": null,
|
| 355 |
+
"blob_id": "eb813ce6bbd97aef8fc6893c7b24e25de05504c8"
|
| 356 |
+
},
|
| 357 |
+
{
|
| 358 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/geometry/flow_context.py",
|
| 359 |
+
"size": 4745,
|
| 360 |
+
"sha256": null,
|
| 361 |
+
"blob_id": "dfc3ce73445ca45a74f6d8e42d2973dbc3d0056f"
|
| 362 |
+
},
|
| 363 |
+
{
|
| 364 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/geometry/flow_trajectory.py",
|
| 365 |
+
"size": 12820,
|
| 366 |
+
"sha256": null,
|
| 367 |
+
"blob_id": "aa2a7bae6aca961f5cfa536b72416708422a8400"
|
| 368 |
+
},
|
| 369 |
+
{
|
| 370 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/geometry/identity.py",
|
| 371 |
+
"size": 5463,
|
| 372 |
+
"sha256": null,
|
| 373 |
+
"blob_id": "7322cadc38c3b9524f23d0270a8b5f7cb5b8b103"
|
| 374 |
+
},
|
| 375 |
+
{
|
| 376 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/geometry/plus_anchors.py",
|
| 377 |
+
"size": 17643,
|
| 378 |
+
"sha256": null,
|
| 379 |
+
"blob_id": "155e35f69a054c091fae01cb82591f6b436fa9ee"
|
| 380 |
+
},
|
| 381 |
+
{
|
| 382 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/geometry/prox_pinhole.py",
|
| 383 |
+
"size": 3570,
|
| 384 |
+
"sha256": null,
|
| 385 |
+
"blob_id": "63525b5f4a848216b057e047aa4c8e5e9d611bf5"
|
| 386 |
+
},
|
| 387 |
+
{
|
| 388 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/geometry/robotwin_flow.py",
|
| 389 |
+
"size": 21052,
|
| 390 |
+
"sha256": null,
|
| 391 |
+
"blob_id": "1ae33b25208913cf44e85f195429c173bf0fd194"
|
| 392 |
+
},
|
| 393 |
+
{
|
| 394 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/geometry/weak_perspective.py",
|
| 395 |
+
"size": 5089,
|
| 396 |
+
"sha256": null,
|
| 397 |
+
"blob_id": "7f16f51493fdc5c1957c6a4efa5b2d9b20c6d953"
|
| 398 |
+
},
|
| 399 |
+
{
|
| 400 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/lr_schedules.py",
|
| 401 |
+
"size": 7988,
|
| 402 |
+
"sha256": null,
|
| 403 |
+
"blob_id": "df51864620d37bc7988f17e6e358a3a58189405b"
|
| 404 |
+
},
|
| 405 |
+
{
|
| 406 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/__init__.py",
|
| 407 |
+
"size": 35,
|
| 408 |
+
"sha256": null,
|
| 409 |
+
"blob_id": "f45b7d25cd81883bbc40b37fd6366225d1e84105"
|
| 410 |
+
},
|
| 411 |
+
{
|
| 412 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/__init__.py",
|
| 413 |
+
"size": 0,
|
| 414 |
+
"sha256": null,
|
| 415 |
+
"blob_id": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"
|
| 416 |
+
},
|
| 417 |
+
{
|
| 418 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/action_dit.py",
|
| 419 |
+
"size": 52467,
|
| 420 |
+
"sha256": null,
|
| 421 |
+
"blob_id": "cd095affb62d566b059ad381b5454d943a00e307"
|
| 422 |
+
},
|
| 423 |
+
{
|
| 424 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/action_mlp.py",
|
| 425 |
+
"size": 9289,
|
| 426 |
+
"sha256": null,
|
| 427 |
+
"blob_id": "5417e8e8874304c0609436e1af17ca9d84a65032"
|
| 428 |
+
},
|
| 429 |
+
{
|
| 430 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/action_proprio_jitter.py",
|
| 431 |
+
"size": 7732,
|
| 432 |
+
"sha256": null,
|
| 433 |
+
"blob_id": "e2852c5faf003256cd851c1d022c806820889166"
|
| 434 |
+
},
|
| 435 |
+
{
|
| 436 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/aligned_3dpft.py",
|
| 437 |
+
"size": 14891,
|
| 438 |
+
"sha256": null,
|
| 439 |
+
"blob_id": "876e508f059e13cab19f760b8f5ab2f2f0cff4e7"
|
| 440 |
+
},
|
| 441 |
+
{
|
| 442 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/aligned_3dpft_x0.py",
|
| 443 |
+
"size": 11619,
|
| 444 |
+
"sha256": null,
|
| 445 |
+
"blob_id": "a0e589a4cf955e223116b1e668b01ef05741f34e"
|
| 446 |
+
},
|
| 447 |
+
{
|
| 448 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/attn_offset_head_anchor.py",
|
| 449 |
+
"size": 10748,
|
| 450 |
+
"sha256": null,
|
| 451 |
+
"blob_id": "1a58ca9cdcdbc333e4cae94898e08b530c346ea6"
|
| 452 |
+
},
|
| 453 |
+
{
|
| 454 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/control_rope.py",
|
| 455 |
+
"size": 7260,
|
| 456 |
+
"sha256": null,
|
| 457 |
+
"blob_id": "3149d1a5360bd2c3d5ced44a0750d7ef3c279ec3"
|
| 458 |
+
},
|
| 459 |
+
{
|
| 460 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/controlnet_pp.py",
|
| 461 |
+
"size": 10714,
|
| 462 |
+
"sha256": null,
|
| 463 |
+
"blob_id": "5bb451df634f1fd2469f9e901bbd75d9d848454c"
|
| 464 |
+
},
|
| 465 |
+
{
|
| 466 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/fasterwam_decoupled.py",
|
| 467 |
+
"size": 83098,
|
| 468 |
+
"sha256": null,
|
| 469 |
+
"blob_id": "8c9791ef4925fbed2976c4febd5309b72b4b98dc"
|
| 470 |
+
},
|
| 471 |
+
{
|
| 472 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/fastwam.py",
|
| 473 |
+
"size": 89934,
|
| 474 |
+
"sha256": null,
|
| 475 |
+
"blob_id": "a7adf6a70cf493de36e96ed8de627362d902dc7c"
|
| 476 |
+
},
|
| 477 |
+
{
|
| 478 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/fastwam_action_mlp.py",
|
| 479 |
+
"size": 21755,
|
| 480 |
+
"sha256": null,
|
| 481 |
+
"blob_id": "28daaff52e33cc945c11461a7bab52c13406d6cb"
|
| 482 |
+
},
|
| 483 |
+
{
|
| 484 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/fastwam_decoupled.py",
|
| 485 |
+
"size": 59696,
|
| 486 |
+
"sha256": null,
|
| 487 |
+
"blob_id": "f12470812b4c8db6e4d6983573370df5b330093e"
|
| 488 |
+
},
|
| 489 |
+
{
|
| 490 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/fastwam_idm.py",
|
| 491 |
+
"size": 20353,
|
| 492 |
+
"sha256": null,
|
| 493 |
+
"blob_id": "d21d69b3ac9a83f931e6d1018b17202d49e1b788"
|
| 494 |
+
},
|
| 495 |
+
{
|
| 496 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/fastwam_joint.py",
|
| 497 |
+
"size": 10088,
|
| 498 |
+
"sha256": null,
|
| 499 |
+
"blob_id": "c0604f15536c5f433ea68faa02284e56088d9260"
|
| 500 |
+
},
|
| 501 |
+
{
|
| 502 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/ha_content_pp.py",
|
| 503 |
+
"size": 3395,
|
| 504 |
+
"sha256": null,
|
| 505 |
+
"blob_id": "1893e772fdd9fda4e2f01848e69cd06c973a341c"
|
| 506 |
+
},
|
| 507 |
+
{
|
| 508 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/helpers/__init__.py",
|
| 509 |
+
"size": 415,
|
| 510 |
+
"sha256": null,
|
| 511 |
+
"blob_id": "35bac73c6b329a83d34b02e39a12012305879347"
|
| 512 |
+
},
|
| 513 |
+
{
|
| 514 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/helpers/gradient.py",
|
| 515 |
+
"size": 565,
|
| 516 |
+
"sha256": null,
|
| 517 |
+
"blob_id": "636ef5c2e29a96553bfc6d21e47c70506a3831f4"
|
| 518 |
+
},
|
| 519 |
+
{
|
| 520 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/helpers/io.py",
|
| 521 |
+
"size": 7751,
|
| 522 |
+
"sha256": null,
|
| 523 |
+
"blob_id": "26d65d08cfa52a40c6e41d4e6b1d9fd4b65843b6"
|
| 524 |
+
},
|
| 525 |
+
{
|
| 526 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/helpers/loader.py",
|
| 527 |
+
"size": 8279,
|
| 528 |
+
"sha256": null,
|
| 529 |
+
"blob_id": "99d92ff409fb104c6ebf8cc29905baa12d80e28f"
|
| 530 |
+
},
|
| 531 |
+
{
|
| 532 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/helpers/state_dict_converters.py",
|
| 533 |
+
"size": 5226,
|
| 534 |
+
"sha256": null,
|
| 535 |
+
"blob_id": "3a83b5c554d79278c3b73859eea092a78f3ec528"
|
| 536 |
+
},
|
| 537 |
+
{
|
| 538 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/iha.py",
|
| 539 |
+
"size": 7474,
|
| 540 |
+
"sha256": null,
|
| 541 |
+
"blob_id": "65e167e35f562e80544ba49178ac7f59871502b9"
|
| 542 |
+
},
|
| 543 |
+
{
|
| 544 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/kv_fusion.py",
|
| 545 |
+
"size": 5917,
|
| 546 |
+
"sha256": null,
|
| 547 |
+
"blob_id": "021c5cb471cf7756bb42cf8f00948ae6b8b9ba90"
|
| 548 |
+
},
|
| 549 |
+
{
|
| 550 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/learnable_head_anchor.py",
|
| 551 |
+
"size": 4046,
|
| 552 |
+
"sha256": null,
|
| 553 |
+
"blob_id": "866a7779829795a2a6bbc1d32c4fdd2efaf284de"
|
| 554 |
+
},
|
| 555 |
+
{
|
| 556 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/mot.py",
|
| 557 |
+
"size": 23212,
|
| 558 |
+
"sha256": null,
|
| 559 |
+
"blob_id": "dfb1a7cfe4b299c3d99d5a118f7728f24069ed0c"
|
| 560 |
+
},
|
| 561 |
+
{
|
| 562 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/mot_decoupled.py",
|
| 563 |
+
"size": 89831,
|
| 564 |
+
"sha256": null,
|
| 565 |
+
"blob_id": "2ec4f3931f07ddf3fd5977e1b95f1c8d847a7b15"
|
| 566 |
+
},
|
| 567 |
+
{
|
| 568 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/offset_head_anchor.py",
|
| 569 |
+
"size": 10467,
|
| 570 |
+
"sha256": null,
|
| 571 |
+
"blob_id": "1ee79a69c81c082f1b9c01e9310995e49d3c9d22"
|
| 572 |
+
},
|
| 573 |
+
{
|
| 574 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/piha.py",
|
| 575 |
+
"size": 4158,
|
| 576 |
+
"sha256": null,
|
| 577 |
+
"blob_id": "a55946e05d6595bd56e4a30f2fc8661e4e6c92a9"
|
| 578 |
+
},
|
| 579 |
+
{
|
| 580 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/piha_post_rope_kv.py",
|
| 581 |
+
"size": 6922,
|
| 582 |
+
"sha256": null,
|
| 583 |
+
"blob_id": "47e8fcab87fc3bed9a8f86b94d3ff4fd0cb13523"
|
| 584 |
+
},
|
| 585 |
+
{
|
| 586 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/proprio_offset_head_anchor.py",
|
| 587 |
+
"size": 7182,
|
| 588 |
+
"sha256": null,
|
| 589 |
+
"blob_id": "99404ba80dff7aa5372726052f188ac7aae8d0b8"
|
| 590 |
+
},
|
| 591 |
+
{
|
| 592 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/robotwin_aligned_3dpft.py",
|
| 593 |
+
"size": 9908,
|
| 594 |
+
"sha256": null,
|
| 595 |
+
"blob_id": "6c4bd2baa2b3d7676e5ee9ff00a6372e12f0e54d"
|
| 596 |
+
},
|
| 597 |
+
{
|
| 598 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/schedulers/scheduler_continuous.py",
|
| 599 |
+
"size": 4068,
|
| 600 |
+
"sha256": null,
|
| 601 |
+
"blob_id": "9028f6c86e2e35bc9efd75dda26d9cf88ff898bb"
|
| 602 |
+
},
|
| 603 |
+
{
|
| 604 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/text_ca_dropout.py",
|
| 605 |
+
"size": 15007,
|
| 606 |
+
"sha256": null,
|
| 607 |
+
"blob_id": "389bda2abf6c557801f7a2bbbc7527ee950cb69e"
|
| 608 |
+
},
|
| 609 |
+
{
|
| 610 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/viewlocal_ha_pp.py",
|
| 611 |
+
"size": 13486,
|
| 612 |
+
"sha256": null,
|
| 613 |
+
"blob_id": "698ea3c6f3b6afd3865e70c6566b19cf9d0fc88f"
|
| 614 |
+
},
|
| 615 |
+
{
|
| 616 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/wan22.py",
|
| 617 |
+
"size": 16945,
|
| 618 |
+
"sha256": null,
|
| 619 |
+
"blob_id": "0a7f5a6bccb07193e2fcaf0329a27b28ddda20f0"
|
| 620 |
+
},
|
| 621 |
+
{
|
| 622 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/wan_video_dit.py",
|
| 623 |
+
"size": 33084,
|
| 624 |
+
"sha256": null,
|
| 625 |
+
"blob_id": "afb9a25b3ca6c8e3819997e26fd5a9ddad6b9a6c"
|
| 626 |
+
},
|
| 627 |
+
{
|
| 628 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/wan_video_text_encoder.py",
|
| 629 |
+
"size": 11459,
|
| 630 |
+
"sha256": null,
|
| 631 |
+
"blob_id": "24f89f49c971d3798a2eed8e20faa98ec01cba20"
|
| 632 |
+
},
|
| 633 |
+
{
|
| 634 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/models/wan22/wan_video_vae.py",
|
| 635 |
+
"size": 50058,
|
| 636 |
+
"sha256": null,
|
| 637 |
+
"blob_id": "0386bdedb6a532781eb81509e5f574011113a706"
|
| 638 |
+
},
|
| 639 |
+
{
|
| 640 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/runtime.py",
|
| 641 |
+
"size": 34288,
|
| 642 |
+
"sha256": null,
|
| 643 |
+
"blob_id": "cdf15830cc1109a0f1361cf97aa2d69ed6f58d2e"
|
| 644 |
+
},
|
| 645 |
+
{
|
| 646 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/trainer.py",
|
| 647 |
+
"size": 66389,
|
| 648 |
+
"sha256": null,
|
| 649 |
+
"blob_id": "ea6e07fb54072e50f98c085395c3344bbcc116f3"
|
| 650 |
+
},
|
| 651 |
+
{
|
| 652 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/utils/__init__.py",
|
| 653 |
+
"size": 96,
|
| 654 |
+
"sha256": null,
|
| 655 |
+
"blob_id": "3d0eb927e25fab27c8dae7daa3d52a31c2d532b2"
|
| 656 |
+
},
|
| 657 |
+
{
|
| 658 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/utils/config_resolvers.py",
|
| 659 |
+
"size": 2526,
|
| 660 |
+
"sha256": null,
|
| 661 |
+
"blob_id": "4b1273b96b716ffa1028dfce42474376930a19f1"
|
| 662 |
+
},
|
| 663 |
+
{
|
| 664 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/utils/fs.py",
|
| 665 |
+
"size": 76,
|
| 666 |
+
"sha256": null,
|
| 667 |
+
"blob_id": "b210bde5a81689be2969db6059ab71833958f43a"
|
| 668 |
+
},
|
| 669 |
+
{
|
| 670 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/utils/logging_config.py",
|
| 671 |
+
"size": 4679,
|
| 672 |
+
"sha256": null,
|
| 673 |
+
"blob_id": "eba39b2fcff02c4d8488cf099d414eca19fbbc47"
|
| 674 |
+
},
|
| 675 |
+
{
|
| 676 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/utils/misc.py",
|
| 677 |
+
"size": 1223,
|
| 678 |
+
"sha256": null,
|
| 679 |
+
"blob_id": "9981aa8913c2b565c3b6cf5e317eed12d6a7222c"
|
| 680 |
+
},
|
| 681 |
+
{
|
| 682 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/utils/pytorch_utils.py",
|
| 683 |
+
"size": 5049,
|
| 684 |
+
"sha256": null,
|
| 685 |
+
"blob_id": "87180a30f9edbba85cc1c94a3fd604b79fd15b1a"
|
| 686 |
+
},
|
| 687 |
+
{
|
| 688 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/utils/samplers.py",
|
| 689 |
+
"size": 1339,
|
| 690 |
+
"sha256": null,
|
| 691 |
+
"blob_id": "8b4f52a26a749fadc78a5c4ae7fa9068570be000"
|
| 692 |
+
},
|
| 693 |
+
{
|
| 694 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/utils/video_io.py",
|
| 695 |
+
"size": 819,
|
| 696 |
+
"sha256": null,
|
| 697 |
+
"blob_id": "74898b9c02a79c6b34b36af215a32743a8541d5d"
|
| 698 |
+
},
|
| 699 |
+
{
|
| 700 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/utils/video_metrics.py",
|
| 701 |
+
"size": 3446,
|
| 702 |
+
"sha256": null,
|
| 703 |
+
"blob_id": "6b2837fa1d7b3c7c2532e99121ee46d68eb6be6e"
|
| 704 |
+
},
|
| 705 |
+
{
|
| 706 |
+
"path": "joint/fasterwam/train90_joint_job4247/training_code/fastwam_joint.py",
|
| 707 |
+
"size": 3994,
|
| 708 |
+
"sha256": null,
|
| 709 |
+
"blob_id": "bcd1ba2657cb2c6ea920a48439feddbb6319ccbf"
|
| 710 |
+
},
|
| 711 |
+
{
|
| 712 |
+
"path": "joint/fasterwam/train90_joint_job4247/upload_manifest.json",
|
| 713 |
+
"size": 36140,
|
| 714 |
+
"sha256": null,
|
| 715 |
+
"blob_id": "aae0341b5ba11619cab14934d870442b604b3fa5"
|
| 716 |
+
},
|
| 717 |
+
{
|
| 718 |
+
"path": "joint/fasterwam/train90_joint_job4247/validation/final_metrics.json",
|
| 719 |
+
"size": 3,
|
| 720 |
+
"sha256": null,
|
| 721 |
+
"blob_id": "0967ef424bce6791893e9a57bb952f80fd536e93"
|
| 722 |
+
}
|
| 723 |
+
]
|
| 724 |
+
}
|
joint/fasterwam/old/README.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Old joint FasterWAM checkpoints
|
| 2 |
+
|
| 3 |
+
[train90_joint_job4247](train90_joint_job4247/README.md) preserves all three historical checkpoints (epochs 10, 20 and 30) and all matching metadata, unchanged. This run used the invalid place_cube spatial crops and is superseded by [job 4414](../train90_joint_job4414/README.md).
|
| 4 |
+
|
| 5 |
+
Original prefix: `joint/fasterwam/train90_joint_job4247/`. Archived prefix: `joint/fasterwam/old/train90_joint_job4247/`. Original manifests retain their original paths as historical provenance; apply this prefix mapping when inspecting them. `ARCHIVE_PROVENANCE.json` records the pinned source revision and original file hashes.
|
joint/fasterwam/train90_joint_job4247/README.md
DELETED
|
@@ -1,9 +0,0 @@
|
|
| 1 |
-
# Joint FasterWAM — job 4247
|
| 2 |
-
|
| 3 |
-
Trained jointly on fruit_pick, dish_utensil, place_cube, and push_t using eight H200 GPUs, global batch 32, and canonical 90/10 episode splits. The user stopped the originally planned 50-epoch run during epoch 33.
|
| 4 |
-
|
| 5 |
-
Published checkpoints: epoch 10 (29310), epoch 20 (58620), epoch 30 (87930). These retain the original 50-epoch cosine schedule; this was not a separate 30-epoch training schedule. Optimizer and resume state are excluded.
|
| 6 |
-
|
| 7 |
-
Use checkpoints/weights with the bundled runtime, config.yaml, dataset_stats.json, and all four task embeddings under conditioning/. Remap training paths locally. The Wan2.2 VAE/base components in the config remain external dependencies. Source snapshots are export-time copies; provenance/implementation.json records training-time source hashes.
|
| 8 |
-
|
| 9 |
-
The W&B summary was not finalized after cancellation. Training-time validation is recorded in provenance/training.log; no robot evaluation is claimed. See manifest.json for provenance and upload_manifest.json for checksums. Bundled code retains upstream licenses.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/checkpoints/weights/step_029310.pt
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:714b360d124faa1eccef880ef97916250bf9b267f84276f9c5235f239fb55ab3
|
| 3 |
-
size 10360250873
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/checkpoints/weights/step_058620.pt
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:229abf320895323b87f42dae740a0b7c9cd8d03860b3a313d3d7e7c9a98fba91
|
| 3 |
-
size 10360250873
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/checkpoints/weights/step_087930.pt
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:0a2e5a3592cfb6d02682183b746e6009300e080d753d22b400b08820d4e1d8c4
|
| 3 |
-
size 10360250873
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/conditioning/dish_utensil/tasks.jsonl
DELETED
|
@@ -1 +0,0 @@
|
|
| 1 |
-
{"task_index": 0, "task": "pick the dishes out of the rack and place them on the table, then pick and place the spoon to the gray dish and fork to the pink dish"}
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/conditioning/fruit_pick/tasks.jsonl
DELETED
|
@@ -1 +0,0 @@
|
|
| 1 |
-
{"task_index": 0, "task": "Lift the lid, put it aside, and pick the black plum."}
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/conditioning/index.json
DELETED
|
@@ -1,22 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"dish_utensil": {
|
| 3 |
-
"embedding": "conditioning/text_embeds_cache/6bbe3e745d0bcd06a540d3d895af431a769ae466d0cf1102bcee7979ba41e95b.t5_len128.wan22ti2v5b.pt",
|
| 4 |
-
"encoded_prompt": "A video recorded from a robot's point of view executing the following instruction: pick the dishes out of the rack and place them on the table, then pick and place the spoon to the gray dish and fork to the pink dish",
|
| 5 |
-
"task": "pick the dishes out of the rack and place them on the table, then pick and place the spoon to the gray dish and fork to the pink dish"
|
| 6 |
-
},
|
| 7 |
-
"fruit_pick": {
|
| 8 |
-
"embedding": "conditioning/text_embeds_cache/3331746089cf26d56af486af1ef7035e746c2e823cc957e2e3b7a0c3baf347ef.t5_len128.wan22ti2v5b.pt",
|
| 9 |
-
"encoded_prompt": "A video recorded from a robot's point of view executing the following instruction: Lift the lid, put it aside, and pick the black plum.",
|
| 10 |
-
"task": "Lift the lid, put it aside, and pick the black plum."
|
| 11 |
-
},
|
| 12 |
-
"place_cube": {
|
| 13 |
-
"embedding": "conditioning/text_embeds_cache/531e2910f4efdc285bcefbeca24a8a1ff789d6c4365dfd7c15de4eda9eb89f6b.t5_len128.wan22ti2v5b.pt",
|
| 14 |
-
"encoded_prompt": "A video recorded from a robot's point of view executing the following instruction: place the cube in the bowl",
|
| 15 |
-
"task": "place the cube in the bowl"
|
| 16 |
-
},
|
| 17 |
-
"push_t": {
|
| 18 |
-
"embedding": "conditioning/text_embeds_cache/71cb088954da46da4e3cb6c6f73ac812690e9bccf886c7858377c61918b4e3e8.t5_len128.wan22ti2v5b.pt",
|
| 19 |
-
"encoded_prompt": "A video recorded from a robot's point of view executing the following instruction: push the T block to the target outline",
|
| 20 |
-
"task": "push the T block to the target outline"
|
| 21 |
-
}
|
| 22 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/conditioning/place_cube/tasks.jsonl
DELETED
|
@@ -1 +0,0 @@
|
|
| 1 |
-
{"task_index": 0, "task": "place the cube in the bowl"}
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/conditioning/prompts.json
DELETED
|
@@ -1,6 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"dish_utensil": "pick the dishes out of the rack and place them on the table, then pick and place the spoon to the gray dish and fork to the pink dish",
|
| 3 |
-
"fruit_pick": "Lift the lid, put it aside, and pick the black plum.",
|
| 4 |
-
"place_cube": "place the cube in the bowl",
|
| 5 |
-
"push_t": "push the T block to the target outline"
|
| 6 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/conditioning/push_t/tasks.jsonl
DELETED
|
@@ -1 +0,0 @@
|
|
| 1 |
-
{"task_index": 0, "task": "push the T block to the target outline"}
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/conditioning/text_embeds_cache/3331746089cf26d56af486af1ef7035e746c2e823cc957e2e3b7a0c3baf347ef.t5_len128.wan22ti2v5b.pt
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:7ddfc1a78ca521bc8793e4a58e8c1f4fa55d83274ae0026483888d21521e5855
|
| 3 |
-
size 1051869
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/conditioning/text_embeds_cache/531e2910f4efdc285bcefbeca24a8a1ff789d6c4365dfd7c15de4eda9eb89f6b.t5_len128.wan22ti2v5b.pt
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:c676ff34af5f0fd05efa441912d0b94569a824caafa5778847b9a885a79c1e23
|
| 3 |
-
size 1051869
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/conditioning/text_embeds_cache/6bbe3e745d0bcd06a540d3d895af431a769ae466d0cf1102bcee7979ba41e95b.t5_len128.wan22ti2v5b.pt
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:f4d0befa15744dccbba163d380fd62e8c0ca8bffc6b5271f200d527abc23d200
|
| 3 |
-
size 1051869
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/conditioning/text_embeds_cache/71cb088954da46da4e3cb6c6f73ac812690e9bccf886c7858377c61918b4e3e8.t5_len128.wan22ti2v5b.pt
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:85b8468de72c7e7c481fe968d6ab5164d3b3c694f64b7037ec2d05fa706c73c6
|
| 3 |
-
size 1051869
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/config.yaml
DELETED
|
@@ -1,344 +0,0 @@
|
|
| 1 |
-
output_dir: /shared_work/amin-a/realworld-wam/fastwam_train/runs/joint_all4_fasterwam/2026-09-17_04-15-26_job4247
|
| 2 |
-
batch_size: 4
|
| 3 |
-
num_workers: 4
|
| 4 |
-
lr_scheduler_type: cosine
|
| 5 |
-
learning_rate: 0.0001
|
| 6 |
-
num_epochs: 50
|
| 7 |
-
max_steps: null
|
| 8 |
-
wsd_decay_fraction: 0.1
|
| 9 |
-
wsd_decay_shape: linear
|
| 10 |
-
wsd_branch_decay_steps: null
|
| 11 |
-
log_every: 10
|
| 12 |
-
save_every: 29310
|
| 13 |
-
save_steps: []
|
| 14 |
-
eval_every: 2931
|
| 15 |
-
eval_num_inference_steps: 10
|
| 16 |
-
gradient_accumulation_steps: 1
|
| 17 |
-
mixed_precision: bf16
|
| 18 |
-
distributed_timeout_minutes: 60
|
| 19 |
-
seed: 42
|
| 20 |
-
max_grad_norm: 1.0
|
| 21 |
-
weight_decay: 0.01
|
| 22 |
-
resume: null
|
| 23 |
-
allow_unverified_full_state_resume: false
|
| 24 |
-
freeze_video_backbone: false
|
| 25 |
-
hf_upload:
|
| 26 |
-
enabled: false
|
| 27 |
-
dry_run: false
|
| 28 |
-
fail_on_error: false
|
| 29 |
-
script_path: huggingface/upload_to_hf.sh
|
| 30 |
-
bucket_run_name: null
|
| 31 |
-
wandb:
|
| 32 |
-
enabled: true
|
| 33 |
-
workspace: aabyaneh
|
| 34 |
-
project: fasterwam-real
|
| 35 |
-
name: joint_all4_fasterwam_2026-09-17_04-15-26_job4247
|
| 36 |
-
group: fasterwam
|
| 37 |
-
mode: online
|
| 38 |
-
data:
|
| 39 |
-
dataset_name: joint_all4
|
| 40 |
-
train:
|
| 41 |
-
_target_: fastwam.datasets.lerobot.robot_video_dataset.RobotVideoDataset
|
| 42 |
-
dataset_dirs:
|
| 43 |
-
- /tmp/amin_fastwam/fruit_pick_lerobot_v21
|
| 44 |
-
- /tmp/amin_fastwam/dish_utensil_lerobot_v21
|
| 45 |
-
- /tmp/amin_fastwam/place_cube_lerobot_v21
|
| 46 |
-
- /tmp/amin_fastwam/push_t_lerobot_v21
|
| 47 |
-
shape_meta:
|
| 48 |
-
images:
|
| 49 |
-
- key: image
|
| 50 |
-
raw_shape:
|
| 51 |
-
- 3
|
| 52 |
-
- 256
|
| 53 |
-
- 256
|
| 54 |
-
shape:
|
| 55 |
-
- 3
|
| 56 |
-
- 224
|
| 57 |
-
- 224
|
| 58 |
-
- key: wrist_image
|
| 59 |
-
raw_shape:
|
| 60 |
-
- 3
|
| 61 |
-
- 256
|
| 62 |
-
- 256
|
| 63 |
-
shape:
|
| 64 |
-
- 3
|
| 65 |
-
- 224
|
| 66 |
-
- 224
|
| 67 |
-
action:
|
| 68 |
-
- key: default
|
| 69 |
-
raw_shape: 7
|
| 70 |
-
shape: 7
|
| 71 |
-
state:
|
| 72 |
-
- key: default
|
| 73 |
-
raw_shape: 8
|
| 74 |
-
shape: 8
|
| 75 |
-
num_frames: 33
|
| 76 |
-
global_sample_stride: 1
|
| 77 |
-
action_video_freq_ratio: 4
|
| 78 |
-
video_size:
|
| 79 |
-
- 224
|
| 80 |
-
- 448
|
| 81 |
-
camera_key: null
|
| 82 |
-
val_set_proportion: 0.0
|
| 83 |
-
is_training_set: true
|
| 84 |
-
episode_indices_path: /shared_work/amin-a/realworld-wam/splits/fruit_pick_lerobot_v21.json
|
| 85 |
-
episode_indices_key: train
|
| 86 |
-
skip_padding_as_possible: false
|
| 87 |
-
concat_multi_camera: horizontal
|
| 88 |
-
processor:
|
| 89 |
-
_target_: fastwam.datasets.lerobot.processors.fastwam_processor.FastWAMProcessor
|
| 90 |
-
shape_meta:
|
| 91 |
-
images:
|
| 92 |
-
- key: image
|
| 93 |
-
raw_shape:
|
| 94 |
-
- 3
|
| 95 |
-
- 256
|
| 96 |
-
- 256
|
| 97 |
-
shape:
|
| 98 |
-
- 3
|
| 99 |
-
- 224
|
| 100 |
-
- 224
|
| 101 |
-
- key: wrist_image
|
| 102 |
-
raw_shape:
|
| 103 |
-
- 3
|
| 104 |
-
- 256
|
| 105 |
-
- 256
|
| 106 |
-
shape:
|
| 107 |
-
- 3
|
| 108 |
-
- 224
|
| 109 |
-
- 224
|
| 110 |
-
action:
|
| 111 |
-
- key: default
|
| 112 |
-
raw_shape: 7
|
| 113 |
-
shape: 7
|
| 114 |
-
state:
|
| 115 |
-
- key: default
|
| 116 |
-
raw_shape: 8
|
| 117 |
-
shape: 8
|
| 118 |
-
num_obs_steps: 33
|
| 119 |
-
num_output_cameras: 2
|
| 120 |
-
action_output_dim: 7
|
| 121 |
-
proprio_output_dim: 8
|
| 122 |
-
delta_action_dim_mask:
|
| 123 |
-
default:
|
| 124 |
-
- true
|
| 125 |
-
- true
|
| 126 |
-
- true
|
| 127 |
-
- true
|
| 128 |
-
- true
|
| 129 |
-
- true
|
| 130 |
-
- false
|
| 131 |
-
action_state_transforms: null
|
| 132 |
-
use_stepwise_action_norm: false
|
| 133 |
-
norm_default_mode: min/max
|
| 134 |
-
norm_exception_mode: null
|
| 135 |
-
action_state_merger:
|
| 136 |
-
_target_: fastwam.datasets.lerobot.transforms.action_state_merger.ConcatLeftAlign
|
| 137 |
-
train_transforms:
|
| 138 |
-
- _target_: fastwam.datasets.lerobot.transforms.image.ToTensor
|
| 139 |
-
- _target_: torchvision.transforms.Resize
|
| 140 |
-
size:
|
| 141 |
-
- 224
|
| 142 |
-
- 224
|
| 143 |
-
val_transforms:
|
| 144 |
-
- _target_: fastwam.datasets.lerobot.transforms.image.ToTensor
|
| 145 |
-
- _target_: torchvision.transforms.Resize
|
| 146 |
-
size:
|
| 147 |
-
- 224
|
| 148 |
-
- 224
|
| 149 |
-
text_embedding_cache_dir: /tmp/amin_fastwam/joint_all4_text_embeds_cache
|
| 150 |
-
context_len: 128
|
| 151 |
-
val:
|
| 152 |
-
_target_: fastwam.datasets.lerobot.robot_video_dataset.RobotVideoDataset
|
| 153 |
-
dataset_dirs:
|
| 154 |
-
- /tmp/amin_fastwam/fruit_pick_lerobot_v21
|
| 155 |
-
- /tmp/amin_fastwam/dish_utensil_lerobot_v21
|
| 156 |
-
- /tmp/amin_fastwam/place_cube_lerobot_v21
|
| 157 |
-
- /tmp/amin_fastwam/push_t_lerobot_v21
|
| 158 |
-
shape_meta:
|
| 159 |
-
images:
|
| 160 |
-
- key: image
|
| 161 |
-
raw_shape:
|
| 162 |
-
- 3
|
| 163 |
-
- 256
|
| 164 |
-
- 256
|
| 165 |
-
shape:
|
| 166 |
-
- 3
|
| 167 |
-
- 224
|
| 168 |
-
- 224
|
| 169 |
-
- key: wrist_image
|
| 170 |
-
raw_shape:
|
| 171 |
-
- 3
|
| 172 |
-
- 256
|
| 173 |
-
- 256
|
| 174 |
-
shape:
|
| 175 |
-
- 3
|
| 176 |
-
- 224
|
| 177 |
-
- 224
|
| 178 |
-
action:
|
| 179 |
-
- key: default
|
| 180 |
-
raw_shape: 7
|
| 181 |
-
shape: 7
|
| 182 |
-
state:
|
| 183 |
-
- key: default
|
| 184 |
-
raw_shape: 8
|
| 185 |
-
shape: 8
|
| 186 |
-
num_frames: 33
|
| 187 |
-
global_sample_stride: 1
|
| 188 |
-
action_video_freq_ratio: 4
|
| 189 |
-
video_size:
|
| 190 |
-
- 224
|
| 191 |
-
- 448
|
| 192 |
-
camera_key: null
|
| 193 |
-
val_set_proportion: 0.0
|
| 194 |
-
is_training_set: false
|
| 195 |
-
episode_indices_path: /shared_work/amin-a/realworld-wam/splits/fruit_pick_lerobot_v21.json
|
| 196 |
-
episode_indices_key: val
|
| 197 |
-
skip_padding_as_possible: false
|
| 198 |
-
concat_multi_camera: horizontal
|
| 199 |
-
processor:
|
| 200 |
-
_target_: fastwam.datasets.lerobot.processors.fastwam_processor.FastWAMProcessor
|
| 201 |
-
shape_meta:
|
| 202 |
-
images:
|
| 203 |
-
- key: image
|
| 204 |
-
raw_shape:
|
| 205 |
-
- 3
|
| 206 |
-
- 256
|
| 207 |
-
- 256
|
| 208 |
-
shape:
|
| 209 |
-
- 3
|
| 210 |
-
- 224
|
| 211 |
-
- 224
|
| 212 |
-
- key: wrist_image
|
| 213 |
-
raw_shape:
|
| 214 |
-
- 3
|
| 215 |
-
- 256
|
| 216 |
-
- 256
|
| 217 |
-
shape:
|
| 218 |
-
- 3
|
| 219 |
-
- 224
|
| 220 |
-
- 224
|
| 221 |
-
action:
|
| 222 |
-
- key: default
|
| 223 |
-
raw_shape: 7
|
| 224 |
-
shape: 7
|
| 225 |
-
state:
|
| 226 |
-
- key: default
|
| 227 |
-
raw_shape: 8
|
| 228 |
-
shape: 8
|
| 229 |
-
num_obs_steps: 33
|
| 230 |
-
num_output_cameras: 2
|
| 231 |
-
action_output_dim: 7
|
| 232 |
-
proprio_output_dim: 8
|
| 233 |
-
delta_action_dim_mask:
|
| 234 |
-
default:
|
| 235 |
-
- true
|
| 236 |
-
- true
|
| 237 |
-
- true
|
| 238 |
-
- true
|
| 239 |
-
- true
|
| 240 |
-
- true
|
| 241 |
-
- false
|
| 242 |
-
action_state_transforms: null
|
| 243 |
-
use_stepwise_action_norm: false
|
| 244 |
-
norm_default_mode: min/max
|
| 245 |
-
norm_exception_mode: null
|
| 246 |
-
action_state_merger:
|
| 247 |
-
_target_: fastwam.datasets.lerobot.transforms.action_state_merger.ConcatLeftAlign
|
| 248 |
-
train_transforms:
|
| 249 |
-
- _target_: fastwam.datasets.lerobot.transforms.image.ToTensor
|
| 250 |
-
- _target_: torchvision.transforms.Resize
|
| 251 |
-
size:
|
| 252 |
-
- 224
|
| 253 |
-
- 224
|
| 254 |
-
val_transforms:
|
| 255 |
-
- _target_: fastwam.datasets.lerobot.transforms.image.ToTensor
|
| 256 |
-
- _target_: torchvision.transforms.Resize
|
| 257 |
-
size:
|
| 258 |
-
- 224
|
| 259 |
-
- 224
|
| 260 |
-
text_embedding_cache_dir: /tmp/amin_fastwam/joint_all4_text_embeds_cache
|
| 261 |
-
context_len: 128
|
| 262 |
-
model:
|
| 263 |
-
_target_: fastwam.models.wan22.piha.create_piha
|
| 264 |
-
model_id: Wan-AI/Wan2.2-TI2V-5B
|
| 265 |
-
tokenizer_model_id: Wan-AI/Wan2.1-T2V-1.3B
|
| 266 |
-
tokenizer_max_len: 128
|
| 267 |
-
load_text_encoder: false
|
| 268 |
-
proprio_dim: 8
|
| 269 |
-
redirect_common_files: true
|
| 270 |
-
mot_checkpoint_mixed_attn: false
|
| 271 |
-
action_dit_pretrained_path: null
|
| 272 |
-
skip_dit_load_from_pretrain: false
|
| 273 |
-
decoupled: true
|
| 274 |
-
kv_source_mode: new_fused_kv
|
| 275 |
-
fusion_hidden_dim: 64
|
| 276 |
-
fusion_use_norm: true
|
| 277 |
-
fixed_rope: true
|
| 278 |
-
new_fused_kv_rope_mode: aligned_3d
|
| 279 |
-
aligned_3d_action_spatial_anchor_layout: horizontal
|
| 280 |
-
new_fused_kv_projection_mode: simple_head_softmax
|
| 281 |
-
new_fused_kv_pos_embed_dim: 128
|
| 282 |
-
new_fused_kv_mlp_mixer_num_blocks: 1
|
| 283 |
-
new_fused_kv_mlp_mixer_token_mlp_ratio: 4.0
|
| 284 |
-
new_fused_kv_mlp_mixer_channel_mlp_ratio: 4.0
|
| 285 |
-
new_fused_kv_head_fused_kv_sin2d_pe_mlp_hidden_dim: 512
|
| 286 |
-
new_fused_kv_simple_head_softmax_fuse_mode: all
|
| 287 |
-
new_fused_kv_head_fused_kv_fuse_mode: all
|
| 288 |
-
video_dit_config:
|
| 289 |
-
has_image_input: false
|
| 290 |
-
patch_size:
|
| 291 |
-
- 1
|
| 292 |
-
- 2
|
| 293 |
-
- 2
|
| 294 |
-
in_dim: 48
|
| 295 |
-
hidden_dim: 3072
|
| 296 |
-
ffn_dim: 14336
|
| 297 |
-
freq_dim: 256
|
| 298 |
-
text_dim: 4096
|
| 299 |
-
out_dim: 48
|
| 300 |
-
num_heads: 24
|
| 301 |
-
attn_head_dim: 128
|
| 302 |
-
num_layers: 30
|
| 303 |
-
eps: 1.0e-06
|
| 304 |
-
seperated_timestep: true
|
| 305 |
-
require_clip_embedding: false
|
| 306 |
-
require_vae_embedding: false
|
| 307 |
-
fuse_vae_embedding_in_latents: true
|
| 308 |
-
use_gradient_checkpointing: false
|
| 309 |
-
video_attention_mask_mode: first_frame_causal
|
| 310 |
-
action_conditioned: false
|
| 311 |
-
action_dim: 7
|
| 312 |
-
action_group_causal_mask_mode: group_diagonal
|
| 313 |
-
action_dit_config:
|
| 314 |
-
action_dim: 7
|
| 315 |
-
hidden_dim: 3072
|
| 316 |
-
ffn_dim: 12288
|
| 317 |
-
num_heads: 24
|
| 318 |
-
attn_head_dim: 128
|
| 319 |
-
num_layers: 1
|
| 320 |
-
layer_selected: null
|
| 321 |
-
text_dim: 4096
|
| 322 |
-
freq_dim: 256
|
| 323 |
-
eps: 1.0e-06
|
| 324 |
-
use_gradient_checkpointing: false
|
| 325 |
-
action_text_cross_attn: false
|
| 326 |
-
video_scheduler:
|
| 327 |
-
train_shift: 5.0
|
| 328 |
-
infer_shift: 5.0
|
| 329 |
-
num_train_timesteps: 1000
|
| 330 |
-
action_scheduler:
|
| 331 |
-
train_shift: 5.0
|
| 332 |
-
infer_shift: 5.0
|
| 333 |
-
num_train_timesteps: 1000
|
| 334 |
-
loss:
|
| 335 |
-
lambda_video: 1.0
|
| 336 |
-
lambda_action: 1.0
|
| 337 |
-
piha_permutation_mode: cyclic
|
| 338 |
-
action_text_ca_dropout_p: 0.0
|
| 339 |
-
method: fasterwam
|
| 340 |
-
implementation:
|
| 341 |
-
repository: https://github.com/rhyang6/fastwam
|
| 342 |
-
branch: new_fused_kv
|
| 343 |
-
commit: 19483b8b1b6a72e697091a07e7df7777aa09fd85
|
| 344 |
-
reference_config: scripts_liheng/final_version/libero.yaml
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/dataset_stats.json
DELETED
|
@@ -1,1938 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"state": {
|
| 3 |
-
"default": {
|
| 4 |
-
"stepwise_min": [
|
| 5 |
-
[
|
| 6 |
-
0.3257139027118683,
|
| 7 |
-
-0.19808503985404968,
|
| 8 |
-
0.11773434281349182,
|
| 9 |
-
2.8797452449798584,
|
| 10 |
-
-1.348800778388977,
|
| 11 |
-
0.1602623164653778,
|
| 12 |
-
5.3190000471659005e-05,
|
| 13 |
-
-0.03993518278002739
|
| 14 |
-
]
|
| 15 |
-
],
|
| 16 |
-
"stepwise_max": [
|
| 17 |
-
[
|
| 18 |
-
0.6804016828536987,
|
| 19 |
-
0.31247836351394653,
|
| 20 |
-
0.45249679684638977,
|
| 21 |
-
3.012880325317383,
|
| 22 |
-
-1.1482024192810059,
|
| 23 |
-
0.589073657989502,
|
| 24 |
-
0.03993518278002739,
|
| 25 |
-
-5.3190000471659005e-05
|
| 26 |
-
]
|
| 27 |
-
],
|
| 28 |
-
"global_min": [
|
| 29 |
-
0.3257139027118683,
|
| 30 |
-
-0.19808503985404968,
|
| 31 |
-
0.11773434281349182,
|
| 32 |
-
2.8797452449798584,
|
| 33 |
-
-1.348800778388977,
|
| 34 |
-
0.1602623164653778,
|
| 35 |
-
5.3190000471659005e-05,
|
| 36 |
-
-0.03993518278002739
|
| 37 |
-
],
|
| 38 |
-
"global_max": [
|
| 39 |
-
0.6804016828536987,
|
| 40 |
-
0.31247836351394653,
|
| 41 |
-
0.45249679684638977,
|
| 42 |
-
3.012880325317383,
|
| 43 |
-
-1.1482024192810059,
|
| 44 |
-
0.589073657989502,
|
| 45 |
-
0.03993518278002739,
|
| 46 |
-
-5.3190000471659005e-05
|
| 47 |
-
],
|
| 48 |
-
"stepwise_q01": [
|
| 49 |
-
[
|
| 50 |
-
0.326332151889801,
|
| 51 |
-
-0.19770283997058868,
|
| 52 |
-
0.1177695095539093,
|
| 53 |
-
2.881575584411621,
|
| 54 |
-
-1.346077799797058,
|
| 55 |
-
0.1623862236738205,
|
| 56 |
-
0.0001012185966828838,
|
| 57 |
-
-0.039905305951833725
|
| 58 |
-
]
|
| 59 |
-
],
|
| 60 |
-
"stepwise_q99": [
|
| 61 |
-
[
|
| 62 |
-
0.6752662658691406,
|
| 63 |
-
0.3044644892215729,
|
| 64 |
-
0.450180321931839,
|
| 65 |
-
3.0091538429260254,
|
| 66 |
-
-1.149796485900879,
|
| 67 |
-
0.5569735765457153,
|
| 68 |
-
0.039905305951833725,
|
| 69 |
-
-0.00010121861123479903
|
| 70 |
-
]
|
| 71 |
-
],
|
| 72 |
-
"global_q01": [
|
| 73 |
-
0.326332151889801,
|
| 74 |
-
-0.19770283997058868,
|
| 75 |
-
0.1177695095539093,
|
| 76 |
-
2.881575584411621,
|
| 77 |
-
-1.346077799797058,
|
| 78 |
-
0.1623862236738205,
|
| 79 |
-
0.0001012185966828838,
|
| 80 |
-
-0.039905305951833725
|
| 81 |
-
],
|
| 82 |
-
"global_q99": [
|
| 83 |
-
0.6752662658691406,
|
| 84 |
-
0.3044644892215729,
|
| 85 |
-
0.450180321931839,
|
| 86 |
-
3.0091538429260254,
|
| 87 |
-
-1.149796485900879,
|
| 88 |
-
0.5569735765457153,
|
| 89 |
-
0.039905305951833725,
|
| 90 |
-
-0.00010121861123479903
|
| 91 |
-
],
|
| 92 |
-
"stepwise_mean": [
|
| 93 |
-
[
|
| 94 |
-
0.4861578345298767,
|
| 95 |
-
0.02602844499051571,
|
| 96 |
-
0.25201132893562317,
|
| 97 |
-
2.952380657196045,
|
| 98 |
-
-1.2511029243469238,
|
| 99 |
-
0.37992680072784424,
|
| 100 |
-
0.021428851410746574,
|
| 101 |
-
-0.021428851410746574
|
| 102 |
-
]
|
| 103 |
-
],
|
| 104 |
-
"stepwise_std": [
|
| 105 |
-
[
|
| 106 |
-
0.04675422981381416,
|
| 107 |
-
0.1213567927479744,
|
| 108 |
-
0.06022870913147926,
|
| 109 |
-
0.017529325559735298,
|
| 110 |
-
0.03535432368516922,
|
| 111 |
-
0.09873220324516296,
|
| 112 |
-
0.01631387695670128,
|
| 113 |
-
0.01631387695670128
|
| 114 |
-
]
|
| 115 |
-
],
|
| 116 |
-
"global_mean": [
|
| 117 |
-
0.4861578345298767,
|
| 118 |
-
0.02602844499051571,
|
| 119 |
-
0.25201132893562317,
|
| 120 |
-
2.952380657196045,
|
| 121 |
-
-1.2511029243469238,
|
| 122 |
-
0.37992680072784424,
|
| 123 |
-
0.021428851410746574,
|
| 124 |
-
-0.021428851410746574
|
| 125 |
-
],
|
| 126 |
-
"global_std": [
|
| 127 |
-
0.04675422981381416,
|
| 128 |
-
0.1213567927479744,
|
| 129 |
-
0.06022870913147926,
|
| 130 |
-
0.017529325559735298,
|
| 131 |
-
0.03535432368516922,
|
| 132 |
-
0.09873220324516296,
|
| 133 |
-
0.01631387695670128,
|
| 134 |
-
0.01631387695670128
|
| 135 |
-
]
|
| 136 |
-
}
|
| 137 |
-
},
|
| 138 |
-
"action": {
|
| 139 |
-
"default": {
|
| 140 |
-
"stepwise_min": [
|
| 141 |
-
[
|
| 142 |
-
-0.023571429774165154,
|
| 143 |
-
-0.03100000135600567,
|
| 144 |
-
-0.025142857804894447,
|
| 145 |
-
0.0,
|
| 146 |
-
-0.0,
|
| 147 |
-
-0.0,
|
| 148 |
-
-1.0
|
| 149 |
-
],
|
| 150 |
-
[
|
| 151 |
-
-0.023571429774165154,
|
| 152 |
-
-0.03100000135600567,
|
| 153 |
-
-0.025142857804894447,
|
| 154 |
-
0.0,
|
| 155 |
-
-0.0,
|
| 156 |
-
-0.0,
|
| 157 |
-
-1.0
|
| 158 |
-
],
|
| 159 |
-
[
|
| 160 |
-
-0.023571429774165154,
|
| 161 |
-
-0.03100000135600567,
|
| 162 |
-
-0.025142857804894447,
|
| 163 |
-
0.0,
|
| 164 |
-
-0.0,
|
| 165 |
-
-0.0,
|
| 166 |
-
-1.0
|
| 167 |
-
],
|
| 168 |
-
[
|
| 169 |
-
-0.023571429774165154,
|
| 170 |
-
-0.03100000135600567,
|
| 171 |
-
-0.025142857804894447,
|
| 172 |
-
0.0,
|
| 173 |
-
-0.0,
|
| 174 |
-
-0.0,
|
| 175 |
-
-1.0
|
| 176 |
-
],
|
| 177 |
-
[
|
| 178 |
-
-0.023571429774165154,
|
| 179 |
-
-0.03100000135600567,
|
| 180 |
-
-0.025142857804894447,
|
| 181 |
-
0.0,
|
| 182 |
-
-0.0,
|
| 183 |
-
-0.0,
|
| 184 |
-
-1.0
|
| 185 |
-
],
|
| 186 |
-
[
|
| 187 |
-
-0.023571429774165154,
|
| 188 |
-
-0.03100000135600567,
|
| 189 |
-
-0.025142857804894447,
|
| 190 |
-
0.0,
|
| 191 |
-
-0.0,
|
| 192 |
-
-0.0,
|
| 193 |
-
-1.0
|
| 194 |
-
],
|
| 195 |
-
[
|
| 196 |
-
-0.023571429774165154,
|
| 197 |
-
-0.03100000135600567,
|
| 198 |
-
-0.025142857804894447,
|
| 199 |
-
0.0,
|
| 200 |
-
-0.0,
|
| 201 |
-
-0.0,
|
| 202 |
-
-1.0
|
| 203 |
-
],
|
| 204 |
-
[
|
| 205 |
-
-0.023571429774165154,
|
| 206 |
-
-0.03100000135600567,
|
| 207 |
-
-0.025142857804894447,
|
| 208 |
-
0.0,
|
| 209 |
-
-0.0,
|
| 210 |
-
-0.0,
|
| 211 |
-
-1.0
|
| 212 |
-
],
|
| 213 |
-
[
|
| 214 |
-
-0.023571429774165154,
|
| 215 |
-
-0.03100000135600567,
|
| 216 |
-
-0.025142857804894447,
|
| 217 |
-
0.0,
|
| 218 |
-
-0.0,
|
| 219 |
-
-0.0,
|
| 220 |
-
-1.0
|
| 221 |
-
],
|
| 222 |
-
[
|
| 223 |
-
-0.023571429774165154,
|
| 224 |
-
-0.03100000135600567,
|
| 225 |
-
-0.025142857804894447,
|
| 226 |
-
0.0,
|
| 227 |
-
-0.0,
|
| 228 |
-
-0.0,
|
| 229 |
-
-1.0
|
| 230 |
-
],
|
| 231 |
-
[
|
| 232 |
-
-0.023571429774165154,
|
| 233 |
-
-0.03100000135600567,
|
| 234 |
-
-0.025142857804894447,
|
| 235 |
-
0.0,
|
| 236 |
-
-0.0,
|
| 237 |
-
-0.0,
|
| 238 |
-
-1.0
|
| 239 |
-
],
|
| 240 |
-
[
|
| 241 |
-
-0.023571429774165154,
|
| 242 |
-
-0.03100000135600567,
|
| 243 |
-
-0.025142857804894447,
|
| 244 |
-
0.0,
|
| 245 |
-
-0.0,
|
| 246 |
-
-0.0,
|
| 247 |
-
-1.0
|
| 248 |
-
],
|
| 249 |
-
[
|
| 250 |
-
-0.023571429774165154,
|
| 251 |
-
-0.03100000135600567,
|
| 252 |
-
-0.025142857804894447,
|
| 253 |
-
0.0,
|
| 254 |
-
-0.0,
|
| 255 |
-
-0.0,
|
| 256 |
-
-1.0
|
| 257 |
-
],
|
| 258 |
-
[
|
| 259 |
-
-0.023571429774165154,
|
| 260 |
-
-0.03100000135600567,
|
| 261 |
-
-0.025142857804894447,
|
| 262 |
-
0.0,
|
| 263 |
-
-0.0,
|
| 264 |
-
-0.0,
|
| 265 |
-
-1.0
|
| 266 |
-
],
|
| 267 |
-
[
|
| 268 |
-
-0.023571429774165154,
|
| 269 |
-
-0.03100000135600567,
|
| 270 |
-
-0.025142857804894447,
|
| 271 |
-
0.0,
|
| 272 |
-
-0.0,
|
| 273 |
-
-0.0,
|
| 274 |
-
-1.0
|
| 275 |
-
],
|
| 276 |
-
[
|
| 277 |
-
-0.023571429774165154,
|
| 278 |
-
-0.03100000135600567,
|
| 279 |
-
-0.025142857804894447,
|
| 280 |
-
0.0,
|
| 281 |
-
-0.0,
|
| 282 |
-
-0.0,
|
| 283 |
-
-1.0
|
| 284 |
-
],
|
| 285 |
-
[
|
| 286 |
-
-0.023571429774165154,
|
| 287 |
-
-0.03100000135600567,
|
| 288 |
-
-0.025142857804894447,
|
| 289 |
-
0.0,
|
| 290 |
-
-0.0,
|
| 291 |
-
-0.0,
|
| 292 |
-
-1.0
|
| 293 |
-
],
|
| 294 |
-
[
|
| 295 |
-
-0.023571429774165154,
|
| 296 |
-
-0.03100000135600567,
|
| 297 |
-
-0.025142857804894447,
|
| 298 |
-
0.0,
|
| 299 |
-
-0.0,
|
| 300 |
-
-0.0,
|
| 301 |
-
-1.0
|
| 302 |
-
],
|
| 303 |
-
[
|
| 304 |
-
-0.023571429774165154,
|
| 305 |
-
-0.03100000135600567,
|
| 306 |
-
-0.025142857804894447,
|
| 307 |
-
0.0,
|
| 308 |
-
-0.0,
|
| 309 |
-
-0.0,
|
| 310 |
-
-1.0
|
| 311 |
-
],
|
| 312 |
-
[
|
| 313 |
-
-0.023571429774165154,
|
| 314 |
-
-0.03100000135600567,
|
| 315 |
-
-0.025142857804894447,
|
| 316 |
-
0.0,
|
| 317 |
-
-0.0,
|
| 318 |
-
-0.0,
|
| 319 |
-
-1.0
|
| 320 |
-
],
|
| 321 |
-
[
|
| 322 |
-
-0.023571429774165154,
|
| 323 |
-
-0.03100000135600567,
|
| 324 |
-
-0.025142857804894447,
|
| 325 |
-
0.0,
|
| 326 |
-
-0.0,
|
| 327 |
-
-0.0,
|
| 328 |
-
-1.0
|
| 329 |
-
],
|
| 330 |
-
[
|
| 331 |
-
-0.023571429774165154,
|
| 332 |
-
-0.03100000135600567,
|
| 333 |
-
-0.025142857804894447,
|
| 334 |
-
0.0,
|
| 335 |
-
-0.0,
|
| 336 |
-
-0.0,
|
| 337 |
-
-1.0
|
| 338 |
-
],
|
| 339 |
-
[
|
| 340 |
-
-0.023571429774165154,
|
| 341 |
-
-0.03100000135600567,
|
| 342 |
-
-0.025142857804894447,
|
| 343 |
-
0.0,
|
| 344 |
-
-0.0,
|
| 345 |
-
-0.0,
|
| 346 |
-
-1.0
|
| 347 |
-
],
|
| 348 |
-
[
|
| 349 |
-
-0.023571429774165154,
|
| 350 |
-
-0.03100000135600567,
|
| 351 |
-
-0.025142857804894447,
|
| 352 |
-
0.0,
|
| 353 |
-
-0.0,
|
| 354 |
-
-0.0,
|
| 355 |
-
-1.0
|
| 356 |
-
],
|
| 357 |
-
[
|
| 358 |
-
-0.023571429774165154,
|
| 359 |
-
-0.03100000135600567,
|
| 360 |
-
-0.025142857804894447,
|
| 361 |
-
0.0,
|
| 362 |
-
-0.0,
|
| 363 |
-
-0.0,
|
| 364 |
-
-1.0
|
| 365 |
-
],
|
| 366 |
-
[
|
| 367 |
-
-0.023571429774165154,
|
| 368 |
-
-0.03100000135600567,
|
| 369 |
-
-0.025142857804894447,
|
| 370 |
-
0.0,
|
| 371 |
-
-0.0,
|
| 372 |
-
-0.0,
|
| 373 |
-
-1.0
|
| 374 |
-
],
|
| 375 |
-
[
|
| 376 |
-
-0.023571429774165154,
|
| 377 |
-
-0.03100000135600567,
|
| 378 |
-
-0.025142857804894447,
|
| 379 |
-
0.0,
|
| 380 |
-
-0.0,
|
| 381 |
-
-0.0,
|
| 382 |
-
-1.0
|
| 383 |
-
],
|
| 384 |
-
[
|
| 385 |
-
-0.023571429774165154,
|
| 386 |
-
-0.03100000135600567,
|
| 387 |
-
-0.025142857804894447,
|
| 388 |
-
0.0,
|
| 389 |
-
-0.0,
|
| 390 |
-
-0.0,
|
| 391 |
-
-1.0
|
| 392 |
-
],
|
| 393 |
-
[
|
| 394 |
-
-0.023571429774165154,
|
| 395 |
-
-0.03100000135600567,
|
| 396 |
-
-0.025142857804894447,
|
| 397 |
-
0.0,
|
| 398 |
-
-0.0,
|
| 399 |
-
-0.0,
|
| 400 |
-
-1.0
|
| 401 |
-
],
|
| 402 |
-
[
|
| 403 |
-
-0.023571429774165154,
|
| 404 |
-
-0.03100000135600567,
|
| 405 |
-
-0.025142857804894447,
|
| 406 |
-
0.0,
|
| 407 |
-
-0.0,
|
| 408 |
-
-0.0,
|
| 409 |
-
-1.0
|
| 410 |
-
],
|
| 411 |
-
[
|
| 412 |
-
-0.023571429774165154,
|
| 413 |
-
-0.03100000135600567,
|
| 414 |
-
-0.025142857804894447,
|
| 415 |
-
0.0,
|
| 416 |
-
-0.0,
|
| 417 |
-
-0.0,
|
| 418 |
-
-1.0
|
| 419 |
-
],
|
| 420 |
-
[
|
| 421 |
-
-0.023571429774165154,
|
| 422 |
-
-0.03100000135600567,
|
| 423 |
-
-0.025142857804894447,
|
| 424 |
-
0.0,
|
| 425 |
-
-0.0,
|
| 426 |
-
-0.0,
|
| 427 |
-
-1.0
|
| 428 |
-
]
|
| 429 |
-
],
|
| 430 |
-
"stepwise_max": [
|
| 431 |
-
[
|
| 432 |
-
0.022142857313156128,
|
| 433 |
-
0.021714285016059875,
|
| 434 |
-
0.03257143124938011,
|
| 435 |
-
0.0,
|
| 436 |
-
-0.0,
|
| 437 |
-
-0.0,
|
| 438 |
-
1.0
|
| 439 |
-
],
|
| 440 |
-
[
|
| 441 |
-
0.022142857313156128,
|
| 442 |
-
0.021714285016059875,
|
| 443 |
-
0.03257143124938011,
|
| 444 |
-
0.0,
|
| 445 |
-
-0.0,
|
| 446 |
-
-0.0,
|
| 447 |
-
1.0
|
| 448 |
-
],
|
| 449 |
-
[
|
| 450 |
-
0.022142857313156128,
|
| 451 |
-
0.021714285016059875,
|
| 452 |
-
0.03257143124938011,
|
| 453 |
-
0.0,
|
| 454 |
-
-0.0,
|
| 455 |
-
-0.0,
|
| 456 |
-
1.0
|
| 457 |
-
],
|
| 458 |
-
[
|
| 459 |
-
0.022142857313156128,
|
| 460 |
-
0.021714285016059875,
|
| 461 |
-
0.03257143124938011,
|
| 462 |
-
0.0,
|
| 463 |
-
-0.0,
|
| 464 |
-
-0.0,
|
| 465 |
-
1.0
|
| 466 |
-
],
|
| 467 |
-
[
|
| 468 |
-
0.022142857313156128,
|
| 469 |
-
0.021714285016059875,
|
| 470 |
-
0.03257143124938011,
|
| 471 |
-
0.0,
|
| 472 |
-
-0.0,
|
| 473 |
-
-0.0,
|
| 474 |
-
1.0
|
| 475 |
-
],
|
| 476 |
-
[
|
| 477 |
-
0.022142857313156128,
|
| 478 |
-
0.021714285016059875,
|
| 479 |
-
0.03257143124938011,
|
| 480 |
-
0.0,
|
| 481 |
-
-0.0,
|
| 482 |
-
-0.0,
|
| 483 |
-
1.0
|
| 484 |
-
],
|
| 485 |
-
[
|
| 486 |
-
0.022142857313156128,
|
| 487 |
-
0.021714285016059875,
|
| 488 |
-
0.03257143124938011,
|
| 489 |
-
0.0,
|
| 490 |
-
-0.0,
|
| 491 |
-
-0.0,
|
| 492 |
-
1.0
|
| 493 |
-
],
|
| 494 |
-
[
|
| 495 |
-
0.022142857313156128,
|
| 496 |
-
0.021714285016059875,
|
| 497 |
-
0.03257143124938011,
|
| 498 |
-
0.0,
|
| 499 |
-
-0.0,
|
| 500 |
-
-0.0,
|
| 501 |
-
1.0
|
| 502 |
-
],
|
| 503 |
-
[
|
| 504 |
-
0.022142857313156128,
|
| 505 |
-
0.021714285016059875,
|
| 506 |
-
0.03257143124938011,
|
| 507 |
-
0.0,
|
| 508 |
-
-0.0,
|
| 509 |
-
-0.0,
|
| 510 |
-
1.0
|
| 511 |
-
],
|
| 512 |
-
[
|
| 513 |
-
0.022142857313156128,
|
| 514 |
-
0.021714285016059875,
|
| 515 |
-
0.03257143124938011,
|
| 516 |
-
0.0,
|
| 517 |
-
-0.0,
|
| 518 |
-
-0.0,
|
| 519 |
-
1.0
|
| 520 |
-
],
|
| 521 |
-
[
|
| 522 |
-
0.022142857313156128,
|
| 523 |
-
0.021714285016059875,
|
| 524 |
-
0.03257143124938011,
|
| 525 |
-
0.0,
|
| 526 |
-
-0.0,
|
| 527 |
-
-0.0,
|
| 528 |
-
1.0
|
| 529 |
-
],
|
| 530 |
-
[
|
| 531 |
-
0.022142857313156128,
|
| 532 |
-
0.021714285016059875,
|
| 533 |
-
0.03257143124938011,
|
| 534 |
-
0.0,
|
| 535 |
-
-0.0,
|
| 536 |
-
-0.0,
|
| 537 |
-
1.0
|
| 538 |
-
],
|
| 539 |
-
[
|
| 540 |
-
0.022142857313156128,
|
| 541 |
-
0.021714285016059875,
|
| 542 |
-
0.03257143124938011,
|
| 543 |
-
0.0,
|
| 544 |
-
-0.0,
|
| 545 |
-
-0.0,
|
| 546 |
-
1.0
|
| 547 |
-
],
|
| 548 |
-
[
|
| 549 |
-
0.022142857313156128,
|
| 550 |
-
0.021714285016059875,
|
| 551 |
-
0.03257143124938011,
|
| 552 |
-
0.0,
|
| 553 |
-
-0.0,
|
| 554 |
-
-0.0,
|
| 555 |
-
1.0
|
| 556 |
-
],
|
| 557 |
-
[
|
| 558 |
-
0.022142857313156128,
|
| 559 |
-
0.01842857152223587,
|
| 560 |
-
0.03257143124938011,
|
| 561 |
-
0.0,
|
| 562 |
-
-0.0,
|
| 563 |
-
-0.0,
|
| 564 |
-
1.0
|
| 565 |
-
],
|
| 566 |
-
[
|
| 567 |
-
0.022142857313156128,
|
| 568 |
-
0.01842857152223587,
|
| 569 |
-
0.03257143124938011,
|
| 570 |
-
0.0,
|
| 571 |
-
-0.0,
|
| 572 |
-
-0.0,
|
| 573 |
-
1.0
|
| 574 |
-
],
|
| 575 |
-
[
|
| 576 |
-
0.022142857313156128,
|
| 577 |
-
0.01842857152223587,
|
| 578 |
-
0.03257143124938011,
|
| 579 |
-
0.0,
|
| 580 |
-
-0.0,
|
| 581 |
-
-0.0,
|
| 582 |
-
1.0
|
| 583 |
-
],
|
| 584 |
-
[
|
| 585 |
-
0.022142857313156128,
|
| 586 |
-
0.01842857152223587,
|
| 587 |
-
0.03257143124938011,
|
| 588 |
-
0.0,
|
| 589 |
-
-0.0,
|
| 590 |
-
-0.0,
|
| 591 |
-
1.0
|
| 592 |
-
],
|
| 593 |
-
[
|
| 594 |
-
0.022142857313156128,
|
| 595 |
-
0.01842857152223587,
|
| 596 |
-
0.03257143124938011,
|
| 597 |
-
0.0,
|
| 598 |
-
-0.0,
|
| 599 |
-
-0.0,
|
| 600 |
-
1.0
|
| 601 |
-
],
|
| 602 |
-
[
|
| 603 |
-
0.022142857313156128,
|
| 604 |
-
0.01842857152223587,
|
| 605 |
-
0.03257143124938011,
|
| 606 |
-
0.0,
|
| 607 |
-
-0.0,
|
| 608 |
-
-0.0,
|
| 609 |
-
1.0
|
| 610 |
-
],
|
| 611 |
-
[
|
| 612 |
-
0.022142857313156128,
|
| 613 |
-
0.01842857152223587,
|
| 614 |
-
0.03257143124938011,
|
| 615 |
-
0.0,
|
| 616 |
-
-0.0,
|
| 617 |
-
-0.0,
|
| 618 |
-
1.0
|
| 619 |
-
],
|
| 620 |
-
[
|
| 621 |
-
0.022142857313156128,
|
| 622 |
-
0.017999999225139618,
|
| 623 |
-
0.03257143124938011,
|
| 624 |
-
0.0,
|
| 625 |
-
-0.0,
|
| 626 |
-
-0.0,
|
| 627 |
-
1.0
|
| 628 |
-
],
|
| 629 |
-
[
|
| 630 |
-
0.022142857313156128,
|
| 631 |
-
0.017999999225139618,
|
| 632 |
-
0.03257143124938011,
|
| 633 |
-
0.0,
|
| 634 |
-
-0.0,
|
| 635 |
-
-0.0,
|
| 636 |
-
1.0
|
| 637 |
-
],
|
| 638 |
-
[
|
| 639 |
-
0.022142857313156128,
|
| 640 |
-
0.017999999225139618,
|
| 641 |
-
0.03257143124938011,
|
| 642 |
-
0.0,
|
| 643 |
-
-0.0,
|
| 644 |
-
-0.0,
|
| 645 |
-
1.0
|
| 646 |
-
],
|
| 647 |
-
[
|
| 648 |
-
0.022142857313156128,
|
| 649 |
-
0.017999999225139618,
|
| 650 |
-
0.03257143124938011,
|
| 651 |
-
0.0,
|
| 652 |
-
-0.0,
|
| 653 |
-
-0.0,
|
| 654 |
-
1.0
|
| 655 |
-
],
|
| 656 |
-
[
|
| 657 |
-
0.022142857313156128,
|
| 658 |
-
0.017999999225139618,
|
| 659 |
-
0.03257143124938011,
|
| 660 |
-
0.0,
|
| 661 |
-
-0.0,
|
| 662 |
-
-0.0,
|
| 663 |
-
1.0
|
| 664 |
-
],
|
| 665 |
-
[
|
| 666 |
-
0.022142857313156128,
|
| 667 |
-
0.017999999225139618,
|
| 668 |
-
0.03257143124938011,
|
| 669 |
-
0.0,
|
| 670 |
-
-0.0,
|
| 671 |
-
-0.0,
|
| 672 |
-
1.0
|
| 673 |
-
],
|
| 674 |
-
[
|
| 675 |
-
0.022142857313156128,
|
| 676 |
-
0.017999999225139618,
|
| 677 |
-
0.03257143124938011,
|
| 678 |
-
0.0,
|
| 679 |
-
-0.0,
|
| 680 |
-
-0.0,
|
| 681 |
-
1.0
|
| 682 |
-
],
|
| 683 |
-
[
|
| 684 |
-
0.022142857313156128,
|
| 685 |
-
0.017999999225139618,
|
| 686 |
-
0.03257143124938011,
|
| 687 |
-
0.0,
|
| 688 |
-
-0.0,
|
| 689 |
-
-0.0,
|
| 690 |
-
1.0
|
| 691 |
-
],
|
| 692 |
-
[
|
| 693 |
-
0.022142857313156128,
|
| 694 |
-
0.017999999225139618,
|
| 695 |
-
0.03257143124938011,
|
| 696 |
-
0.0,
|
| 697 |
-
-0.0,
|
| 698 |
-
-0.0,
|
| 699 |
-
1.0
|
| 700 |
-
],
|
| 701 |
-
[
|
| 702 |
-
0.022142857313156128,
|
| 703 |
-
0.017999999225139618,
|
| 704 |
-
0.03257143124938011,
|
| 705 |
-
0.0,
|
| 706 |
-
-0.0,
|
| 707 |
-
-0.0,
|
| 708 |
-
1.0
|
| 709 |
-
],
|
| 710 |
-
[
|
| 711 |
-
0.022142857313156128,
|
| 712 |
-
0.017999999225139618,
|
| 713 |
-
0.03257143124938011,
|
| 714 |
-
0.0,
|
| 715 |
-
-0.0,
|
| 716 |
-
-0.0,
|
| 717 |
-
1.0
|
| 718 |
-
]
|
| 719 |
-
],
|
| 720 |
-
"global_min": [
|
| 721 |
-
-0.023571429774165154,
|
| 722 |
-
-0.03100000135600567,
|
| 723 |
-
-0.025142857804894447,
|
| 724 |
-
0.0,
|
| 725 |
-
-0.0,
|
| 726 |
-
-0.0,
|
| 727 |
-
-1.0
|
| 728 |
-
],
|
| 729 |
-
"global_max": [
|
| 730 |
-
0.022142857313156128,
|
| 731 |
-
0.021714285016059875,
|
| 732 |
-
0.03257143124938011,
|
| 733 |
-
0.0,
|
| 734 |
-
-0.0,
|
| 735 |
-
-0.0,
|
| 736 |
-
1.0
|
| 737 |
-
],
|
| 738 |
-
"stepwise_q01": [
|
| 739 |
-
[
|
| 740 |
-
-0.017999999225139618,
|
| 741 |
-
-0.028668571263551712,
|
| 742 |
-
-0.020428571850061417,
|
| 743 |
-
0.0,
|
| 744 |
-
-0.0,
|
| 745 |
-
-0.0,
|
| 746 |
-
-1.0
|
| 747 |
-
],
|
| 748 |
-
[
|
| 749 |
-
-0.017999999225139618,
|
| 750 |
-
-0.028668571263551712,
|
| 751 |
-
-0.020428571850061417,
|
| 752 |
-
0.0,
|
| 753 |
-
-0.0,
|
| 754 |
-
-0.0,
|
| 755 |
-
-1.0
|
| 756 |
-
],
|
| 757 |
-
[
|
| 758 |
-
-0.017999999225139618,
|
| 759 |
-
-0.028668571263551712,
|
| 760 |
-
-0.020428571850061417,
|
| 761 |
-
0.0,
|
| 762 |
-
-0.0,
|
| 763 |
-
-0.0,
|
| 764 |
-
-1.0
|
| 765 |
-
],
|
| 766 |
-
[
|
| 767 |
-
-0.017999999225139618,
|
| 768 |
-
-0.028668571263551712,
|
| 769 |
-
-0.020428571850061417,
|
| 770 |
-
0.0,
|
| 771 |
-
-0.0,
|
| 772 |
-
-0.0,
|
| 773 |
-
-1.0
|
| 774 |
-
],
|
| 775 |
-
[
|
| 776 |
-
-0.017999999225139618,
|
| 777 |
-
-0.028668571263551712,
|
| 778 |
-
-0.020428571850061417,
|
| 779 |
-
0.0,
|
| 780 |
-
-0.0,
|
| 781 |
-
-0.0,
|
| 782 |
-
-1.0
|
| 783 |
-
],
|
| 784 |
-
[
|
| 785 |
-
-0.017999999225139618,
|
| 786 |
-
-0.028668571263551712,
|
| 787 |
-
-0.020428571850061417,
|
| 788 |
-
0.0,
|
| 789 |
-
0.0,
|
| 790 |
-
-0.0,
|
| 791 |
-
-1.0
|
| 792 |
-
],
|
| 793 |
-
[
|
| 794 |
-
-0.017999999225139618,
|
| 795 |
-
-0.028668571263551712,
|
| 796 |
-
-0.020428571850061417,
|
| 797 |
-
0.0,
|
| 798 |
-
0.0,
|
| 799 |
-
-0.0,
|
| 800 |
-
-1.0
|
| 801 |
-
],
|
| 802 |
-
[
|
| 803 |
-
-0.017999999225139618,
|
| 804 |
-
-0.028668571263551712,
|
| 805 |
-
-0.020428571850061417,
|
| 806 |
-
0.0,
|
| 807 |
-
-0.0,
|
| 808 |
-
-0.0,
|
| 809 |
-
-1.0
|
| 810 |
-
],
|
| 811 |
-
[
|
| 812 |
-
-0.017999999225139618,
|
| 813 |
-
-0.028668571263551712,
|
| 814 |
-
-0.020428571850061417,
|
| 815 |
-
0.0,
|
| 816 |
-
-0.0,
|
| 817 |
-
-0.0,
|
| 818 |
-
-1.0
|
| 819 |
-
],
|
| 820 |
-
[
|
| 821 |
-
-0.017999999225139618,
|
| 822 |
-
-0.028668571263551712,
|
| 823 |
-
-0.020428571850061417,
|
| 824 |
-
0.0,
|
| 825 |
-
-0.0,
|
| 826 |
-
-0.0,
|
| 827 |
-
-1.0
|
| 828 |
-
],
|
| 829 |
-
[
|
| 830 |
-
-0.017999999225139618,
|
| 831 |
-
-0.028668571263551712,
|
| 832 |
-
-0.020428571850061417,
|
| 833 |
-
0.0,
|
| 834 |
-
-0.0,
|
| 835 |
-
0.0,
|
| 836 |
-
-1.0
|
| 837 |
-
],
|
| 838 |
-
[
|
| 839 |
-
-0.017999999225139618,
|
| 840 |
-
-0.028668571263551712,
|
| 841 |
-
-0.020428571850061417,
|
| 842 |
-
0.0,
|
| 843 |
-
-0.0,
|
| 844 |
-
0.0,
|
| 845 |
-
-1.0
|
| 846 |
-
],
|
| 847 |
-
[
|
| 848 |
-
-0.017999999225139618,
|
| 849 |
-
-0.028668571263551712,
|
| 850 |
-
-0.020428571850061417,
|
| 851 |
-
0.0,
|
| 852 |
-
-0.0,
|
| 853 |
-
-0.0,
|
| 854 |
-
-1.0
|
| 855 |
-
],
|
| 856 |
-
[
|
| 857 |
-
-0.017999999225139618,
|
| 858 |
-
-0.028668571263551712,
|
| 859 |
-
-0.020428571850061417,
|
| 860 |
-
0.0,
|
| 861 |
-
-0.0,
|
| 862 |
-
-0.0,
|
| 863 |
-
-1.0
|
| 864 |
-
],
|
| 865 |
-
[
|
| 866 |
-
-0.017999999225139618,
|
| 867 |
-
-0.028668571263551712,
|
| 868 |
-
-0.020428571850061417,
|
| 869 |
-
0.0,
|
| 870 |
-
-0.0,
|
| 871 |
-
-0.0,
|
| 872 |
-
-1.0
|
| 873 |
-
],
|
| 874 |
-
[
|
| 875 |
-
-0.017999999225139618,
|
| 876 |
-
-0.028668571263551712,
|
| 877 |
-
-0.020428571850061417,
|
| 878 |
-
0.0,
|
| 879 |
-
-0.0,
|
| 880 |
-
-0.0,
|
| 881 |
-
-1.0
|
| 882 |
-
],
|
| 883 |
-
[
|
| 884 |
-
-0.017999999225139618,
|
| 885 |
-
-0.028668571263551712,
|
| 886 |
-
-0.020428571850061417,
|
| 887 |
-
0.0,
|
| 888 |
-
-0.0,
|
| 889 |
-
-0.0,
|
| 890 |
-
-1.0
|
| 891 |
-
],
|
| 892 |
-
[
|
| 893 |
-
-0.017999999225139618,
|
| 894 |
-
-0.028668571263551712,
|
| 895 |
-
-0.020428571850061417,
|
| 896 |
-
0.0,
|
| 897 |
-
-0.0,
|
| 898 |
-
-0.0,
|
| 899 |
-
-1.0
|
| 900 |
-
],
|
| 901 |
-
[
|
| 902 |
-
-0.017999999225139618,
|
| 903 |
-
-0.028668571263551712,
|
| 904 |
-
-0.020428571850061417,
|
| 905 |
-
0.0,
|
| 906 |
-
-0.0,
|
| 907 |
-
-0.0,
|
| 908 |
-
-1.0
|
| 909 |
-
],
|
| 910 |
-
[
|
| 911 |
-
-0.017999999225139618,
|
| 912 |
-
-0.028668571263551712,
|
| 913 |
-
-0.020428571850061417,
|
| 914 |
-
0.0,
|
| 915 |
-
-0.0,
|
| 916 |
-
-0.0,
|
| 917 |
-
-1.0
|
| 918 |
-
],
|
| 919 |
-
[
|
| 920 |
-
-0.017999999225139618,
|
| 921 |
-
-0.028668571263551712,
|
| 922 |
-
-0.020428571850061417,
|
| 923 |
-
0.0,
|
| 924 |
-
-0.0,
|
| 925 |
-
-0.0,
|
| 926 |
-
-1.0
|
| 927 |
-
],
|
| 928 |
-
[
|
| 929 |
-
-0.017999999225139618,
|
| 930 |
-
-0.028668571263551712,
|
| 931 |
-
-0.020428571850061417,
|
| 932 |
-
0.0,
|
| 933 |
-
-0.0,
|
| 934 |
-
-0.0,
|
| 935 |
-
-1.0
|
| 936 |
-
],
|
| 937 |
-
[
|
| 938 |
-
-0.017999999225139618,
|
| 939 |
-
-0.028668571263551712,
|
| 940 |
-
-0.020428571850061417,
|
| 941 |
-
0.0,
|
| 942 |
-
-0.0,
|
| 943 |
-
-0.0,
|
| 944 |
-
-1.0
|
| 945 |
-
],
|
| 946 |
-
[
|
| 947 |
-
-0.017999999225139618,
|
| 948 |
-
-0.028668571263551712,
|
| 949 |
-
-0.020428571850061417,
|
| 950 |
-
0.0,
|
| 951 |
-
-0.0,
|
| 952 |
-
-0.0,
|
| 953 |
-
-1.0
|
| 954 |
-
],
|
| 955 |
-
[
|
| 956 |
-
-0.017999999225139618,
|
| 957 |
-
-0.028668571263551712,
|
| 958 |
-
-0.020428571850061417,
|
| 959 |
-
0.0,
|
| 960 |
-
-0.0,
|
| 961 |
-
-0.0,
|
| 962 |
-
-1.0
|
| 963 |
-
],
|
| 964 |
-
[
|
| 965 |
-
-0.017999999225139618,
|
| 966 |
-
-0.028668571263551712,
|
| 967 |
-
-0.020428571850061417,
|
| 968 |
-
0.0,
|
| 969 |
-
-0.0,
|
| 970 |
-
-0.0,
|
| 971 |
-
-1.0
|
| 972 |
-
],
|
| 973 |
-
[
|
| 974 |
-
-0.017999999225139618,
|
| 975 |
-
-0.028668571263551712,
|
| 976 |
-
-0.020428571850061417,
|
| 977 |
-
0.0,
|
| 978 |
-
-0.0,
|
| 979 |
-
-0.0,
|
| 980 |
-
-1.0
|
| 981 |
-
],
|
| 982 |
-
[
|
| 983 |
-
-0.017999999225139618,
|
| 984 |
-
-0.028668571263551712,
|
| 985 |
-
-0.020428571850061417,
|
| 986 |
-
0.0,
|
| 987 |
-
-0.0,
|
| 988 |
-
-0.0,
|
| 989 |
-
-1.0
|
| 990 |
-
],
|
| 991 |
-
[
|
| 992 |
-
-0.017999999225139618,
|
| 993 |
-
-0.028668571263551712,
|
| 994 |
-
-0.020428571850061417,
|
| 995 |
-
0.0,
|
| 996 |
-
-0.0,
|
| 997 |
-
-0.0,
|
| 998 |
-
-1.0
|
| 999 |
-
],
|
| 1000 |
-
[
|
| 1001 |
-
-0.017999999225139618,
|
| 1002 |
-
-0.028668571263551712,
|
| 1003 |
-
-0.020428571850061417,
|
| 1004 |
-
0.0,
|
| 1005 |
-
-0.0,
|
| 1006 |
-
-0.0,
|
| 1007 |
-
-1.0
|
| 1008 |
-
],
|
| 1009 |
-
[
|
| 1010 |
-
-0.017999999225139618,
|
| 1011 |
-
-0.028668571263551712,
|
| 1012 |
-
-0.020428571850061417,
|
| 1013 |
-
0.0,
|
| 1014 |
-
-0.0,
|
| 1015 |
-
-0.0,
|
| 1016 |
-
-1.0
|
| 1017 |
-
],
|
| 1018 |
-
[
|
| 1019 |
-
-0.017999999225139618,
|
| 1020 |
-
-0.028668571263551712,
|
| 1021 |
-
-0.020428571850061417,
|
| 1022 |
-
0.0,
|
| 1023 |
-
-0.0,
|
| 1024 |
-
-0.0,
|
| 1025 |
-
-1.0
|
| 1026 |
-
]
|
| 1027 |
-
],
|
| 1028 |
-
"stepwise_q99": [
|
| 1029 |
-
[
|
| 1030 |
-
0.01874857023358345,
|
| 1031 |
-
0.017999999225139618,
|
| 1032 |
-
0.032182857394218445,
|
| 1033 |
-
0.0,
|
| 1034 |
-
0.0,
|
| 1035 |
-
0.0,
|
| 1036 |
-
1.0
|
| 1037 |
-
],
|
| 1038 |
-
[
|
| 1039 |
-
0.01874857023358345,
|
| 1040 |
-
0.017999999225139618,
|
| 1041 |
-
0.032182857394218445,
|
| 1042 |
-
0.0,
|
| 1043 |
-
0.0,
|
| 1044 |
-
0.0,
|
| 1045 |
-
1.0
|
| 1046 |
-
],
|
| 1047 |
-
[
|
| 1048 |
-
0.01874857023358345,
|
| 1049 |
-
0.017999999225139618,
|
| 1050 |
-
0.032182857394218445,
|
| 1051 |
-
0.0,
|
| 1052 |
-
0.0,
|
| 1053 |
-
0.0,
|
| 1054 |
-
1.0
|
| 1055 |
-
],
|
| 1056 |
-
[
|
| 1057 |
-
0.01874857023358345,
|
| 1058 |
-
0.017999999225139618,
|
| 1059 |
-
0.032182857394218445,
|
| 1060 |
-
0.0,
|
| 1061 |
-
0.0,
|
| 1062 |
-
0.0,
|
| 1063 |
-
1.0
|
| 1064 |
-
],
|
| 1065 |
-
[
|
| 1066 |
-
0.01874857023358345,
|
| 1067 |
-
0.017999999225139618,
|
| 1068 |
-
0.032182857394218445,
|
| 1069 |
-
0.0,
|
| 1070 |
-
0.0,
|
| 1071 |
-
0.0,
|
| 1072 |
-
1.0
|
| 1073 |
-
],
|
| 1074 |
-
[
|
| 1075 |
-
0.01874857023358345,
|
| 1076 |
-
0.017999999225139618,
|
| 1077 |
-
0.032182857394218445,
|
| 1078 |
-
0.0,
|
| 1079 |
-
0.0,
|
| 1080 |
-
0.0,
|
| 1081 |
-
1.0
|
| 1082 |
-
],
|
| 1083 |
-
[
|
| 1084 |
-
0.01874857023358345,
|
| 1085 |
-
0.017999999225139618,
|
| 1086 |
-
0.032182857394218445,
|
| 1087 |
-
0.0,
|
| 1088 |
-
0.0,
|
| 1089 |
-
0.0,
|
| 1090 |
-
1.0
|
| 1091 |
-
],
|
| 1092 |
-
[
|
| 1093 |
-
0.01874857023358345,
|
| 1094 |
-
0.017999999225139618,
|
| 1095 |
-
0.032182857394218445,
|
| 1096 |
-
0.0,
|
| 1097 |
-
0.0,
|
| 1098 |
-
0.0,
|
| 1099 |
-
1.0
|
| 1100 |
-
],
|
| 1101 |
-
[
|
| 1102 |
-
0.01874857023358345,
|
| 1103 |
-
0.017999999225139618,
|
| 1104 |
-
0.032182857394218445,
|
| 1105 |
-
0.0,
|
| 1106 |
-
0.0,
|
| 1107 |
-
0.0,
|
| 1108 |
-
1.0
|
| 1109 |
-
],
|
| 1110 |
-
[
|
| 1111 |
-
0.01874857023358345,
|
| 1112 |
-
0.017999999225139618,
|
| 1113 |
-
0.032182857394218445,
|
| 1114 |
-
0.0,
|
| 1115 |
-
0.0,
|
| 1116 |
-
0.0,
|
| 1117 |
-
1.0
|
| 1118 |
-
],
|
| 1119 |
-
[
|
| 1120 |
-
0.01874857023358345,
|
| 1121 |
-
0.017999999225139618,
|
| 1122 |
-
0.032182857394218445,
|
| 1123 |
-
0.0,
|
| 1124 |
-
0.0,
|
| 1125 |
-
0.0,
|
| 1126 |
-
1.0
|
| 1127 |
-
],
|
| 1128 |
-
[
|
| 1129 |
-
0.01874857023358345,
|
| 1130 |
-
0.017999999225139618,
|
| 1131 |
-
0.032182857394218445,
|
| 1132 |
-
0.0,
|
| 1133 |
-
0.0,
|
| 1134 |
-
0.0,
|
| 1135 |
-
1.0
|
| 1136 |
-
],
|
| 1137 |
-
[
|
| 1138 |
-
0.01811428926885128,
|
| 1139 |
-
0.017999999225139618,
|
| 1140 |
-
0.032182857394218445,
|
| 1141 |
-
0.0,
|
| 1142 |
-
0.0,
|
| 1143 |
-
0.0,
|
| 1144 |
-
1.0
|
| 1145 |
-
],
|
| 1146 |
-
[
|
| 1147 |
-
0.01811428926885128,
|
| 1148 |
-
0.017999999225139618,
|
| 1149 |
-
0.032182857394218445,
|
| 1150 |
-
0.0,
|
| 1151 |
-
0.0,
|
| 1152 |
-
0.0,
|
| 1153 |
-
1.0
|
| 1154 |
-
],
|
| 1155 |
-
[
|
| 1156 |
-
0.01811428926885128,
|
| 1157 |
-
0.017999999225139618,
|
| 1158 |
-
0.032182857394218445,
|
| 1159 |
-
0.0,
|
| 1160 |
-
0.0,
|
| 1161 |
-
0.0,
|
| 1162 |
-
1.0
|
| 1163 |
-
],
|
| 1164 |
-
[
|
| 1165 |
-
0.01811428926885128,
|
| 1166 |
-
0.017999999225139618,
|
| 1167 |
-
0.032182857394218445,
|
| 1168 |
-
0.0,
|
| 1169 |
-
0.0,
|
| 1170 |
-
0.0,
|
| 1171 |
-
1.0
|
| 1172 |
-
],
|
| 1173 |
-
[
|
| 1174 |
-
0.01811428926885128,
|
| 1175 |
-
0.017999999225139618,
|
| 1176 |
-
0.032182857394218445,
|
| 1177 |
-
0.0,
|
| 1178 |
-
0.0,
|
| 1179 |
-
0.0,
|
| 1180 |
-
1.0
|
| 1181 |
-
],
|
| 1182 |
-
[
|
| 1183 |
-
0.01811428926885128,
|
| 1184 |
-
0.017999999225139618,
|
| 1185 |
-
0.032182857394218445,
|
| 1186 |
-
0.0,
|
| 1187 |
-
0.0,
|
| 1188 |
-
0.0,
|
| 1189 |
-
1.0
|
| 1190 |
-
],
|
| 1191 |
-
[
|
| 1192 |
-
0.01811428926885128,
|
| 1193 |
-
0.017999999225139618,
|
| 1194 |
-
0.032182857394218445,
|
| 1195 |
-
0.0,
|
| 1196 |
-
0.0,
|
| 1197 |
-
0.0,
|
| 1198 |
-
1.0
|
| 1199 |
-
],
|
| 1200 |
-
[
|
| 1201 |
-
0.01811428926885128,
|
| 1202 |
-
0.017999999225139618,
|
| 1203 |
-
0.032182857394218445,
|
| 1204 |
-
0.0,
|
| 1205 |
-
0.0,
|
| 1206 |
-
0.0,
|
| 1207 |
-
1.0
|
| 1208 |
-
],
|
| 1209 |
-
[
|
| 1210 |
-
0.01811428926885128,
|
| 1211 |
-
0.017999999225139618,
|
| 1212 |
-
0.032182857394218445,
|
| 1213 |
-
0.0,
|
| 1214 |
-
0.0,
|
| 1215 |
-
0.0,
|
| 1216 |
-
1.0
|
| 1217 |
-
],
|
| 1218 |
-
[
|
| 1219 |
-
0.01811428926885128,
|
| 1220 |
-
0.017999999225139618,
|
| 1221 |
-
0.032182857394218445,
|
| 1222 |
-
0.0,
|
| 1223 |
-
0.0,
|
| 1224 |
-
0.0,
|
| 1225 |
-
1.0
|
| 1226 |
-
],
|
| 1227 |
-
[
|
| 1228 |
-
0.01811428926885128,
|
| 1229 |
-
0.017999999225139618,
|
| 1230 |
-
0.032182857394218445,
|
| 1231 |
-
0.0,
|
| 1232 |
-
0.0,
|
| 1233 |
-
0.0,
|
| 1234 |
-
1.0
|
| 1235 |
-
],
|
| 1236 |
-
[
|
| 1237 |
-
0.01811428926885128,
|
| 1238 |
-
0.017999999225139618,
|
| 1239 |
-
0.032182857394218445,
|
| 1240 |
-
0.0,
|
| 1241 |
-
0.0,
|
| 1242 |
-
0.0,
|
| 1243 |
-
1.0
|
| 1244 |
-
],
|
| 1245 |
-
[
|
| 1246 |
-
0.01811428926885128,
|
| 1247 |
-
0.017999999225139618,
|
| 1248 |
-
0.032182857394218445,
|
| 1249 |
-
0.0,
|
| 1250 |
-
0.0,
|
| 1251 |
-
0.0,
|
| 1252 |
-
1.0
|
| 1253 |
-
],
|
| 1254 |
-
[
|
| 1255 |
-
0.01811428926885128,
|
| 1256 |
-
0.017999999225139618,
|
| 1257 |
-
0.032182857394218445,
|
| 1258 |
-
0.0,
|
| 1259 |
-
0.0,
|
| 1260 |
-
0.0,
|
| 1261 |
-
1.0
|
| 1262 |
-
],
|
| 1263 |
-
[
|
| 1264 |
-
0.01811428926885128,
|
| 1265 |
-
0.017999999225139618,
|
| 1266 |
-
0.032182857394218445,
|
| 1267 |
-
0.0,
|
| 1268 |
-
0.0,
|
| 1269 |
-
0.0,
|
| 1270 |
-
1.0
|
| 1271 |
-
],
|
| 1272 |
-
[
|
| 1273 |
-
0.01811428926885128,
|
| 1274 |
-
0.017999999225139618,
|
| 1275 |
-
0.032182857394218445,
|
| 1276 |
-
0.0,
|
| 1277 |
-
0.0,
|
| 1278 |
-
0.0,
|
| 1279 |
-
1.0
|
| 1280 |
-
],
|
| 1281 |
-
[
|
| 1282 |
-
0.01811428926885128,
|
| 1283 |
-
0.017999999225139618,
|
| 1284 |
-
0.032182857394218445,
|
| 1285 |
-
0.0,
|
| 1286 |
-
0.0,
|
| 1287 |
-
0.0,
|
| 1288 |
-
1.0
|
| 1289 |
-
],
|
| 1290 |
-
[
|
| 1291 |
-
0.01811428926885128,
|
| 1292 |
-
0.017999999225139618,
|
| 1293 |
-
0.032182857394218445,
|
| 1294 |
-
0.0,
|
| 1295 |
-
0.0,
|
| 1296 |
-
0.0,
|
| 1297 |
-
1.0
|
| 1298 |
-
],
|
| 1299 |
-
[
|
| 1300 |
-
0.01811428926885128,
|
| 1301 |
-
0.017999999225139618,
|
| 1302 |
-
0.032182857394218445,
|
| 1303 |
-
0.0,
|
| 1304 |
-
0.0,
|
| 1305 |
-
0.0,
|
| 1306 |
-
1.0
|
| 1307 |
-
],
|
| 1308 |
-
[
|
| 1309 |
-
0.01811428926885128,
|
| 1310 |
-
0.017999999225139618,
|
| 1311 |
-
0.032182857394218445,
|
| 1312 |
-
0.0,
|
| 1313 |
-
0.0,
|
| 1314 |
-
0.0,
|
| 1315 |
-
1.0
|
| 1316 |
-
]
|
| 1317 |
-
],
|
| 1318 |
-
"global_q01": [
|
| 1319 |
-
-0.017999999225139618,
|
| 1320 |
-
-0.028668571263551712,
|
| 1321 |
-
-0.020428571850061417,
|
| 1322 |
-
0.0,
|
| 1323 |
-
-0.0,
|
| 1324 |
-
-0.0,
|
| 1325 |
-
-1.0
|
| 1326 |
-
],
|
| 1327 |
-
"global_q99": [
|
| 1328 |
-
0.01874857023358345,
|
| 1329 |
-
0.017999999225139618,
|
| 1330 |
-
0.032182857394218445,
|
| 1331 |
-
0.0,
|
| 1332 |
-
0.0,
|
| 1333 |
-
0.0,
|
| 1334 |
-
1.0
|
| 1335 |
-
],
|
| 1336 |
-
"stepwise_mean": [
|
| 1337 |
-
[
|
| 1338 |
-
0.00010599139204714447,
|
| 1339 |
-
-0.0003520426689647138,
|
| 1340 |
-
0.00014291385014075786,
|
| 1341 |
-
0.0,
|
| 1342 |
-
0.0,
|
| 1343 |
-
0.0,
|
| 1344 |
-
0.2183247208595276
|
| 1345 |
-
],
|
| 1346 |
-
[
|
| 1347 |
-
0.00010662782733561471,
|
| 1348 |
-
-0.00035185267915949225,
|
| 1349 |
-
0.00014307233504951,
|
| 1350 |
-
0.0,
|
| 1351 |
-
0.0,
|
| 1352 |
-
0.0,
|
| 1353 |
-
0.22085411846637726
|
| 1354 |
-
],
|
| 1355 |
-
[
|
| 1356 |
-
0.00010768464562715963,
|
| 1357 |
-
-0.0003513394040055573,
|
| 1358 |
-
0.0001433969009667635,
|
| 1359 |
-
0.0,
|
| 1360 |
-
0.0,
|
| 1361 |
-
0.0,
|
| 1362 |
-
0.22338351607322693
|
| 1363 |
-
],
|
| 1364 |
-
[
|
| 1365 |
-
0.0001071520455298014,
|
| 1366 |
-
-0.0003502023755572736,
|
| 1367 |
-
0.0001435836311429739,
|
| 1368 |
-
0.0,
|
| 1369 |
-
0.0,
|
| 1370 |
-
0.0,
|
| 1371 |
-
0.22591295838356018
|
| 1372 |
-
],
|
| 1373 |
-
[
|
| 1374 |
-
0.00010332007514080033,
|
| 1375 |
-
-0.00034813376259990036,
|
| 1376 |
-
0.00014470236783381552,
|
| 1377 |
-
0.0,
|
| 1378 |
-
0.0,
|
| 1379 |
-
0.0,
|
| 1380 |
-
0.22844235599040985
|
| 1381 |
-
],
|
| 1382 |
-
[
|
| 1383 |
-
9.708326979307458e-05,
|
| 1384 |
-
-0.0003456552803982049,
|
| 1385 |
-
0.0001498961355537176,
|
| 1386 |
-
0.0,
|
| 1387 |
-
0.0,
|
| 1388 |
-
0.0,
|
| 1389 |
-
0.23097175359725952
|
| 1390 |
-
],
|
| 1391 |
-
[
|
| 1392 |
-
8.982994040707126e-05,
|
| 1393 |
-
-0.00034212053287774324,
|
| 1394 |
-
0.00015701490337960422,
|
| 1395 |
-
0.0,
|
| 1396 |
-
0.0,
|
| 1397 |
-
0.0,
|
| 1398 |
-
0.23350116610527039
|
| 1399 |
-
],
|
| 1400 |
-
[
|
| 1401 |
-
8.295998850371689e-05,
|
| 1402 |
-
-0.00033426276058889925,
|
| 1403 |
-
0.00016626888827886432,
|
| 1404 |
-
0.0,
|
| 1405 |
-
0.0,
|
| 1406 |
-
0.0,
|
| 1407 |
-
0.23603059351444244
|
| 1408 |
-
],
|
| 1409 |
-
[
|
| 1410 |
-
7.580933743156493e-05,
|
| 1411 |
-
-0.00032417502370662987,
|
| 1412 |
-
0.00018232851289212704,
|
| 1413 |
-
0.0,
|
| 1414 |
-
0.0,
|
| 1415 |
-
0.0,
|
| 1416 |
-
0.23855999112129211
|
| 1417 |
-
],
|
| 1418 |
-
[
|
| 1419 |
-
6.725409912178293e-05,
|
| 1420 |
-
-0.00031425998895429075,
|
| 1421 |
-
0.00019788365170825273,
|
| 1422 |
-
0.0,
|
| 1423 |
-
0.0,
|
| 1424 |
-
0.0,
|
| 1425 |
-
0.24108940362930298
|
| 1426 |
-
],
|
| 1427 |
-
[
|
| 1428 |
-
5.8587662351783365e-05,
|
| 1429 |
-
-0.0003024389152415097,
|
| 1430 |
-
0.0002139062125934288,
|
| 1431 |
-
0.0,
|
| 1432 |
-
0.0,
|
| 1433 |
-
0.0,
|
| 1434 |
-
0.24361883103847504
|
| 1435 |
-
],
|
| 1436 |
-
[
|
| 1437 |
-
4.8913931095739827e-05,
|
| 1438 |
-
-0.00029040378285571933,
|
| 1439 |
-
0.00023386623070109636,
|
| 1440 |
-
0.0,
|
| 1441 |
-
0.0,
|
| 1442 |
-
0.0,
|
| 1443 |
-
0.2461482435464859
|
| 1444 |
-
],
|
| 1445 |
-
[
|
| 1446 |
-
3.9833157643442973e-05,
|
| 1447 |
-
-0.0002796816115733236,
|
| 1448 |
-
0.0002501923299860209,
|
| 1449 |
-
0.0,
|
| 1450 |
-
0.0,
|
| 1451 |
-
0.0,
|
| 1452 |
-
0.24867764115333557
|
| 1453 |
-
],
|
| 1454 |
-
[
|
| 1455 |
-
3.252932947361842e-05,
|
| 1456 |
-
-0.0002679046301636845,
|
| 1457 |
-
0.00026465911651030183,
|
| 1458 |
-
0.0,
|
| 1459 |
-
0.0,
|
| 1460 |
-
0.0,
|
| 1461 |
-
0.25120702385902405
|
| 1462 |
-
],
|
| 1463 |
-
[
|
| 1464 |
-
2.6598059776006266e-05,
|
| 1465 |
-
-0.0002585168113000691,
|
| 1466 |
-
0.00028005309286527336,
|
| 1467 |
-
0.0,
|
| 1468 |
-
0.0,
|
| 1469 |
-
0.0,
|
| 1470 |
-
0.2537364661693573
|
| 1471 |
-
],
|
| 1472 |
-
[
|
| 1473 |
-
1.9946868633269332e-05,
|
| 1474 |
-
-0.00025132004520855844,
|
| 1475 |
-
0.00029630353674292564,
|
| 1476 |
-
0.0,
|
| 1477 |
-
0.0,
|
| 1478 |
-
0.0,
|
| 1479 |
-
0.25626587867736816
|
| 1480 |
-
],
|
| 1481 |
-
[
|
| 1482 |
-
1.303988574363757e-05,
|
| 1483 |
-
-0.00024510364164598286,
|
| 1484 |
-
0.0003103403723798692,
|
| 1485 |
-
0.0,
|
| 1486 |
-
0.0,
|
| 1487 |
-
0.0,
|
| 1488 |
-
0.25880569219589233
|
| 1489 |
-
],
|
| 1490 |
-
[
|
| 1491 |
-
5.248548404779285e-06,
|
| 1492 |
-
-0.00024028636107686907,
|
| 1493 |
-
0.00032640460995025933,
|
| 1494 |
-
0.0,
|
| 1495 |
-
0.0,
|
| 1496 |
-
0.0,
|
| 1497 |
-
0.2613455355167389
|
| 1498 |
-
],
|
| 1499 |
-
[
|
| 1500 |
-
-2.630091103128507e-06,
|
| 1501 |
-
-0.00023644340399187058,
|
| 1502 |
-
0.0003419383428990841,
|
| 1503 |
-
0.0,
|
| 1504 |
-
0.0,
|
| 1505 |
-
0.0,
|
| 1506 |
-
0.2638853192329407
|
| 1507 |
-
],
|
| 1508 |
-
[
|
| 1509 |
-
-1.1612431080720853e-05,
|
| 1510 |
-
-0.00023524471907876432,
|
| 1511 |
-
0.00035437088808976114,
|
| 1512 |
-
0.0,
|
| 1513 |
-
0.0,
|
| 1514 |
-
0.0,
|
| 1515 |
-
0.2664651870727539
|
| 1516 |
-
],
|
| 1517 |
-
[
|
| 1518 |
-
-2.4109574951580726e-05,
|
| 1519 |
-
-0.00023595777747686952,
|
| 1520 |
-
0.0003668583813123405,
|
| 1521 |
-
0.0,
|
| 1522 |
-
0.0,
|
| 1523 |
-
0.0,
|
| 1524 |
-
0.26908746361732483
|
| 1525 |
-
],
|
| 1526 |
-
[
|
| 1527 |
-
-3.409310011193156e-05,
|
| 1528 |
-
-0.00023765936202835292,
|
| 1529 |
-
0.0003780024708248675,
|
| 1530 |
-
0.0,
|
| 1531 |
-
0.0,
|
| 1532 |
-
0.0,
|
| 1533 |
-
0.2717488706111908
|
| 1534 |
-
],
|
| 1535 |
-
[
|
| 1536 |
-
-4.41225383838173e-05,
|
| 1537 |
-
-0.00024006325111258775,
|
| 1538 |
-
0.0003892174281645566,
|
| 1539 |
-
0.0,
|
| 1540 |
-
0.0,
|
| 1541 |
-
0.0,
|
| 1542 |
-
0.2744331955909729
|
| 1543 |
-
],
|
| 1544 |
-
[
|
| 1545 |
-
-5.318918192642741e-05,
|
| 1546 |
-
-0.00024481830769218504,
|
| 1547 |
-
0.0003998273750767112,
|
| 1548 |
-
0.0,
|
| 1549 |
-
0.0,
|
| 1550 |
-
0.0,
|
| 1551 |
-
0.27719661593437195
|
| 1552 |
-
],
|
| 1553 |
-
[
|
| 1554 |
-
-6.362147541949525e-05,
|
| 1555 |
-
-0.00025020778411999345,
|
| 1556 |
-
0.0004108487628400326,
|
| 1557 |
-
0.0,
|
| 1558 |
-
0.0,
|
| 1559 |
-
0.0,
|
| 1560 |
-
0.27999645471572876
|
| 1561 |
-
],
|
| 1562 |
-
[
|
| 1563 |
-
-7.399872993119061e-05,
|
| 1564 |
-
-0.0002569758507888764,
|
| 1565 |
-
0.00042012453195638955,
|
| 1566 |
-
0.0,
|
| 1567 |
-
0.0,
|
| 1568 |
-
0.0,
|
| 1569 |
-
0.28288376331329346
|
| 1570 |
-
],
|
| 1571 |
-
[
|
| 1572 |
-
-8.447915024589747e-05,
|
| 1573 |
-
-0.00026511374744586647,
|
| 1574 |
-
0.00042987134656868875,
|
| 1575 |
-
0.0,
|
| 1576 |
-
0.0,
|
| 1577 |
-
0.0,
|
| 1578 |
-
0.28581443428993225
|
| 1579 |
-
],
|
| 1580 |
-
[
|
| 1581 |
-
-9.251773008145392e-05,
|
| 1582 |
-
-0.00027324925758875906,
|
| 1583 |
-
0.00043566094245761633,
|
| 1584 |
-
0.0,
|
| 1585 |
-
0.0,
|
| 1586 |
-
0.0,
|
| 1587 |
-
0.28880083560943604
|
| 1588 |
-
],
|
| 1589 |
-
[
|
| 1590 |
-
-0.0001004255173029378,
|
| 1591 |
-
-0.00028087335522286594,
|
| 1592 |
-
0.00044270692160353065,
|
| 1593 |
-
0.0,
|
| 1594 |
-
0.0,
|
| 1595 |
-
0.0,
|
| 1596 |
-
0.2919144332408905
|
| 1597 |
-
],
|
| 1598 |
-
[
|
| 1599 |
-
-0.00010663300781743601,
|
| 1600 |
-
-0.0002883909037336707,
|
| 1601 |
-
0.0004484386881813407,
|
| 1602 |
-
0.0,
|
| 1603 |
-
0.0,
|
| 1604 |
-
0.0,
|
| 1605 |
-
0.29495498538017273
|
| 1606 |
-
],
|
| 1607 |
-
[
|
| 1608 |
-
-0.00011239774903515354,
|
| 1609 |
-
-0.0002963065926451236,
|
| 1610 |
-
0.000453940243460238,
|
| 1611 |
-
0.0,
|
| 1612 |
-
0.0,
|
| 1613 |
-
0.0,
|
| 1614 |
-
0.2980213463306427
|
| 1615 |
-
],
|
| 1616 |
-
[
|
| 1617 |
-
-0.00011664993508020416,
|
| 1618 |
-
-0.0003038592985831201,
|
| 1619 |
-
0.00045629238593392074,
|
| 1620 |
-
0.0,
|
| 1621 |
-
0.0,
|
| 1622 |
-
0.0,
|
| 1623 |
-
0.3011433184146881
|
| 1624 |
-
]
|
| 1625 |
-
],
|
| 1626 |
-
"stepwise_std": [
|
| 1627 |
-
[
|
| 1628 |
-
0.003859531134366989,
|
| 1629 |
-
0.005849294830113649,
|
| 1630 |
-
0.005096182227134705,
|
| 1631 |
-
0.0,
|
| 1632 |
-
0.0,
|
| 1633 |
-
0.0,
|
| 1634 |
-
0.6930140852928162
|
| 1635 |
-
],
|
| 1636 |
-
[
|
| 1637 |
-
0.003858074778690934,
|
| 1638 |
-
0.005849248263984919,
|
| 1639 |
-
0.005096119828522205,
|
| 1640 |
-
0.0,
|
| 1641 |
-
0.0,
|
| 1642 |
-
0.0,
|
| 1643 |
-
0.692183256149292
|
| 1644 |
-
],
|
| 1645 |
-
[
|
| 1646 |
-
0.00385070638731122,
|
| 1647 |
-
0.005849029868841171,
|
| 1648 |
-
0.005095901433378458,
|
| 1649 |
-
0.0,
|
| 1650 |
-
0.0,
|
| 1651 |
-
0.0,
|
| 1652 |
-
0.6913419961929321
|
| 1653 |
-
],
|
| 1654 |
-
[
|
| 1655 |
-
0.003835494164377451,
|
| 1656 |
-
0.005848364904522896,
|
| 1657 |
-
0.0050956266932189465,
|
| 1658 |
-
0.0,
|
| 1659 |
-
0.0,
|
| 1660 |
-
0.0,
|
| 1661 |
-
0.6904901266098022
|
| 1662 |
-
],
|
| 1663 |
-
[
|
| 1664 |
-
0.0038173042703419924,
|
| 1665 |
-
0.0058466228656470776,
|
| 1666 |
-
0.005094226449728012,
|
| 1667 |
-
0.0,
|
| 1668 |
-
0.0,
|
| 1669 |
-
0.0,
|
| 1670 |
-
0.6896276473999023
|
| 1671 |
-
],
|
| 1672 |
-
[
|
| 1673 |
-
0.003798459656536579,
|
| 1674 |
-
0.005840709898620844,
|
| 1675 |
-
0.005085964687168598,
|
| 1676 |
-
0.0,
|
| 1677 |
-
0.0,
|
| 1678 |
-
0.0,
|
| 1679 |
-
0.6887545585632324
|
| 1680 |
-
],
|
| 1681 |
-
[
|
| 1682 |
-
0.003779440186917782,
|
| 1683 |
-
0.0058306735008955,
|
| 1684 |
-
0.0050780801102519035,
|
| 1685 |
-
0.0,
|
| 1686 |
-
0.0,
|
| 1687 |
-
0.0,
|
| 1688 |
-
0.6878708600997925
|
| 1689 |
-
],
|
| 1690 |
-
[
|
| 1691 |
-
0.0037602565716952085,
|
| 1692 |
-
0.005817433353513479,
|
| 1693 |
-
0.005068507045507431,
|
| 1694 |
-
0.0,
|
| 1695 |
-
0.0,
|
| 1696 |
-
0.0,
|
| 1697 |
-
0.686976432800293
|
| 1698 |
-
],
|
| 1699 |
-
[
|
| 1700 |
-
0.0037413816899061203,
|
| 1701 |
-
0.005803139880299568,
|
| 1702 |
-
0.00504791084676981,
|
| 1703 |
-
0.0,
|
| 1704 |
-
0.0,
|
| 1705 |
-
0.0,
|
| 1706 |
-
0.6860713362693787
|
| 1707 |
-
],
|
| 1708 |
-
[
|
| 1709 |
-
0.003722784109413624,
|
| 1710 |
-
0.005785479210317135,
|
| 1711 |
-
0.005028924439102411,
|
| 1712 |
-
0.0,
|
| 1713 |
-
0.0,
|
| 1714 |
-
0.0,
|
| 1715 |
-
0.6851553320884705
|
| 1716 |
-
],
|
| 1717 |
-
[
|
| 1718 |
-
0.003704249393194914,
|
| 1719 |
-
0.005768594332039356,
|
| 1720 |
-
0.005011409055441618,
|
| 1721 |
-
0.0,
|
| 1722 |
-
0.0,
|
| 1723 |
-
0.0,
|
| 1724 |
-
0.6842285990715027
|
| 1725 |
-
],
|
| 1726 |
-
[
|
| 1727 |
-
0.003684787079691887,
|
| 1728 |
-
0.005749644245952368,
|
| 1729 |
-
0.004986910615116358,
|
| 1730 |
-
0.0,
|
| 1731 |
-
0.0,
|
| 1732 |
-
0.0,
|
| 1733 |
-
0.683290958404541
|
| 1734 |
-
],
|
| 1735 |
-
[
|
| 1736 |
-
0.003669159021228552,
|
| 1737 |
-
0.005727663636207581,
|
| 1738 |
-
0.004969390109181404,
|
| 1739 |
-
0.0,
|
| 1740 |
-
0.0,
|
| 1741 |
-
0.0,
|
| 1742 |
-
0.6823424696922302
|
| 1743 |
-
],
|
| 1744 |
-
[
|
| 1745 |
-
0.0036586951464414597,
|
| 1746 |
-
0.005707941949367523,
|
| 1747 |
-
0.00495464401319623,
|
| 1748 |
-
0.0,
|
| 1749 |
-
0.0,
|
| 1750 |
-
0.0,
|
| 1751 |
-
0.681382954120636
|
| 1752 |
-
],
|
| 1753 |
-
[
|
| 1754 |
-
0.0036503244191408157,
|
| 1755 |
-
0.005686633288860321,
|
| 1756 |
-
0.0049393498338758945,
|
| 1757 |
-
0.0,
|
| 1758 |
-
0.0,
|
| 1759 |
-
0.0,
|
| 1760 |
-
0.6804124116897583
|
| 1761 |
-
],
|
| 1762 |
-
[
|
| 1763 |
-
0.0036399371456354856,
|
| 1764 |
-
0.005666919052600861,
|
| 1765 |
-
0.004921806510537863,
|
| 1766 |
-
0.0,
|
| 1767 |
-
0.0,
|
| 1768 |
-
0.0,
|
| 1769 |
-
0.6794309020042419
|
| 1770 |
-
],
|
| 1771 |
-
[
|
| 1772 |
-
0.0036300860811024904,
|
| 1773 |
-
0.005649130791425705,
|
| 1774 |
-
0.004907391965389252,
|
| 1775 |
-
0.0,
|
| 1776 |
-
0.0,
|
| 1777 |
-
0.0,
|
| 1778 |
-
0.6784419417381287
|
| 1779 |
-
],
|
| 1780 |
-
[
|
| 1781 |
-
0.003619162132963538,
|
| 1782 |
-
0.005632068496197462,
|
| 1783 |
-
0.004889165051281452,
|
| 1784 |
-
0.0,
|
| 1785 |
-
0.0,
|
| 1786 |
-
0.0,
|
| 1787 |
-
0.6774417757987976
|
| 1788 |
-
],
|
| 1789 |
-
[
|
| 1790 |
-
0.0036096996627748013,
|
| 1791 |
-
0.005616484675556421,
|
| 1792 |
-
0.00487248320132494,
|
| 1793 |
-
0.0,
|
| 1794 |
-
0.0,
|
| 1795 |
-
0.0,
|
| 1796 |
-
0.6764302849769592
|
| 1797 |
-
],
|
| 1798 |
-
[
|
| 1799 |
-
0.0035996257793158293,
|
| 1800 |
-
0.005601839628070593,
|
| 1801 |
-
0.004860007204115391,
|
| 1802 |
-
0.0,
|
| 1803 |
-
0.0,
|
| 1804 |
-
0.0,
|
| 1805 |
-
0.675421416759491
|
| 1806 |
-
],
|
| 1807 |
-
[
|
| 1808 |
-
0.003584834048524499,
|
| 1809 |
-
0.0055876681581139565,
|
| 1810 |
-
0.004846835974603891,
|
| 1811 |
-
0.0,
|
| 1812 |
-
0.0,
|
| 1813 |
-
0.0,
|
| 1814 |
-
0.6744153499603271
|
| 1815 |
-
],
|
| 1816 |
-
[
|
| 1817 |
-
0.0035738751757889986,
|
| 1818 |
-
0.00557406060397625,
|
| 1819 |
-
0.004837150685489178,
|
| 1820 |
-
0.0,
|
| 1821 |
-
0.0,
|
| 1822 |
-
0.0,
|
| 1823 |
-
0.6734107136726379
|
| 1824 |
-
],
|
| 1825 |
-
[
|
| 1826 |
-
0.0035626839380711317,
|
| 1827 |
-
0.005561233498156071,
|
| 1828 |
-
0.00482589565217495,
|
| 1829 |
-
0.0,
|
| 1830 |
-
0.0,
|
| 1831 |
-
0.0,
|
| 1832 |
-
0.6724013686180115
|
| 1833 |
-
],
|
| 1834 |
-
[
|
| 1835 |
-
0.0035529215820133686,
|
| 1836 |
-
0.005548112094402313,
|
| 1837 |
-
0.004816059954464436,
|
| 1838 |
-
0.0,
|
| 1839 |
-
0.0,
|
| 1840 |
-
0.0,
|
| 1841 |
-
0.6714058518409729
|
| 1842 |
-
],
|
| 1843 |
-
[
|
| 1844 |
-
0.0035408444236963987,
|
| 1845 |
-
0.005534714087843895,
|
| 1846 |
-
0.0048048244789242744,
|
| 1847 |
-
0.0,
|
| 1848 |
-
0.0,
|
| 1849 |
-
0.0,
|
| 1850 |
-
0.670409083366394
|
| 1851 |
-
],
|
| 1852 |
-
[
|
| 1853 |
-
0.0035294988192617893,
|
| 1854 |
-
0.005521110724657774,
|
| 1855 |
-
0.004796639084815979,
|
| 1856 |
-
0.0,
|
| 1857 |
-
0.0,
|
| 1858 |
-
0.0,
|
| 1859 |
-
0.669427216053009
|
| 1860 |
-
],
|
| 1861 |
-
[
|
| 1862 |
-
0.003518011188134551,
|
| 1863 |
-
0.0055075655691325665,
|
| 1864 |
-
0.0047874050214886665,
|
| 1865 |
-
0.0,
|
| 1866 |
-
0.0,
|
| 1867 |
-
0.0,
|
| 1868 |
-
0.6684450507164001
|
| 1869 |
-
],
|
| 1870 |
-
[
|
| 1871 |
-
0.003509625094011426,
|
| 1872 |
-
0.005495153367519379,
|
| 1873 |
-
0.004781167954206467,
|
| 1874 |
-
0.0,
|
| 1875 |
-
0.0,
|
| 1876 |
-
0.0,
|
| 1877 |
-
0.6674659252166748
|
| 1878 |
-
],
|
| 1879 |
-
[
|
| 1880 |
-
0.003499576123431325,
|
| 1881 |
-
0.005482127424329519,
|
| 1882 |
-
0.0047730510123074055,
|
| 1883 |
-
0.0,
|
| 1884 |
-
0.0,
|
| 1885 |
-
0.0,
|
| 1886 |
-
0.6665111780166626
|
| 1887 |
-
],
|
| 1888 |
-
[
|
| 1889 |
-
0.0034931653644889593,
|
| 1890 |
-
0.0054698726162314415,
|
| 1891 |
-
0.004765379708260298,
|
| 1892 |
-
0.0,
|
| 1893 |
-
0.0,
|
| 1894 |
-
0.0,
|
| 1895 |
-
0.665599524974823
|
| 1896 |
-
],
|
| 1897 |
-
[
|
| 1898 |
-
0.0034858165308833122,
|
| 1899 |
-
0.005457438062876463,
|
| 1900 |
-
0.0047576818615198135,
|
| 1901 |
-
0.0,
|
| 1902 |
-
0.0,
|
| 1903 |
-
0.0,
|
| 1904 |
-
0.6647313833236694
|
| 1905 |
-
],
|
| 1906 |
-
[
|
| 1907 |
-
0.0034800912253558636,
|
| 1908 |
-
0.005446141120046377,
|
| 1909 |
-
0.004752232693135738,
|
| 1910 |
-
0.0,
|
| 1911 |
-
0.0,
|
| 1912 |
-
0.0,
|
| 1913 |
-
0.6638643145561218
|
| 1914 |
-
]
|
| 1915 |
-
],
|
| 1916 |
-
"global_mean": [
|
| 1917 |
-
8.372806405532174e-06,
|
| 1918 |
-
-0.00028733949875459075,
|
| 1919 |
-
0.0002960901183541864,
|
| 1920 |
-
0.0,
|
| 1921 |
-
0.0,
|
| 1922 |
-
0.0,
|
| 1923 |
-
0.2582257091999054
|
| 1924 |
-
],
|
| 1925 |
-
"global_std": [
|
| 1926 |
-
0.0036533514503389597,
|
| 1927 |
-
0.005667832214385271,
|
| 1928 |
-
0.004929195158183575,
|
| 1929 |
-
0.0,
|
| 1930 |
-
0.0,
|
| 1931 |
-
0.0,
|
| 1932 |
-
0.6791926622390747
|
| 1933 |
-
]
|
| 1934 |
-
}
|
| 1935 |
-
},
|
| 1936 |
-
"num_episodes": 360,
|
| 1937 |
-
"num_transition": 93771
|
| 1938 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/manifest.json
DELETED
|
@@ -1,45 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"base_model": "Wan-AI/Wan2.2-TI2V-5B",
|
| 3 |
-
"checkpoint_contents": "three inference checkpoints and matching metadata",
|
| 4 |
-
"checkpoint_epochs": [
|
| 5 |
-
10,
|
| 6 |
-
20,
|
| 7 |
-
30
|
| 8 |
-
],
|
| 9 |
-
"checkpoint_selection": "epochs 10, 20, and 30; stopped early at user request",
|
| 10 |
-
"completed_updates": 94160,
|
| 11 |
-
"ended_utc": "2026-09-17T15:38:29Z",
|
| 12 |
-
"epochs": 50,
|
| 13 |
-
"final_checkpoint": "checkpoints/weights/step_087930.pt",
|
| 14 |
-
"final_checkpoint_step": 87930,
|
| 15 |
-
"global_batch_size": 32,
|
| 16 |
-
"includes_training_state": false,
|
| 17 |
-
"integrity_inventory": "upload_manifest.json",
|
| 18 |
-
"last_logged_training_step": 94160,
|
| 19 |
-
"model": "fasterwam",
|
| 20 |
-
"native_checkpoint_steps": [
|
| 21 |
-
29310,
|
| 22 |
-
58620,
|
| 23 |
-
87930
|
| 24 |
-
],
|
| 25 |
-
"planned_epochs": 50,
|
| 26 |
-
"prompts": {
|
| 27 |
-
"dish_utensil": "pick the dishes out of the rack and place them on the table, then pick and place the spoon to the gray dish and fork to the pink dish",
|
| 28 |
-
"fruit_pick": "Lift the lid, put it aside, and pick the black plum.",
|
| 29 |
-
"place_cube": "place the cube in the bowl",
|
| 30 |
-
"push_t": "push the T block to the target outline"
|
| 31 |
-
},
|
| 32 |
-
"retained_through_epoch": 30,
|
| 33 |
-
"robot_evaluation": "not performed for these runs",
|
| 34 |
-
"run_id": "train90_joint_job4247",
|
| 35 |
-
"schema_version": 1,
|
| 36 |
-
"slurm_job": 4247,
|
| 37 |
-
"source_dir": "fastwam_train/runs/joint_all4_fasterwam/2026-09-17_04-15-26_job4247",
|
| 38 |
-
"stop_reason": "User requested cancellation and publication of epochs 10, 20, 30 only",
|
| 39 |
-
"task": "joint",
|
| 40 |
-
"training_gpus": 8,
|
| 41 |
-
"training_mode": "joint",
|
| 42 |
-
"training_status": "cancelled_by_user",
|
| 43 |
-
"validation_note": "No finalized W&B summary was available after cancellation. See training log for validation history; no robot evaluation claimed.",
|
| 44 |
-
"wandb_run": "https://wandb.ai/aabyaneh/fasterwam-real/runs/pp7o49m6"
|
| 45 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/provenance/code.json
DELETED
|
@@ -1,22 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"args": [
|
| 3 |
-
"--config-dir",
|
| 4 |
-
"/shared_work/amin-a/realworld-wam/fastwam_train/configs",
|
| 5 |
-
"task=fasterwam_joint_split90",
|
| 6 |
-
"output_dir=/shared_work/amin-a/realworld-wam/fastwam_train/runs/joint_all4_fasterwam/2026-09-17_04-15-26_job4247",
|
| 7 |
-
"wandb.name=joint_all4_fasterwam_2026-09-17_04-15-26_job4247",
|
| 8 |
-
"wandb.workspace=aabyaneh",
|
| 9 |
-
"wandb.project=fasterwam-real",
|
| 10 |
-
"wandb.mode=online",
|
| 11 |
-
"hydra/job_logging=stdout",
|
| 12 |
-
"data.dataset_name=joint_all4",
|
| 13 |
-
"batch_size=4",
|
| 14 |
-
"gradient_accumulation_steps=1",
|
| 15 |
-
"num_epochs=50",
|
| 16 |
-
"save_every=29310",
|
| 17 |
-
"eval_every=2931"
|
| 18 |
-
],
|
| 19 |
-
"code_snapshot_note": "Bundled source files are export-time snapshots; saved run config and checkpoint are authoritative.",
|
| 20 |
-
"python": "CPython 3.10.20",
|
| 21 |
-
"startedAt": "2026-09-17T04:17:33.873343Z"
|
| 22 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/provenance/implementation.json
DELETED
|
@@ -1,364 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"repository": "https://github.com/rhyang6/fastwam",
|
| 3 |
-
"branch": "new_fused_kv",
|
| 4 |
-
"commit": "19483b8b1b6a72e697091a07e7df7777aa09fd85",
|
| 5 |
-
"reference_config": "scripts_liheng/final_version/libero.yaml",
|
| 6 |
-
"method": "fasterwam",
|
| 7 |
-
"files": {
|
| 8 |
-
"LICENSE": "8379dddfbbb1154ad9cc57f008f1f8d4a8d26c3de99bd6b36aa4d8067888aa92",
|
| 9 |
-
"configs/calibration/libero_camera_calibration_v1.json": "dfd4faa7ed6ccbf27b3ef69a682377b9e839a75e757caaa16f41d86c3faa685e",
|
| 10 |
-
"configs/calibration/libero_plus_anchors_v1.json": "67abf6f8c5b6067d3cc93a806299947de47f8b8393d895757dbf2880757349c1",
|
| 11 |
-
"configs/data/libero_2cam.yaml": "67a6b911352cef43bb2e5da4a60083a6c94af0143bfbf811e9d612b72bfa5960",
|
| 12 |
-
"configs/data/libero_2cam_aligned_3dpft.yaml": "3f8f0448440db7b0cdb5c5e1cc408e3b19dc8b4b564d4e196e781d6327152ab2",
|
| 13 |
-
"configs/data/roboreal.yaml": "ed35d3f0cf25a3939a703fedcc547015fcb5415d683df57ae39243447efbb944",
|
| 14 |
-
"configs/data/robotwin.yaml": "f1ba509fac21fc59d5a210d6f68bcf94640729ce00dce695b7ca6df24c7b5aa7",
|
| 15 |
-
"configs/data/robotwin_clean_random.yaml": "53ff96c11d41c47ac137109d53c7f5ae6f73abc9042607dcccbd3a7d8e0a1387",
|
| 16 |
-
"configs/data/robotwin_v30.yaml": "72b59238d3699d41eda61af3871419505ac6b7c0adda58af66c33bdfa403db8f",
|
| 17 |
-
"configs/data/robotwin_v30_aligned_3dpft.yaml": "8646fba876beb63b9ac79cf54628016b2fd60596eee77a73d9fc808b1ed46174",
|
| 18 |
-
"configs/data/robotwin_v30_delta.yaml": "4a4fa6d059c5f5c90a1bb464b4d76bad06e67a1f0c934bb20e5b001fe8621c92",
|
| 19 |
-
"configs/model/faster_wam.yaml": "4376e8b8e5fde662d3722404819f4bd5247236e8dae93857871f09b2d587d059",
|
| 20 |
-
"configs/model/fasterwam_decoupled_action_rope.yaml": "35b34784bf44ca502b691c294e6835ac5a4b171bcaeb7b205b845b456af0064c",
|
| 21 |
-
"configs/model/fasterwam_decoupled_aligned_3dpft.yaml": "e02fcba5a4edfbbe3d369b046fd956c6329e5efdf7df48dd19697580321c0de0",
|
| 22 |
-
"configs/model/fasterwam_decoupled_aligned_3dpft_weakpersp.yaml": "38c0a978291c47e65e135f8a98a7080919a83e7ca276b5eb47329df9f2599596",
|
| 23 |
-
"configs/model/fasterwam_decoupled_aligned_3dpft_x0.yaml": "c6aa72fcf8ffae0390216f2cc7614c54f94b1ba1d2796e1cc8ecf05b0431dcf7",
|
| 24 |
-
"configs/model/fasterwam_decoupled_aligned_3dpft_x0_proxpinhole.yaml": "8e71445d25266dba71a923dfb436bebd0e9d751d5cc7bad20a1eab1eff575e94",
|
| 25 |
-
"configs/model/fasterwam_decoupled_aligned_3dpft_x0_weakpersp.yaml": "fe99f4df2febd7251b70179367135969215ceb9fb8b71ebcc18842ce453c130a",
|
| 26 |
-
"configs/model/fasterwam_decoupled_attn_offset_head_anchor.yaml": "6806230f3272c222c47d66e3e7ab06b70d31038fad945649254059e7be0b1d11",
|
| 27 |
-
"configs/model/fasterwam_decoupled_control_rope.yaml": "46af59125fbd223540c3180553681094e1bdf12e384c703bb11d352793ed3daf",
|
| 28 |
-
"configs/model/fasterwam_decoupled_controlnet_pp.yaml": "bd56cb94c5252b1eadf580b2b8c323f5b0f284120a4e55a5f7cc8caf03fb4e24",
|
| 29 |
-
"configs/model/fasterwam_decoupled_ha_content_pp.yaml": "88c894f3d7092b09a73a72767ec230cbfdee48a23a443446afc47dd7b51f6cd4",
|
| 30 |
-
"configs/model/fasterwam_decoupled_ha_origami.yaml": "723f97e6bc43e3110564af570f05cdb6b4d55d7c817c3f0c81b8aaa4517c686b",
|
| 31 |
-
"configs/model/fasterwam_decoupled_head_anchor_h3072.yaml": "802896b938dfec82fbb1e1c4c79cde8d48cce474c8017095fe0faefd657f51cf",
|
| 32 |
-
"configs/model/fasterwam_decoupled_iha.yaml": "478b106254f15562e72d4e669d7171a397ea968018a0766183d37eb24d92e2af",
|
| 33 |
-
"configs/model/fasterwam_decoupled_learnable_head_anchor.yaml": "820e603a7a303950f5bb1db63d1f33cd47ad43ce2f0684e5cfa5d3f04ffe19e9",
|
| 34 |
-
"configs/model/fasterwam_decoupled_learnable_head_anchor_h3072.yaml": "635214d40f122009807edbb255815367ecb382e4b6185466aeff9d75dde3e4f7",
|
| 35 |
-
"configs/model/fasterwam_decoupled_non_fixed_rope.yaml": "c18df423fe45ca49682511d46194a3b823938b4d045260580fada97f50f74763",
|
| 36 |
-
"configs/model/fasterwam_decoupled_offset_head_anchor.yaml": "a1cc2b511321031fe2533bad45936fb082fb47f6203231af781e6a3def58854a",
|
| 37 |
-
"configs/model/fasterwam_decoupled_piha.yaml": "8c92c8c77af46dacdc6a3b42ed5e70cafff1be65efae075b0c98008da8d8cd2f",
|
| 38 |
-
"configs/model/fasterwam_decoupled_piha_post_rope_kv_simplepad_wide_newdrop05.yaml": "f94784772f55edfd5463b642f2b1e01bbf50f94f862b38543360a1d328d09749",
|
| 39 |
-
"configs/model/fasterwam_decoupled_piha_proprio_adaln_zero.yaml": "7738bab2cf88206c13dca23a828899edd61d6b1062b85554042acc0a26f91892",
|
| 40 |
-
"configs/model/fasterwam_decoupled_piha_proprio_adaln_zero_cfgdrop01.yaml": "c775698ea84f8a4ede6b68a043fee6bdce31e1f45b8bdb7e6f931ba6f6a627b9",
|
| 41 |
-
"configs/model/fasterwam_decoupled_piha_proprio_adaln_zero_drop02.yaml": "3a4b6d439c1ba523b7a2a0d01f96a1327ffc6de79ee04a5fb7ed0c43c73ab990",
|
| 42 |
-
"configs/model/fasterwam_decoupled_piha_proprio_adaln_zero_jitter05.yaml": "a518782be1d7840d97e96c92c055b5affcd57b7dfa15cbf3e38a37f9df2b425d",
|
| 43 |
-
"configs/model/fasterwam_decoupled_piha_proprio_adaln_zero_newdrop01.yaml": "1d37eee2d374798fed73dbbca610a0efcd24f4cf2534082198216d93821c1845",
|
| 44 |
-
"configs/model/fasterwam_decoupled_piha_proprio_adaln_zero_newdrop05.yaml": "117db49eadf95e8ae708ba29c8c9ca9a76725a7f6eab5e92c0f1681d89e9fe1f",
|
| 45 |
-
"configs/model/fasterwam_decoupled_piha_proprio_adaln_zero_simple_cfgdrop01.yaml": "0d5ee96e2a370a0dbc5b9d99851fe28642cf9f5a4d0f06fe1bc69d9636e07627",
|
| 46 |
-
"configs/model/fasterwam_decoupled_piha_proprio_adaln_zero_simple_wide_newdrop01.yaml": "e5a1c21b7dd751872ba4975fcbbf002b13e5220d37add2b05b200a680d803983",
|
| 47 |
-
"configs/model/fasterwam_decoupled_piha_proprio_adaln_zero_simple_wide_newdrop05.yaml": "900d8de2a7e89a0732942b93187b409bca96d4f63df5a311aba2763af22c738c",
|
| 48 |
-
"configs/model/fasterwam_decoupled_piha_proprio_adaln_zero_simple_wide_nulldrop0.yaml": "661cf1ae45c855829631ca6727e612a8510a70f297954e124e3fcf69603d6cdf",
|
| 49 |
-
"configs/model/fasterwam_decoupled_piha_proprio_adaln_zero_tgate_drop02.yaml": "7cef525d1debc26fbb0a9d4524e710898a834f1d44c3ca351ed7aa5d50799c84",
|
| 50 |
-
"configs/model/fasterwam_decoupled_piha_proprio_adaln_zero_wide_cfgdrop01.yaml": "68b49e4dea0f3b0282d3708c2b843f4a7872d2d947d8238f8103e3a1fb82d340",
|
| 51 |
-
"configs/model/fasterwam_decoupled_piha_proprio_adaln_zero_wide_newdrop01.yaml": "20ec0e1e879739d845fac9a20255fc5f87ce42a67eb60e5ae78e992d49adefee",
|
| 52 |
-
"configs/model/fasterwam_decoupled_piha_proprio_adaln_zero_wide_newdrop05.yaml": "51ff20d87979292fe5e26d97a7a23bb7ecad2b9f1f6f21082cc712bcd1b036b2",
|
| 53 |
-
"configs/model/fasterwam_decoupled_piha_proprioca_pre_piha_adaln_zero.yaml": "203dab8186358b7e00d3ec29548bdcbe7689d9833d88d5b656cd20ec91885405",
|
| 54 |
-
"configs/model/fasterwam_decoupled_piha_s2_notextca_wide.yaml": "428f1cd7e15c7f73de8a902a922d1901f589bb8776dd43514d0e250a17c7027a",
|
| 55 |
-
"configs/model/fasterwam_decoupled_piha_textca_cfgdrop01.yaml": "ad068306feb58b79e78c35d7df2404212aacf1c532ad00f5d5e732e69a036ad9",
|
| 56 |
-
"configs/model/fasterwam_decoupled_piha_textca_post_droppath02.yaml": "af9e3c11ad60b6b421953a8578fcdaed7e303463e357bee052b7d1a267fdda6e",
|
| 57 |
-
"configs/model/fasterwam_decoupled_piha_textca_post_piha_adaln_zero.yaml": "d3bd137c793d81c550e27da27d5d112adaf8ca1254e51f1856be9abdde0f4efe",
|
| 58 |
-
"configs/model/fasterwam_decoupled_piha_textca_post_piha_adaln_zero_cfgdrop01.yaml": "b935f7b017640b1921b6933bf4db47d0552166fde149b0d143935fcc4743fadf",
|
| 59 |
-
"configs/model/fasterwam_decoupled_piha_textca_pre_piha_adaln_zero.yaml": "c7db20a11dbcdb7a7e5eb3d8016ec6ae388642e3be50f9d01e7cade8f12ab468",
|
| 60 |
-
"configs/model/fasterwam_decoupled_piha_textca_pre_piha_adaln_zero_drop01.yaml": "0decdda84bacafcdaf8a6d0b9240b799d62ad6fee7544ff83636087dcefaf199",
|
| 61 |
-
"configs/model/fasterwam_decoupled_piha_textca_pre_piha_adaln_zero_drop02.yaml": "0c7bed756eacf69ff48a7642708fde7c45a002bff0080c630e20ec789d7a0f8a",
|
| 62 |
-
"configs/model/fasterwam_decoupled_piha_textca_pre_piha_adaln_zero_newdp01.yaml": "e4edb493c653218fd3242f5427897b9ee40e22c7484295b783df0673d26c08a8",
|
| 63 |
-
"configs/model/fasterwam_decoupled_piha_textca_proprio_jitter.yaml": "2f546b9609b6fa4b396962a84837f0f45bbc35122c59e0dc7d5c24195fd3baf5",
|
| 64 |
-
"configs/model/fasterwam_decoupled_piha_textca_separate_null_drop01.yaml": "4039be28e1ae9c67c683b27ee62014a4b2e91400e88eed7333594be5539500aa",
|
| 65 |
-
"configs/model/fasterwam_decoupled_piha_textca_separate_null_drop01_wide.yaml": "80443ead682fb85e943307ab18ede4e78cffe1d2d97b7c6c9268721de13588c5",
|
| 66 |
-
"configs/model/fasterwam_decoupled_piha_textca_separate_null_drop02.yaml": "731d5ad71209f77578e6b68e7a43dabfc614c34fe5f512128dfdadcd3d116694",
|
| 67 |
-
"configs/model/fasterwam_decoupled_piha_textca_text_only.yaml": "054c236c5c7560f4c09b37c53031fd75e72530fa5cc3d63cde1ceca5d4efcb5a",
|
| 68 |
-
"configs/model/fasterwam_decoupled_proprio_offset_head_anchor.yaml": "5a991a2a83c3aca15b6505f94fc7b16cf989e21796915ad7e59e2e2995be503b",
|
| 69 |
-
"configs/model/fasterwam_decoupled_robotwin_aligned_3dpft.yaml": "1ad5b5203967f4b699b1dcd452b9517b0fb18cf22bd2596a031d9f7bba287cc5",
|
| 70 |
-
"configs/model/fasterwam_decoupled_robotwin_piha.yaml": "589d760a4bdeff1462c11473091d904e14e6fee364eb19f28abe82a8cd789a3f",
|
| 71 |
-
"configs/model/fasterwam_decoupled_robotwin_piha_cyclic_notextca_wide.yaml": "7d83328f3115ecb382fb08a304d838ca73e917fe307577ef33d33f586eb9a238",
|
| 72 |
-
"configs/model/fasterwam_decoupled_robotwin_piha_cyclic_notextca_wide_m2.yaml": "033ed8c5ba8df6dba7babe8614010fd964cdfc794da491afe48f65772be2ee57",
|
| 73 |
-
"configs/model/fasterwam_decoupled_robotwin_piha_cyclic_proprio_adaln_zero_simple_wide_newdrop01.yaml": "ecd85b1b781a5c701f2e30ac5048113a0c29d2575a704e382e9d2acffb5d84ef",
|
| 74 |
-
"configs/model/fasterwam_decoupled_robotwin_piha_s3_notextca_wide.yaml": "65c04fc915408e51161a56910b2ce867718125c67608e8946c49217893cf292a",
|
| 75 |
-
"configs/model/fasterwam_decoupled_robotwin_piha_s3_notextca_wide_m2.yaml": "bb6b3c81557db91d781c9194bf17bc8ccacd1e143dbf526c1e0c96cd6d1ac93c",
|
| 76 |
-
"configs/model/fasterwam_decoupled_robotwin_piha_s3_post_rope_kv_simplepad_wide_newdrop01.yaml": "64b2d3128b2e1132ccbcb7952f91e31e5080acf0cea820455cc99174eeae7b06",
|
| 77 |
-
"configs/model/fasterwam_decoupled_robotwin_piha_s3_proprio_adaln_zero.yaml": "2835c16bc27a1861ece3111ad2bbcc0ca6c8c163888269d658fee93116298716",
|
| 78 |
-
"configs/model/fasterwam_decoupled_robotwin_piha_s3_proprio_adaln_zero_cfgdrop01.yaml": "1d52f29de3d8137eaef46016b83813e4e739f55574fbcdb722e2f5b4dd4fe5a1",
|
| 79 |
-
"configs/model/fasterwam_decoupled_robotwin_piha_s3_proprio_adaln_zero_jitter05.yaml": "9709256567b7eb05cbf6a601f602878a94e0f34b43f58a52375c193810bf68c3",
|
| 80 |
-
"configs/model/fasterwam_decoupled_robotwin_piha_s3_proprio_adaln_zero_simple_wide_newdrop01.yaml": "522d322b47eb9bff865b77dae1626596cbf3105ec1b22141d42ce7c8ee36f835",
|
| 81 |
-
"configs/model/fasterwam_decoupled_robotwin_piha_s3_proprio_adaln_zero_simple_wide_nulldrop0.yaml": "ed9421ab8c79fb242626fd0bf7b86bcabfafed1b83269bbeecf9ed11d9db4410",
|
| 82 |
-
"configs/model/fasterwam_decoupled_robotwin_piha_s3_proprio_adaln_zero_wide_cfgdrop01.yaml": "7df67a49dba60c481f3acf8633f73f62f8088615f5402a9d939ef4dfbe66e873",
|
| 83 |
-
"configs/model/fasterwam_decoupled_robotwin_piha_s3_textca.yaml": "23b28a10d06b5711a6f3ac71a93b278525845a0868c6d1c2e8f55bac16cd4c2c",
|
| 84 |
-
"configs/model/fasterwam_decoupled_robotwin_piha_s3_textca_cfgdrop01.yaml": "dd681117e2d45190138e7713de107d57b6af158be77b5bcf49fa40433556f0f9",
|
| 85 |
-
"configs/model/fasterwam_decoupled_robotwin_piha_s3_textca_post_droppath01_wide.yaml": "71f561f22621b36924a11fb2b23b290f8a22e622f6b23265fe6bdc8d7d708226",
|
| 86 |
-
"configs/model/fasterwam_decoupled_robotwin_piha_s3_textca_pre_piha_adaln_zero.yaml": "f1bd375a3eb80505646796ebb9578215b8ae3330da1a004e83819b8a9e9d9197",
|
| 87 |
-
"configs/model/fasterwam_decoupled_robotwin_piha_s3_textca_separate_null_drop01_wide.yaml": "04ce7e36b50dafc99cb1e75190b97d32d45bbb9fceb51d8e2a86123ae6d3c7d5",
|
| 88 |
-
"configs/model/fasterwam_decoupled_viewlocal_ha_pp.yaml": "809db6d01a4f9640be616d8e1b8ce44f16b0bd8ab3d27c6c62d3cee3d88e319c",
|
| 89 |
-
"configs/model/fastwam.yaml": "e19fd569ca168f9621567bd273cba544251f57609972c3ab95d9125b3ab7146d",
|
| 90 |
-
"configs/model/fastwam_action_mlp.yaml": "c5090b5e1ef85f2e82df82844fef4a3d0ed6d69a3d1715471399c1b0fcbcc08b",
|
| 91 |
-
"configs/model/fastwam_decoupled.yaml": "32ca8b9d20ad26add7de7a3ab0a564de7ee7f785567f9f35d5716617e2171067",
|
| 92 |
-
"configs/model/fastwam_idm.yaml": "951c508dfee6a3b4066489a57d633ee83743d2ecb96ba695c61c38cded7528f2",
|
| 93 |
-
"configs/model/fastwam_joint.yaml": "4bb1ed76ff315d11ee4de8804740393c06e9736517fb232117f58005f100c3bb",
|
| 94 |
-
"configs/sim_libero.yaml": "aaf0ca1c9fa847b5084e0b849520a1bafec406914b75ad409432b142f43ac5cb",
|
| 95 |
-
"configs/task/libero_idm_2cam224_1e-4.yaml": "5df6cf62843806b0d9d2fb48b873945865bbfa74d135c58032651d54d6992c4e",
|
| 96 |
-
"configs/task/libero_joint_2cam224_1e-4.yaml": "1c46f34058c9c5363bab6814a0b86eb13be3a0077e944db7d39cf151da07636e",
|
| 97 |
-
"configs/task/libero_uncond_2cam224_1e-4.yaml": "27bdc30545aa06bca81137690a241d469d5a67a433881976bd79da3d4171d1a0",
|
| 98 |
-
"configs/task/roboreal_uncond_3cam_384_1e-4.yaml": "654614f5a146dc7d02aae59b9a184efdf6f88f1a49ca76d48b4eb97847a7bcfa",
|
| 99 |
-
"configs/task/robotwin_action_mlp_3cam_384_1e-4_v30.yaml": "26d29ac6cba793ccda1e659e6dc495b88f140ebc97257975dc95cedc146c5b76",
|
| 100 |
-
"configs/task/robotwin_decoupled_3cam_384_1e-4.yaml": "fb0b79ddcfcaf1f04030477d2dda04b0b931d4a85a3b5a7ff253883865ce198f",
|
| 101 |
-
"configs/task/robotwin_decoupled_3cam_384_1e-4_clean_random.yaml": "7c1273a424a6df2b7407ce692756186d9e42e8cd54451912f200a12a8de02cf7",
|
| 102 |
-
"configs/task/robotwin_decoupled_3cam_384_1e-4_v30.yaml": "f7f5d3d06b596ce0fc42d44a95d394bf0d1a081c313e2e6336c43aaf7d198642",
|
| 103 |
-
"configs/task/robotwin_fasterwam_3cam_384_1e-4_v30.yaml": "e03f812c18296d3d9ca9dc6006d18a0db8316dae89d37eb5d87918424fc238b8",
|
| 104 |
-
"configs/task/robotwin_fasterwam_3cam_384_1e-4_v30_delta.yaml": "11442397245491db776b70bdab6e0c53de8193e340a5d687f158de5be0f9e46f",
|
| 105 |
-
"configs/task/robotwin_fasterwam_aligned_3dpft_3cam_384_1e-4_v30.yaml": "b5d4e77f862163bb5e5198347a970f1a1c80598062682217e1aac459ae879b40",
|
| 106 |
-
"configs/task/robotwin_fasterwam_fixed_rope_starclean_holdout.yaml": "4ed28ff0d2749008aabe0eb7768ac42870ff516adbc1fb24cc76ed114abe17c8",
|
| 107 |
-
"configs/task/robotwin_fasterwam_non_fixed_rope_starclean_holdout.yaml": "72b8e49fa073e9b21f9fb6e2c97cbf10fa93dfaff224726e90a82fed1fb4eb52",
|
| 108 |
-
"configs/task/robotwin_fastwam_30layer_starclean_holdout.yaml": "7c23c35d1dea094aae9adee6449dc207d4cf6f910ee91528e2aaa2ce3a4bcb31",
|
| 109 |
-
"configs/task/robotwin_fused_kv_3cam_384_1e-4_v30.yaml": "6ed7b018130805be3d29c7f298697288ba7f95bc9dabf8bec372574897ae4859",
|
| 110 |
-
"configs/task/robotwin_idm_3cam_384_1e-4.yaml": "2e67c9f301105752962af825e57e5b46ef5e6ba4290e397e5efc7abb88652619",
|
| 111 |
-
"configs/task/robotwin_joint_3cam_384_1e-4.yaml": "daf4cb5246728ba60ae6903fbfd9d5e029d7172f30916b8143f81783450fa874",
|
| 112 |
-
"configs/task/robotwin_uncond_3cam_384_1e-4.yaml": "2f78a207415b452b05e0238f3e00eb9942d7960413076b5b3cdcf1ce09caef9f",
|
| 113 |
-
"configs/task/robotwin_uncond_3cam_384_1e-4_v30.yaml": "f64f830ce7331b8fb6925cd275f23cf34ed7a848a584f2fa5176c7b5aa720e69",
|
| 114 |
-
"configs/train.yaml": "3d1294b83b7de598fa65e29e96988694be7f4b4c211f5f0890418313421c659c",
|
| 115 |
-
"pyproject.toml": "cd7abcb7b19b3ab6e2b2f3dd57e3ac7f8f329b07a7f1ff4f819b6627e9045a1a",
|
| 116 |
-
"scripts/__init__.py": "5a71e51c716ea7579151f36996bebb1ff82c6fedd0c45c68f2918cf5812f1053",
|
| 117 |
-
"scripts/accelerate_configs/accelerate_zero0.yaml": "dacdf1cee3675246567f1f61e943c6762a4700b8b40c888af8fdf89773adc35b",
|
| 118 |
-
"scripts/accelerate_configs/accelerate_zero1_ds.yaml": "5b9e24f38c199fdff6bbd17981d86e2624f855f707660094c99f711efc8e0833",
|
| 119 |
-
"scripts/consolidate_parquets.py": "aeea6ee5c4536843daa5a192280d8f4b126e70a0b5b17d67927b6fb64da2b23e",
|
| 120 |
-
"scripts/convert_multitask_to_v30.py": "989dfb32c6e2869d8ce6003f3ade338035dcddf6102723dfb3f190cb77f850d8",
|
| 121 |
-
"scripts/convert_to_v30.py": "55a0685d75287c687759f75ba66faa4c5f2e9f4131e33386c308e4ab5f453dca",
|
| 122 |
-
"scripts/ds_configs/ds_zero1_config.json": "8b65ebcb8de8c3c89113695a61783cdb97c2aa5003477f0ca743aa511bc68312",
|
| 123 |
-
"scripts/find_lowest_inference_time.py": "09060fec278c0e107dc1a84ff326ecb0b25dbfd58f83b7bf544d5a6a404e4fe3",
|
| 124 |
-
"scripts/fix_step5.py": "c7d1a306f3714d48a384e162a1b5c1473e3d7fc6a73d68816ccefc928cd6da5f",
|
| 125 |
-
"scripts/nccl_smoke_test.py": "207c69bdbacc8fc837372866bd9cf9e50049985d633988b10d972119216c9f0a",
|
| 126 |
-
"scripts/precompute_clean2rand_text_embeds.sh": "ba39e5506ec920d78f707cb4bf14af44ac0013b7928a130de44f63b088abf59a",
|
| 127 |
-
"scripts/precompute_libero_plus_eval_prompt_caches.sh": "77d7fd49bca0794a20fb3cbf09102726eb43dae59675c89af6c17d3e5fd7839f",
|
| 128 |
-
"scripts/precompute_text_embeds.py": "a1c0b63a0cac37394bfb4d023ae5dd916ca64ffbb87b8a086b34c5e4c903ba1e",
|
| 129 |
-
"scripts/precompute_video_latents.py": "25191edbc21862b87549d613d2d9590772adc67fbbdd3aeee354cc146126c141",
|
| 130 |
-
"scripts/preprocess_action_dit_backbone.py": "0fb11f04756d71e6b1b1d26cdf9e5831dfead339da38aa25c02f171d7f484a94",
|
| 131 |
-
"scripts/run_eval.sh": "0f95ef66bf81cbb12857805a96a7d560f7bd56efbe36be4a29b65c55b3497472",
|
| 132 |
-
"scripts/run_train.sh": "bf470e305d1f663372e7a966bfac2ec8fd5a9bdf0c32f5f028dc135b24b5f610",
|
| 133 |
-
"scripts/slurm_train.sh": "54a212c718c6b199a9d5e67e726a390adacbde70eec32e0933a6029aaae7f333",
|
| 134 |
-
"scripts/test_find_lowest_inference_time.py": "23354d0b3fa5b29928597dc9df8ca5ae2e38675d5c59001a212d90c242fa3a54",
|
| 135 |
-
"scripts/train.py": "0b137862ae1a269863960508d282a27dbaee3caae90c9989403fef977fbbe8b8",
|
| 136 |
-
"scripts/train_zero1.sh": "3eb17cb89605954acf5652768b1fc174be17c9776d9178c4a82d7483e6a8934c",
|
| 137 |
-
"scripts_liheng/final_version/README.md": "eefa3d83dd86d0d2b2b90eb8f2e05d553a9f7f66708aebd5f3a0d08cb02cf736",
|
| 138 |
-
"scripts_liheng/final_version/libero.yaml": "3593f63981c929d21c3f9f61d802d9ede835d6fe9767bf71b9774d00fed26e65",
|
| 139 |
-
"scripts_liheng/final_version/robotwin.yaml": "4b2e79381fcb82ed39097dc21f6f40c169cbb4f3c766080e851c930ff3bafb40",
|
| 140 |
-
"src/fastwam/__init__.py": "c4149c5ff0f9abd1517360daf761e692feb8570eb7a0caa2dfde52d4412c3e23",
|
| 141 |
-
"src/fastwam/datasets/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
| 142 |
-
"src/fastwam/datasets/aligned_3dpft.py": "48a439a71ca5e7687f76304d50c3c8b401fce6c255feb60fbab4bd24affbfa7f",
|
| 143 |
-
"src/fastwam/datasets/dataset_utils.py": "3bc17590049c7cb54061acf8d731b07892e7f530c5d7eeac2613fa77a285a392",
|
| 144 |
-
"src/fastwam/datasets/eef_anchors.py": "2e0cdd77ab4072a0355f379bbd3c1aaaa845c5ba1098b59b652b8f08495ea961",
|
| 145 |
-
"src/fastwam/datasets/lerobot/base_lerobot_dataset.py": "4d264f9f96e067883053843c7711644cd129353a9be9a5b0e41c4ab9099174f6",
|
| 146 |
-
"src/fastwam/datasets/lerobot/constants.py": "11ac9260341e1560c5eb0dd7acb79ed63c74180b8ab4113c27622ff213db417f",
|
| 147 |
-
"src/fastwam/datasets/lerobot/lerobot/datasets/compute_stats.py": "7d7daab219332b5abdfd5ec67ccaf3502e8eb583a17a4e482c3f3d4f7a691e89",
|
| 148 |
-
"src/fastwam/datasets/lerobot/lerobot/datasets/utils.py": "f2cfe722464cbe2144efa42eab48e92c4db06cfe0301217c12e03bc9b9a6cee4",
|
| 149 |
-
"src/fastwam/datasets/lerobot/lerobot/datasets/video_utils.py": "cb647a1e955c3279e39ce8d7af7a37ea7432bbd71534c183f9ceebc8557dd89f",
|
| 150 |
-
"src/fastwam/datasets/lerobot/lerobot/lerobot_dataset.py": "ef054e5b0dfb3a26e392376699e31808174afd620298f5977e1eb88385d93963",
|
| 151 |
-
"src/fastwam/datasets/lerobot/processors/base_processor.py": "1f47bc85fee11e3d16714b2f1e3a2dc874f4609a1706a788617156d34b48b58e",
|
| 152 |
-
"src/fastwam/datasets/lerobot/processors/fastwam_processor.py": "f61b2ed19e199f0e063e727878b17fce70ba451b3ee32b036f0b19e1b2d74384",
|
| 153 |
-
"src/fastwam/datasets/lerobot/robot_video_dataset.py": "6a2538f41567cc86435d36a90e09c819a82eb0e1ce8897ee10b817758cc0dada",
|
| 154 |
-
"src/fastwam/datasets/lerobot/transforms/action_state_merger.py": "669d6991415fc5eca44b32b129d15fee1e06e2f17d59d90350c252598033b427",
|
| 155 |
-
"src/fastwam/datasets/lerobot/transforms/image.py": "4d7ab61d0844918525244db653831f0f632730046b2714a6163ff57c441a16fa",
|
| 156 |
-
"src/fastwam/datasets/lerobot/transforms/misc.py": "8b505bd9e3a54ab2db7efcd64f0929d2e0303f5db1123de1074fd01fa9887e2b",
|
| 157 |
-
"src/fastwam/datasets/lerobot/transforms/relative_action.py": "ebd0a50b91b44aac2959b0903d22b197490355ebf1371fb906d424cd1ed4fbb0",
|
| 158 |
-
"src/fastwam/datasets/lerobot/transforms/rotation.py": "0de34b252d60b956cda07c0c19baebbd3c8a28916face700c6664c5815e11e91",
|
| 159 |
-
"src/fastwam/datasets/lerobot/utils/normalizer.py": "5ac89a646cd6395e98feaa832f8fdf7c7e00857080af3d9c15710e243c43ad43",
|
| 160 |
-
"src/fastwam/datasets/lerobot/utils/rotation.py": "6169162f98faf02a3fe5201e2b8a1069fe299840d036ee7cad8af5fa8f561542",
|
| 161 |
-
"src/fastwam/datasets/robotwin_aligned_3dpft.py": "a25697adce91bb50bc647b5a2750cc6c06a734a853a18e73c7c45ff3575b2aa4",
|
| 162 |
-
"src/fastwam/datasets/video_latent_cache.py": "029685a2c508093d4103e91b4cfe4752cab02c8a339854c54996ef410d932860",
|
| 163 |
-
"src/fastwam/geometry/__init__.py": "6dca1e525b0309aa1dc652bc358da8bbffdf6a1b897d550f94e3b6475af25bdb",
|
| 164 |
-
"src/fastwam/geometry/bearing.py": "b532e46f4ee370512bbb85c8ec6953984d60f45bc7023b25d50b0a7c715af367",
|
| 165 |
-
"src/fastwam/geometry/calibration.py": "27fd1ac432e2f84e4f93a81c44212e43242935e8e740e4cbe62cc369ce3c040d",
|
| 166 |
-
"src/fastwam/geometry/camera_source.py": "c1ed83f4ca07906a93591e0909273e9c11e8ae557869a10f2710a40fcdb09389",
|
| 167 |
-
"src/fastwam/geometry/control_rope.py": "faf4b8161d551bf2f0e04d50863997972e8b3838547309052c02877f65370d53",
|
| 168 |
-
"src/fastwam/geometry/eef_projector.py": "4573508ee3f4dbe5f73a99267cf8b3e5c039ca8067a8a3060d6653b81e052964",
|
| 169 |
-
"src/fastwam/geometry/flow_context.py": "176f1f5bec816d79de152a914e6b438dff2f6aa6b86e0cd61b078a0d80f7bd04",
|
| 170 |
-
"src/fastwam/geometry/flow_trajectory.py": "eb886b53e1c5efe333bbf3dcf7437235168c5d685739a5c12ae9cb487bf45c01",
|
| 171 |
-
"src/fastwam/geometry/identity.py": "5ce73d68a505f9ade3a607ccb3f87f7c5498acdc64b5f9669b80fb9a2a695102",
|
| 172 |
-
"src/fastwam/geometry/plus_anchors.py": "0819cfcedfa19a20345c2107e292a5c70bac3ac806054f647ca41581b17fef5f",
|
| 173 |
-
"src/fastwam/geometry/prox_pinhole.py": "c2e5924c93b6628f22a3609b01a84403821f4ff43e9ebc09fcec1477987908bd",
|
| 174 |
-
"src/fastwam/geometry/robotwin_flow.py": "ed872b88878961c434ae3cee4d9e36bcf802371c8b5b3e66d3b9784d797c35d2",
|
| 175 |
-
"src/fastwam/geometry/weak_perspective.py": "5dda53e80d8d69eafb5b6b391c38115f60e263da20f014bede43bc4c38a170a5",
|
| 176 |
-
"src/fastwam/lr_schedules.py": "a55094b749307d792f10bd8dcee7fec6e64767592fd11ca609efe6bcf2b64ab2",
|
| 177 |
-
"src/fastwam/models/__init__.py": "ae4c5733f4bbf7caf31df2ae6f789516f6a10cd84a321f7d0375a7034253ac6d",
|
| 178 |
-
"src/fastwam/models/wan22/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
| 179 |
-
"src/fastwam/models/wan22/action_dit.py": "b44dbb467bbe4bdb7aecd3d62398887e969d2322f9b7fa5ba4d1f0d7512f076b",
|
| 180 |
-
"src/fastwam/models/wan22/action_mlp.py": "cae2696f55eb3ad6a9e0ad57808670e4f5daa2c3cfab779849adeafbf8f64a0f",
|
| 181 |
-
"src/fastwam/models/wan22/action_proprio_jitter.py": "5e0514d8b6c4b7055ef3d1cbdee7ef8c48f01b68c74ca05f55c757ffece3d359",
|
| 182 |
-
"src/fastwam/models/wan22/aligned_3dpft.py": "dadf2af499fd1c885c4208eda3d99d9359b9c9e1c8117019886161fdec7ff3c1",
|
| 183 |
-
"src/fastwam/models/wan22/aligned_3dpft_x0.py": "6457955b5d917b19a887903ef40d1c99c4279aacf8bc1bb04900ba77fa1959aa",
|
| 184 |
-
"src/fastwam/models/wan22/attn_offset_head_anchor.py": "72db2485774b4092e14b7277a49e4e7faed1afa4b319f7921e5dea27b44795e3",
|
| 185 |
-
"src/fastwam/models/wan22/control_rope.py": "dc38bac44b7255333db11c51f342b4dada4b1a8583f8c664cc7d905bec7e886b",
|
| 186 |
-
"src/fastwam/models/wan22/controlnet_pp.py": "9705427f6210b11c6180bd61e7079c3c7d1a06f8c564d1358f63a28f69ead4b6",
|
| 187 |
-
"src/fastwam/models/wan22/fasterwam_decoupled.py": "1c75e685f0a930dd318f6be2c8440f07ad70c97e23bb889b82272df065d6712c",
|
| 188 |
-
"src/fastwam/models/wan22/fastwam.py": "22ca5d635f84205f820a9bb2bad618aaa0a2cf0ac34e6296d9209c8e8c59b28e",
|
| 189 |
-
"src/fastwam/models/wan22/fastwam_action_mlp.py": "6900181ba52cd469d6b67059d1ed1877776bd4f6eaf8e95305467153e2c7b3e2",
|
| 190 |
-
"src/fastwam/models/wan22/fastwam_decoupled.py": "2e2b1ef09c60a497e778cb8dfde72bb9cc0853651c072c9fa9c9bd910f2134ae",
|
| 191 |
-
"src/fastwam/models/wan22/fastwam_idm.py": "0f380cef6363123531b116712f7b46dafa16961f50de822881e76fc8b1313b1d",
|
| 192 |
-
"src/fastwam/models/wan22/fastwam_joint.py": "35bf9bceba78b5c49b6655e5e103fce3566595fce31974a5da54a35ddc3a2ffb",
|
| 193 |
-
"src/fastwam/models/wan22/ha_content_pp.py": "14419e79fb5bc42f8c3c63385bb6c7d943844fcc5a069ed9baecbfa16241431b",
|
| 194 |
-
"src/fastwam/models/wan22/helpers/__init__.py": "f26116de229557a37a4812dc4ee75971f5f9e8b80240786ea4d0e5b0ff703cbf",
|
| 195 |
-
"src/fastwam/models/wan22/helpers/gradient.py": "ba5d8f7272eb029dc6cd2849ca99b70f6ad5abb838d21c818beb0590620dc793",
|
| 196 |
-
"src/fastwam/models/wan22/helpers/io.py": "1c6c1bc8a975b47092912833194fce25e2e3ac886fbab72d73af3ff5a00b3c62",
|
| 197 |
-
"src/fastwam/models/wan22/helpers/loader.py": "792f66bd0609c1365256aa24d43301340f81260c1651d89b04d2ae8224a08726",
|
| 198 |
-
"src/fastwam/models/wan22/helpers/state_dict_converters.py": "81d213373e5056a8d8bf31768b9b04164138ea78d0b306e316334841499f4bf9",
|
| 199 |
-
"src/fastwam/models/wan22/iha.py": "9ebd044a7a1bc27192425c1ddaee52f6d009b176f632c99b01f5993dd8b6e38a",
|
| 200 |
-
"src/fastwam/models/wan22/kv_fusion.py": "6d0923ac3c13b003d80c532c33f2f072c88a4a407b631da9f751bbbea8491f49",
|
| 201 |
-
"src/fastwam/models/wan22/learnable_head_anchor.py": "e4535aa748092bd63786bdcb078655d3fc79cc4260dc69c15f946657a7cbc676",
|
| 202 |
-
"src/fastwam/models/wan22/mot.py": "e4572d5a63e8a0329a365208161a923116f3d49fe4fe9992998de26abc83c09d",
|
| 203 |
-
"src/fastwam/models/wan22/mot_decoupled.py": "ecb2feefbb15f0f4c5081f2ed7eed8e0c16dc6ad5fbe3e5c3323d54997f27ca7",
|
| 204 |
-
"src/fastwam/models/wan22/offset_head_anchor.py": "ded0371aa5e376f2ba54886d3200bdff09d41223d58846ec10d13f25f59c139a",
|
| 205 |
-
"src/fastwam/models/wan22/piha.py": "671de66cbd53af8af281fd8fa2f3e3eeb7b499d2bc2da30c70c1a0ee5bdb0b99",
|
| 206 |
-
"src/fastwam/models/wan22/piha_post_rope_kv.py": "98aeffc362e21fb9417264c837ae9a8fc47165ad0aa4421aa0690643c8a46201",
|
| 207 |
-
"src/fastwam/models/wan22/proprio_offset_head_anchor.py": "46030d28f3beee04900d5ea52c59bed0cf25f2e65efa228671ef69cdea7e4805",
|
| 208 |
-
"src/fastwam/models/wan22/robotwin_aligned_3dpft.py": "db4ea90fe871746c5fa6afe27bee3d7ee4a9064b3f390d79eecb617906574360",
|
| 209 |
-
"src/fastwam/models/wan22/schedulers/scheduler_continuous.py": "2ececce284f7b9fe876965fbf5e11ca7b69caaf693979266b0f63062a589f181",
|
| 210 |
-
"src/fastwam/models/wan22/text_ca_dropout.py": "65d621fb0e3c0c4f10db1d58c7cd53eb53078e44d9ad3266a9f2b1fee8cd2f7a",
|
| 211 |
-
"src/fastwam/models/wan22/viewlocal_ha_pp.py": "350b06631f6b98056f2e0a9221776e8715614284894e8f28c380c232c5598f04",
|
| 212 |
-
"src/fastwam/models/wan22/wan22.py": "b72998999b4b2c5096773092339b8ca81e9e7d96f398b81c57d3d22d14972ac4",
|
| 213 |
-
"src/fastwam/models/wan22/wan_video_dit.py": "9fe059b41fa8248bee5d0e6b49fd22c2d2fe5ef48553a7f1cb06f769a06e6feb",
|
| 214 |
-
"src/fastwam/models/wan22/wan_video_text_encoder.py": "aedf7f131556a39b99a273deec3a85d67f41b5367cef41f310f33a807ae60a87",
|
| 215 |
-
"src/fastwam/models/wan22/wan_video_vae.py": "31b3fb9f844a76f5db5af4854e14802aae640b85b61d0de03a4b53b52515abb7",
|
| 216 |
-
"src/fastwam/runtime.py": "253454009a5defad0f4138875304999ea36195dd59ce4745ab79149880204887",
|
| 217 |
-
"src/fastwam/trainer.py": "80afaf3dd3d3bffaec81023bc6bd3b7efc822bf5e836f983c2e97e9bc2d96fa9",
|
| 218 |
-
"src/fastwam/utils/__init__.py": "2893c05b99b17162941c70a41859c2808f8ae390be367a26cac7d5ab93ee197b",
|
| 219 |
-
"src/fastwam/utils/config_resolvers.py": "01c48cbd42b86e636b70ccc3e193a81147162ba890777102b2c61086fa415340",
|
| 220 |
-
"src/fastwam/utils/fs.py": "69e6df236b43360428a613686c8f37c531c0d16a3a2c5b06a725c46b49d657c5",
|
| 221 |
-
"src/fastwam/utils/logging_config.py": "cadc4f6ad487c3f37171a6defad36d23d9ab8bf262f73a461cd9ee9b03b757e7",
|
| 222 |
-
"src/fastwam/utils/misc.py": "05aa51247936a8d3faac27f90b78b65ff83a688259bed55d114b6a617ced532d",
|
| 223 |
-
"src/fastwam/utils/pytorch_utils.py": "ffc483e7fb435cd654326750eaffdbfc9243837c3140dcc74e45b24abb751a33",
|
| 224 |
-
"src/fastwam/utils/samplers.py": "4d3bd9b2d498f4ad8f2cf9765d60c4bf5368fa6fa2a7d42d0db6210f66899652",
|
| 225 |
-
"src/fastwam/utils/video_io.py": "9e9898b021a44e87aa1b4e6d13e3755a9869a2e27a7eb53c72a6802808d5bd80",
|
| 226 |
-
"src/fastwam/utils/video_metrics.py": "aaa37e458cc9e4bb79a17923b5ff5900c97b4309f7abd50db44cf76e9143ffd6",
|
| 227 |
-
"tests/print_eval_results.py": "34590e8ce1baa7a93a453e0ac3af0e1be38392e20d8e19330932f1e598ac5f80",
|
| 228 |
-
"tests/print_real_dimensions.py": "bf718b8feb599a9e7f52d3227171079b6acee5c4dbc8d520d6567bfd0da0e3c2",
|
| 229 |
-
"tests/test_action_dit_selective_init.py": "0f8e8ab3ed9366b797a51a092e5eec57a516462105137e207dc52cea93ae8ff1",
|
| 230 |
-
"tests/test_action_mlp.py": "6880720c982d1350ee207c21c32e74af4ffc89fd6c4673a9fe7a5fef74984005",
|
| 231 |
-
"tests/test_action_proprio_condition_jitter.py": "99877f4f7f5256fec08c3043b3abadc90bc89e8d411db5c7f30d5e754595978b",
|
| 232 |
-
"tests/test_action_proprio_null_dropout.py": "1bfa23472c4493b6e5d8c046a988e3d98ea9e2de7f48591bba968a623374eff3",
|
| 233 |
-
"tests/test_action_text_ca_dropout.py": "ffd1bd7c0cab920bef709f18fb3cca7d31e88fcc8c4542b4c1436e65aa38f624",
|
| 234 |
-
"tests/test_action_text_ca_post_droppath.py": "ffc4f40854b2a21260a4d6ebf8250599ef88fe5972974e77eb29c9fbe4a9bc13",
|
| 235 |
-
"tests/test_action_text_ca_proprio_jitter.py": "1256041d8c86a4a9ecdc3be51e6ff4c494ea13fbbc5c95849049fce5c30d0a1e",
|
| 236 |
-
"tests/test_action_text_cross_attn.py": "58a2f441f666ebef0d755c9c894b4fd55720600899db00f47e4b2901c4fb0487",
|
| 237 |
-
"tests/test_aligned_3dpft.py": "be54483206fed5410491116487975bc5626712c9bfa9b9ed6116ec21b8ad3a85",
|
| 238 |
-
"tests/test_aligned_3dpft_eval_context.py": "9c7097662669a1122d2f39fbcb5f758e1e79d5e80c34f7c6ae84a682e27f3b13",
|
| 239 |
-
"tests/test_aligned_3dpft_factory.py": "fe052ecfdc71c84c7747e49e28a7537e776751f874443d2fbf75fc19ef425941",
|
| 240 |
-
"tests/test_aligned_3dpft_live_camera.py": "0ff58b5ecc6a67d9eb8602499c0c24206c60cbe2b1a676b07ba58eea13ea369b",
|
| 241 |
-
"tests/test_aligned_3dpft_native_launchers.py": "408b9efc6f1727f030e03ba244d20066fd5cb950d6d5a91bc4475570175244c5",
|
| 242 |
-
"tests/test_aligned_3dpft_x0.py": "097aff5b5e3094999d95ca63b5cc9ffaabec98fe45646c15bfa2b17d2d98d18c",
|
| 243 |
-
"tests/test_attn_head_softmax_libero.py": "ef1d4a23aa160c328d57afae626cd509f193041cf5b5507a762d2792c8119e77",
|
| 244 |
-
"tests/test_attn_offset_head_anchor.py": "08d86090997ac6f8c0564e50664c7b8a0f5541c8d92ee5acc5bec8f8d9b057e1",
|
| 245 |
-
"tests/test_bearing_projection.py": "84b2bad0bc07d8b936b78d30ac72bd0c750db8f0e72b0816b1e9e6fec8f1c190",
|
| 246 |
-
"tests/test_checkpoint_identity_metadata.py": "4f89721f55275c1d0dfac8156ba5aed8618f6c5b02194ef1565f714ffc5b418c",
|
| 247 |
-
"tests/test_config_resolvers.py": "f3a3686cf924797c4b24caa97dcad12d65eb5de950a6a449483109c94fb2da05",
|
| 248 |
-
"tests/test_control_rope.py": "6281fc66eea8b5c1340a8549b77d3928f276e1fffa2635072d1118dd4d5b2d83",
|
| 249 |
-
"tests/test_controlnet_pp.py": "eac6a8e177f68421035b6d6f062686ab15cdb0c051b6f3432311baf2daeb8d1d",
|
| 250 |
-
"tests/test_decoupled_full_integration.py": "671a9e8caea55b9532f9637b4030664d9e141576c99a8ce112ea279711585d54",
|
| 251 |
-
"tests/test_decoupled_prelaunch_gate.py": "bea2f1e5834183b6143b16b8683c7433aa3250760b4f2d18120bf568e6b2e916",
|
| 252 |
-
"tests/test_decoupled_shapes.py": "560de0e0593933284e27c418b8a9776e2ac613d9e13dadbeb086e5dfc86954d5",
|
| 253 |
-
"tests/test_decoupled_stress_edge_cases.py": "d2b9ca8ede032e64ddfb925a0beacbc2ba8425c25048ed515d8cd3442b93ad55",
|
| 254 |
-
"tests/test_decoupled_stress_mutation.py": "ed17b747c1db8467ac75407180ad32f5d840b41fdc3c9b099a03a18e987364fb",
|
| 255 |
-
"tests/test_decoupled_stress_pipeline.py": "9b90e942fb935d7e6d96b9a5a34f62e75a991bb6603499a92bd0853a11482b52",
|
| 256 |
-
"tests/test_decoupled_vs_baseline_comparison.py": "f004729b97c47224f62539ef1f8256315f6544c0109cde952b6712b1192fd1fc",
|
| 257 |
-
"tests/test_eef_anchor_dataset_threading.py": "8608c1fdf80ed434bd1e389dd9f6132bb39d077f3574e328d4955fc49bcece12",
|
| 258 |
-
"tests/test_eef_anchor_tooling.py": "0e16f0dac6bf17dd9ef50cc622fd0a786f120b7fbaa36c399e99eeede7126958",
|
| 259 |
-
"tests/test_eef_calibration_artifact.py": "32c8b89e0531d3cda947aee57841de68bdf44125af34ce0e92538681e4501422",
|
| 260 |
-
"tests/test_eef_calibration_parity.py": "80f4d3dac2056428629868cc2c8e61bcbab71aa45ea2ae70b92c06aacbdb9e3a",
|
| 261 |
-
"tests/test_eef_projector.py": "c564ea2b643a78407307b47828f4beee56b3750a838df0f71fcaa6b39d080edf",
|
| 262 |
-
"tests/test_explicit_checkpoint_steps.py": "feaeb15ee0aee6a43c473d586ebaf6fc8d321fe7cec571ab643870298495d68a",
|
| 263 |
-
"tests/test_fasterwam_fused_inference.py": "db548954165f610c066b643cab72617c2fe78661f2214b3e4a56bebf9f42a2f0",
|
| 264 |
-
"tests/test_fasterwam_fused_kv_rope_gate.py": "54362f3121f98031a5b46490ac81c67b563cd6a480ef49bcfc2062d9475f2f06",
|
| 265 |
-
"tests/test_fasterwam_fused_mlp.py": "6bef5c70b3e2e48524420f34f36578c12041ed9eff37d1f6fac0beea3e907da3",
|
| 266 |
-
"tests/test_fasterwam_fused_mlp_gate.py": "277aaf626e82618586583dca51b04a759de94b2ce2247e58362d40d4be911931",
|
| 267 |
-
"tests/test_fastwam_decoupled.py": "3d1139dc08434a20767abd34c42557335dac2323e04517243a555e09bde8ef7a",
|
| 268 |
-
"tests/test_fastwam_idm.py": "9c265791e9bb0ac010e793de2febb57cffae8296a168959a26b4d3b132da4b9c",
|
| 269 |
-
"tests/test_fastwam_joint.py": "9b739c632f32f48e170b71acd6804654e732f02809d10e61cd738b3d65009b5c",
|
| 270 |
-
"tests/test_freeze_integration_gpu.py": "4716b14ae346d032147ec4c59a9611080835728c6d83005705a28c0e9e82c18b",
|
| 271 |
-
"tests/test_freeze_trainer_wiring.py": "2398d3b91e004931f60ee1695a932dba1a3195c360cb1daf0c697b11e2b813b7",
|
| 272 |
-
"tests/test_freeze_video_backbone.py": "a703963d4ba806cac1d022ef398919eb9db892f68d8fea213be3eb71b1724a7f",
|
| 273 |
-
"tests/test_fused_kv_checkpoint_guard.py": "916c878cce9aedaf68e4390606c317398cc3ac9604a0b372609702ede87f2185",
|
| 274 |
-
"tests/test_fused_kv_prefill_consistency.py": "50dfd01e6e00cc289bc483df1242ee58d504d2c48e7670a69331ef0ee14bf39e",
|
| 275 |
-
"tests/test_ha_content_pp.py": "ede7c7543fd7fd78b108dee29b60abbe8308ef1fff55fd2b779aba272ddb1a87",
|
| 276 |
-
"tests/test_ha_origami.py": "c9dcbfe0449f4c5332bcb89be8a549cfaf4e94d83cd92f2b5acb1cc75412110d",
|
| 277 |
-
"tests/test_iha.py": "e53b7a14e27b57798929b0da06370dc08d7204dd2b422ccecb05004e7670f8c5",
|
| 278 |
-
"tests/test_interleaved_forward.py": "533e43c99a2de4d3ff4fb2ae982e9d8fab8b8a99d539411f8391f0e30c2bcdc0",
|
| 279 |
-
"tests/test_kv_fusion.py": "7aafff16c4e2c47468d64920fb1937e9570c234b02996ddf0453c96d3640c36a",
|
| 280 |
-
"tests/test_kv_fusion_factory_integration_gate.py": "e03cbb0163bb75f18c9f3d619976f143665a6f9c69edce52521cf970379512c5",
|
| 281 |
-
"tests/test_kv_source_mapping.py": "de282041d88a5dfcd026498e103603292186dae3b341f265f9b6c74a785f5e33",
|
| 282 |
-
"tests/test_learnable_head_anchor.py": "9d71e07cc3a7c1066ecc1f2e2907435eeff24d82ddaa1cf07629d2ab84cd8760",
|
| 283 |
-
"tests/test_libero_4090_dispatcher_policy.py": "9acfd91c87fc3298e0b67a71048f11fa5b943d42ee29c3756e10d33bd887aaac",
|
| 284 |
-
"tests/test_libero_4090_dispatcher_sim.py": "353483387264277c129ed693fb508ea5a2c809a8c651154f95141c33c16eb514",
|
| 285 |
-
"tests/test_libero_actor_topology.py": "1b2087b23fa811653b102c5e5c83a98b12e6c25dd5e9ef9f4559855cd25119e3",
|
| 286 |
-
"tests/test_libero_batch_dispatch.py": "9252872495832d5a999f11968cd2e843dc54c9c2db96697c3620239aa29014b7",
|
| 287 |
-
"tests/test_libero_batched_inference_gate.py": "1174a1d8237cf72b711a4915327d0a5444fb7440c5b30312eb8230a1bd58bb55",
|
| 288 |
-
"tests/test_libero_context_cache.py": "e550ff058b42015e61b4a13e3cdad060155e0ed107d1441c0f0b8f4d0082995a",
|
| 289 |
-
"tests/test_libero_eval_batch_topology.py": "3c81cd05c52f3f0784f54adb7cb9ac0876ffb8cf95b936444a5568f76a43ec58",
|
| 290 |
-
"tests/test_libero_fixedenv_actor.py": "aa9c29060e45d47aa13fcd77b66264c4a0b78ff4862d697c6e5cca6102c0748c",
|
| 291 |
-
"tests/test_libero_image_preprocessing.py": "f54af57369de94461d7f5223ae42f20d435b92ec5997eccdf9dd79d132ebc1e7",
|
| 292 |
-
"tests/test_libero_jitter_handoff_queue.py": "357c463799c87b6b9b27de818479e281120f3d2268a541a0d9e48c80eab93f2b",
|
| 293 |
-
"tests/test_libero_localpipeline_cluster.py": "1dacea0ccbbb5f6b008996433ce8d301ac7ba0721b5763a449f6642bd1b49714",
|
| 294 |
-
"tests/test_libero_manager_shutdown.py": "7296534d9b2d4aa7a0077732361810de4a326de32bf5f0dbedf092eef5b3e107",
|
| 295 |
-
"tests/test_libero_manager_topology.py": "532614cf5fdca51e43c54f89164bce1202048f84203349f6bd87e62e4addc4d1",
|
| 296 |
-
"tests/test_libero_plus_gpu_defaults.py": "9584355e771ea339bb267775b9015e1870116885011a5e2a46980a3b4b061df3",
|
| 297 |
-
"tests/test_libero_precision_pair.py": "d79d4e7db637c00d8ba5d76ac6c884996fb107da2ea5437fb8200d2e6658e267",
|
| 298 |
-
"tests/test_libero_shared_model_batch.py": "9e98c9605ab229bf8389abe693524133c877fe20e4ca074f0e6ef6dfc84bf086",
|
| 299 |
-
"tests/test_libero_standard_gpu_defaults.py": "1d86ca160c1a0130c046dbaa97a7ad32f6f22d9e53445cd6a706d9fa9239d79d",
|
| 300 |
-
"tests/test_libero_standard_protocol.py": "6586b7e55cea78b1e8299c5d8a8e27a7f05c6585640b01b35bc191485a9fc66a",
|
| 301 |
-
"tests/test_libero_task_work_queue.py": "be8b7430624bfdabb10980f2969dd24c73206679c2339ff5faad9f3539d9665c",
|
| 302 |
-
"tests/test_libero_topology_config.py": "48b9ee1f0684037c1ad17b9ce82ed738534a0b977f1ac3da2c194689e0645aa3",
|
| 303 |
-
"tests/test_libero_wide_s2_notextca_switch.py": "1bb77467c705d9327cbbf5309ee5749ea20e1704b3c054459e82c859846b0e7b",
|
| 304 |
-
"tests/test_local_libero_reference_verifier.py": "015d4f8a30a56d2aecdcafd4fba8224d1867e787938cb7d2de8f9669b54101fe",
|
| 305 |
-
"tests/test_lr_schedules.py": "e95695bc09ab2b73b91f4e0cdc744c1622e80f9b3ce6bf8bc2b72eae7e0bea77",
|
| 306 |
-
"tests/test_nd01_resume_topology.py": "4626002a1106f9f391e84138d6c1b0fe912984e6efdcd8766442048c7404129c",
|
| 307 |
-
"tests/test_new_fused_kv_freqs_guard.py": "1a05a96c6aa6a90c9c866bdc96e019402e8ab38cb8a02d58b00dd7f49fe10abe",
|
| 308 |
-
"tests/test_new_fused_kv_projection_contracts.py": "a57ff0c233fb2a1674ff24e791b2f446c5fb36697b87738849cc33d3f854c40e",
|
| 309 |
-
"tests/test_non_decoupled_inference.py": "083ec475d1c2e8fc051cbeaa347ad8ab53ff616095e78cc6eaf4f147dc4123c0",
|
| 310 |
-
"tests/test_normalizer.py": "9a4385f581ef300d1a6c56ad354665bc78e4ddb00abd928fba27e8eed697299d",
|
| 311 |
-
"tests/test_offset_head_anchor.py": "46da333b0d6958935a1e16fc251383f9b2c0730c0c5465e5547f36a3ecba0197",
|
| 312 |
-
"tests/test_per_request_noise.py": "4983702be58d30196e1cccbc1dc168e6492617de2ff7f69a7bb57eb4f1c204ad",
|
| 313 |
-
"tests/test_piha.py": "6af1a7db6bcba26b74423f39582bb8d299035bba02a4eb3711efea83f0645b59",
|
| 314 |
-
"tests/test_piha_post_rope_kv.py": "211b76bd730f4030c3c4dbaa8b6e8074f9b7b2e1eaf061db474be60a1ca1b27b",
|
| 315 |
-
"tests/test_plus_anchors.py": "665d9cf67b9c0c7f3b867c3a4b1a9ccd81ea18b262feca008f7151d7adc01d65",
|
| 316 |
-
"tests/test_postrope_readout_observer.py": "1555c682e6c2e4c183c1dfcbd50d336d3ae04fd903f1a1c5b58f7644e2d7813a",
|
| 317 |
-
"tests/test_preflight_libero.py": "252ec7ee0ecab2a39decf9a1118fb07787e9bc11fb1631c8aec71288f08b7eb4",
|
| 318 |
-
"tests/test_proprio_offset_head_anchor.py": "9f0d076810f56874f4367f65806c34d94b7af5ac8230229fb99de5ca83899b2c",
|
| 319 |
-
"tests/test_prox_pinhole.py": "b3c1a59252d3f5443e796283760f46157011ddb7461c0c52304161637e619ee5",
|
| 320 |
-
"tests/test_relative_joint_transform.py": "f2df795ad3f9ec3eca37279e60d97602dc44508b1fe09d63907f0251c8ec46fd",
|
| 321 |
-
"tests/test_resume_eval_manager.py": "7244d315c62c05aa111e99e0f81ef2757d49f1385798e2be70dbdce36cbeb8af",
|
| 322 |
-
"tests/test_robotwin_3843_env0_extra2.py": "40e3f20410af3351872be41a3136653e7500148583e466e31012f911265e8c6f",
|
| 323 |
-
"tests/test_robotwin_3843_env0_extra3.py": "d5ca67a8de097c1e837c1f6228ee9d4326295094370e87b0370fd987c8a3e61e",
|
| 324 |
-
"tests/test_robotwin_3843_env0_switch.py": "b1b41709a15db2676683e04889a7efddb4fe1e8cbebb9a3238ee585e30c73e44",
|
| 325 |
-
"tests/test_robotwin_3843_env42_switch.py": "10cad34ccab31e551a55ce8325d450ad63c39e3ff4c6c874f39de7aa36340355",
|
| 326 |
-
"tests/test_robotwin_aligned_3dpft.py": "b04376e1b9417f47e30bcec7aeea88e32e722250c165125448749fda1b31c661",
|
| 327 |
-
"tests/test_robotwin_aligned_3dpft_factory.py": "376cce62d42a209da5624ab46f63c362bae6f469605ead6fa87f0c38a99ce443",
|
| 328 |
-
"tests/test_robotwin_aligned_3dpft_rope.py": "48b64a1d3b5e3f32e2dae228bd9e1d36e03a760c9a1433a5798a718f17914a41",
|
| 329 |
-
"tests/test_robotwin_bf16first_overlay.py": "e30ccd71b92296444cbe76647f3ee0e1b17203ac2a3ab9bf54d85d965633dba6",
|
| 330 |
-
"tests/test_robotwin_bf16first_repeats.py": "651c698df4210e43f8f49abbd838c7dd109695c79f1582bbda28ccc54ed3a54a",
|
| 331 |
-
"tests/test_robotwin_cyclic3911_extra3.py": "d7f2af23780f066a2e0eb440d5a0181c6ce3e16ab9b6cd5bbc141bb9da930857",
|
| 332 |
-
"tests/test_robotwin_cyclic_error_retry.py": "660bb6cf0199a49260cc1d18f0ccdfffe1cb1afddef5dee30b5a09b907a12e3e",
|
| 333 |
-
"tests/test_robotwin_m2_wide_cyclic_notextca_recipe.py": "68c670f513b36683a62e5e48863f710fb73147281f6fe738d1e8f847cc84f4ac",
|
| 334 |
-
"tests/test_robotwin_nd05_lr5e5_recipe.py": "adbac1f1c54b815541c31d32b9031c0a820923fceb0d60a7481dc74da3398110",
|
| 335 |
-
"tests/test_robotwin_piha_post_rope_kv.py": "b2164aab5d28321e3bb8b303cf3d2012be706b1938b03408c02ee20a64044d36",
|
| 336 |
-
"tests/test_robotwin_wide_cyclic_notextca_recipe.py": "95b93ece32702fc8adcbba2e82869b0228c25c8aa5a14ba5e47512e98220e787",
|
| 337 |
-
"tests/test_robotwin_wide_s3_notextca_cosine_8ep_recipe.py": "e6d47bb5ec9ec6959bf8db9957ed0a007b7f7e1f33764aaa8124d0872209ef95",
|
| 338 |
-
"tests/test_samplers.py": "998afae7f0e0d461b56ca195218b2ec428e6be5a0c29baee2e0103e8687510df",
|
| 339 |
-
"tests/test_scheduler_continuous.py": "e1014ef8883075686c09faeb2c1e7a814dd20e25657ec409bb9b120b6db0a1bb",
|
| 340 |
-
"tests/test_sepnull01_eval_summary.py": "56860f190ed804d549cfba18c9ea49b3d682971e1c32f7f2fd46eb9bf147257c",
|
| 341 |
-
"tests/test_sepnull01_fixedenv.py": "c9ccc86f1315efce4d277c849277475e76cd1a2bd1e3de6e330386531a98f03f",
|
| 342 |
-
"tests/test_simplepad_standard_cfgdrop01.py": "0de131a91a0118e131ff0f9aeb95dfabc3c536360f9cc7b3fce12959cca3ba26",
|
| 343 |
-
"tests/test_state_dict_converters.py": "a5c2ee0e6fb098e9c07327afd55eb9aeecec8a24fc2b1e8b18e951ed8a9e5482",
|
| 344 |
-
"tests/test_summarize_libero.py": "43ec6f729c399df11b192bff4b2f0a82310a118194efcc61f0fd3c51bf13bd60",
|
| 345 |
-
"tests/test_transforms.py": "2893a02cab2eca2b94bf2f91a8c559094bae7c2d36bc25b79d41bce7ba795e81",
|
| 346 |
-
"tests/test_v30_dataset.py": "355c6c29185e39279d8267e52b98eb3336284f2f4d64cb5c030d536b993cdb1e",
|
| 347 |
-
"tests/test_verify_liberoplus_install.py": "79dfd53fbaed29dd687f198f7ffea70302ef5110fd50b1db6a57e172e80dfc8b",
|
| 348 |
-
"tests/test_video_latent_cache.py": "791c0d93ef99735fd64c05235037042caf8cefda8682478d5eedf44cdbae6334",
|
| 349 |
-
"tests/test_video_latent_cache_real_gate.py": "c087aeb585504c154bf2216791148a9858238f2d8295afe88cb4cab596c69435",
|
| 350 |
-
"tests/test_video_metrics.py": "5d6ffdde7c0a642807f2c728b44d16909574118616ebfb70de66494e1435a7c7",
|
| 351 |
-
"tests/test_viewlocal_ha_pp.py": "13159450cd3a6761edd4c35cbfbaab3addbfa3a2b3f6f516f3589bc18f46840a",
|
| 352 |
-
"tests/test_weak_perspective.py": "edfda5a6793f76074548019c165b2285fc091916fa30ba93a6a81f8d2c29a76b",
|
| 353 |
-
"tests/test_wsd_extension_preparation.py": "c1a6165849f88c78d9a14b3fa78dfd7c082086b78047fce22dfae3f9eeb380d8",
|
| 354 |
-
"tests/verify_decoupled_config.py": "c20f11c029b168605a8b1c0b56d68cbeafea9649ceb54414c32f973282d61dd5",
|
| 355 |
-
"tests/verify_dimensions_both_modes.py": "faeba9f69770520b4fcb849d2e277a9e4f14c968d69d7b493f17035fbb4a19ee",
|
| 356 |
-
"tests/verify_kb_lean.py": "6527db5b95d7188b0d66f11ab3236e426b149261920c10f5503514fc6676c7b7",
|
| 357 |
-
"tests/verify_kb_real_gpu.py": "6ce6180d2e16df40adffea84f56e85cadec81f90c2261728f5e0ba6f249cb0b7",
|
| 358 |
-
"tests/verify_kb_sysdiag_gaps.py": "32d17be18535e8dd0a1326af5028f3a6ed66ff11f4ada626cb5ca87d6b8bda0f",
|
| 359 |
-
"tests/verify_knowledge_base_deep_dive.py": "001a19226ca0c6b087609845e54677c609308ca549804df55365374905d1bafe",
|
| 360 |
-
"tests/verify_knowledge_base_system_diagram.py": "6c5f554e5c4add0c51cf3c8d6d11b6b5bb0436bf4f38ab4028965d1a46f2665c",
|
| 361 |
-
"tests/verify_mot_mask_topology.py": "32d50a2f48a93963d78916eace52414e8ef32bfa3462d6d6435f3e8b30ed0af6",
|
| 362 |
-
"tests/verify_selective_init_integration.py": "518ad075e1c758c9cc655637ea4a4edfc99b9a053f36ad8ac570fb78976da00e"
|
| 363 |
-
}
|
| 364 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/provenance/training.log
DELETED
|
The diff for this file is too large to render.
See raw diff
|
|
|
joint/fasterwam/train90_joint_job4247/provenance/training_summary.json
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"note": "Run cancelled by user; W&B summary not finalized."
|
| 3 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/requirements.txt
DELETED
|
@@ -1,226 +0,0 @@
|
|
| 1 |
-
anyio==4.14.2
|
| 2 |
-
httpx==0.28.1
|
| 3 |
-
nvidia-ml-py==13.595.45
|
| 4 |
-
tqdm==4.70.0
|
| 5 |
-
click==8.5.0
|
| 6 |
-
h5py==3.16.0
|
| 7 |
-
httpcore==1.0.9
|
| 8 |
-
fsspec==2026.7.0
|
| 9 |
-
numpy==2.2.6
|
| 10 |
-
huggingface_hub==1.29.0
|
| 11 |
-
nvitop==1.7.1
|
| 12 |
-
filelock==3.32.4
|
| 13 |
-
hf-xet==1.6.0
|
| 14 |
-
typing_extensions==4.16.0
|
| 15 |
-
exceptiongroup==1.3.1
|
| 16 |
-
h11==0.16.0
|
| 17 |
-
psutil==7.2.2
|
| 18 |
-
Flask==3.1.3
|
| 19 |
-
gymnasium==1.3.0
|
| 20 |
-
packaging==25.0
|
| 21 |
-
packaging==26.0
|
| 22 |
-
Jinja2==3.1.6
|
| 23 |
-
lazy-loader==0.5
|
| 24 |
-
fsspec==2025.3.0
|
| 25 |
-
pillow==12.0.0
|
| 26 |
-
six==1.17.0
|
| 27 |
-
frozenlist==1.8.0
|
| 28 |
-
idna==3.16
|
| 29 |
-
mplib==0.2.1
|
| 30 |
-
aiosignal==1.4.0
|
| 31 |
-
nvidia_curobo==0.0.0
|
| 32 |
-
setuptools-scm==10.0.5
|
| 33 |
-
sympy==1.14.0
|
| 34 |
-
widgetsnbextension==4.0.15
|
| 35 |
-
ConfigArgParse==1.7.5
|
| 36 |
-
msgpack==1.1.2
|
| 37 |
-
embreex==4.4.0
|
| 38 |
-
parso==0.8.7
|
| 39 |
-
zipp==4.1.0
|
| 40 |
-
nvidia-cuda-nvrtc-cu12==12.8.61
|
| 41 |
-
exceptiongroup==1.3.1
|
| 42 |
-
datasets==3.6.0
|
| 43 |
-
triton==3.3.1
|
| 44 |
-
av==16.0.1
|
| 45 |
-
tokenizers==0.21.4
|
| 46 |
-
nvidia-nvjitlink-cu12==12.8.61
|
| 47 |
-
fastwam==0.1.0
|
| 48 |
-
Werkzeug==3.1.8
|
| 49 |
-
retrying==1.4.2
|
| 50 |
-
aiohttp==3.13.5
|
| 51 |
-
dash==4.1.0
|
| 52 |
-
propcache==0.5.2
|
| 53 |
-
joblib==1.5.3
|
| 54 |
-
tzdata==2026.2
|
| 55 |
-
pandas==2.2.3
|
| 56 |
-
nvidia-cusparse-cu12==12.5.7.53
|
| 57 |
-
typing-inspection==0.4.2
|
| 58 |
-
charset-normalizer==3.4.7
|
| 59 |
-
nbformat==5.10.4
|
| 60 |
-
boto3==1.35.99
|
| 61 |
-
cycler==0.12.1
|
| 62 |
-
ipython==8.39.0
|
| 63 |
-
omegaconf==2.3.0
|
| 64 |
-
setuptools==69.5.1
|
| 65 |
-
setuptools==82.0.1
|
| 66 |
-
jsonschema==4.26.0
|
| 67 |
-
python-dateutil==2.9.0.post0
|
| 68 |
-
pexpect==4.9.0
|
| 69 |
-
svg.path==7.0
|
| 70 |
-
numpy==1.26.4
|
| 71 |
-
vcs-versioning==1.1.1
|
| 72 |
-
blinker==1.9.0
|
| 73 |
-
modelscope==1.34.0
|
| 74 |
-
scikit-image==0.25.2
|
| 75 |
-
fusepy==3.0.1
|
| 76 |
-
plotly==6.7.0
|
| 77 |
-
requests==2.34.2
|
| 78 |
-
stack-data==0.6.3
|
| 79 |
-
shapely==2.1.2
|
| 80 |
-
jsonlines==4.0.0
|
| 81 |
-
sapien==3.0.0b1
|
| 82 |
-
typer==0.25.1
|
| 83 |
-
hf-xet==1.5.0
|
| 84 |
-
jedi==0.20.0
|
| 85 |
-
imageio-ffmpeg==0.6.0
|
| 86 |
-
ninja==1.13.0
|
| 87 |
-
gitdb==4.0.12
|
| 88 |
-
mapbox_earcut==2.0.0
|
| 89 |
-
jsonschema-specifications==2025.9.1
|
| 90 |
-
s3transfer==0.10.4
|
| 91 |
-
Farama-Notifications==0.0.6
|
| 92 |
-
tifffile==2025.5.10
|
| 93 |
-
smmap==5.0.3
|
| 94 |
-
nvidia-cudnn-cu12==9.7.1.26
|
| 95 |
-
trimesh==4.12.2
|
| 96 |
-
pydantic==2.13.4
|
| 97 |
-
pycollada==0.9.3
|
| 98 |
-
scipy==1.15.3
|
| 99 |
-
nvidia-nccl-cu12==2.26.2
|
| 100 |
-
rich==14.2.0
|
| 101 |
-
mpmath==1.3.0
|
| 102 |
-
nvidia-cuda-cupti-cu12==12.8.57
|
| 103 |
-
aiohappyeyeballs==2.6.2
|
| 104 |
-
torchvision==0.22.1+cu128
|
| 105 |
-
torch==2.7.1+cu128
|
| 106 |
-
Pygments==2.20.0
|
| 107 |
-
annotated-types==0.7.0
|
| 108 |
-
traitlets==5.15.0
|
| 109 |
-
GitPython==3.1.45
|
| 110 |
-
toppra==0.6.8
|
| 111 |
-
opencv-python==4.11.0.86
|
| 112 |
-
h5py==3.16.0
|
| 113 |
-
vhacdx==0.0.10
|
| 114 |
-
rpds-py==0.30.0
|
| 115 |
-
yourdfpy==0.0.60
|
| 116 |
-
torchcodec==0.5
|
| 117 |
-
tqdm==4.66.5
|
| 118 |
-
referencing==0.37.0
|
| 119 |
-
transformers==4.49.0
|
| 120 |
-
pytz==2026.2
|
| 121 |
-
PyYAML==6.0.3
|
| 122 |
-
itsdangerous==2.2.0
|
| 123 |
-
warp-lang==1.6.1
|
| 124 |
-
antlr4-python3-runtime==4.9.3
|
| 125 |
-
regex==2025.11.3
|
| 126 |
-
addict==2.4.0
|
| 127 |
-
nvidia-cusolver-cu12==11.7.2.55
|
| 128 |
-
pyarrow==23.0.0
|
| 129 |
-
botocore==1.35.99
|
| 130 |
-
httpcore==1.0.9
|
| 131 |
-
imageio==2.37.0
|
| 132 |
-
einops==0.8.1
|
| 133 |
-
threadpoolctl==3.6.0
|
| 134 |
-
multidict==6.7.1
|
| 135 |
-
urllib3==2.7.0
|
| 136 |
-
nvidia-curand-cu12==10.3.9.55
|
| 137 |
-
anyio==4.13.0
|
| 138 |
-
asttokens==3.0.1
|
| 139 |
-
open3d==0.19.0
|
| 140 |
-
fonttools==4.63.0
|
| 141 |
-
certifi==2026.5.20
|
| 142 |
-
narwhals==2.21.2
|
| 143 |
-
safetensors==0.5.3
|
| 144 |
-
jupyter_core==5.9.1
|
| 145 |
-
h11==0.16.0
|
| 146 |
-
hjson==3.1.0
|
| 147 |
-
ipywidgets==8.1.8
|
| 148 |
-
markdown-it-py==4.2.0
|
| 149 |
-
deepspeed==0.18.5
|
| 150 |
-
jupyterlab_widgets==3.0.16
|
| 151 |
-
contourpy==1.3.2
|
| 152 |
-
scikit-learn==1.7.2
|
| 153 |
-
pyperclip==1.11.0
|
| 154 |
-
pydantic_core==2.46.4
|
| 155 |
-
annotated-doc==0.0.4
|
| 156 |
-
dill==0.3.8
|
| 157 |
-
pure_eval==0.2.3
|
| 158 |
-
shellingham==1.5.4
|
| 159 |
-
jmespath==1.1.0
|
| 160 |
-
transforms3d==0.4.2
|
| 161 |
-
psutil==7.2.2
|
| 162 |
-
importlib_resources==7.1.0
|
| 163 |
-
pyparsing==3.3.2
|
| 164 |
-
importlib_metadata==9.0.0
|
| 165 |
-
nvidia-nvtx-cu12==12.8.55
|
| 166 |
-
MarkupSafe==3.0.3
|
| 167 |
-
nvidia-cufile-cu12==1.13.0.11
|
| 168 |
-
matplotlib==3.10.9
|
| 169 |
-
click==8.4.1
|
| 170 |
-
nest-asyncio==1.6.0
|
| 171 |
-
nvidia-cusparselt-cu12==0.6.3
|
| 172 |
-
kiwisolver==1.5.0
|
| 173 |
-
numpy-quaternion==2024.0.13
|
| 174 |
-
rtree==1.4.1
|
| 175 |
-
sentry-sdk==2.60.0
|
| 176 |
-
manifold3d==3.5.0
|
| 177 |
-
matplotlib-inline==0.2.2
|
| 178 |
-
multiprocess==0.70.16
|
| 179 |
-
mdurl==0.1.2
|
| 180 |
-
platformdirs==4.9.6
|
| 181 |
-
nvidia-cufft-cu12==11.3.3.41
|
| 182 |
-
nvidia-cuda-runtime-cu12==12.8.57
|
| 183 |
-
accelerate==1.12.0
|
| 184 |
-
xxhash==3.7.0
|
| 185 |
-
wandb==0.23.1
|
| 186 |
-
cloudpickle==3.1.2
|
| 187 |
-
networkx==3.4.2
|
| 188 |
-
ptyprocess==0.7.0
|
| 189 |
-
termcolor==2.5.0
|
| 190 |
-
tomli==2.4.1
|
| 191 |
-
async-timeout==5.0.1
|
| 192 |
-
typing_extensions==4.15.0
|
| 193 |
-
wcwidth==0.7.0
|
| 194 |
-
comm==0.2.3
|
| 195 |
-
py-cpuinfo==9.0.0
|
| 196 |
-
decorator==5.3.1
|
| 197 |
-
prompt_toolkit==3.0.52
|
| 198 |
-
nvidia-cublas-cu12==12.8.3.14
|
| 199 |
-
hydra-core==1.3.2
|
| 200 |
-
fastjsonschema==2.21.2
|
| 201 |
-
filelock==3.29.0
|
| 202 |
-
httpx==0.28.1
|
| 203 |
-
attrs==26.1.0
|
| 204 |
-
pybind11==3.0.4
|
| 205 |
-
yarl==1.24.2
|
| 206 |
-
executing==2.2.1
|
| 207 |
-
protobuf==6.33.6
|
| 208 |
-
colorlog==6.10.1
|
| 209 |
-
lxml==6.1.1
|
| 210 |
-
pyquaternion==0.9.9
|
| 211 |
-
wheel==0.46.3
|
| 212 |
-
pip==26.0.1
|
| 213 |
-
huggingface-hub==0.29.2
|
| 214 |
-
fastwam==0.1.0
|
| 215 |
-
autocommand==2.2.2
|
| 216 |
-
backports.tarfile==1.2.0
|
| 217 |
-
importlib_metadata==8.7.1
|
| 218 |
-
jaraco.text==4.0.0
|
| 219 |
-
jaraco.context==6.1.0
|
| 220 |
-
jaraco.functools==4.4.0
|
| 221 |
-
more-itertools==10.8.0
|
| 222 |
-
packaging==26.0
|
| 223 |
-
platformdirs==4.4.0
|
| 224 |
-
tomli==2.4.0
|
| 225 |
-
wheel==0.46.3
|
| 226 |
-
zipp==3.23.0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/splits/dish_utensil_lerobot_v21.json
DELETED
|
@@ -1,118 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"dataset": "dish_utensil_lerobot_v21",
|
| 3 |
-
"dataset_dir": "/shared_work/amin-a/realworld-wam/data/dish_utensil_lerobot_v21",
|
| 4 |
-
"generated": "2026-09-10T20:23:03Z",
|
| 5 |
-
"seed": 42,
|
| 6 |
-
"val_proportion": 0.1,
|
| 7 |
-
"recipe": "sorted(episode_ids) shuffled by np.random.default_rng(seed), split at int(total_episodes * (1 - val_proportion)); matches fastwam base_lerobot_dataset.py",
|
| 8 |
-
"total_episodes": 100,
|
| 9 |
-
"total_frames": 42863,
|
| 10 |
-
"train_episodes": 90,
|
| 11 |
-
"train_frames": 37936,
|
| 12 |
-
"val_episodes": 10,
|
| 13 |
-
"val_frames": 4927,
|
| 14 |
-
"train": [
|
| 15 |
-
0,
|
| 16 |
-
1,
|
| 17 |
-
2,
|
| 18 |
-
3,
|
| 19 |
-
4,
|
| 20 |
-
5,
|
| 21 |
-
6,
|
| 22 |
-
7,
|
| 23 |
-
9,
|
| 24 |
-
10,
|
| 25 |
-
11,
|
| 26 |
-
15,
|
| 27 |
-
16,
|
| 28 |
-
17,
|
| 29 |
-
18,
|
| 30 |
-
19,
|
| 31 |
-
20,
|
| 32 |
-
21,
|
| 33 |
-
22,
|
| 34 |
-
23,
|
| 35 |
-
24,
|
| 36 |
-
25,
|
| 37 |
-
26,
|
| 38 |
-
27,
|
| 39 |
-
28,
|
| 40 |
-
29,
|
| 41 |
-
30,
|
| 42 |
-
31,
|
| 43 |
-
32,
|
| 44 |
-
33,
|
| 45 |
-
34,
|
| 46 |
-
35,
|
| 47 |
-
37,
|
| 48 |
-
38,
|
| 49 |
-
39,
|
| 50 |
-
40,
|
| 51 |
-
41,
|
| 52 |
-
42,
|
| 53 |
-
43,
|
| 54 |
-
44,
|
| 55 |
-
45,
|
| 56 |
-
46,
|
| 57 |
-
48,
|
| 58 |
-
49,
|
| 59 |
-
50,
|
| 60 |
-
51,
|
| 61 |
-
52,
|
| 62 |
-
54,
|
| 63 |
-
55,
|
| 64 |
-
56,
|
| 65 |
-
57,
|
| 66 |
-
58,
|
| 67 |
-
59,
|
| 68 |
-
60,
|
| 69 |
-
61,
|
| 70 |
-
62,
|
| 71 |
-
63,
|
| 72 |
-
64,
|
| 73 |
-
67,
|
| 74 |
-
68,
|
| 75 |
-
69,
|
| 76 |
-
70,
|
| 77 |
-
71,
|
| 78 |
-
72,
|
| 79 |
-
73,
|
| 80 |
-
74,
|
| 81 |
-
75,
|
| 82 |
-
76,
|
| 83 |
-
78,
|
| 84 |
-
79,
|
| 85 |
-
80,
|
| 86 |
-
81,
|
| 87 |
-
82,
|
| 88 |
-
83,
|
| 89 |
-
84,
|
| 90 |
-
85,
|
| 91 |
-
86,
|
| 92 |
-
87,
|
| 93 |
-
88,
|
| 94 |
-
89,
|
| 95 |
-
90,
|
| 96 |
-
91,
|
| 97 |
-
92,
|
| 98 |
-
93,
|
| 99 |
-
94,
|
| 100 |
-
95,
|
| 101 |
-
96,
|
| 102 |
-
97,
|
| 103 |
-
98,
|
| 104 |
-
99
|
| 105 |
-
],
|
| 106 |
-
"val": [
|
| 107 |
-
8,
|
| 108 |
-
12,
|
| 109 |
-
13,
|
| 110 |
-
14,
|
| 111 |
-
36,
|
| 112 |
-
47,
|
| 113 |
-
53,
|
| 114 |
-
65,
|
| 115 |
-
66,
|
| 116 |
-
77
|
| 117 |
-
]
|
| 118 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/splits/fruit_pick_lerobot_v21.json
DELETED
|
@@ -1,118 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"dataset": "fruit_pick_lerobot_v21",
|
| 3 |
-
"dataset_dir": "/shared_work/amin-a/realworld-wam/data/fruit_pick_lerobot_v21",
|
| 4 |
-
"generated": "2026-09-10T20:23:10Z",
|
| 5 |
-
"seed": 42,
|
| 6 |
-
"val_proportion": 0.1,
|
| 7 |
-
"recipe": "sorted(episode_ids) shuffled by np.random.default_rng(seed), split at int(total_episodes * (1 - val_proportion)); matches fastwam base_lerobot_dataset.py",
|
| 8 |
-
"total_episodes": 100,
|
| 9 |
-
"total_frames": 20149,
|
| 10 |
-
"train_episodes": 90,
|
| 11 |
-
"train_frames": 17863,
|
| 12 |
-
"val_episodes": 10,
|
| 13 |
-
"val_frames": 2286,
|
| 14 |
-
"train": [
|
| 15 |
-
0,
|
| 16 |
-
1,
|
| 17 |
-
2,
|
| 18 |
-
3,
|
| 19 |
-
4,
|
| 20 |
-
5,
|
| 21 |
-
6,
|
| 22 |
-
7,
|
| 23 |
-
9,
|
| 24 |
-
10,
|
| 25 |
-
11,
|
| 26 |
-
15,
|
| 27 |
-
16,
|
| 28 |
-
17,
|
| 29 |
-
18,
|
| 30 |
-
19,
|
| 31 |
-
20,
|
| 32 |
-
21,
|
| 33 |
-
22,
|
| 34 |
-
23,
|
| 35 |
-
24,
|
| 36 |
-
25,
|
| 37 |
-
26,
|
| 38 |
-
27,
|
| 39 |
-
28,
|
| 40 |
-
29,
|
| 41 |
-
30,
|
| 42 |
-
31,
|
| 43 |
-
32,
|
| 44 |
-
33,
|
| 45 |
-
34,
|
| 46 |
-
35,
|
| 47 |
-
37,
|
| 48 |
-
38,
|
| 49 |
-
39,
|
| 50 |
-
40,
|
| 51 |
-
41,
|
| 52 |
-
42,
|
| 53 |
-
43,
|
| 54 |
-
44,
|
| 55 |
-
45,
|
| 56 |
-
46,
|
| 57 |
-
48,
|
| 58 |
-
49,
|
| 59 |
-
50,
|
| 60 |
-
51,
|
| 61 |
-
52,
|
| 62 |
-
54,
|
| 63 |
-
55,
|
| 64 |
-
56,
|
| 65 |
-
57,
|
| 66 |
-
58,
|
| 67 |
-
59,
|
| 68 |
-
60,
|
| 69 |
-
61,
|
| 70 |
-
62,
|
| 71 |
-
63,
|
| 72 |
-
64,
|
| 73 |
-
67,
|
| 74 |
-
68,
|
| 75 |
-
69,
|
| 76 |
-
70,
|
| 77 |
-
71,
|
| 78 |
-
72,
|
| 79 |
-
73,
|
| 80 |
-
74,
|
| 81 |
-
75,
|
| 82 |
-
76,
|
| 83 |
-
78,
|
| 84 |
-
79,
|
| 85 |
-
80,
|
| 86 |
-
81,
|
| 87 |
-
82,
|
| 88 |
-
83,
|
| 89 |
-
84,
|
| 90 |
-
85,
|
| 91 |
-
86,
|
| 92 |
-
87,
|
| 93 |
-
88,
|
| 94 |
-
89,
|
| 95 |
-
90,
|
| 96 |
-
91,
|
| 97 |
-
92,
|
| 98 |
-
93,
|
| 99 |
-
94,
|
| 100 |
-
95,
|
| 101 |
-
96,
|
| 102 |
-
97,
|
| 103 |
-
98,
|
| 104 |
-
99
|
| 105 |
-
],
|
| 106 |
-
"val": [
|
| 107 |
-
8,
|
| 108 |
-
12,
|
| 109 |
-
13,
|
| 110 |
-
14,
|
| 111 |
-
36,
|
| 112 |
-
47,
|
| 113 |
-
53,
|
| 114 |
-
65,
|
| 115 |
-
66,
|
| 116 |
-
77
|
| 117 |
-
]
|
| 118 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/splits/place_cube_lerobot_v21.json
DELETED
|
@@ -1,118 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"dataset": "place_cube_lerobot_v21",
|
| 3 |
-
"dataset_dir": "/shared_work/amin-a/realworld-wam/data/place_cube_lerobot_v21",
|
| 4 |
-
"generated": "2026-09-10T20:23:10Z",
|
| 5 |
-
"seed": 42,
|
| 6 |
-
"val_proportion": 0.1,
|
| 7 |
-
"recipe": "sorted(episode_ids) shuffled by np.random.default_rng(seed), split at int(total_episodes * (1 - val_proportion)); matches fastwam base_lerobot_dataset.py",
|
| 8 |
-
"total_episodes": 100,
|
| 9 |
-
"total_frames": 9267,
|
| 10 |
-
"train_episodes": 90,
|
| 11 |
-
"train_frames": 8362,
|
| 12 |
-
"val_episodes": 10,
|
| 13 |
-
"val_frames": 905,
|
| 14 |
-
"train": [
|
| 15 |
-
0,
|
| 16 |
-
1,
|
| 17 |
-
2,
|
| 18 |
-
3,
|
| 19 |
-
4,
|
| 20 |
-
5,
|
| 21 |
-
6,
|
| 22 |
-
7,
|
| 23 |
-
9,
|
| 24 |
-
10,
|
| 25 |
-
11,
|
| 26 |
-
15,
|
| 27 |
-
16,
|
| 28 |
-
17,
|
| 29 |
-
18,
|
| 30 |
-
19,
|
| 31 |
-
20,
|
| 32 |
-
21,
|
| 33 |
-
22,
|
| 34 |
-
23,
|
| 35 |
-
24,
|
| 36 |
-
25,
|
| 37 |
-
26,
|
| 38 |
-
27,
|
| 39 |
-
28,
|
| 40 |
-
29,
|
| 41 |
-
30,
|
| 42 |
-
31,
|
| 43 |
-
32,
|
| 44 |
-
33,
|
| 45 |
-
34,
|
| 46 |
-
35,
|
| 47 |
-
37,
|
| 48 |
-
38,
|
| 49 |
-
39,
|
| 50 |
-
40,
|
| 51 |
-
41,
|
| 52 |
-
42,
|
| 53 |
-
43,
|
| 54 |
-
44,
|
| 55 |
-
45,
|
| 56 |
-
46,
|
| 57 |
-
48,
|
| 58 |
-
49,
|
| 59 |
-
50,
|
| 60 |
-
51,
|
| 61 |
-
52,
|
| 62 |
-
54,
|
| 63 |
-
55,
|
| 64 |
-
56,
|
| 65 |
-
57,
|
| 66 |
-
58,
|
| 67 |
-
59,
|
| 68 |
-
60,
|
| 69 |
-
61,
|
| 70 |
-
62,
|
| 71 |
-
63,
|
| 72 |
-
64,
|
| 73 |
-
67,
|
| 74 |
-
68,
|
| 75 |
-
69,
|
| 76 |
-
70,
|
| 77 |
-
71,
|
| 78 |
-
72,
|
| 79 |
-
73,
|
| 80 |
-
74,
|
| 81 |
-
75,
|
| 82 |
-
76,
|
| 83 |
-
78,
|
| 84 |
-
79,
|
| 85 |
-
80,
|
| 86 |
-
81,
|
| 87 |
-
82,
|
| 88 |
-
83,
|
| 89 |
-
84,
|
| 90 |
-
85,
|
| 91 |
-
86,
|
| 92 |
-
87,
|
| 93 |
-
88,
|
| 94 |
-
89,
|
| 95 |
-
90,
|
| 96 |
-
91,
|
| 97 |
-
92,
|
| 98 |
-
93,
|
| 99 |
-
94,
|
| 100 |
-
95,
|
| 101 |
-
96,
|
| 102 |
-
97,
|
| 103 |
-
98,
|
| 104 |
-
99
|
| 105 |
-
],
|
| 106 |
-
"val": [
|
| 107 |
-
8,
|
| 108 |
-
12,
|
| 109 |
-
13,
|
| 110 |
-
14,
|
| 111 |
-
36,
|
| 112 |
-
47,
|
| 113 |
-
53,
|
| 114 |
-
65,
|
| 115 |
-
66,
|
| 116 |
-
77
|
| 117 |
-
]
|
| 118 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/splits/push_t_lerobot_v21.json
DELETED
|
@@ -1,118 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"dataset": "push_t_lerobot_v21",
|
| 3 |
-
"dataset_dir": "/shared_work/amin-a/realworld-wam/data/push_t_lerobot_v21",
|
| 4 |
-
"generated": "2026-09-10T20:23:10Z",
|
| 5 |
-
"seed": 42,
|
| 6 |
-
"val_proportion": 0.1,
|
| 7 |
-
"recipe": "sorted(episode_ids) shuffled by np.random.default_rng(seed), split at int(total_episodes * (1 - val_proportion)); matches fastwam base_lerobot_dataset.py",
|
| 8 |
-
"total_episodes": 100,
|
| 9 |
-
"total_frames": 32131,
|
| 10 |
-
"train_episodes": 90,
|
| 11 |
-
"train_frames": 29610,
|
| 12 |
-
"val_episodes": 10,
|
| 13 |
-
"val_frames": 2521,
|
| 14 |
-
"train": [
|
| 15 |
-
0,
|
| 16 |
-
1,
|
| 17 |
-
2,
|
| 18 |
-
3,
|
| 19 |
-
4,
|
| 20 |
-
5,
|
| 21 |
-
6,
|
| 22 |
-
7,
|
| 23 |
-
9,
|
| 24 |
-
10,
|
| 25 |
-
11,
|
| 26 |
-
15,
|
| 27 |
-
16,
|
| 28 |
-
17,
|
| 29 |
-
18,
|
| 30 |
-
19,
|
| 31 |
-
20,
|
| 32 |
-
21,
|
| 33 |
-
22,
|
| 34 |
-
23,
|
| 35 |
-
24,
|
| 36 |
-
25,
|
| 37 |
-
26,
|
| 38 |
-
27,
|
| 39 |
-
28,
|
| 40 |
-
29,
|
| 41 |
-
30,
|
| 42 |
-
31,
|
| 43 |
-
32,
|
| 44 |
-
33,
|
| 45 |
-
34,
|
| 46 |
-
35,
|
| 47 |
-
37,
|
| 48 |
-
38,
|
| 49 |
-
39,
|
| 50 |
-
40,
|
| 51 |
-
41,
|
| 52 |
-
42,
|
| 53 |
-
43,
|
| 54 |
-
44,
|
| 55 |
-
45,
|
| 56 |
-
46,
|
| 57 |
-
48,
|
| 58 |
-
49,
|
| 59 |
-
50,
|
| 60 |
-
51,
|
| 61 |
-
52,
|
| 62 |
-
54,
|
| 63 |
-
55,
|
| 64 |
-
56,
|
| 65 |
-
57,
|
| 66 |
-
58,
|
| 67 |
-
59,
|
| 68 |
-
60,
|
| 69 |
-
61,
|
| 70 |
-
62,
|
| 71 |
-
63,
|
| 72 |
-
64,
|
| 73 |
-
67,
|
| 74 |
-
68,
|
| 75 |
-
69,
|
| 76 |
-
70,
|
| 77 |
-
71,
|
| 78 |
-
72,
|
| 79 |
-
73,
|
| 80 |
-
74,
|
| 81 |
-
75,
|
| 82 |
-
76,
|
| 83 |
-
78,
|
| 84 |
-
79,
|
| 85 |
-
80,
|
| 86 |
-
81,
|
| 87 |
-
82,
|
| 88 |
-
83,
|
| 89 |
-
84,
|
| 90 |
-
85,
|
| 91 |
-
86,
|
| 92 |
-
87,
|
| 93 |
-
88,
|
| 94 |
-
89,
|
| 95 |
-
90,
|
| 96 |
-
91,
|
| 97 |
-
92,
|
| 98 |
-
93,
|
| 99 |
-
94,
|
| 100 |
-
95,
|
| 101 |
-
96,
|
| 102 |
-
97,
|
| 103 |
-
98,
|
| 104 |
-
99
|
| 105 |
-
],
|
| 106 |
-
"val": [
|
| 107 |
-
8,
|
| 108 |
-
12,
|
| 109 |
-
13,
|
| 110 |
-
14,
|
| 111 |
-
36,
|
| 112 |
-
47,
|
| 113 |
-
53,
|
| 114 |
-
65,
|
| 115 |
-
66,
|
| 116 |
-
77
|
| 117 |
-
]
|
| 118 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/training_code/fastwam/LICENSE
DELETED
|
@@ -1,24 +0,0 @@
|
|
| 1 |
-
MIT License
|
| 2 |
-
|
| 3 |
-
Copyright (c) 2026 The FastWAM Authors
|
| 4 |
-
|
| 5 |
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 6 |
-
of this software and associated documentation files (the "Software"), to deal
|
| 7 |
-
in the Software without restriction, including without limitation the rights
|
| 8 |
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 9 |
-
copies of the Software, and to permit persons to whom the Software is
|
| 10 |
-
furnished to do so, subject to the following conditions:
|
| 11 |
-
|
| 12 |
-
The above copyright notice and this permission notice shall be included in all
|
| 13 |
-
copies or substantial portions of the Software.
|
| 14 |
-
|
| 15 |
-
Except for third-party code and files that retain their original license
|
| 16 |
-
headers, this repository is released under the MIT License.
|
| 17 |
-
|
| 18 |
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 19 |
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 20 |
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 21 |
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 22 |
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 23 |
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 24 |
-
SOFTWARE.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/training_code/fastwam/pyproject.toml
DELETED
|
@@ -1,53 +0,0 @@
|
|
| 1 |
-
[build-system]
|
| 2 |
-
requires = ["setuptools>=68", "wheel"]
|
| 3 |
-
build-backend = "setuptools.build_meta"
|
| 4 |
-
|
| 5 |
-
[project]
|
| 6 |
-
name = "fastwam"
|
| 7 |
-
version = "0.1.0"
|
| 8 |
-
description = "FastWAM: standalone Wan2.2-TI2V-5B training/inference package"
|
| 9 |
-
requires-python = ">=3.10"
|
| 10 |
-
dependencies = [
|
| 11 |
-
"accelerate==1.12.0",
|
| 12 |
-
"av==16.0.1",
|
| 13 |
-
"boto3==1.35.99",
|
| 14 |
-
"datasets==3.6.0",
|
| 15 |
-
"deepspeed==0.18.5",
|
| 16 |
-
"einops==0.8.1",
|
| 17 |
-
"gitpython==3.1.45",
|
| 18 |
-
"huggingface-hub==0.29.2",
|
| 19 |
-
"hydra-core==1.3.2",
|
| 20 |
-
"imageio==2.37.0",
|
| 21 |
-
"imageio-ffmpeg==0.6.0",
|
| 22 |
-
"jsonlines==4.0.0",
|
| 23 |
-
"modelscope==1.34.0",
|
| 24 |
-
"numpy==1.26.4",
|
| 25 |
-
"omegaconf==2.3.0",
|
| 26 |
-
"packaging==25.0",
|
| 27 |
-
"pandas==2.2.3",
|
| 28 |
-
"pillow==12.0.0",
|
| 29 |
-
"pyarrow==23.0.0",
|
| 30 |
-
"regex==2025.11.3",
|
| 31 |
-
"rich==14.2.0",
|
| 32 |
-
"safetensors==0.5.3",
|
| 33 |
-
"termcolor==2.5.0",
|
| 34 |
-
"torch==2.7.1+cu128",
|
| 35 |
-
"torchcodec==0.5",
|
| 36 |
-
"torchvision==0.22.1+cu128",
|
| 37 |
-
"tqdm==4.66.5",
|
| 38 |
-
"transformers==4.49.0",
|
| 39 |
-
"typing-extensions==4.15.0",
|
| 40 |
-
"wandb==0.23.1",
|
| 41 |
-
]
|
| 42 |
-
|
| 43 |
-
[tool.setuptools.package-dir]
|
| 44 |
-
"" = "src"
|
| 45 |
-
|
| 46 |
-
[tool.setuptools.packages.find]
|
| 47 |
-
where = ["src"]
|
| 48 |
-
include = ["fastwam*"]
|
| 49 |
-
|
| 50 |
-
[tool.pytest.ini_options]
|
| 51 |
-
markers = [
|
| 52 |
-
"slow: marks tests as slow (deselect with -m 'not slow')",
|
| 53 |
-
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/training_code/fastwam/scripts/train.py
DELETED
|
@@ -1,24 +0,0 @@
|
|
| 1 |
-
import sys
|
| 2 |
-
from pathlib import Path
|
| 3 |
-
|
| 4 |
-
import hydra
|
| 5 |
-
from omegaconf import DictConfig
|
| 6 |
-
|
| 7 |
-
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
| 8 |
-
SRC_DIR = str(PROJECT_ROOT / "src")
|
| 9 |
-
if SRC_DIR not in sys.path:
|
| 10 |
-
sys.path.insert(0, SRC_DIR)
|
| 11 |
-
|
| 12 |
-
from fastwam.runtime import run_training
|
| 13 |
-
from fastwam.utils.config_resolvers import register_default_resolvers
|
| 14 |
-
|
| 15 |
-
register_default_resolvers()
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
@hydra.main(config_path="../configs", config_name="train", version_base="1.3")
|
| 19 |
-
def main(cfg: DictConfig):
|
| 20 |
-
run_training(cfg)
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
if __name__ == "__main__":
|
| 24 |
-
main()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/__init__.py
DELETED
|
@@ -1 +0,0 @@
|
|
| 1 |
-
"""FastWAM package."""
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/__init__.py
DELETED
|
File without changes
|
joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/aligned_3dpft.py
DELETED
|
@@ -1,91 +0,0 @@
|
|
| 1 |
-
"""Opt-in LIBERO dataset context for ``aligned_3dpft``."""
|
| 2 |
-
|
| 3 |
-
from __future__ import annotations
|
| 4 |
-
|
| 5 |
-
import numpy as np
|
| 6 |
-
import torch
|
| 7 |
-
|
| 8 |
-
from fastwam.geometry.flow_context import build_flow_trajectory_context
|
| 9 |
-
from fastwam.geometry.flow_trajectory import LIBERO_OSC_POSITION_SCALE
|
| 10 |
-
|
| 11 |
-
from .lerobot.robot_video_dataset import DEFAULT_PROMPT, RobotVideoDataset
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
class Aligned3DPFTRobotVideoDataset(RobotVideoDataset):
|
| 15 |
-
"""Attach observed cameras and normalization affine to each training sample."""
|
| 16 |
-
|
| 17 |
-
def __init__(self, *args, **kwargs):
|
| 18 |
-
if not kwargs.get("eef_anchor_calibration_path"):
|
| 19 |
-
raise ValueError(
|
| 20 |
-
"Aligned3DPFTRobotVideoDataset requires eef_anchor_calibration_path"
|
| 21 |
-
)
|
| 22 |
-
# Optional geometry-channel augmentation: gaussian noise on the observed
|
| 23 |
-
# EEF pose BEFORE the flow context is built, as [position_std_m,
|
| 24 |
-
# orientation_std_rad]. Perturbs only the anchor geometry (trajectory
|
| 25 |
-
# origin + reconstructed wrist camera); the proprio the model consumes
|
| 26 |
-
# is untouched. Teaches partial trust in the anchor under sensor noise.
|
| 27 |
-
noise = kwargs.pop("aligned_3dpft_eef_noise_std", None)
|
| 28 |
-
if noise is not None:
|
| 29 |
-
noise = tuple(float(value) for value in noise)
|
| 30 |
-
if len(noise) != 2 or any(value < 0 for value in noise):
|
| 31 |
-
raise ValueError(
|
| 32 |
-
"aligned_3dpft_eef_noise_std must be "
|
| 33 |
-
f"[position_std_m>=0, orientation_std_rad>=0], got {noise}"
|
| 34 |
-
)
|
| 35 |
-
if noise == (0.0, 0.0):
|
| 36 |
-
noise = None
|
| 37 |
-
self.aligned_3dpft_eef_noise_std = noise
|
| 38 |
-
super().__init__(*args, **kwargs)
|
| 39 |
-
|
| 40 |
-
@staticmethod
|
| 41 |
-
def _merged_normalization(processor, field: str) -> tuple[torch.Tensor, torch.Tensor]:
|
| 42 |
-
meta_entries = processor.shape_meta[field]
|
| 43 |
-
scales = []
|
| 44 |
-
offsets = []
|
| 45 |
-
for meta in meta_entries:
|
| 46 |
-
normalizer = processor.normalizer.normalizers[field][meta["key"]]
|
| 47 |
-
scales.append(torch.as_tensor(normalizer.scale, dtype=torch.float32))
|
| 48 |
-
offsets.append(torch.as_tensor(normalizer.offset, dtype=torch.float32))
|
| 49 |
-
return torch.cat(scales, dim=-1), torch.cat(offsets, dim=-1)
|
| 50 |
-
|
| 51 |
-
def _get(self, idx):
|
| 52 |
-
data = super()._get(idx)
|
| 53 |
-
if self.precompute_video_only:
|
| 54 |
-
return data
|
| 55 |
-
if self.eef_anchor_index is None:
|
| 56 |
-
raise RuntimeError("aligned_3dpft EEF projector was not initialized")
|
| 57 |
-
processor = self.lerobot_dataset.processor
|
| 58 |
-
if processor is None:
|
| 59 |
-
raise RuntimeError("aligned_3dpft requires a configured processor")
|
| 60 |
-
|
| 61 |
-
state_scale, state_offset = self._merged_normalization(processor, "state")
|
| 62 |
-
normalized_state = torch.as_tensor(data["proprio"][0], dtype=torch.float32)
|
| 63 |
-
raw_state = (normalized_state[: state_scale.numel()] - state_offset) / state_scale
|
| 64 |
-
if raw_state.numel() < 6:
|
| 65 |
-
raise ValueError("aligned_3dpft requires at least six EEF state dimensions")
|
| 66 |
-
|
| 67 |
-
prefix = DEFAULT_PROMPT.split("{task}", 1)[0]
|
| 68 |
-
prompt = str(data["prompt"])
|
| 69 |
-
if not prompt.startswith(prefix):
|
| 70 |
-
raise ValueError(f"unexpected training prompt format: {prompt!r}")
|
| 71 |
-
task_language = prompt[len(prefix):]
|
| 72 |
-
eef_state = raw_state[:6].numpy().copy()
|
| 73 |
-
if self.aligned_3dpft_eef_noise_std is not None:
|
| 74 |
-
position_std, orientation_std = self.aligned_3dpft_eef_noise_std
|
| 75 |
-
eef_state[:3] += np.random.normal(0.0, position_std, size=3)
|
| 76 |
-
eef_state[3:6] += np.random.normal(0.0, orientation_std, size=3)
|
| 77 |
-
context = build_flow_trajectory_context(
|
| 78 |
-
self.eef_anchor_index.projector,
|
| 79 |
-
task_language,
|
| 80 |
-
eef_state,
|
| 81 |
-
)
|
| 82 |
-
action_scale, action_offset = self._merged_normalization(processor, "action")
|
| 83 |
-
context["action_scale"] = action_scale.numpy()
|
| 84 |
-
context["action_offset"] = action_offset.numpy()
|
| 85 |
-
# Denormalized LIBERO xyz actions are OSC commands, not meters.
|
| 86 |
-
context["action_translation_scale"] = np.float32(LIBERO_OSC_POSITION_SCALE)
|
| 87 |
-
data["aligned_3dpft_context"] = {
|
| 88 |
-
key: torch.as_tensor(np.asarray(value, dtype=np.float32).copy())
|
| 89 |
-
for key, value in context.items()
|
| 90 |
-
}
|
| 91 |
-
return data
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/dataset_utils.py
DELETED
|
@@ -1,109 +0,0 @@
|
|
| 1 |
-
|
| 2 |
-
from typing import Optional
|
| 3 |
-
|
| 4 |
-
import torch
|
| 5 |
-
import torchvision.transforms.functional as transforms_F
|
| 6 |
-
from PIL import Image
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
def obtain_image_size(data: torch.Tensor | Image.Image) -> tuple[int, int]:
|
| 10 |
-
r"""Return spatial size from a PIL image or image/video tensor.
|
| 11 |
-
|
| 12 |
-
Args:
|
| 13 |
-
data (torch.Tensor | Image.Image): Input image or video tensor.
|
| 14 |
-
Returns:
|
| 15 |
-
width (int): Input width.
|
| 16 |
-
height (int): Input height.
|
| 17 |
-
"""
|
| 18 |
-
|
| 19 |
-
if isinstance(data, Image.Image):
|
| 20 |
-
width, height = data.size
|
| 21 |
-
elif isinstance(data, torch.Tensor):
|
| 22 |
-
height, width = data.size()[-2:]
|
| 23 |
-
else:
|
| 24 |
-
raise ValueError("data to random crop should be PIL Image or tensor")
|
| 25 |
-
|
| 26 |
-
return width, height
|
| 27 |
-
|
| 28 |
-
class ResizeSmallestSideAspectPreserving:
|
| 29 |
-
def __init__(self, args: Optional[dict] = None) -> None:
|
| 30 |
-
self.args = args
|
| 31 |
-
|
| 32 |
-
def __call__(self, video: torch.Tensor | Image.Image) -> torch.Tensor | Image.Image:
|
| 33 |
-
r"""Resize while preserving aspect ratio.
|
| 34 |
-
|
| 35 |
-
The output is scaled so both spatial dimensions are at least the
|
| 36 |
-
requested target size.
|
| 37 |
-
|
| 38 |
-
Args:
|
| 39 |
-
video (torch.Tensor | Image.Image): Input image or video tensor.
|
| 40 |
-
Returns:
|
| 41 |
-
torch.Tensor | Image.Image: Resized image or video tensor.
|
| 42 |
-
"""
|
| 43 |
-
|
| 44 |
-
assert self.args is not None, "Please specify args in augmentations"
|
| 45 |
-
|
| 46 |
-
img_w, img_h = self.args["img_w"], self.args["img_h"]
|
| 47 |
-
|
| 48 |
-
orig_w, orig_h = obtain_image_size(video)
|
| 49 |
-
scaling_ratio = max((img_w / orig_w), (img_h / orig_h))
|
| 50 |
-
target_size = (int(scaling_ratio * orig_h + 0.5), int(scaling_ratio * orig_w + 0.5))
|
| 51 |
-
|
| 52 |
-
assert (
|
| 53 |
-
target_size[0] >= img_h and target_size[1] >= img_w
|
| 54 |
-
), f"Resize error. orig {(orig_w, orig_h)} desire {(img_w, img_h)} compute {target_size}"
|
| 55 |
-
|
| 56 |
-
return transforms_F.resize(
|
| 57 |
-
video,
|
| 58 |
-
size=target_size, # type: ignore
|
| 59 |
-
interpolation=self.args.get("interpolation", transforms_F.InterpolationMode.BICUBIC),
|
| 60 |
-
antialias=True,
|
| 61 |
-
)
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
class CenterCrop:
|
| 65 |
-
def __init__(self, args: Optional[dict] = None) -> None:
|
| 66 |
-
self.args = args
|
| 67 |
-
|
| 68 |
-
def __call__(self, video: torch.Tensor | Image.Image) -> torch.Tensor | Image.Image:
|
| 69 |
-
r"""Center crop to the requested spatial size.
|
| 70 |
-
|
| 71 |
-
Args:
|
| 72 |
-
video (torch.Tensor | Image.Image): Input image or video tensor.
|
| 73 |
-
Returns:
|
| 74 |
-
torch.Tensor | Image.Image: Center cropped image or video tensor.
|
| 75 |
-
"""
|
| 76 |
-
assert (
|
| 77 |
-
(self.args is not None) and ("img_w" in self.args) and ("img_h" in self.args)
|
| 78 |
-
), "Please specify size in args"
|
| 79 |
-
|
| 80 |
-
img_w, img_h = self.args["img_w"], self.args["img_h"]
|
| 81 |
-
return transforms_F.center_crop(video, [img_h, img_w])
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
class Normalize:
|
| 85 |
-
def __init__(self, args: Optional[dict] = None) -> None:
|
| 86 |
-
self.args = args
|
| 87 |
-
|
| 88 |
-
def __call__(self, video: torch.Tensor | Image.Image) -> torch.Tensor:
|
| 89 |
-
r"""Convert to tensor if needed and normalize by mean/std.
|
| 90 |
-
|
| 91 |
-
Args:
|
| 92 |
-
video (torch.Tensor | Image.Image): Input image or video tensor.
|
| 93 |
-
Returns:
|
| 94 |
-
torch.Tensor: Normalized image or video tensor.
|
| 95 |
-
"""
|
| 96 |
-
assert self.args is not None, "Please specify args"
|
| 97 |
-
|
| 98 |
-
mean = self.args["mean"]
|
| 99 |
-
std = self.args["std"]
|
| 100 |
-
|
| 101 |
-
if isinstance(video, torch.Tensor):
|
| 102 |
-
data = video.to(dtype=torch.float32)
|
| 103 |
-
if video.dtype == torch.uint8:
|
| 104 |
-
data = data / 255.0
|
| 105 |
-
data = data.to(dtype=torch.get_default_dtype())
|
| 106 |
-
else:
|
| 107 |
-
data = transforms_F.to_tensor(video) # division by 255 is applied in to_tensor()
|
| 108 |
-
|
| 109 |
-
return transforms_F.normalize(tensor=data, mean=mean, std=std)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/eef_anchors.py
DELETED
|
@@ -1,310 +0,0 @@
|
|
| 1 |
-
# Author: Rui Heng Yang
|
| 2 |
-
"""Load-time per-episode EEF anchor resolution.
|
| 3 |
-
|
| 4 |
-
There is no sidecar. Anchors are projected and hold-resolved once per episode at
|
| 5 |
-
dataset initialisation and held in RAM (plan Section 15). Projection costs about
|
| 6 |
-
35 microseconds per frame, so precomputing to disk bought nothing while adding
|
| 7 |
-
stale-artifact and partial-write failure modes.
|
| 8 |
-
|
| 9 |
-
Two traps this module exists to close:
|
| 10 |
-
|
| 11 |
-
* **Episode identity is ``(dataset_index, episode_index)``, not
|
| 12 |
-
``episode_index``.** A ``MultiLeRobotDataset`` concatenates several LeRobot
|
| 13 |
-
directories, each numbering its episodes from zero, so ``episode_index`` alone
|
| 14 |
-
collides across directories and would silently pair one suite's frames with
|
| 15 |
-
another suite's gripper positions.
|
| 16 |
-
* **The anchor must key off the RETURNED sample, not the requested index.**
|
| 17 |
-
Both ``RobotVideoDataset._get()`` and ``__getitem__()`` resample to a random
|
| 18 |
-
global index on padding or on exception, so a lookup by requested ``idx``
|
| 19 |
-
attaches geometry from whichever episode was originally asked for -- with no
|
| 20 |
-
error and no log.
|
| 21 |
-
"""
|
| 22 |
-
|
| 23 |
-
from __future__ import annotations
|
| 24 |
-
|
| 25 |
-
import glob
|
| 26 |
-
import json
|
| 27 |
-
import logging
|
| 28 |
-
import os
|
| 29 |
-
from dataclasses import dataclass, field
|
| 30 |
-
from typing import Any, Mapping, Sequence
|
| 31 |
-
|
| 32 |
-
import numpy as np
|
| 33 |
-
|
| 34 |
-
from fastwam.geometry import (
|
| 35 |
-
CAMERA_ORDER,
|
| 36 |
-
CalibrationTable,
|
| 37 |
-
EEFProjector,
|
| 38 |
-
load_calibration,
|
| 39 |
-
resolve_anchor_series,
|
| 40 |
-
)
|
| 41 |
-
|
| 42 |
-
logger = logging.getLogger(__name__)
|
| 43 |
-
|
| 44 |
-
EEF_POSE_DIMS = 6
|
| 45 |
-
"""``observation.state[0:3]`` is metric position, ``[3:6]`` axis-angle."""
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
@dataclass
|
| 49 |
-
class AnchorResolutionStats:
|
| 50 |
-
"""Substitution accounting, so no substitution is ever silent (Section 19.2)."""
|
| 51 |
-
|
| 52 |
-
episodes: int = 0
|
| 53 |
-
frames: int = 0
|
| 54 |
-
observed_frames: int = 0
|
| 55 |
-
held_offscreen_frames: int = 0
|
| 56 |
-
centre_default_frames: int = 0
|
| 57 |
-
max_consecutive_held: int = 0
|
| 58 |
-
per_camera_observed: dict[str, int] = field(default_factory=dict)
|
| 59 |
-
|
| 60 |
-
def as_dict(self) -> dict[str, Any]:
|
| 61 |
-
return {
|
| 62 |
-
"episodes": self.episodes,
|
| 63 |
-
"frames": self.frames,
|
| 64 |
-
"observed_frames": self.observed_frames,
|
| 65 |
-
"held_offscreen_frames": self.held_offscreen_frames,
|
| 66 |
-
"centre_default_frames": self.centre_default_frames,
|
| 67 |
-
"max_consecutive_held": self.max_consecutive_held,
|
| 68 |
-
"per_camera_observed": dict(self.per_camera_observed),
|
| 69 |
-
}
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
class EpisodeAnchorIndex:
|
| 73 |
-
"""Resolved per-episode anchors for every episode of every dataset dir.
|
| 74 |
-
|
| 75 |
-
Keyed by ``(dataset_index, episode_index)``; ``lookup()`` then indexes the
|
| 76 |
-
episode's series at the sample's own ``frame_index``.
|
| 77 |
-
"""
|
| 78 |
-
|
| 79 |
-
def __init__(
|
| 80 |
-
self,
|
| 81 |
-
*,
|
| 82 |
-
calibration: CalibrationTable,
|
| 83 |
-
projector: EEFProjector,
|
| 84 |
-
anchors: Mapping[tuple[int, int], np.ndarray],
|
| 85 |
-
stats: AnchorResolutionStats,
|
| 86 |
-
) -> None:
|
| 87 |
-
self.calibration = calibration
|
| 88 |
-
self.projector = projector
|
| 89 |
-
self._anchors = dict(anchors)
|
| 90 |
-
self.stats = stats
|
| 91 |
-
|
| 92 |
-
@property
|
| 93 |
-
def calibration_digest(self) -> str:
|
| 94 |
-
"""Content digest of the calibration this index was resolved against."""
|
| 95 |
-
return self.calibration.digest
|
| 96 |
-
|
| 97 |
-
def __len__(self) -> int:
|
| 98 |
-
return len(self._anchors)
|
| 99 |
-
|
| 100 |
-
def lookup(
|
| 101 |
-
self, dataset_index: int, episode_index: int, frame_index: int
|
| 102 |
-
) -> np.ndarray:
|
| 103 |
-
"""Return the ``[2, 2]`` float32 anchor for one frame, as ``(y, x)``.
|
| 104 |
-
|
| 105 |
-
Args:
|
| 106 |
-
dataset_index: Which LeRobot directory the returned sample came from.
|
| 107 |
-
episode_index: Episode index **within that directory**.
|
| 108 |
-
frame_index: Episode-local frame index of the sample's ``t0``.
|
| 109 |
-
|
| 110 |
-
Raises:
|
| 111 |
-
KeyError: If the episode was not resolved at initialisation.
|
| 112 |
-
IndexError: If ``frame_index`` lies outside the episode.
|
| 113 |
-
"""
|
| 114 |
-
key = (int(dataset_index), int(episode_index))
|
| 115 |
-
try:
|
| 116 |
-
series = self._anchors[key]
|
| 117 |
-
except KeyError as err:
|
| 118 |
-
raise KeyError(
|
| 119 |
-
f"no resolved anchors for (dataset_index={dataset_index}, "
|
| 120 |
-
f"episode_index={episode_index}); the anchor index and the "
|
| 121 |
-
"dataset disagree about which episodes exist"
|
| 122 |
-
) from err
|
| 123 |
-
frame = int(frame_index)
|
| 124 |
-
if not 0 <= frame < series.shape[0]:
|
| 125 |
-
raise IndexError(
|
| 126 |
-
f"frame_index {frame} outside episode "
|
| 127 |
-
f"(dataset_index={dataset_index}, episode_index={episode_index}) "
|
| 128 |
-
f"of length {series.shape[0]}"
|
| 129 |
-
)
|
| 130 |
-
return series[frame]
|
| 131 |
-
|
| 132 |
-
# ------------------------------------------------------------------
|
| 133 |
-
# Construction
|
| 134 |
-
# ------------------------------------------------------------------
|
| 135 |
-
|
| 136 |
-
@classmethod
|
| 137 |
-
def build(
|
| 138 |
-
cls,
|
| 139 |
-
dataset_dirs: Sequence[str],
|
| 140 |
-
*,
|
| 141 |
-
calibration_path: str,
|
| 142 |
-
projector: EEFProjector | None = None,
|
| 143 |
-
episode_filter: Mapping[int, Sequence[int]] | None = None,
|
| 144 |
-
) -> "EpisodeAnchorIndex":
|
| 145 |
-
"""Project and hold-resolve every episode of every directory.
|
| 146 |
-
|
| 147 |
-
Args:
|
| 148 |
-
dataset_dirs: LeRobot directories, in the order the dataset stacks
|
| 149 |
-
them -- this ordering defines ``dataset_index``.
|
| 150 |
-
calibration_path: Versioned calibration artifact (Section 15.3).
|
| 151 |
-
projector: Defaults to the training projector (raw 512).
|
| 152 |
-
episode_filter: Optional ``{dataset_index: [episode_index, ...]}``
|
| 153 |
-
restricting work to the episodes actually selected by the split.
|
| 154 |
-
|
| 155 |
-
Raises:
|
| 156 |
-
InvalidProjectionError: If any frame projects to a nonfinite
|
| 157 |
-
coordinate or at/behind the camera plane (Section 19.1
|
| 158 |
-
Decision 1). This is a hard error by design: substituting a
|
| 159 |
-
stale anchor would convert a detectable geometry fault into
|
| 160 |
-
silently wrong training data.
|
| 161 |
-
"""
|
| 162 |
-
calibration = load_calibration(calibration_path)
|
| 163 |
-
if projector is None:
|
| 164 |
-
projector = EEFProjector.for_training(calibration)
|
| 165 |
-
if tuple(projector.camera_order) != CAMERA_ORDER:
|
| 166 |
-
raise ValueError(
|
| 167 |
-
f"camera order is LOCKED to {CAMERA_ORDER}, got "
|
| 168 |
-
f"{tuple(projector.camera_order)}"
|
| 169 |
-
)
|
| 170 |
-
|
| 171 |
-
anchors: dict[tuple[int, int], np.ndarray] = {}
|
| 172 |
-
stats = AnchorResolutionStats(
|
| 173 |
-
per_camera_observed={name: 0 for name in CAMERA_ORDER}
|
| 174 |
-
)
|
| 175 |
-
|
| 176 |
-
for dataset_index, root in enumerate(dataset_dirs):
|
| 177 |
-
wanted = None
|
| 178 |
-
if episode_filter is not None:
|
| 179 |
-
wanted = {int(e) for e in episode_filter.get(dataset_index, ())}
|
| 180 |
-
cls._resolve_one_directory(
|
| 181 |
-
root=root,
|
| 182 |
-
dataset_index=dataset_index,
|
| 183 |
-
projector=projector,
|
| 184 |
-
anchors=anchors,
|
| 185 |
-
stats=stats,
|
| 186 |
-
wanted_episodes=wanted,
|
| 187 |
-
)
|
| 188 |
-
|
| 189 |
-
logger.info(
|
| 190 |
-
"EEF anchors resolved at load time: %d episodes, %d frames, "
|
| 191 |
-
"%d observed, %d held-offscreen, %d centre-default, "
|
| 192 |
-
"longest hold %d frames (calibration %s)",
|
| 193 |
-
stats.episodes,
|
| 194 |
-
stats.frames,
|
| 195 |
-
stats.observed_frames,
|
| 196 |
-
stats.held_offscreen_frames,
|
| 197 |
-
stats.centre_default_frames,
|
| 198 |
-
stats.max_consecutive_held,
|
| 199 |
-
calibration.digest[:12],
|
| 200 |
-
)
|
| 201 |
-
return cls(
|
| 202 |
-
calibration=calibration,
|
| 203 |
-
projector=projector,
|
| 204 |
-
anchors=anchors,
|
| 205 |
-
stats=stats,
|
| 206 |
-
)
|
| 207 |
-
|
| 208 |
-
@staticmethod
|
| 209 |
-
def _episode_task_languages(root: str) -> dict[int, str]:
|
| 210 |
-
"""Map episode index to its task language string.
|
| 211 |
-
|
| 212 |
-
Calibration is joined by **language string**, never ``task_index``:
|
| 213 |
-
the dataset's task ordering differs from the benchmark's, so an
|
| 214 |
-
index join silently selects another task's camera pose (Section 6.1).
|
| 215 |
-
"""
|
| 216 |
-
path = os.path.join(root, "meta", "episodes.jsonl")
|
| 217 |
-
languages: dict[int, str] = {}
|
| 218 |
-
with open(path, "r", encoding="utf-8") as handle:
|
| 219 |
-
for line in handle:
|
| 220 |
-
line = line.strip()
|
| 221 |
-
if not line:
|
| 222 |
-
continue
|
| 223 |
-
record = json.loads(line)
|
| 224 |
-
tasks = record.get("tasks") or []
|
| 225 |
-
if not tasks:
|
| 226 |
-
raise ValueError(
|
| 227 |
-
f"episode {record.get('episode_index')} in {root} has no "
|
| 228 |
-
"task language; calibration cannot be joined"
|
| 229 |
-
)
|
| 230 |
-
languages[int(record["episode_index"])] = str(tasks[0])
|
| 231 |
-
if not languages:
|
| 232 |
-
raise ValueError(f"no episodes found in {path}")
|
| 233 |
-
return languages
|
| 234 |
-
|
| 235 |
-
@classmethod
|
| 236 |
-
def _resolve_one_directory(
|
| 237 |
-
cls,
|
| 238 |
-
*,
|
| 239 |
-
root: str,
|
| 240 |
-
dataset_index: int,
|
| 241 |
-
projector: EEFProjector,
|
| 242 |
-
anchors: dict[tuple[int, int], np.ndarray],
|
| 243 |
-
stats: AnchorResolutionStats,
|
| 244 |
-
wanted_episodes: set[int] | None,
|
| 245 |
-
) -> None:
|
| 246 |
-
import pandas as pd # local: keeps the module importable without pandas
|
| 247 |
-
|
| 248 |
-
languages = cls._episode_task_languages(root)
|
| 249 |
-
files = sorted(
|
| 250 |
-
glob.glob(os.path.join(root, "data", "**", "*.parquet"), recursive=True)
|
| 251 |
-
)
|
| 252 |
-
if not files:
|
| 253 |
-
raise FileNotFoundError(f"no parquet shards under {root}/data")
|
| 254 |
-
|
| 255 |
-
columns = ["episode_index", "frame_index", "observation.state"]
|
| 256 |
-
frames = pd.concat(
|
| 257 |
-
(pd.read_parquet(path, columns=columns) for path in files),
|
| 258 |
-
ignore_index=True,
|
| 259 |
-
)
|
| 260 |
-
|
| 261 |
-
for episode_index, group in frames.groupby("episode_index", sort=True):
|
| 262 |
-
episode_index = int(episode_index)
|
| 263 |
-
if wanted_episodes is not None and episode_index not in wanted_episodes:
|
| 264 |
-
continue
|
| 265 |
-
ordered = group.sort_values("frame_index")
|
| 266 |
-
state = np.stack(
|
| 267 |
-
[np.asarray(row, dtype=np.float64) for row in ordered["observation.state"]]
|
| 268 |
-
)
|
| 269 |
-
if state.ndim != 2 or state.shape[1] < EEF_POSE_DIMS:
|
| 270 |
-
raise ValueError(
|
| 271 |
-
f"observation.state for episode {episode_index} in {root} has "
|
| 272 |
-
f"shape {state.shape}; expected [N, >= {EEF_POSE_DIMS}]"
|
| 273 |
-
)
|
| 274 |
-
|
| 275 |
-
language = languages.get(episode_index)
|
| 276 |
-
if language is None:
|
| 277 |
-
raise KeyError(
|
| 278 |
-
f"episode {episode_index} present in {root}/data but absent "
|
| 279 |
-
"from meta/episodes.jsonl; cannot resolve its task language"
|
| 280 |
-
)
|
| 281 |
-
|
| 282 |
-
projection = projector.project(language, state)
|
| 283 |
-
resolved = np.empty(projection.anchor_token.shape, dtype=np.float32)
|
| 284 |
-
episode_max_hold = 0
|
| 285 |
-
for camera_index, camera_name in enumerate(CAMERA_ORDER):
|
| 286 |
-
series, camera_stats = resolve_anchor_series(
|
| 287 |
-
projection.anchor_token_precise[:, camera_index, :],
|
| 288 |
-
projection.onscreen[:, camera_index],
|
| 289 |
-
)
|
| 290 |
-
resolved[:, camera_index, :] = series.astype(np.float32)
|
| 291 |
-
stats.observed_frames += int(camera_stats.get("observed_frames", 0))
|
| 292 |
-
stats.held_offscreen_frames += int(
|
| 293 |
-
camera_stats.get("held_offscreen_frames", 0)
|
| 294 |
-
)
|
| 295 |
-
stats.centre_default_frames += int(
|
| 296 |
-
camera_stats.get("centre_default_frames", 0)
|
| 297 |
-
)
|
| 298 |
-
stats.per_camera_observed[camera_name] += int(
|
| 299 |
-
camera_stats.get("observed_frames", 0)
|
| 300 |
-
)
|
| 301 |
-
episode_max_hold = max(
|
| 302 |
-
episode_max_hold, int(camera_stats.get("max_consecutive_held", 0))
|
| 303 |
-
)
|
| 304 |
-
|
| 305 |
-
anchors[(dataset_index, episode_index)] = resolved
|
| 306 |
-
stats.episodes += 1
|
| 307 |
-
stats.frames += int(state.shape[0])
|
| 308 |
-
stats.max_consecutive_held = max(
|
| 309 |
-
stats.max_consecutive_held, episode_max_hold
|
| 310 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/base_lerobot_dataset.py
DELETED
|
@@ -1,517 +0,0 @@
|
|
| 1 |
-
# Author: Rui Heng Yang
|
| 2 |
-
|
| 3 |
-
import json
|
| 4 |
-
import torch
|
| 5 |
-
import numpy as np
|
| 6 |
-
from pathlib import Path
|
| 7 |
-
from typing import List, Literal, Dict, Optional, Any, DefaultDict, Sequence
|
| 8 |
-
from tqdm import tqdm
|
| 9 |
-
from .lerobot.lerobot_dataset import (
|
| 10 |
-
LeRobotDatasetMetadata,
|
| 11 |
-
MultiLeRobotDataset,
|
| 12 |
-
dataset_dir_to_repo_id,
|
| 13 |
-
)
|
| 14 |
-
|
| 15 |
-
from concurrent.futures import ThreadPoolExecutor, as_completed
|
| 16 |
-
import traceback
|
| 17 |
-
from fastwam.utils.logging_config import get_logger
|
| 18 |
-
from .processors.base_processor import BaseProcessor
|
| 19 |
-
|
| 20 |
-
logger = get_logger(__name__)
|
| 21 |
-
|
| 22 |
-
MAX_GETITEM_ATTEMPT = 5
|
| 23 |
-
|
| 24 |
-
class BaseLerobotDataset(torch.utils.data.Dataset):
|
| 25 |
-
def __init__(
|
| 26 |
-
self,
|
| 27 |
-
dataset_dirs: List[str],
|
| 28 |
-
|
| 29 |
-
# shapes
|
| 30 |
-
shape_meta: Dict[str, Any],
|
| 31 |
-
action_size: int = 1,
|
| 32 |
-
past_action_size: int = 0, # Excludes the current frame
|
| 33 |
-
obs_size: int = 1, # should be
|
| 34 |
-
past_obs_size: int = 0,
|
| 35 |
-
|
| 36 |
-
# train vs val
|
| 37 |
-
val_set_proportion: float = 0.05,
|
| 38 |
-
is_training_set: bool = False,
|
| 39 |
-
seed: int = 42,
|
| 40 |
-
episode_indices: Optional[Sequence[int]] = None,
|
| 41 |
-
episode_indices_path: Optional[str] = None,
|
| 42 |
-
episode_indices_key: Optional[str] = None,
|
| 43 |
-
|
| 44 |
-
# sampling
|
| 45 |
-
global_sample_stride: int = 1,
|
| 46 |
-
video_backend: Optional[str] = None,
|
| 47 |
-
strict_getitem: bool = False,
|
| 48 |
-
image_only: bool = False,
|
| 49 |
-
image_sample_indices: Optional[Sequence[int]] = None,
|
| 50 |
-
):
|
| 51 |
-
assert len(dataset_dirs) > 0, "At least one dataset directory is required"
|
| 52 |
-
assert past_action_size == 0
|
| 53 |
-
assert past_obs_size == 0
|
| 54 |
-
assert action_size == obs_size - 1, "In this dataset, action_size should be obs_size - 1"
|
| 55 |
-
|
| 56 |
-
self.dataset_dirs = dataset_dirs
|
| 57 |
-
self.shape_meta = shape_meta
|
| 58 |
-
self.action_size = action_size
|
| 59 |
-
self.past_action_size = past_action_size
|
| 60 |
-
self.obs_size = obs_size
|
| 61 |
-
self.processor = None # Will be set externally
|
| 62 |
-
self.return_images = True
|
| 63 |
-
self.strict_getitem = bool(strict_getitem)
|
| 64 |
-
self.image_only = bool(image_only)
|
| 65 |
-
self.image_sample_indices = (
|
| 66 |
-
None
|
| 67 |
-
if image_sample_indices is None
|
| 68 |
-
else [int(index) for index in image_sample_indices]
|
| 69 |
-
)
|
| 70 |
-
if self.image_only and not self.image_sample_indices:
|
| 71 |
-
raise ValueError("image_only mode requires nonempty image_sample_indices.")
|
| 72 |
-
metas = []
|
| 73 |
-
for ds_dir in dataset_dirs:
|
| 74 |
-
ds_root = Path(ds_dir)
|
| 75 |
-
repo_id = dataset_dir_to_repo_id(ds_dir)
|
| 76 |
-
meta = LeRobotDatasetMetadata(repo_id=repo_id, root=ds_root)
|
| 77 |
-
metas.append(meta)
|
| 78 |
-
|
| 79 |
-
fps_list = [m.fps for m in metas]
|
| 80 |
-
assert len(set(fps_list)) == 1, f"All dataset_dirs must have the same fps, got {fps_list}"
|
| 81 |
-
fps = fps_list[0]
|
| 82 |
-
|
| 83 |
-
self.global_sample_stride = global_sample_stride
|
| 84 |
-
|
| 85 |
-
self.val_set_proportion = val_set_proportion
|
| 86 |
-
self.is_training_set = is_training_set
|
| 87 |
-
self.episode_indices = self._load_episode_indices(
|
| 88 |
-
episode_indices=episode_indices,
|
| 89 |
-
episode_indices_path=episode_indices_path,
|
| 90 |
-
episode_indices_key=episode_indices_key,
|
| 91 |
-
)
|
| 92 |
-
|
| 93 |
-
self.image_meta = shape_meta["images"]
|
| 94 |
-
self.state_meta = shape_meta["state"]
|
| 95 |
-
self.action_meta = shape_meta["action"]
|
| 96 |
-
|
| 97 |
-
delta_timestamps = {}
|
| 98 |
-
image_offsets = (
|
| 99 |
-
range(-past_obs_size, -past_obs_size + obs_size)
|
| 100 |
-
if self.image_sample_indices is None
|
| 101 |
-
else self.image_sample_indices
|
| 102 |
-
)
|
| 103 |
-
for meta in self.image_meta:
|
| 104 |
-
key = meta["key"]
|
| 105 |
-
meta["lerobot_key"] = f"observation.images.{key}" if key != "default" else "observation.images"
|
| 106 |
-
delta_timestamps[meta["lerobot_key"]] = [
|
| 107 |
-
(t * global_sample_stride) / fps for t in image_offsets
|
| 108 |
-
]
|
| 109 |
-
|
| 110 |
-
for meta in self.state_meta:
|
| 111 |
-
key = meta["key"]
|
| 112 |
-
meta["lerobot_key"] = f"observation.state.{key}" if key != "default" else "observation.state"
|
| 113 |
-
if not self.image_only:
|
| 114 |
-
delta_timestamps[meta["lerobot_key"]] = [
|
| 115 |
-
(t * global_sample_stride) / fps for t in range(-past_obs_size, -past_obs_size + obs_size)
|
| 116 |
-
]
|
| 117 |
-
|
| 118 |
-
for meta in self.action_meta:
|
| 119 |
-
key = meta["key"]
|
| 120 |
-
meta["lerobot_key"] = f"action.{key}" if key != "default" else "action"
|
| 121 |
-
if not self.image_only:
|
| 122 |
-
delta_timestamps[meta["lerobot_key"]] = [(t * global_sample_stride) / fps for t in range(-past_action_size, -past_action_size + action_size)]
|
| 123 |
-
|
| 124 |
-
episodes = {}
|
| 125 |
-
if self.episode_indices is not None:
|
| 126 |
-
requested = sorted(set(int(i) for i in self.episode_indices))
|
| 127 |
-
for meta in metas:
|
| 128 |
-
available = set(meta.episodes.keys())
|
| 129 |
-
valid = [i for i in requested if i in available]
|
| 130 |
-
missing = len(requested) - len(valid)
|
| 131 |
-
if missing:
|
| 132 |
-
logger.warning(
|
| 133 |
-
"Ignoring %d episode indices not present in %s",
|
| 134 |
-
missing,
|
| 135 |
-
meta.repo_id,
|
| 136 |
-
)
|
| 137 |
-
episodes.update({meta.repo_id: valid})
|
| 138 |
-
elif val_set_proportion < 1e-6:
|
| 139 |
-
for meta in metas:
|
| 140 |
-
episodes.update({meta.repo_id: sorted(meta.episodes.keys())})
|
| 141 |
-
else:
|
| 142 |
-
for meta in metas:
|
| 143 |
-
split_idx = int(meta.total_episodes * (1 - val_set_proportion))
|
| 144 |
-
# random shuffle episode indices before splitting
|
| 145 |
-
episode_indices = sorted(meta.episodes.keys())
|
| 146 |
-
rng = np.random.default_rng(seed)
|
| 147 |
-
rng.shuffle(episode_indices)
|
| 148 |
-
if self.is_training_set:
|
| 149 |
-
episodes.update({meta.repo_id: [episode_indices[i] for i in range(split_idx)]})
|
| 150 |
-
else:
|
| 151 |
-
episodes.update({meta.repo_id: [episode_indices[i] for i in range(split_idx, meta.total_episodes)]})
|
| 152 |
-
|
| 153 |
-
self.multi_dataset = MultiLeRobotDataset(
|
| 154 |
-
dataset_dirs=self.dataset_dirs,
|
| 155 |
-
episodes=episodes,
|
| 156 |
-
delta_timestamps=delta_timestamps,
|
| 157 |
-
video_backend=video_backend,
|
| 158 |
-
)
|
| 159 |
-
|
| 160 |
-
# HACK: lerobot 3.0 will fix this
|
| 161 |
-
episode_data_index = []
|
| 162 |
-
end_index = 0
|
| 163 |
-
for dataset in self.multi_dataset._datasets:
|
| 164 |
-
multi_episode_data_index = {
|
| 165 |
-
"from": dataset.episode_data_index["from"] + end_index,
|
| 166 |
-
"to": dataset.episode_data_index["to"] + end_index,
|
| 167 |
-
}
|
| 168 |
-
episode_data_index.append(multi_episode_data_index)
|
| 169 |
-
end_index = multi_episode_data_index["to"][-1]
|
| 170 |
-
|
| 171 |
-
self.episode_data_index = {
|
| 172 |
-
"from": torch.cat([dataset["from"] for dataset in episode_data_index]),
|
| 173 |
-
"to": torch.cat([dataset["to"] for dataset in episode_data_index]),
|
| 174 |
-
}
|
| 175 |
-
|
| 176 |
-
@staticmethod
|
| 177 |
-
def _load_episode_indices(
|
| 178 |
-
*,
|
| 179 |
-
episode_indices: Optional[Sequence[int]],
|
| 180 |
-
episode_indices_path: Optional[str],
|
| 181 |
-
episode_indices_key: Optional[str],
|
| 182 |
-
) -> Optional[list[int]]:
|
| 183 |
-
if episode_indices is not None and episode_indices_path is not None:
|
| 184 |
-
raise ValueError("Only one of `episode_indices` and `episode_indices_path` can be set.")
|
| 185 |
-
if episode_indices is not None:
|
| 186 |
-
return [int(i) for i in episode_indices]
|
| 187 |
-
if episode_indices_path is None:
|
| 188 |
-
return None
|
| 189 |
-
|
| 190 |
-
path = Path(episode_indices_path)
|
| 191 |
-
with path.open("r", encoding="utf-8") as f:
|
| 192 |
-
payload = json.load(f)
|
| 193 |
-
if episode_indices_key is not None:
|
| 194 |
-
if episode_indices_key not in payload:
|
| 195 |
-
raise KeyError(f"`{episode_indices_key}` not found in episode split file: {path}")
|
| 196 |
-
payload = payload[episode_indices_key]
|
| 197 |
-
if isinstance(payload, dict) and "episodes" in payload:
|
| 198 |
-
payload = payload["episodes"]
|
| 199 |
-
if not isinstance(payload, list):
|
| 200 |
-
raise ValueError(
|
| 201 |
-
f"Episode split in {path} must be a list, or a dict containing an `episodes` list."
|
| 202 |
-
)
|
| 203 |
-
return [int(i) for i in payload]
|
| 204 |
-
|
| 205 |
-
def _get_action(self, meta, lerobot_sample) -> torch.Tensor:
|
| 206 |
-
key, lerobot_key, raw_shape = meta["key"], meta["lerobot_key"], meta["raw_shape"]
|
| 207 |
-
action: torch.Tensor = lerobot_sample[lerobot_key] # [T, action_dim]
|
| 208 |
-
if action.ndim == 1: # for shape of 1, like gripper
|
| 209 |
-
action = action.unsqueeze(-1)
|
| 210 |
-
assert action.shape[-1] == raw_shape, f"Action '{key}' shape {action.shape[-1]} mismatch with meta {raw_shape}."
|
| 211 |
-
return action
|
| 212 |
-
|
| 213 |
-
def _get_state(self, meta, lerobot_sample) -> torch.Tensor:
|
| 214 |
-
key, lerobot_key, raw_shape = meta["key"], meta["lerobot_key"], meta["raw_shape"]
|
| 215 |
-
state: torch.Tensor = lerobot_sample[lerobot_key]
|
| 216 |
-
if state.ndim == 1: # for shape of 1, like gripper
|
| 217 |
-
state = state.unsqueeze(-1)
|
| 218 |
-
# state = state[..., :-1, :] # use state_{t} as observation_t
|
| 219 |
-
assert state.shape[-1] == raw_shape, f"State '{key}' shape {state.shape[-1]} mismatch with meta {raw_shape}."
|
| 220 |
-
return state
|
| 221 |
-
|
| 222 |
-
def _get_image(self, meta, lerobot_sample) -> torch.Tensor:
|
| 223 |
-
key, lerobot_key, raw_shape = meta["key"], meta["lerobot_key"], meta["raw_shape"]
|
| 224 |
-
image: torch.Tensor = lerobot_sample[lerobot_key]
|
| 225 |
-
if image.ndim == 3: # time dim will lost when obs_size is 1
|
| 226 |
-
image = image.unsqueeze(0)
|
| 227 |
-
image = (image * 255).to(torch.uint8) # (1, 3, H, W)
|
| 228 |
-
# For config simplication
|
| 229 |
-
# assert image.shape[1:] == raw_shape, f"Image '{key}' shape {image.shape[1:]} mismatch with {raw_shape}."
|
| 230 |
-
return image
|
| 231 |
-
|
| 232 |
-
def _split_lerobot_sample(self, lerobot_sample) -> Dict[str, Any]:
|
| 233 |
-
return lerobot_sample
|
| 234 |
-
|
| 235 |
-
def _get_episode_data(self, episode_idx):
|
| 236 |
-
lerobot_sample = self.multi_dataset.get_episode_data(episode_idx)
|
| 237 |
-
lerobot_sample = self._split_lerobot_sample(lerobot_sample)
|
| 238 |
-
state, action = {}, {}
|
| 239 |
-
for meta in self.state_meta:
|
| 240 |
-
s = self._get_state(meta, lerobot_sample)
|
| 241 |
-
state[meta["key"]] = s.unsqueeze(1).float()
|
| 242 |
-
for meta in self.action_meta:
|
| 243 |
-
a = self._get_action(meta, lerobot_sample)
|
| 244 |
-
a = sliding_window_with_replication(a, self.action_size)
|
| 245 |
-
action[meta["key"]] = a.float()
|
| 246 |
-
return {"action": action, "state": state}
|
| 247 |
-
|
| 248 |
-
def _set_return_images(self, flag: bool):
|
| 249 |
-
self.return_images = flag
|
| 250 |
-
self.multi_dataset.set_during_training(flag)
|
| 251 |
-
|
| 252 |
-
def __len__(self):
|
| 253 |
-
return self.multi_dataset.num_frames
|
| 254 |
-
|
| 255 |
-
def _get_additional_data(self, sample, lerobot_sample):
|
| 256 |
-
return sample
|
| 257 |
-
|
| 258 |
-
def __getitem__(self, idx):
|
| 259 |
-
if idx >= len(self):
|
| 260 |
-
raise IndexError(f"Index {idx} out of bounds {len(self)}.")
|
| 261 |
-
|
| 262 |
-
# Cache construction and cache-backed training require index identity:
|
| 263 |
-
# a requested global index must never silently resolve to another
|
| 264 |
-
# sample. Other existing datasets retain the historical retry behavior.
|
| 265 |
-
sample_idx = idx
|
| 266 |
-
attempt = 0
|
| 267 |
-
last_exception: Optional[Exception] = None
|
| 268 |
-
strict_getitem = bool(getattr(self, "strict_getitem", False))
|
| 269 |
-
max_attempts = 1 if strict_getitem else MAX_GETITEM_ATTEMPT
|
| 270 |
-
while attempt < max_attempts:
|
| 271 |
-
try:
|
| 272 |
-
lerobot_sample = self.multi_dataset[sample_idx]
|
| 273 |
-
lerobot_sample = self._split_lerobot_sample(lerobot_sample)
|
| 274 |
-
break
|
| 275 |
-
except Exception as err:
|
| 276 |
-
attempt += 1
|
| 277 |
-
last_exception = err
|
| 278 |
-
if strict_getitem:
|
| 279 |
-
raise RuntimeError(f"Strict sample load failed for index {idx}.") from err
|
| 280 |
-
logger.warning(
|
| 281 |
-
f"Error loading sample {sample_idx} (attempt {attempt}). "
|
| 282 |
-
"Retrying with a random index. "
|
| 283 |
-
f"Error: {err}"
|
| 284 |
-
)
|
| 285 |
-
sample_idx = np.random.randint(len(self))
|
| 286 |
-
print(traceback.format_exc())
|
| 287 |
-
else:
|
| 288 |
-
raise RuntimeError(
|
| 289 |
-
f"Failed to load a valid sample after {MAX_GETITEM_ATTEMPT} attempts "
|
| 290 |
-
f"for index {idx}."
|
| 291 |
-
) from last_exception
|
| 292 |
-
|
| 293 |
-
# Get data from lerobot, organized in nested dict
|
| 294 |
-
sample = {
|
| 295 |
-
"idx": sample_idx,
|
| 296 |
-
"task": lerobot_sample["task"],
|
| 297 |
-
"action": {},
|
| 298 |
-
"state": {},
|
| 299 |
-
"images": {},
|
| 300 |
-
}
|
| 301 |
-
image_only = bool(getattr(self, "image_only", False))
|
| 302 |
-
if not image_only:
|
| 303 |
-
for meta in self.state_meta:
|
| 304 |
-
sample["state"][meta["key"]] = self._get_state(meta, lerobot_sample)
|
| 305 |
-
|
| 306 |
-
for meta in self.action_meta:
|
| 307 |
-
sample["action"][meta["key"]] = self._get_action(meta, lerobot_sample)
|
| 308 |
-
|
| 309 |
-
if bool(getattr(self, "return_images", True)):
|
| 310 |
-
for meta in self.image_meta:
|
| 311 |
-
sample["images"][meta["key"]] = self._get_image(meta, lerobot_sample)
|
| 312 |
-
|
| 313 |
-
sample["image_is_pad"] = lerobot_sample[f"{self.image_meta[0]['lerobot_key']}_is_pad"]
|
| 314 |
-
if not image_only:
|
| 315 |
-
sample["action_is_pad"] = lerobot_sample[f"{self.action_meta[0]['lerobot_key']}_is_pad"]
|
| 316 |
-
sample["state_is_pad"] = lerobot_sample[f"{self.state_meta[0]['lerobot_key']}_is_pad"]
|
| 317 |
-
|
| 318 |
-
sample = self._get_additional_data(sample, lerobot_sample)
|
| 319 |
-
|
| 320 |
-
for key in lerobot_sample:
|
| 321 |
-
if key not in sample and "observation" not in key and "action" not in key:
|
| 322 |
-
sample[key] = lerobot_sample[key]
|
| 323 |
-
|
| 324 |
-
# Preprocess the sample using the processor
|
| 325 |
-
# for quick data loading
|
| 326 |
-
if self.processor is not None:
|
| 327 |
-
if image_only:
|
| 328 |
-
pixel_values = self.processor.preprocess_images(
|
| 329 |
-
sample["images"],
|
| 330 |
-
expected_num_obs_steps=len(self.image_sample_indices),
|
| 331 |
-
)
|
| 332 |
-
sample = {
|
| 333 |
-
"idx": sample["idx"],
|
| 334 |
-
"pixel_values": pixel_values,
|
| 335 |
-
"image_is_pad": sample["image_is_pad"],
|
| 336 |
-
**{
|
| 337 |
-
key: sample[key]
|
| 338 |
-
for key in ("dataset_index", "episode_index", "frame_index")
|
| 339 |
-
if key in sample
|
| 340 |
-
},
|
| 341 |
-
}
|
| 342 |
-
else:
|
| 343 |
-
sample = self.processor.preprocess(sample)
|
| 344 |
-
|
| 345 |
-
return sample
|
| 346 |
-
|
| 347 |
-
def set_processor(self, processor: BaseProcessor):
|
| 348 |
-
"""Set processor instance from external initialization."""
|
| 349 |
-
self.processor = processor
|
| 350 |
-
if self.is_training_set:
|
| 351 |
-
self.processor.train()
|
| 352 |
-
else:
|
| 353 |
-
self.processor.eval()
|
| 354 |
-
return self
|
| 355 |
-
|
| 356 |
-
def get_dataset_stats(self, preprocessor: BaseProcessor):
|
| 357 |
-
state_min = DefaultDict(list)
|
| 358 |
-
state_max = DefaultDict(list)
|
| 359 |
-
state_mean = DefaultDict(list)
|
| 360 |
-
state_var = DefaultDict(list)
|
| 361 |
-
state_q01 = DefaultDict(list)
|
| 362 |
-
state_q99 = DefaultDict(list)
|
| 363 |
-
|
| 364 |
-
action_min = DefaultDict(list)
|
| 365 |
-
action_max = DefaultDict(list)
|
| 366 |
-
action_mean = DefaultDict(list)
|
| 367 |
-
action_var = DefaultDict(list)
|
| 368 |
-
action_q01 = DefaultDict(list)
|
| 369 |
-
action_q99 = DefaultDict(list)
|
| 370 |
-
|
| 371 |
-
episodes_num = self.multi_dataset.num_episodes
|
| 372 |
-
|
| 373 |
-
def process_episode(episode_idx):
|
| 374 |
-
batch = self._get_episode_data(episode_idx)
|
| 375 |
-
batch = preprocessor.action_state_transform(batch)
|
| 376 |
-
return batch
|
| 377 |
-
|
| 378 |
-
multi_thread = True
|
| 379 |
-
if not multi_thread:
|
| 380 |
-
for episode_idx in tqdm(range(episodes_num), desc="Iterating dataset to get normalization"):
|
| 381 |
-
batch = process_episode(episode_idx)
|
| 382 |
-
for meta in self.state_meta:
|
| 383 |
-
key = meta["key"]
|
| 384 |
-
cur_state: torch.Tensor = batch["state"][key] # (B, T, dim)
|
| 385 |
-
state_min[key].append(cur_state.amin(0))
|
| 386 |
-
state_max[key].append(cur_state.amax(0))
|
| 387 |
-
state_mean[key].append(cur_state.mean(0))
|
| 388 |
-
state_var[key].append(cur_state.var(0))
|
| 389 |
-
state_q01[key].append(torch.quantile(cur_state, 0.01, dim=0, keepdim=False))
|
| 390 |
-
state_q99[key].append(torch.quantile(cur_state, 0.99, dim=0, keepdim=False))
|
| 391 |
-
for meta in self.action_meta:
|
| 392 |
-
key = meta["key"]
|
| 393 |
-
cur_action: torch.Tensor = batch["action"][key] # (B, T, dim)
|
| 394 |
-
action_min[key].append(cur_action.amin(0))
|
| 395 |
-
action_max[key].append(cur_action.amax(0))
|
| 396 |
-
action_mean[key].append(cur_action.mean(0))
|
| 397 |
-
action_var[key].append(cur_action.var(0))
|
| 398 |
-
action_q01[key].append(torch.quantile(cur_action, 0.01, dim=0, keepdim=False))
|
| 399 |
-
action_q99[key].append(torch.quantile(cur_action, 0.99, dim=0, keepdim=False))
|
| 400 |
-
|
| 401 |
-
else:
|
| 402 |
-
with ThreadPoolExecutor() as executor:
|
| 403 |
-
futures = [executor.submit(process_episode, num) for num in range(episodes_num)]
|
| 404 |
-
|
| 405 |
-
for future in tqdm(as_completed(futures), total=episodes_num, desc="Iterating dataset to get normalization"):
|
| 406 |
-
try:
|
| 407 |
-
batch = future.result()
|
| 408 |
-
for meta in self.state_meta:
|
| 409 |
-
key = meta["key"]
|
| 410 |
-
cur_state: torch.Tensor = batch["state"][key] # (B, T, dim)
|
| 411 |
-
state_min[key].append(cur_state.amin(0))
|
| 412 |
-
state_max[key].append(cur_state.amax(0))
|
| 413 |
-
state_mean[key].append(cur_state.mean(0))
|
| 414 |
-
state_var[key].append(cur_state.var(0))
|
| 415 |
-
state_q01[key].append(torch.quantile(cur_state, 0.01, dim=0, keepdim=False))
|
| 416 |
-
state_q99[key].append(torch.quantile(cur_state, 0.99, dim=0, keepdim=False))
|
| 417 |
-
|
| 418 |
-
for meta in self.action_meta:
|
| 419 |
-
key = meta["key"]
|
| 420 |
-
cur_action: torch.Tensor = batch["action"][key] # (B, T, dim)
|
| 421 |
-
action_min[key].append(cur_action.amin(0))
|
| 422 |
-
action_max[key].append(cur_action.amax(0))
|
| 423 |
-
action_mean[key].append(cur_action.mean(0))
|
| 424 |
-
action_var[key].append(cur_action.var(0))
|
| 425 |
-
action_q01[key].append(torch.quantile(cur_action, 0.01, dim=0, keepdim=False))
|
| 426 |
-
action_q99[key].append(torch.quantile(cur_action, 0.99, dim=0, keepdim=False))
|
| 427 |
-
|
| 428 |
-
except Exception as e:
|
| 429 |
-
logger.error(f"Error processing episode: {e}")
|
| 430 |
-
print(traceback.format_exc())
|
| 431 |
-
raise e
|
| 432 |
-
|
| 433 |
-
# assume that each minibatch has equal number of samples
|
| 434 |
-
def get_mean_std(means, vars):
|
| 435 |
-
means = torch.stack(means)
|
| 436 |
-
vars = torch.stack(vars)
|
| 437 |
-
stepwise_mean = means.mean(0)
|
| 438 |
-
stepwise_std = (vars + (means - stepwise_mean) ** 2).mean(0).sqrt()
|
| 439 |
-
global_mean = means.mean((0, 1))
|
| 440 |
-
global_std = (vars + (means - global_mean) ** 2).mean((0, 1)).sqrt()
|
| 441 |
-
return stepwise_mean, stepwise_std, global_mean, global_std
|
| 442 |
-
|
| 443 |
-
stats = {"state": DefaultDict(dict), "action": DefaultDict(dict), "num_episodes": episodes_num, "num_transition": self.multi_dataset.num_frames}
|
| 444 |
-
for meta in self.state_meta:
|
| 445 |
-
key = meta["key"]
|
| 446 |
-
stats["state"][key]["stepwise_min"] = torch.stack(state_min[key]).amin(0)
|
| 447 |
-
stats["state"][key]["stepwise_max"] = torch.stack(state_max[key]).amax(0)
|
| 448 |
-
stats["state"][key]["global_min"] = stats["state"][key]["stepwise_min"].amin(0)
|
| 449 |
-
stats["state"][key]["global_max"] = stats["state"][key]["stepwise_max"].amax(0)
|
| 450 |
-
stats["state"][key]["stepwise_q01"] = torch.stack(state_q01[key]).amin(0)
|
| 451 |
-
stats["state"][key]["stepwise_q99"] = torch.stack(state_q99[key]).amax(0)
|
| 452 |
-
stats["state"][key]["global_q01"] = stats["state"][key]["stepwise_q01"].amin(0)
|
| 453 |
-
stats["state"][key]["global_q99"] = stats["state"][key]["stepwise_q99"].amax(0)
|
| 454 |
-
(
|
| 455 |
-
stats["state"][key]["stepwise_mean"],
|
| 456 |
-
stats["state"][key]["stepwise_std"],
|
| 457 |
-
stats["state"][key]["global_mean"],
|
| 458 |
-
stats["state"][key]["global_std"],
|
| 459 |
-
) = get_mean_std(state_mean[key], state_var[key])
|
| 460 |
-
|
| 461 |
-
for meta in self.action_meta:
|
| 462 |
-
key = meta["key"]
|
| 463 |
-
stats["action"][key]["stepwise_min"] = torch.stack(action_min[key]).amin(0)
|
| 464 |
-
stats["action"][key]["stepwise_max"] = torch.stack(action_max[key]).amax(0)
|
| 465 |
-
stats["action"][key]["global_min"] = stats["action"][key]["stepwise_min"].amin(0)
|
| 466 |
-
stats["action"][key]["global_max"] = stats["action"][key]["stepwise_max"].amax(0)
|
| 467 |
-
stats["action"][key]["stepwise_q01"] = torch.stack(action_q01[key]).amin(0)
|
| 468 |
-
stats["action"][key]["stepwise_q99"] = torch.stack(action_q99[key]).amax(0)
|
| 469 |
-
stats["action"][key]["global_q01"] = stats["action"][key]["stepwise_q01"].amin(0)
|
| 470 |
-
stats["action"][key]["global_q99"] = stats["action"][key]["stepwise_q99"].amax(0)
|
| 471 |
-
(
|
| 472 |
-
stats["action"][key]["stepwise_mean"],
|
| 473 |
-
stats["action"][key]["stepwise_std"],
|
| 474 |
-
stats["action"][key]["global_mean"],
|
| 475 |
-
stats["action"][key]["global_std"],
|
| 476 |
-
) = get_mean_std(action_mean[key], action_var[key])
|
| 477 |
-
|
| 478 |
-
return stats
|
| 479 |
-
|
| 480 |
-
|
| 481 |
-
def sliding_window_with_replication(x: torch.Tensor, window_size: int) -> torch.Tensor:
|
| 482 |
-
"""
|
| 483 |
-
Construct a sliding-window tensor from the input tensor x (shape: [N, D]).
|
| 484 |
-
The output shape is [N, window_size, D].
|
| 485 |
-
|
| 486 |
-
For each starting index i:
|
| 487 |
-
out[i, j, :] =
|
| 488 |
-
x[i + j, :] if i + j < N
|
| 489 |
-
x[-1, :] otherwise (replicate the last row when out of bounds)
|
| 490 |
-
|
| 491 |
-
Args:
|
| 492 |
-
x (torch.Tensor): Input tensor of shape [N, D]
|
| 493 |
-
window_size (int): Size of the sliding window
|
| 494 |
-
|
| 495 |
-
Returns:
|
| 496 |
-
torch.Tensor: Tensor of shape [N, window_size, D]
|
| 497 |
-
"""
|
| 498 |
-
assert x.dim() == 2
|
| 499 |
-
assert window_size > 0
|
| 500 |
-
|
| 501 |
-
N, D = x.shape
|
| 502 |
-
|
| 503 |
-
# shape [N, window_size]
|
| 504 |
-
# indices[i, j] = i + j
|
| 505 |
-
i_indices = torch.arange(N).unsqueeze(1) # [N, 1]
|
| 506 |
-
j_indices = torch.arange(window_size).unsqueeze(0) # [1, window_size]
|
| 507 |
-
indices = i_indices + j_indices # [N, window_size]
|
| 508 |
-
|
| 509 |
-
# N-1
|
| 510 |
-
# torch.clamp [0, N-1]
|
| 511 |
-
clamped_indices = torch.clamp(indices, min=0, max=N - 1)
|
| 512 |
-
|
| 513 |
-
# clamped_indices [N, window_size],x [N, D]
|
| 514 |
-
# out[i, j, :] = x[clamped_indices[i, j], :]
|
| 515 |
-
out = x[clamped_indices] # [N, window_size, D]
|
| 516 |
-
|
| 517 |
-
return out
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/constants.py
DELETED
|
@@ -1,54 +0,0 @@
|
|
| 1 |
-
# Copyright 2024 The HuggingFace Inc. team. All rights reserved.
|
| 2 |
-
#
|
| 3 |
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
-
# you may not use this file except in compliance with the License.
|
| 5 |
-
# You may obtain a copy of the License at
|
| 6 |
-
#
|
| 7 |
-
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
-
#
|
| 9 |
-
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
-
# See the License for the specific language governing permissions and
|
| 13 |
-
# limitations under the License.
|
| 14 |
-
# keys
|
| 15 |
-
import os
|
| 16 |
-
from pathlib import Path
|
| 17 |
-
|
| 18 |
-
from huggingface_hub.constants import HF_HOME
|
| 19 |
-
|
| 20 |
-
OBS_ENV_STATE = "observation.environment_state"
|
| 21 |
-
OBS_STATE = "observation.state"
|
| 22 |
-
OBS_IMAGE = "observation.image"
|
| 23 |
-
OBS_IMAGES = "observation.images"
|
| 24 |
-
ACTION = "action"
|
| 25 |
-
REWARD = "next.reward"
|
| 26 |
-
|
| 27 |
-
ROBOTS = "robots"
|
| 28 |
-
ROBOT_TYPE = "robot_type"
|
| 29 |
-
TELEOPERATORS = "teleoperators"
|
| 30 |
-
|
| 31 |
-
# files & directories
|
| 32 |
-
CHECKPOINTS_DIR = "checkpoints"
|
| 33 |
-
LAST_CHECKPOINT_LINK = "last"
|
| 34 |
-
PRETRAINED_MODEL_DIR = "pretrained_model"
|
| 35 |
-
TRAINING_STATE_DIR = "training_state"
|
| 36 |
-
RNG_STATE = "rng_state.safetensors"
|
| 37 |
-
TRAINING_STEP = "training_step.json"
|
| 38 |
-
OPTIMIZER_STATE = "optimizer_state.safetensors"
|
| 39 |
-
OPTIMIZER_PARAM_GROUPS = "optimizer_param_groups.json"
|
| 40 |
-
SCHEDULER_STATE = "scheduler_state.json"
|
| 41 |
-
|
| 42 |
-
if "LEROBOT_HOME" in os.environ:
|
| 43 |
-
raise ValueError(
|
| 44 |
-
f"You have a 'LEROBOT_HOME' environment variable set to '{os.getenv('LEROBOT_HOME')}'.\n"
|
| 45 |
-
"'LEROBOT_HOME' is deprecated, please use 'HF_LEROBOT_HOME' instead."
|
| 46 |
-
)
|
| 47 |
-
|
| 48 |
-
# cache dir
|
| 49 |
-
default_cache_path = Path(HF_HOME) / "lerobot"
|
| 50 |
-
HF_LEROBOT_HOME = Path(os.getenv("HF_LEROBOT_HOME", default_cache_path)).expanduser()
|
| 51 |
-
|
| 52 |
-
# calibration dir
|
| 53 |
-
default_calibration_path = HF_LEROBOT_HOME / "calibration"
|
| 54 |
-
HF_LEROBOT_CALIBRATION = Path(os.getenv("HF_LEROBOT_CALIBRATION", default_calibration_path)).expanduser()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/lerobot/datasets/compute_stats.py
DELETED
|
@@ -1,179 +0,0 @@
|
|
| 1 |
-
#!/usr/bin/env python
|
| 2 |
-
|
| 3 |
-
# Copyright 2024 The HuggingFace Inc. team. All rights reserved.
|
| 4 |
-
#
|
| 5 |
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 6 |
-
# you may not use this file except in compliance with the License.
|
| 7 |
-
# You may obtain a copy of the License at
|
| 8 |
-
#
|
| 9 |
-
# http://www.apache.org/licenses/LICENSE-2.0
|
| 10 |
-
#
|
| 11 |
-
# Unless required by applicable law or agreed to in writing, software
|
| 12 |
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 13 |
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 14 |
-
# See the License for the specific language governing permissions and
|
| 15 |
-
# limitations under the License.
|
| 16 |
-
import numpy as np
|
| 17 |
-
|
| 18 |
-
from .utils import load_image_as_numpy
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
def estimate_num_samples(
|
| 22 |
-
dataset_len: int, min_num_samples: int = 100, max_num_samples: int = 10_000, power: float = 0.75
|
| 23 |
-
) -> int:
|
| 24 |
-
"""Heuristic to estimate the number of samples based on dataset size.
|
| 25 |
-
The power controls the sample growth relative to dataset size.
|
| 26 |
-
Lower the power for less number of samples.
|
| 27 |
-
|
| 28 |
-
For default arguments, we have:
|
| 29 |
-
- from 1 to ~500, num_samples=100
|
| 30 |
-
- at 1000, num_samples=177
|
| 31 |
-
- at 2000, num_samples=299
|
| 32 |
-
- at 5000, num_samples=594
|
| 33 |
-
- at 10000, num_samples=1000
|
| 34 |
-
- at 20000, num_samples=1681
|
| 35 |
-
"""
|
| 36 |
-
if dataset_len < min_num_samples:
|
| 37 |
-
min_num_samples = dataset_len
|
| 38 |
-
return max(min_num_samples, min(int(dataset_len**power), max_num_samples))
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
def sample_indices(data_len: int) -> list[int]:
|
| 42 |
-
num_samples = estimate_num_samples(data_len)
|
| 43 |
-
return np.round(np.linspace(0, data_len - 1, num_samples)).astype(int).tolist()
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
def auto_downsample_height_width(img: np.ndarray, target_size: int = 150, max_size_threshold: int = 300):
|
| 47 |
-
_, height, width = img.shape
|
| 48 |
-
|
| 49 |
-
if max(width, height) < max_size_threshold:
|
| 50 |
-
# no downsampling needed
|
| 51 |
-
return img
|
| 52 |
-
|
| 53 |
-
downsample_factor = int(width / target_size) if width > height else int(height / target_size)
|
| 54 |
-
return img[:, ::downsample_factor, ::downsample_factor]
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
def sample_images(image_paths: list[str]) -> np.ndarray:
|
| 58 |
-
sampled_indices = sample_indices(len(image_paths))
|
| 59 |
-
|
| 60 |
-
images = None
|
| 61 |
-
for i, idx in enumerate(sampled_indices):
|
| 62 |
-
path = image_paths[idx]
|
| 63 |
-
# we load as uint8 to reduce memory usage
|
| 64 |
-
img = load_image_as_numpy(path, dtype=np.uint8, channel_first=True)
|
| 65 |
-
img = auto_downsample_height_width(img)
|
| 66 |
-
|
| 67 |
-
if images is None:
|
| 68 |
-
images = np.empty((len(sampled_indices), *img.shape), dtype=np.uint8)
|
| 69 |
-
|
| 70 |
-
images[i] = img
|
| 71 |
-
|
| 72 |
-
return images
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
def get_feature_stats(array: np.ndarray, axis: tuple, keepdims: bool) -> dict[str, np.ndarray]:
|
| 76 |
-
return {
|
| 77 |
-
"min": np.min(array, axis=axis, keepdims=keepdims),
|
| 78 |
-
"max": np.max(array, axis=axis, keepdims=keepdims),
|
| 79 |
-
"mean": np.mean(array, axis=axis, keepdims=keepdims),
|
| 80 |
-
"std": np.std(array, axis=axis, keepdims=keepdims),
|
| 81 |
-
"count": np.array([len(array)]),
|
| 82 |
-
}
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
def compute_episode_stats(episode_data: dict[str, list[str] | np.ndarray], features: dict, is_compute_episode_stats_image : bool) -> dict:
|
| 86 |
-
ep_stats = {}
|
| 87 |
-
for key, data in episode_data.items():
|
| 88 |
-
if features[key]["dtype"] == "string":
|
| 89 |
-
continue # HACK: we should receive np.arrays of strings
|
| 90 |
-
elif features[key]["dtype"] in ["image", "video"]:
|
| 91 |
-
if is_compute_episode_stats_image:
|
| 92 |
-
ep_ft_array = sample_images(data) # data is a list of image paths
|
| 93 |
-
axes_to_reduce = (0, 2, 3) # keep channel dim
|
| 94 |
-
keepdims = True
|
| 95 |
-
else:
|
| 96 |
-
continue
|
| 97 |
-
else:
|
| 98 |
-
ep_ft_array = data # data is already a np.ndarray
|
| 99 |
-
axes_to_reduce = 0 # compute stats over the first axis
|
| 100 |
-
keepdims = data.ndim == 1 # keep as np.array
|
| 101 |
-
|
| 102 |
-
ep_stats[key] = get_feature_stats(ep_ft_array, axis=axes_to_reduce, keepdims=keepdims)
|
| 103 |
-
|
| 104 |
-
# finally, we normalize and remove batch dim for images
|
| 105 |
-
if features[key]["dtype"] in ["image", "video"]:
|
| 106 |
-
ep_stats[key] = {
|
| 107 |
-
k: v if k == "count" else np.squeeze(v / 255.0, axis=0) for k, v in ep_stats[key].items()
|
| 108 |
-
}
|
| 109 |
-
|
| 110 |
-
return ep_stats
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
def _assert_type_and_shape(stats_list: list[dict[str, dict]]):
|
| 114 |
-
for i in range(len(stats_list)):
|
| 115 |
-
for fkey in stats_list[i]:
|
| 116 |
-
for k, v in stats_list[i][fkey].items():
|
| 117 |
-
if not isinstance(v, np.ndarray):
|
| 118 |
-
raise ValueError(
|
| 119 |
-
f"Stats must be composed of numpy array, but key '{k}' of feature '{fkey}' is of type '{type(v)}' instead."
|
| 120 |
-
)
|
| 121 |
-
if v.ndim == 0:
|
| 122 |
-
raise ValueError("Number of dimensions must be at least 1, and is 0 instead.")
|
| 123 |
-
if k == "count" and v.shape != (1,):
|
| 124 |
-
raise ValueError(f"Shape of 'count' must be (1), but is {v.shape} instead.")
|
| 125 |
-
if "image" in fkey and k != "count" and v.shape != (3, 1, 1):
|
| 126 |
-
raise ValueError(f"Shape of '{k}' must be (3,1,1), but is {v.shape} instead.")
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
def aggregate_feature_stats(stats_ft_list: list[dict[str, dict]]) -> dict[str, dict[str, np.ndarray]]:
|
| 130 |
-
"""Aggregates stats for a single feature."""
|
| 131 |
-
means = np.stack([s["mean"] for s in stats_ft_list])
|
| 132 |
-
variances = np.stack([s["std"] ** 2 for s in stats_ft_list])
|
| 133 |
-
counts = np.stack([s["count"] for s in stats_ft_list])
|
| 134 |
-
total_count = counts.sum(axis=0)
|
| 135 |
-
|
| 136 |
-
# Prepare weighted mean by matching number of dimensions
|
| 137 |
-
while counts.ndim < means.ndim:
|
| 138 |
-
counts = np.expand_dims(counts, axis=-1)
|
| 139 |
-
|
| 140 |
-
# Compute the weighted mean
|
| 141 |
-
weighted_means = means * counts
|
| 142 |
-
total_mean = weighted_means.sum(axis=0) / total_count
|
| 143 |
-
|
| 144 |
-
# Compute the variance using the parallel algorithm
|
| 145 |
-
delta_means = means - total_mean
|
| 146 |
-
weighted_variances = (variances + delta_means**2) * counts
|
| 147 |
-
total_variance = weighted_variances.sum(axis=0) / total_count
|
| 148 |
-
|
| 149 |
-
return {
|
| 150 |
-
"min": np.min(np.stack([s["min"] for s in stats_ft_list]), axis=0),
|
| 151 |
-
"max": np.max(np.stack([s["max"] for s in stats_ft_list]), axis=0),
|
| 152 |
-
"mean": total_mean,
|
| 153 |
-
"std": np.sqrt(total_variance),
|
| 154 |
-
"count": total_count,
|
| 155 |
-
}
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
def aggregate_stats(stats_list: list[dict[str, dict]]) -> dict[str, dict[str, np.ndarray]]:
|
| 159 |
-
"""Aggregate stats from multiple compute_stats outputs into a single set of stats.
|
| 160 |
-
|
| 161 |
-
The final stats will have the union of all data keys from each of the stats dicts.
|
| 162 |
-
|
| 163 |
-
For instance:
|
| 164 |
-
- new_min = min(min_dataset_0, min_dataset_1, ...)
|
| 165 |
-
- new_max = max(max_dataset_0, max_dataset_1, ...)
|
| 166 |
-
- new_mean = (mean of all data, weighted by counts)
|
| 167 |
-
- new_std = (std of all data)
|
| 168 |
-
"""
|
| 169 |
-
|
| 170 |
-
_assert_type_and_shape(stats_list)
|
| 171 |
-
|
| 172 |
-
data_keys = {key for stats in stats_list for key in stats}
|
| 173 |
-
aggregated_stats = {key: {} for key in data_keys}
|
| 174 |
-
|
| 175 |
-
for key in data_keys:
|
| 176 |
-
stats_with_key = [stats[key] for stats in stats_list if key in stats]
|
| 177 |
-
aggregated_stats[key] = aggregate_feature_stats(stats_with_key)
|
| 178 |
-
|
| 179 |
-
return aggregated_stats
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/lerobot/datasets/utils.py
DELETED
|
@@ -1,965 +0,0 @@
|
|
| 1 |
-
#!/usr/bin/env python
|
| 2 |
-
|
| 3 |
-
# Copyright 2024 The HuggingFace Inc. team. All rights reserved.
|
| 4 |
-
#
|
| 5 |
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 6 |
-
# you may not use this file except in compliance with the License.
|
| 7 |
-
# You may obtain a copy of the License at
|
| 8 |
-
#
|
| 9 |
-
# http://www.apache.org/licenses/LICENSE-2.0
|
| 10 |
-
#
|
| 11 |
-
# Unless required by applicable law or agreed to in writing, software
|
| 12 |
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 13 |
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 14 |
-
# See the License for the specific language governing permissions and
|
| 15 |
-
# limitations under the License.
|
| 16 |
-
import contextlib
|
| 17 |
-
import importlib.resources
|
| 18 |
-
import io
|
| 19 |
-
import json
|
| 20 |
-
import logging
|
| 21 |
-
from collections.abc import Iterator
|
| 22 |
-
from itertools import accumulate
|
| 23 |
-
from pathlib import Path
|
| 24 |
-
from pprint import pformat
|
| 25 |
-
from types import SimpleNamespace
|
| 26 |
-
from typing import Any
|
| 27 |
-
import array
|
| 28 |
-
|
| 29 |
-
import datasets
|
| 30 |
-
import jsonlines
|
| 31 |
-
import numpy as np
|
| 32 |
-
import packaging.version
|
| 33 |
-
import torch
|
| 34 |
-
from datasets.table import embed_table_storage
|
| 35 |
-
from huggingface_hub import DatasetCard, DatasetCardData, HfApi
|
| 36 |
-
from huggingface_hub.errors import RevisionNotFoundError
|
| 37 |
-
from PIL import Image as PILImage
|
| 38 |
-
from torchvision import transforms
|
| 39 |
-
|
| 40 |
-
from functools import partial
|
| 41 |
-
|
| 42 |
-
# from lerobot.configs.types import DictLike, FeatureType, PolicyFeature
|
| 43 |
-
# from lerobot.datasets.backward_compatibility import (
|
| 44 |
-
# V21_MESSAGE,
|
| 45 |
-
# BackwardCompatibilityError,
|
| 46 |
-
# ForwardCompatibilityError,
|
| 47 |
-
# )
|
| 48 |
-
# from lerobot.robots import Robot
|
| 49 |
-
# from lerobot.utils.utils import is_valid_numpy_dtype_string
|
| 50 |
-
|
| 51 |
-
DEFAULT_CHUNK_SIZE = 1000 # Max number of episodes per chunk
|
| 52 |
-
|
| 53 |
-
INFO_PATH = "meta/info.json"
|
| 54 |
-
EPISODES_PATH = "meta/episodes.jsonl"
|
| 55 |
-
STATS_PATH = "meta/stats.json"
|
| 56 |
-
EPISODES_STATS_PATH = "meta/episodes_stats.jsonl"
|
| 57 |
-
TASKS_PATH = "meta/tasks.jsonl"
|
| 58 |
-
|
| 59 |
-
ANNOTATION_PATHS = {
|
| 60 |
-
"subtask": "annotations/subtask_annotations.jsonl",
|
| 61 |
-
"scene": "annotations/scene_annotations.jsonl",
|
| 62 |
-
"gripper_mode": "annotations/gripper_mode_annotation.jsonl",
|
| 63 |
-
"gripper_activity": "annotations/gripper_activity_annotation.jsonl",
|
| 64 |
-
"eef_velocity": "annotations/eef_velocity_annotation.jsonl",
|
| 65 |
-
"eef_acc_mag": "annotations/eef_acc_mag_annotation.jsonl",
|
| 66 |
-
"eef_direction": "annotations/eef_direction_annotation.jsonl",
|
| 67 |
-
}
|
| 68 |
-
|
| 69 |
-
DEFAULT_VIDEO_PATH = "videos/chunk-{episode_chunk:03d}/{video_key}/episode_{episode_index:06d}.mp4"
|
| 70 |
-
DEFAULT_PARQUET_PATH = "data/chunk-{episode_chunk:03d}/episode_{episode_index:06d}.parquet"
|
| 71 |
-
DEFAULT_IMAGE_PATH = "images/{image_key}/episode_{episode_index:06d}/frame_{frame_index:06d}.jpeg"
|
| 72 |
-
|
| 73 |
-
# v3.0 paths — multi-episode files, paths derived from per-episode metadata
|
| 74 |
-
DEFAULT_DATA_PATH_V30 = "data/chunk-{chunk_index:03d}/file-{file_index:03d}.parquet"
|
| 75 |
-
DEFAULT_VIDEO_PATH_V30 = "videos/{video_key}/chunk-{chunk_index:03d}/file-{file_index:03d}.mp4"
|
| 76 |
-
EPISODES_DIR_V30 = "meta/episodes"
|
| 77 |
-
TASKS_PATH_V30 = "meta/tasks.parquet" # flat single-file in v3.0
|
| 78 |
-
_TASKS_V30_CACHE = {}
|
| 79 |
-
|
| 80 |
-
DATASET_CARD_TEMPLATE = """
|
| 81 |
-
---
|
| 82 |
-
# Metadata will go there
|
| 83 |
-
---
|
| 84 |
-
This dataset was created using [LeRobot](https://github.com/huggingface/lerobot).
|
| 85 |
-
|
| 86 |
-
## {}
|
| 87 |
-
|
| 88 |
-
"""
|
| 89 |
-
|
| 90 |
-
DEFAULT_FEATURES = {
|
| 91 |
-
"timestamp": {"dtype": "float32", "shape": (1,), "names": None},
|
| 92 |
-
"frame_index": {"dtype": "int64", "shape": (1,), "names": None},
|
| 93 |
-
"episode_index": {"dtype": "int64", "shape": (1,), "names": None},
|
| 94 |
-
"index": {"dtype": "int64", "shape": (1,), "names": None},
|
| 95 |
-
"coarse_task_index": {"dtype": "int64", "shape": (1,), "names": None},
|
| 96 |
-
"task_index": {"dtype": "int64", "shape": (1,), "names": None},
|
| 97 |
-
"coarse_quality_index": {"dtype": "int64", "shape": (1,), "names": None},
|
| 98 |
-
"quality_index": {"dtype": "int64", "shape": (1,), "names": None},
|
| 99 |
-
}
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
def flatten_dict(d: dict, parent_key: str = "", sep: str = "/") -> dict:
|
| 103 |
-
"""Flatten a nested dictionary structure by collapsing nested keys into one key with a separator.
|
| 104 |
-
|
| 105 |
-
For example:
|
| 106 |
-
```
|
| 107 |
-
>>> dct = {"a": {"b": 1, "c": {"d": 2}}, "e": 3}`
|
| 108 |
-
>>> print(flatten_dict(dct))
|
| 109 |
-
{"a/b": 1, "a/c/d": 2, "e": 3}
|
| 110 |
-
"""
|
| 111 |
-
items = []
|
| 112 |
-
for k, v in d.items():
|
| 113 |
-
new_key = f"{parent_key}{sep}{k}" if parent_key else k
|
| 114 |
-
if isinstance(v, dict):
|
| 115 |
-
items.extend(flatten_dict(v, new_key, sep=sep).items())
|
| 116 |
-
else:
|
| 117 |
-
items.append((new_key, v))
|
| 118 |
-
return dict(items)
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
def unflatten_dict(d: dict, sep: str = "/") -> dict:
|
| 122 |
-
outdict = {}
|
| 123 |
-
for key, value in d.items():
|
| 124 |
-
parts = key.split(sep)
|
| 125 |
-
d = outdict
|
| 126 |
-
for part in parts[:-1]:
|
| 127 |
-
if part not in d:
|
| 128 |
-
d[part] = {}
|
| 129 |
-
d = d[part]
|
| 130 |
-
d[parts[-1]] = value
|
| 131 |
-
return outdict
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
# def get_nested_item(obj: DictLike, flattened_key: str, sep: str = "/") -> Any:
|
| 135 |
-
# split_keys = flattened_key.split(sep)
|
| 136 |
-
# getter = obj[split_keys[0]]
|
| 137 |
-
# if len(split_keys) == 1:
|
| 138 |
-
# return getter
|
| 139 |
-
|
| 140 |
-
# for key in split_keys[1:]:
|
| 141 |
-
# getter = getter[key]
|
| 142 |
-
|
| 143 |
-
# return getter
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
def serialize_dict(stats: dict[str, torch.Tensor | np.ndarray | dict]) -> dict:
|
| 147 |
-
serialized_dict = {}
|
| 148 |
-
for key, value in flatten_dict(stats).items():
|
| 149 |
-
if isinstance(value, (torch.Tensor, np.ndarray)):
|
| 150 |
-
serialized_dict[key] = value.tolist()
|
| 151 |
-
elif isinstance(value, np.generic):
|
| 152 |
-
serialized_dict[key] = value.item()
|
| 153 |
-
elif isinstance(value, (int, float)):
|
| 154 |
-
serialized_dict[key] = value
|
| 155 |
-
else:
|
| 156 |
-
raise NotImplementedError(f"The value '{value}' of type '{type(value)}' is not supported.")
|
| 157 |
-
return unflatten_dict(serialized_dict)
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
def embed_images(dataset: datasets.Dataset) -> datasets.Dataset:
|
| 161 |
-
# Embed image bytes into the table before saving to parquet
|
| 162 |
-
format = dataset.format
|
| 163 |
-
dataset = dataset.with_format("arrow")
|
| 164 |
-
dataset = dataset.map(embed_table_storage, batched=False)
|
| 165 |
-
dataset = dataset.with_format(**format)
|
| 166 |
-
return dataset
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
def load_json(fpath: Path) -> Any:
|
| 170 |
-
with open(fpath) as f:
|
| 171 |
-
return json.load(f)
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
def write_json(data: dict, fpath: Path) -> None:
|
| 175 |
-
fpath.parent.mkdir(exist_ok=True, parents=True)
|
| 176 |
-
with open(fpath, "w") as f:
|
| 177 |
-
json.dump(data, f, indent=4, ensure_ascii=False)
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
def load_jsonlines(fpath: Path) -> list[Any]:
|
| 181 |
-
# allow \t and \n
|
| 182 |
-
loose_loader = partial(json.loads, strict=False)
|
| 183 |
-
with jsonlines.open(fpath, "r", loads=loose_loader) as reader:
|
| 184 |
-
return list(reader)
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
def write_jsonlines(data: dict, fpath: Path) -> None:
|
| 188 |
-
fpath.parent.mkdir(exist_ok=True, parents=True)
|
| 189 |
-
with jsonlines.open(fpath, "w") as writer:
|
| 190 |
-
writer.write_all(data)
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
def append_jsonlines(data: dict, fpath: Path) -> None:
|
| 194 |
-
fpath.parent.mkdir(exist_ok=True, parents=True)
|
| 195 |
-
with jsonlines.open(fpath, "a") as writer:
|
| 196 |
-
writer.write(data)
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
def write_info(info: dict, local_dir: Path):
|
| 200 |
-
write_json(info, local_dir / INFO_PATH)
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
def load_info(local_dir: Path) -> dict:
|
| 204 |
-
info = load_json(local_dir / INFO_PATH)
|
| 205 |
-
for ft in info["features"].values():
|
| 206 |
-
ft["shape"] = tuple(ft["shape"])
|
| 207 |
-
return info
|
| 208 |
-
|
| 209 |
-
|
| 210 |
-
def write_stats(stats: dict, local_dir: Path):
|
| 211 |
-
serialized_stats = serialize_dict(stats)
|
| 212 |
-
write_json(serialized_stats, local_dir / STATS_PATH)
|
| 213 |
-
|
| 214 |
-
|
| 215 |
-
def cast_stats_to_numpy(stats) -> dict[str, dict[str, np.ndarray]]:
|
| 216 |
-
stats = {key: np.array(value) for key, value in flatten_dict(stats).items()}
|
| 217 |
-
return unflatten_dict(stats)
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
def load_stats(local_dir: Path) -> dict[str, dict[str, np.ndarray]]:
|
| 221 |
-
if not (local_dir / STATS_PATH).exists():
|
| 222 |
-
return None
|
| 223 |
-
stats = load_json(local_dir / STATS_PATH)
|
| 224 |
-
return cast_stats_to_numpy(stats)
|
| 225 |
-
|
| 226 |
-
|
| 227 |
-
def write_task(task_index: int, task: dict, local_dir: Path):
|
| 228 |
-
task_dict = {
|
| 229 |
-
"task_index": task_index,
|
| 230 |
-
"task": task,
|
| 231 |
-
}
|
| 232 |
-
append_jsonlines(task_dict, local_dir / TASKS_PATH)
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
def load_tasks(local_dir: Path) -> tuple[dict, dict]:
|
| 236 |
-
tasks = load_jsonlines(local_dir / TASKS_PATH)
|
| 237 |
-
tasks = {item["task_index"]: item["task"] for item in sorted(tasks, key=lambda x: x["task_index"])}
|
| 238 |
-
task_to_task_index = {task: task_index for task_index, task in tasks.items()}
|
| 239 |
-
return tasks, task_to_task_index
|
| 240 |
-
|
| 241 |
-
|
| 242 |
-
def load_tasks_v30(local_dir: Path) -> tuple[dict, dict]:
|
| 243 |
-
"""Load tasks from v3.0 parquet format (meta/tasks.parquet).
|
| 244 |
-
|
| 245 |
-
The parquet has index=task_string, column="task_index" (integer).
|
| 246 |
-
Returns (tasks, task_to_task_index) matching the v2.1 interface.
|
| 247 |
-
"""
|
| 248 |
-
import pandas as pd
|
| 249 |
-
path = local_dir / TASKS_PATH_V30
|
| 250 |
-
if not path.exists():
|
| 251 |
-
raise FileNotFoundError(f"Tasks parquet not found: {path}")
|
| 252 |
-
stat = path.stat()
|
| 253 |
-
cache_key = (path.name, stat.st_size, stat.st_mtime_ns)
|
| 254 |
-
if cache_key in _TASKS_V30_CACHE:
|
| 255 |
-
return _TASKS_V30_CACHE[cache_key]
|
| 256 |
-
df = pd.read_parquet(path)
|
| 257 |
-
# index = task string, column "task_index" = integer task index
|
| 258 |
-
tasks = {int(row["task_index"]): task_str for task_str, row in df.iterrows()}
|
| 259 |
-
task_to_task_index = {task_str: int(row["task_index"]) for task_str, row in df.iterrows()}
|
| 260 |
-
result = (tasks, task_to_task_index)
|
| 261 |
-
_TASKS_V30_CACHE[cache_key] = result
|
| 262 |
-
return result
|
| 263 |
-
|
| 264 |
-
|
| 265 |
-
def load_episodes_v30(local_dir: Path) -> dict:
|
| 266 |
-
"""Load episodes from v3.0 parquet format (meta/episodes/chunk-000/file-000.parquet).
|
| 267 |
-
|
| 268 |
-
Returns a dict mapping episode_index → row dict, compatible with get_episode_data_index.
|
| 269 |
-
Each row contains at minimum: episode_index, tasks, length, dataset_from_index,
|
| 270 |
-
dataset_to_index, data/chunk_index, data/file_index, videos/{key}/chunk_index,
|
| 271 |
-
videos/{key}/file_index, videos/{key}/from_timestamp, videos/{key}/to_timestamp.
|
| 272 |
-
"""
|
| 273 |
-
import pandas as pd
|
| 274 |
-
paths = sorted((local_dir / EPISODES_DIR_V30).glob("*/*.parquet"))
|
| 275 |
-
if not paths:
|
| 276 |
-
raise FileNotFoundError(f"No episodes parquet found in {local_dir / EPISODES_DIR_V30}")
|
| 277 |
-
# Drop stats/* and tasks columns — arrays not needed for data loading
|
| 278 |
-
import numpy as np
|
| 279 |
-
dfs = []
|
| 280 |
-
for p in paths:
|
| 281 |
-
df_part = pd.read_parquet(p)
|
| 282 |
-
drop_cols = [c for c in df_part.columns if c.startswith("stats/") or c == "tasks"]
|
| 283 |
-
dfs.append(df_part.drop(columns=drop_cols))
|
| 284 |
-
df = pd.concat(dfs).reset_index(drop=True)
|
| 285 |
-
episodes = {}
|
| 286 |
-
for _, row in df.iterrows():
|
| 287 |
-
ep_idx = int(row["episode_index"])
|
| 288 |
-
episodes[ep_idx] = {
|
| 289 |
-
k: (int(v) if isinstance(v, (int, np.integer)) else
|
| 290 |
-
float(v) if isinstance(v, (float, np.floating)) else v)
|
| 291 |
-
for k, v in row.items()
|
| 292 |
-
}
|
| 293 |
-
episodes[ep_idx]["length"] = int(row["length"])
|
| 294 |
-
return episodes
|
| 295 |
-
|
| 296 |
-
def load_annotations(local_dir: Path) -> dict[str, dict[int, str]]:
|
| 297 |
-
annotations = {}
|
| 298 |
-
for key, path in ANNOTATION_PATHS.items():
|
| 299 |
-
anno = load_jsonlines(local_dir / path)
|
| 300 |
-
anno = {item[f"{key}_index"]: item[key] for item in sorted(anno, key=lambda x: x[f"{key}_index"])}
|
| 301 |
-
annotations[key] = anno
|
| 302 |
-
return annotations
|
| 303 |
-
|
| 304 |
-
def write_episode(episode: dict, local_dir: Path):
|
| 305 |
-
append_jsonlines(episode, local_dir / EPISODES_PATH)
|
| 306 |
-
|
| 307 |
-
|
| 308 |
-
def load_episodes(local_dir: Path) -> dict:
|
| 309 |
-
episodes = load_jsonlines(local_dir / EPISODES_PATH)
|
| 310 |
-
return {item["episode_index"]: item for item in sorted(episodes, key=lambda x: x["episode_index"])}
|
| 311 |
-
|
| 312 |
-
|
| 313 |
-
def write_episode_stats(episode_index: int, episode_stats: dict, local_dir: Path):
|
| 314 |
-
# We wrap episode_stats in a dictionary since `episode_stats["episode_index"]`
|
| 315 |
-
# is a dictionary of stats and not an integer.
|
| 316 |
-
episode_stats = {"episode_index": episode_index, "stats": serialize_dict(episode_stats)}
|
| 317 |
-
append_jsonlines(episode_stats, local_dir / EPISODES_STATS_PATH)
|
| 318 |
-
|
| 319 |
-
|
| 320 |
-
def load_episodes_stats(local_dir: Path) -> dict:
|
| 321 |
-
episodes_stats = load_jsonlines(local_dir / EPISODES_STATS_PATH)
|
| 322 |
-
return {
|
| 323 |
-
item["episode_index"]: cast_stats_to_numpy(item["stats"])
|
| 324 |
-
for item in sorted(episodes_stats, key=lambda x: x["episode_index"])
|
| 325 |
-
}
|
| 326 |
-
|
| 327 |
-
|
| 328 |
-
def backward_compatible_episodes_stats(
|
| 329 |
-
stats: dict[str, dict[str, np.ndarray]], episodes: list[int]
|
| 330 |
-
) -> dict[str, dict[str, np.ndarray]]:
|
| 331 |
-
return dict.fromkeys(episodes, stats)
|
| 332 |
-
|
| 333 |
-
|
| 334 |
-
def load_image_as_numpy(
|
| 335 |
-
fpath: str | Path, dtype: np.dtype = np.float32, channel_first: bool = True
|
| 336 |
-
) -> np.ndarray:
|
| 337 |
-
img = PILImage.open(fpath).convert("RGB")
|
| 338 |
-
img_array = np.array(img, dtype=dtype)
|
| 339 |
-
if channel_first: # (H, W, C) -> (C, H, W)
|
| 340 |
-
img_array = np.transpose(img_array, (2, 0, 1))
|
| 341 |
-
if np.issubdtype(dtype, np.floating):
|
| 342 |
-
img_array /= 255.0
|
| 343 |
-
return img_array
|
| 344 |
-
|
| 345 |
-
|
| 346 |
-
def hf_transform_to_torch(items_dict: dict[torch.Tensor | None]):
|
| 347 |
-
"""Get a transform function that convert items from Hugging Face dataset (pyarrow)
|
| 348 |
-
to torch tensors. Importantly, images are converted from PIL, which corresponds to
|
| 349 |
-
a channel last representation (h w c) of uint8 type, to a torch image representation
|
| 350 |
-
with channel first (c h w) of float32 type in range [0,1].
|
| 351 |
-
"""
|
| 352 |
-
for key in items_dict:
|
| 353 |
-
first_item = items_dict[key][0]
|
| 354 |
-
if type(first_item) == dict and 'bytes' in first_item and first_item['bytes'] is not None:
|
| 355 |
-
to_pil = lambda img: PILImage.open(io.BytesIO(img['bytes']))
|
| 356 |
-
items_dict[key] = [to_pil(img) for img in items_dict[key]]
|
| 357 |
-
first_item = items_dict[key][0]
|
| 358 |
-
if isinstance(first_item, PILImage.Image):
|
| 359 |
-
to_tensor = transforms.ToTensor()
|
| 360 |
-
items_dict[key] = [to_tensor(img) for img in items_dict[key]]
|
| 361 |
-
elif first_item is None:
|
| 362 |
-
pass
|
| 363 |
-
else:
|
| 364 |
-
items_dict[key] = [x if isinstance(x, str) else torch.tensor(x) for x in items_dict[key]]
|
| 365 |
-
return items_dict
|
| 366 |
-
|
| 367 |
-
|
| 368 |
-
def is_valid_version(version: str) -> bool:
|
| 369 |
-
try:
|
| 370 |
-
packaging.version.parse(version)
|
| 371 |
-
return True
|
| 372 |
-
except packaging.version.InvalidVersion:
|
| 373 |
-
return False
|
| 374 |
-
|
| 375 |
-
|
| 376 |
-
# def check_version_compatibility(
|
| 377 |
-
# repo_id: str,
|
| 378 |
-
# version_to_check: str | packaging.version.Version,
|
| 379 |
-
# current_version: str | packaging.version.Version,
|
| 380 |
-
# enforce_breaking_major: bool = True,
|
| 381 |
-
# ) -> None:
|
| 382 |
-
# v_check = (
|
| 383 |
-
# packaging.version.parse(version_to_check)
|
| 384 |
-
# if not isinstance(version_to_check, packaging.version.Version)
|
| 385 |
-
# else version_to_check
|
| 386 |
-
# )
|
| 387 |
-
# v_current = (
|
| 388 |
-
# packaging.version.parse(current_version)
|
| 389 |
-
# if not isinstance(current_version, packaging.version.Version)
|
| 390 |
-
# else current_version
|
| 391 |
-
# )
|
| 392 |
-
# if v_check.major < v_current.major and enforce_breaking_major:
|
| 393 |
-
# raise BackwardCompatibilityError(repo_id, v_check)
|
| 394 |
-
# elif v_check.minor < v_current.minor:
|
| 395 |
-
# logging.warning(V21_MESSAGE.format(repo_id=repo_id, version=v_check))
|
| 396 |
-
|
| 397 |
-
|
| 398 |
-
def get_repo_versions(repo_id: str) -> list[packaging.version.Version]:
|
| 399 |
-
"""Returns available valid versions (branches and tags) on given repo."""
|
| 400 |
-
api = HfApi()
|
| 401 |
-
repo_refs = api.list_repo_refs(repo_id, repo_type="dataset")
|
| 402 |
-
repo_refs = [b.name for b in repo_refs.branches + repo_refs.tags]
|
| 403 |
-
repo_versions = []
|
| 404 |
-
for ref in repo_refs:
|
| 405 |
-
with contextlib.suppress(packaging.version.InvalidVersion):
|
| 406 |
-
repo_versions.append(packaging.version.parse(ref))
|
| 407 |
-
|
| 408 |
-
return repo_versions
|
| 409 |
-
|
| 410 |
-
|
| 411 |
-
# def get_safe_version(repo_id: str, version: str | packaging.version.Version) -> str:
|
| 412 |
-
# """
|
| 413 |
-
# Returns the version if available on repo or the latest compatible one.
|
| 414 |
-
# Otherwise, will throw a `CompatibilityError`.
|
| 415 |
-
# """
|
| 416 |
-
# target_version = (
|
| 417 |
-
# packaging.version.parse(version) if not isinstance(version, packaging.version.Version) else version
|
| 418 |
-
# )
|
| 419 |
-
# hub_versions = get_repo_versions(repo_id)
|
| 420 |
-
|
| 421 |
-
# if not hub_versions:
|
| 422 |
-
# raise RevisionNotFoundError(
|
| 423 |
-
# f"""Your dataset must be tagged with a codebase version.
|
| 424 |
-
# Assuming _version_ is the codebase_version value in the info.json, you can run this:
|
| 425 |
-
# ```python
|
| 426 |
-
# from huggingface_hub import HfApi
|
| 427 |
-
|
| 428 |
-
# hub_api = HfApi()
|
| 429 |
-
# hub_api.create_tag("{repo_id}", tag="_version_", repo_type="dataset")
|
| 430 |
-
# ```
|
| 431 |
-
# """
|
| 432 |
-
# )
|
| 433 |
-
|
| 434 |
-
# if target_version in hub_versions:
|
| 435 |
-
# return f"v{target_version}"
|
| 436 |
-
|
| 437 |
-
# compatibles = [
|
| 438 |
-
# v for v in hub_versions if v.major == target_version.major and v.minor <= target_version.minor
|
| 439 |
-
# ]
|
| 440 |
-
# if compatibles:
|
| 441 |
-
# return_version = max(compatibles)
|
| 442 |
-
# if return_version < target_version:
|
| 443 |
-
# logging.warning(f"Revision {version} for {repo_id} not found, using version v{return_version}")
|
| 444 |
-
# return f"v{return_version}"
|
| 445 |
-
|
| 446 |
-
# lower_major = [v for v in hub_versions if v.major < target_version.major]
|
| 447 |
-
# if lower_major:
|
| 448 |
-
# raise BackwardCompatibilityError(repo_id, max(lower_major))
|
| 449 |
-
|
| 450 |
-
# upper_versions = [v for v in hub_versions if v > target_version]
|
| 451 |
-
# assert len(upper_versions) > 0
|
| 452 |
-
# raise ForwardCompatibilityError(repo_id, min(upper_versions))
|
| 453 |
-
|
| 454 |
-
|
| 455 |
-
def get_hf_features_from_features(features: dict) -> datasets.Features:
|
| 456 |
-
hf_features = {}
|
| 457 |
-
for key, ft in features.items():
|
| 458 |
-
if ft["dtype"] == "video":
|
| 459 |
-
continue
|
| 460 |
-
elif ft["dtype"] == "image":
|
| 461 |
-
hf_features[key] = datasets.Image()
|
| 462 |
-
elif ft["shape"] == (1,):
|
| 463 |
-
hf_features[key] = datasets.Value(dtype=ft["dtype"])
|
| 464 |
-
elif len(ft["shape"]) == 1:
|
| 465 |
-
hf_features[key] = datasets.Sequence(
|
| 466 |
-
length=ft["shape"][0], feature=datasets.Value(dtype=ft["dtype"])
|
| 467 |
-
)
|
| 468 |
-
elif len(ft["shape"]) == 2:
|
| 469 |
-
hf_features[key] = datasets.Array2D(shape=ft["shape"], dtype=ft["dtype"])
|
| 470 |
-
elif len(ft["shape"]) == 3:
|
| 471 |
-
hf_features[key] = datasets.Array3D(shape=ft["shape"], dtype=ft["dtype"])
|
| 472 |
-
elif len(ft["shape"]) == 4:
|
| 473 |
-
hf_features[key] = datasets.Array4D(shape=ft["shape"], dtype=ft["dtype"])
|
| 474 |
-
elif len(ft["shape"]) == 5:
|
| 475 |
-
hf_features[key] = datasets.Array5D(shape=ft["shape"], dtype=ft["dtype"])
|
| 476 |
-
else:
|
| 477 |
-
raise ValueError(f"Corresponding feature is not valid: {ft}")
|
| 478 |
-
|
| 479 |
-
return datasets.Features(hf_features)
|
| 480 |
-
|
| 481 |
-
|
| 482 |
-
def _validate_feature_names(features: dict[str, dict]) -> None:
|
| 483 |
-
invalid_features = {name: ft for name, ft in features.items() if "/" in name}
|
| 484 |
-
if invalid_features:
|
| 485 |
-
raise ValueError(f"Feature names should not contain '/'. Found '/' in '{invalid_features}'.")
|
| 486 |
-
|
| 487 |
-
|
| 488 |
-
def hw_to_dataset_features(
|
| 489 |
-
hw_features: dict[str, type | tuple], prefix: str, use_video: bool = True
|
| 490 |
-
) -> dict[str, dict]:
|
| 491 |
-
features = {}
|
| 492 |
-
joint_fts = {key: ftype for key, ftype in hw_features.items() if ftype is float}
|
| 493 |
-
cam_fts = {key: shape for key, shape in hw_features.items() if isinstance(shape, tuple)}
|
| 494 |
-
|
| 495 |
-
if joint_fts and prefix == "action":
|
| 496 |
-
features[prefix] = {
|
| 497 |
-
"dtype": "float32",
|
| 498 |
-
"shape": (len(joint_fts),),
|
| 499 |
-
"names": list(joint_fts),
|
| 500 |
-
}
|
| 501 |
-
|
| 502 |
-
if joint_fts and prefix == "observation":
|
| 503 |
-
features[f"{prefix}.state"] = {
|
| 504 |
-
"dtype": "float32",
|
| 505 |
-
"shape": (len(joint_fts),),
|
| 506 |
-
"names": list(joint_fts),
|
| 507 |
-
}
|
| 508 |
-
|
| 509 |
-
for key, shape in cam_fts.items():
|
| 510 |
-
features[f"{prefix}.images.{key}"] = {
|
| 511 |
-
"dtype": "video" if use_video else "image",
|
| 512 |
-
"shape": shape,
|
| 513 |
-
"names": ["height", "width", "channels"],
|
| 514 |
-
}
|
| 515 |
-
|
| 516 |
-
_validate_feature_names(features)
|
| 517 |
-
return features
|
| 518 |
-
|
| 519 |
-
|
| 520 |
-
def build_dataset_frame(
|
| 521 |
-
ds_features: dict[str, dict], values: dict[str, Any], prefix: str
|
| 522 |
-
) -> dict[str, np.ndarray]:
|
| 523 |
-
frame = {}
|
| 524 |
-
for key, ft in ds_features.items():
|
| 525 |
-
if key in DEFAULT_FEATURES or not key.startswith(prefix):
|
| 526 |
-
continue
|
| 527 |
-
elif ft["dtype"] == "float32" and len(ft["shape"]) == 1:
|
| 528 |
-
frame[key] = np.array([values[name] for name in ft["names"]], dtype=np.float32)
|
| 529 |
-
elif ft["dtype"] in ["image", "video"]:
|
| 530 |
-
frame[key] = values[key.removeprefix(f"{prefix}.images.")]
|
| 531 |
-
|
| 532 |
-
return frame
|
| 533 |
-
|
| 534 |
-
|
| 535 |
-
# def get_features_from_robot(robot: Robot, use_videos: bool = True) -> dict:
|
| 536 |
-
# camera_ft = {}
|
| 537 |
-
# if robot.cameras:
|
| 538 |
-
# camera_ft = {
|
| 539 |
-
# key: {"dtype": "video" if use_videos else "image", **ft}
|
| 540 |
-
# for key, ft in robot.camera_features.items()
|
| 541 |
-
# }
|
| 542 |
-
# return {**robot.motor_features, **camera_ft, **DEFAULT_FEATURES}
|
| 543 |
-
|
| 544 |
-
|
| 545 |
-
# def dataset_to_policy_features(features: dict[str, dict]) -> dict[str, PolicyFeature]:
|
| 546 |
-
# # TODO(aliberts): Implement "type" in dataset features and simplify this
|
| 547 |
-
# policy_features = {}
|
| 548 |
-
# for key, ft in features.items():
|
| 549 |
-
# shape = ft["shape"]
|
| 550 |
-
# if ft["dtype"] in ["image", "video"]:
|
| 551 |
-
# type = FeatureType.VISUAL
|
| 552 |
-
# if len(shape) != 3:
|
| 553 |
-
# raise ValueError(f"Number of dimensions of {key} != 3 (shape={shape})")
|
| 554 |
-
|
| 555 |
-
# names = ft["names"]
|
| 556 |
-
# # Backward compatibility for "channel" which is an error introduced in LeRobotDataset v2.0 for ported datasets.
|
| 557 |
-
# if names[2] in ["channel", "channels"]: # (h, w, c) -> (c, h, w)
|
| 558 |
-
# shape = (shape[2], shape[0], shape[1])
|
| 559 |
-
# elif key == "observation.environment_state":
|
| 560 |
-
# type = FeatureType.ENV
|
| 561 |
-
# elif key.startswith("observation"):
|
| 562 |
-
# type = FeatureType.STATE
|
| 563 |
-
# elif key.startswith("action"):
|
| 564 |
-
# type = FeatureType.ACTION
|
| 565 |
-
# else:
|
| 566 |
-
# continue
|
| 567 |
-
|
| 568 |
-
# policy_features[key] = PolicyFeature(
|
| 569 |
-
# type=type,
|
| 570 |
-
# shape=shape,
|
| 571 |
-
# )
|
| 572 |
-
|
| 573 |
-
# return policy_features
|
| 574 |
-
|
| 575 |
-
|
| 576 |
-
def create_empty_dataset_info(
|
| 577 |
-
codebase_version: str,
|
| 578 |
-
fps: int,
|
| 579 |
-
features: dict,
|
| 580 |
-
use_videos: bool,
|
| 581 |
-
robot_type: str | None = None,
|
| 582 |
-
) -> dict:
|
| 583 |
-
return {
|
| 584 |
-
"codebase_version": codebase_version,
|
| 585 |
-
"robot_type": robot_type,
|
| 586 |
-
"total_episodes": 0,
|
| 587 |
-
"total_frames": 0,
|
| 588 |
-
"total_tasks": 0,
|
| 589 |
-
"total_videos": 0,
|
| 590 |
-
"total_chunks": 0,
|
| 591 |
-
"chunks_size": DEFAULT_CHUNK_SIZE,
|
| 592 |
-
"fps": fps,
|
| 593 |
-
"splits": {},
|
| 594 |
-
"data_path": DEFAULT_PARQUET_PATH,
|
| 595 |
-
"video_path": DEFAULT_VIDEO_PATH if use_videos else None,
|
| 596 |
-
"features": features,
|
| 597 |
-
}
|
| 598 |
-
|
| 599 |
-
|
| 600 |
-
def get_episode_data_index(
|
| 601 |
-
episode_dicts: dict[dict], episodes: list[int] | None = None
|
| 602 |
-
) -> dict[str, torch.Tensor]:
|
| 603 |
-
episode_lengths = {ep_idx: ep_dict["length"] for ep_idx, ep_dict in episode_dicts.items()}
|
| 604 |
-
if episodes is not None:
|
| 605 |
-
episode_lengths = {ep_idx: episode_lengths[ep_idx] for ep_idx in episodes}
|
| 606 |
-
|
| 607 |
-
cumulative_lengths = list(accumulate(episode_lengths.values()))
|
| 608 |
-
return {
|
| 609 |
-
"from": torch.LongTensor([0] + cumulative_lengths[:-1]),
|
| 610 |
-
"to": torch.LongTensor(cumulative_lengths),
|
| 611 |
-
}
|
| 612 |
-
|
| 613 |
-
|
| 614 |
-
def check_timestamps_sync(
|
| 615 |
-
timestamps: np.ndarray,
|
| 616 |
-
episode_indices: np.ndarray,
|
| 617 |
-
episode_data_index: dict[str, np.ndarray],
|
| 618 |
-
fps: int,
|
| 619 |
-
tolerance_s: float,
|
| 620 |
-
raise_value_error: bool = True,
|
| 621 |
-
) -> bool:
|
| 622 |
-
"""
|
| 623 |
-
This check is to make sure that each timestamp is separated from the next by (1/fps) +/- tolerance
|
| 624 |
-
to account for possible numerical error.
|
| 625 |
-
|
| 626 |
-
Args:
|
| 627 |
-
timestamps (np.ndarray): Array of timestamps in seconds.
|
| 628 |
-
episode_indices (np.ndarray): Array indicating the episode index for each timestamp.
|
| 629 |
-
episode_data_index (dict[str, np.ndarray]): A dictionary that includes 'to',
|
| 630 |
-
which identifies indices for the end of each episode.
|
| 631 |
-
fps (int): Frames per second. Used to check the expected difference between consecutive timestamps.
|
| 632 |
-
tolerance_s (float): Allowed deviation from the expected (1/fps) difference.
|
| 633 |
-
raise_value_error (bool): Whether to raise a ValueError if the check fails.
|
| 634 |
-
|
| 635 |
-
Returns:
|
| 636 |
-
bool: True if all checked timestamp differences lie within tolerance, False otherwise.
|
| 637 |
-
|
| 638 |
-
Raises:
|
| 639 |
-
ValueError: If the check fails and `raise_value_error` is True.
|
| 640 |
-
"""
|
| 641 |
-
if timestamps.shape != episode_indices.shape:
|
| 642 |
-
raise ValueError(
|
| 643 |
-
"timestamps and episode_indices should have the same shape. "
|
| 644 |
-
f"Found {timestamps.shape=} and {episode_indices.shape=}."
|
| 645 |
-
)
|
| 646 |
-
|
| 647 |
-
# Consecutive differences
|
| 648 |
-
diffs = np.diff(timestamps)
|
| 649 |
-
within_tolerance = np.abs(diffs - (1.0 / fps)) <= tolerance_s
|
| 650 |
-
|
| 651 |
-
# Mask to ignore differences at the boundaries between episodes
|
| 652 |
-
mask = np.ones(len(diffs), dtype=bool)
|
| 653 |
-
ignored_diffs = episode_data_index["to"][:-1] - 1 # indices at the end of each episode
|
| 654 |
-
mask[ignored_diffs] = False
|
| 655 |
-
filtered_within_tolerance = within_tolerance[mask]
|
| 656 |
-
|
| 657 |
-
# Check if all remaining diffs are within tolerance
|
| 658 |
-
if not np.all(filtered_within_tolerance):
|
| 659 |
-
# Track original indices before masking
|
| 660 |
-
original_indices = np.arange(len(diffs))
|
| 661 |
-
filtered_indices = original_indices[mask]
|
| 662 |
-
outside_tolerance_filtered_indices = np.nonzero(~filtered_within_tolerance)[0]
|
| 663 |
-
outside_tolerance_indices = filtered_indices[outside_tolerance_filtered_indices]
|
| 664 |
-
|
| 665 |
-
outside_tolerances = []
|
| 666 |
-
for idx in outside_tolerance_indices:
|
| 667 |
-
entry = {
|
| 668 |
-
"timestamps": [timestamps[idx], timestamps[idx + 1]],
|
| 669 |
-
"diff": diffs[idx],
|
| 670 |
-
"episode_index": episode_indices[idx].item()
|
| 671 |
-
if hasattr(episode_indices[idx], "item")
|
| 672 |
-
else episode_indices[idx],
|
| 673 |
-
}
|
| 674 |
-
outside_tolerances.append(entry)
|
| 675 |
-
|
| 676 |
-
if raise_value_error:
|
| 677 |
-
raise ValueError(
|
| 678 |
-
f"""One or several timestamps unexpectedly violate the tolerance inside episode range.
|
| 679 |
-
This might be due to synchronization issues during data collection.
|
| 680 |
-
\n{pformat(outside_tolerances)}"""
|
| 681 |
-
)
|
| 682 |
-
return False
|
| 683 |
-
|
| 684 |
-
return True
|
| 685 |
-
|
| 686 |
-
|
| 687 |
-
def check_delta_timestamps(
|
| 688 |
-
delta_timestamps: dict[str, list[float]], fps: int, tolerance_s: float, raise_value_error: bool = True
|
| 689 |
-
) -> bool:
|
| 690 |
-
"""This will check if all the values in delta_timestamps are multiples of 1/fps +/- tolerance.
|
| 691 |
-
This is to ensure that these delta_timestamps added to any timestamp from a dataset will themselves be
|
| 692 |
-
actual timestamps from the dataset.
|
| 693 |
-
"""
|
| 694 |
-
outside_tolerance = {}
|
| 695 |
-
for key, delta_ts in delta_timestamps.items():
|
| 696 |
-
within_tolerance = [abs(ts * fps - round(ts * fps)) / fps <= tolerance_s for ts in delta_ts]
|
| 697 |
-
if not all(within_tolerance):
|
| 698 |
-
outside_tolerance[key] = [
|
| 699 |
-
ts for ts, is_within in zip(delta_ts, within_tolerance, strict=True) if not is_within
|
| 700 |
-
]
|
| 701 |
-
|
| 702 |
-
if len(outside_tolerance) > 0:
|
| 703 |
-
if raise_value_error:
|
| 704 |
-
raise ValueError(
|
| 705 |
-
f"""
|
| 706 |
-
The following delta_timestamps are found outside of tolerance range.
|
| 707 |
-
Please make sure they are multiples of 1/{fps} +/- tolerance and adjust
|
| 708 |
-
their values accordingly.
|
| 709 |
-
\n{pformat(outside_tolerance)}
|
| 710 |
-
"""
|
| 711 |
-
)
|
| 712 |
-
return False
|
| 713 |
-
|
| 714 |
-
return True
|
| 715 |
-
|
| 716 |
-
|
| 717 |
-
def get_delta_indices(delta_timestamps: dict[str, list[float]], fps: int) -> dict[str, list[int]]:
|
| 718 |
-
delta_indices = {}
|
| 719 |
-
for key, delta_ts in delta_timestamps.items():
|
| 720 |
-
delta_indices[key] = [round(d * fps) for d in delta_ts]
|
| 721 |
-
|
| 722 |
-
return delta_indices
|
| 723 |
-
|
| 724 |
-
|
| 725 |
-
def cycle(iterable):
|
| 726 |
-
"""The equivalent of itertools.cycle, but safe for Pytorch dataloaders.
|
| 727 |
-
|
| 728 |
-
See https://github.com/pytorch/pytorch/issues/23900 for information on why itertools.cycle is not safe.
|
| 729 |
-
"""
|
| 730 |
-
iterator = iter(iterable)
|
| 731 |
-
while True:
|
| 732 |
-
try:
|
| 733 |
-
yield next(iterator)
|
| 734 |
-
except StopIteration:
|
| 735 |
-
iterator = iter(iterable)
|
| 736 |
-
|
| 737 |
-
|
| 738 |
-
def create_branch(repo_id, *, branch: str, repo_type: str | None = None) -> None:
|
| 739 |
-
"""Create a branch on a existing Hugging Face repo. Delete the branch if it already
|
| 740 |
-
exists before creating it.
|
| 741 |
-
"""
|
| 742 |
-
api = HfApi()
|
| 743 |
-
|
| 744 |
-
branches = api.list_repo_refs(repo_id, repo_type=repo_type).branches
|
| 745 |
-
refs = [branch.ref for branch in branches]
|
| 746 |
-
ref = f"refs/heads/{branch}"
|
| 747 |
-
if ref in refs:
|
| 748 |
-
api.delete_branch(repo_id, repo_type=repo_type, branch=branch)
|
| 749 |
-
|
| 750 |
-
api.create_branch(repo_id, repo_type=repo_type, branch=branch)
|
| 751 |
-
|
| 752 |
-
|
| 753 |
-
def create_lerobot_dataset_card(
|
| 754 |
-
tags: list | None = None,
|
| 755 |
-
dataset_info: dict | None = None,
|
| 756 |
-
**kwargs,
|
| 757 |
-
) -> DatasetCard:
|
| 758 |
-
"""
|
| 759 |
-
Keyword arguments will be used to replace values in src/lerobot/datasets/card_template.md.
|
| 760 |
-
Note: If specified, license must be one of https://huggingface.co/docs/hub/repositories-licenses.
|
| 761 |
-
"""
|
| 762 |
-
card_tags = ["LeRobot"]
|
| 763 |
-
|
| 764 |
-
if tags:
|
| 765 |
-
card_tags += tags
|
| 766 |
-
if dataset_info:
|
| 767 |
-
dataset_structure = "[meta/info.json](meta/info.json):\n"
|
| 768 |
-
dataset_structure += f"```json\n{json.dumps(dataset_info, indent=4)}\n```\n"
|
| 769 |
-
kwargs = {**kwargs, "dataset_structure": dataset_structure}
|
| 770 |
-
card_data = DatasetCardData(
|
| 771 |
-
license=kwargs.get("license"),
|
| 772 |
-
tags=card_tags,
|
| 773 |
-
task_categories=["robotics"],
|
| 774 |
-
configs=[
|
| 775 |
-
{
|
| 776 |
-
"config_name": "default",
|
| 777 |
-
"data_files": "data/*/*.parquet",
|
| 778 |
-
}
|
| 779 |
-
],
|
| 780 |
-
)
|
| 781 |
-
|
| 782 |
-
card_template = (importlib.resources.files("lerobot.datasets") / "card_template.md").read_text()
|
| 783 |
-
|
| 784 |
-
return DatasetCard.from_template(
|
| 785 |
-
card_data=card_data,
|
| 786 |
-
template_str=card_template,
|
| 787 |
-
**kwargs,
|
| 788 |
-
)
|
| 789 |
-
|
| 790 |
-
|
| 791 |
-
class IterableNamespace(SimpleNamespace):
|
| 792 |
-
"""
|
| 793 |
-
A namespace object that supports both dictionary-like iteration and dot notation access.
|
| 794 |
-
Automatically converts nested dictionaries into IterableNamespaces.
|
| 795 |
-
|
| 796 |
-
This class extends SimpleNamespace to provide:
|
| 797 |
-
- Dictionary-style iteration over keys
|
| 798 |
-
- Access to items via both dot notation (obj.key) and brackets (obj["key"])
|
| 799 |
-
- Dictionary-like methods: items(), keys(), values()
|
| 800 |
-
- Recursive conversion of nested dictionaries
|
| 801 |
-
|
| 802 |
-
Args:
|
| 803 |
-
dictionary: Optional dictionary to initialize the namespace
|
| 804 |
-
**kwargs: Additional keyword arguments passed to SimpleNamespace
|
| 805 |
-
|
| 806 |
-
Examples:
|
| 807 |
-
>>> data = {"name": "Alice", "details": {"age": 25}}
|
| 808 |
-
>>> ns = IterableNamespace(data)
|
| 809 |
-
>>> ns.name
|
| 810 |
-
'Alice'
|
| 811 |
-
>>> ns.details.age
|
| 812 |
-
25
|
| 813 |
-
>>> list(ns.keys())
|
| 814 |
-
['name', 'details']
|
| 815 |
-
>>> for key, value in ns.items():
|
| 816 |
-
... print(f"{key}: {value}")
|
| 817 |
-
name: Alice
|
| 818 |
-
details: IterableNamespace(age=25)
|
| 819 |
-
"""
|
| 820 |
-
|
| 821 |
-
def __init__(self, dictionary: dict[str, Any] = None, **kwargs):
|
| 822 |
-
super().__init__(**kwargs)
|
| 823 |
-
if dictionary is not None:
|
| 824 |
-
for key, value in dictionary.items():
|
| 825 |
-
if isinstance(value, dict):
|
| 826 |
-
setattr(self, key, IterableNamespace(value))
|
| 827 |
-
else:
|
| 828 |
-
setattr(self, key, value)
|
| 829 |
-
|
| 830 |
-
def __iter__(self) -> Iterator[str]:
|
| 831 |
-
return iter(vars(self))
|
| 832 |
-
|
| 833 |
-
def __getitem__(self, key: str) -> Any:
|
| 834 |
-
return vars(self)[key]
|
| 835 |
-
|
| 836 |
-
def items(self):
|
| 837 |
-
return vars(self).items()
|
| 838 |
-
|
| 839 |
-
def values(self):
|
| 840 |
-
return vars(self).values()
|
| 841 |
-
|
| 842 |
-
def keys(self):
|
| 843 |
-
return vars(self).keys()
|
| 844 |
-
|
| 845 |
-
|
| 846 |
-
def validate_frame(frame: dict, features: dict):
|
| 847 |
-
expected_features = set(features) - set(DEFAULT_FEATURES)
|
| 848 |
-
actual_features = set(frame)
|
| 849 |
-
|
| 850 |
-
error_message = validate_features_presence(actual_features, expected_features)
|
| 851 |
-
|
| 852 |
-
common_features = actual_features & expected_features
|
| 853 |
-
for name in common_features - {"task"}:
|
| 854 |
-
error_message += validate_feature_dtype_and_shape(name, features[name], frame[name])
|
| 855 |
-
|
| 856 |
-
if error_message:
|
| 857 |
-
raise ValueError(error_message)
|
| 858 |
-
|
| 859 |
-
|
| 860 |
-
def validate_features_presence(actual_features: set[str], expected_features: set[str]):
|
| 861 |
-
error_message = ""
|
| 862 |
-
missing_features = expected_features - actual_features
|
| 863 |
-
extra_features = actual_features - expected_features
|
| 864 |
-
|
| 865 |
-
if missing_features or extra_features:
|
| 866 |
-
error_message += "Feature mismatch in `frame` dictionary:\n"
|
| 867 |
-
if missing_features:
|
| 868 |
-
error_message += f"Missing features: {missing_features}\n"
|
| 869 |
-
if extra_features:
|
| 870 |
-
error_message += f"Extra features: {extra_features}\n"
|
| 871 |
-
|
| 872 |
-
return error_message
|
| 873 |
-
|
| 874 |
-
def is_valid_numpy_dtype_string(dtype_str: str) -> bool:
|
| 875 |
-
"""
|
| 876 |
-
Return True if a given string can be converted to a numpy dtype.
|
| 877 |
-
"""
|
| 878 |
-
try:
|
| 879 |
-
# Attempt to convert the string to a numpy dtype
|
| 880 |
-
np.dtype(dtype_str)
|
| 881 |
-
return True
|
| 882 |
-
except TypeError:
|
| 883 |
-
# If a TypeError is raised, the string is not a valid dtype
|
| 884 |
-
return False
|
| 885 |
-
def validate_feature_dtype_and_shape(name: str, feature: dict, value: np.ndarray | PILImage.Image | str | bytes):
|
| 886 |
-
if isinstance(value, bytes) or isinstance(value, array.array): # ROS 1 and 2
|
| 887 |
-
#TODO fix bytes
|
| 888 |
-
return ""
|
| 889 |
-
expected_dtype = feature["dtype"]
|
| 890 |
-
expected_shape = feature["shape"]
|
| 891 |
-
if is_valid_numpy_dtype_string(expected_dtype):
|
| 892 |
-
return validate_feature_numpy_array(name, expected_dtype, expected_shape, value)
|
| 893 |
-
elif expected_dtype in ["image", "video"]:
|
| 894 |
-
return validate_feature_image_or_video(name, expected_shape, value)
|
| 895 |
-
elif expected_dtype == "string":
|
| 896 |
-
return validate_feature_string(name, value)
|
| 897 |
-
else:
|
| 898 |
-
raise NotImplementedError(f"The feature dtype '{expected_dtype}' is not implemented yet.")
|
| 899 |
-
|
| 900 |
-
|
| 901 |
-
def validate_feature_numpy_array(
|
| 902 |
-
name: str, expected_dtype: str, expected_shape: list[int], value: np.ndarray
|
| 903 |
-
):
|
| 904 |
-
error_message = ""
|
| 905 |
-
if isinstance(value, np.ndarray):
|
| 906 |
-
actual_dtype = value.dtype
|
| 907 |
-
actual_shape = value.shape
|
| 908 |
-
|
| 909 |
-
if actual_dtype != np.dtype(expected_dtype):
|
| 910 |
-
error_message += f"The feature '{name}' of dtype '{actual_dtype}' is not of the expected dtype '{expected_dtype}'.\n"
|
| 911 |
-
|
| 912 |
-
if actual_shape != expected_shape:
|
| 913 |
-
error_message += f"The feature '{name}' of shape '{actual_shape}' does not have the expected shape '{expected_shape}'.\n"
|
| 914 |
-
else:
|
| 915 |
-
error_message += f"The feature '{name}' is not a 'np.ndarray'. Expected type is '{expected_dtype}', but type '{type(value)}' provided instead.\n"
|
| 916 |
-
|
| 917 |
-
return error_message
|
| 918 |
-
|
| 919 |
-
|
| 920 |
-
def validate_feature_image_or_video(name: str, expected_shape: list[str], value: np.ndarray | PILImage.Image):
|
| 921 |
-
# Note: The check of pixels range ([0,1] for float and [0,255] for uint8) is done by the image writer threads.
|
| 922 |
-
error_message = ""
|
| 923 |
-
if isinstance(value, np.ndarray):
|
| 924 |
-
actual_shape = value.shape
|
| 925 |
-
c, h, w = expected_shape
|
| 926 |
-
if len(actual_shape) != 3 or (actual_shape != (c, h, w) and actual_shape != (h, w, c)):
|
| 927 |
-
error_message += f"The feature '{name}' of shape '{actual_shape}' does not have the expected shape '{(c, h, w)}' or '{(h, w, c)}'.\n"
|
| 928 |
-
elif isinstance(value, PILImage.Image):
|
| 929 |
-
pass
|
| 930 |
-
else:
|
| 931 |
-
error_message += f"The feature '{name}' is expected to be of type 'PIL.Image' or 'np.ndarray' channel first or channel last, but type '{type(value)}' provided instead.\n"
|
| 932 |
-
|
| 933 |
-
return error_message
|
| 934 |
-
|
| 935 |
-
|
| 936 |
-
def validate_feature_string(name: str, value: str):
|
| 937 |
-
if not isinstance(value, str):
|
| 938 |
-
return f"The feature '{name}' is expected to be of type 'str', but type '{type(value)}' provided instead.\n"
|
| 939 |
-
return ""
|
| 940 |
-
|
| 941 |
-
|
| 942 |
-
def validate_episode_buffer(episode_buffer: dict, total_episodes: int, features: dict):
|
| 943 |
-
if "size" not in episode_buffer:
|
| 944 |
-
raise ValueError("size key not found in episode_buffer")
|
| 945 |
-
|
| 946 |
-
if "task" not in episode_buffer:
|
| 947 |
-
raise ValueError("task key not found in episode_buffer")
|
| 948 |
-
|
| 949 |
-
if episode_buffer["episode_index"] != total_episodes:
|
| 950 |
-
# TODO(aliberts): Add option to use existing episode_index
|
| 951 |
-
raise NotImplementedError(
|
| 952 |
-
"You might have manually provided the episode_buffer with an episode_index that doesn't "
|
| 953 |
-
"match the total number of episodes already in the dataset. This is not supported for now."
|
| 954 |
-
)
|
| 955 |
-
|
| 956 |
-
if episode_buffer["size"] == 0:
|
| 957 |
-
raise ValueError("You must add one or several frames with `add_frame` before calling `add_episode`.")
|
| 958 |
-
|
| 959 |
-
buffer_keys = set(episode_buffer.keys()) - {"task", "size"}
|
| 960 |
-
if not buffer_keys == set(features):
|
| 961 |
-
raise ValueError(
|
| 962 |
-
f"Features from `episode_buffer` don't match the ones in `features`."
|
| 963 |
-
f"In episode_buffer not in features: {buffer_keys - set(features)}"
|
| 964 |
-
f"In features not in episode_buffer: {set(features) - buffer_keys}"
|
| 965 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/lerobot/datasets/video_utils.py
DELETED
|
@@ -1,527 +0,0 @@
|
|
| 1 |
-
#!/usr/bin/env python
|
| 2 |
-
|
| 3 |
-
# Copyright 2024 The HuggingFace Inc. team. All rights reserved.
|
| 4 |
-
#
|
| 5 |
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 6 |
-
# you may not use this file except in compliance with the License.
|
| 7 |
-
# You may obtain a copy of the License at
|
| 8 |
-
#
|
| 9 |
-
# http://www.apache.org/licenses/LICENSE-2.0
|
| 10 |
-
#
|
| 11 |
-
# Unless required by applicable law or agreed to in writing, software
|
| 12 |
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 13 |
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 14 |
-
# See the License for the specific language governing permissions and
|
| 15 |
-
# limitations under the License.
|
| 16 |
-
import glob
|
| 17 |
-
import importlib
|
| 18 |
-
import logging
|
| 19 |
-
import warnings
|
| 20 |
-
from dataclasses import dataclass, field
|
| 21 |
-
from pathlib import Path
|
| 22 |
-
from typing import Any, ClassVar
|
| 23 |
-
|
| 24 |
-
import av
|
| 25 |
-
import pyarrow as pa
|
| 26 |
-
import torch
|
| 27 |
-
import torchvision
|
| 28 |
-
from datasets.features.features import register_feature
|
| 29 |
-
from PIL import Image
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
def get_safe_default_codec():
|
| 33 |
-
if importlib.util.find_spec("torchcodec"):
|
| 34 |
-
return "torchcodec"
|
| 35 |
-
else:
|
| 36 |
-
logging.warning(
|
| 37 |
-
"'torchcodec' is not available in your platform, falling back to 'pyav' as a default decoder"
|
| 38 |
-
)
|
| 39 |
-
return "pyav"
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
def decode_video_frames(
|
| 43 |
-
video_path: Path | str,
|
| 44 |
-
timestamps: list[float],
|
| 45 |
-
tolerance_s: float,
|
| 46 |
-
backend: str | None = None,
|
| 47 |
-
) -> torch.Tensor:
|
| 48 |
-
"""
|
| 49 |
-
Decodes video frames using the specified backend.
|
| 50 |
-
|
| 51 |
-
Args:
|
| 52 |
-
video_path (Path): Path to the video file.
|
| 53 |
-
timestamps (list[float]): List of timestamps to extract frames.
|
| 54 |
-
tolerance_s (float): Allowed deviation in seconds for frame retrieval.
|
| 55 |
-
backend (str, optional): Backend to use for decoding. Defaults to "torchcodec" when available in the platform; otherwise, defaults to "pyav"..
|
| 56 |
-
|
| 57 |
-
Returns:
|
| 58 |
-
torch.Tensor: Decoded frames.
|
| 59 |
-
|
| 60 |
-
Currently supports torchcodec on cpu and pyav.
|
| 61 |
-
"""
|
| 62 |
-
if backend is None:
|
| 63 |
-
backend = get_safe_default_codec()
|
| 64 |
-
if backend == "torchcodec":
|
| 65 |
-
try:
|
| 66 |
-
return decode_video_frames_torchcodec(video_path, timestamps, tolerance_s)
|
| 67 |
-
except Exception as err:
|
| 68 |
-
warnings.warn(
|
| 69 |
-
f"torchcodec video decode failed ({type(err).__name__}: {err}); falling back to torchvision/pyav."
|
| 70 |
-
)
|
| 71 |
-
return decode_video_frames_torchvision(video_path, timestamps, tolerance_s, backend="pyav")
|
| 72 |
-
elif backend in ["pyav", "video_reader"]:
|
| 73 |
-
return decode_video_frames_torchvision(video_path, timestamps, tolerance_s, backend)
|
| 74 |
-
else:
|
| 75 |
-
raise ValueError(f"Unsupported video backend: {backend}")
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
def decode_video_frames_torchvision(
|
| 79 |
-
video_path: Path | str,
|
| 80 |
-
timestamps: list[float],
|
| 81 |
-
tolerance_s: float,
|
| 82 |
-
backend: str = "pyav",
|
| 83 |
-
log_loaded_timestamps: bool = False,
|
| 84 |
-
) -> torch.Tensor:
|
| 85 |
-
"""Loads frames associated to the requested timestamps of a video
|
| 86 |
-
|
| 87 |
-
The backend can be either "pyav" (default) or "video_reader".
|
| 88 |
-
"video_reader" requires installing torchvision from source, see:
|
| 89 |
-
https://github.com/pytorch/vision/blob/main/torchvision/csrc/io/decoder/gpu/README.rst
|
| 90 |
-
(note that you need to compile against ffmpeg<4.3)
|
| 91 |
-
|
| 92 |
-
While both use cpu, "video_reader" is supposedly faster than "pyav" but requires additional setup.
|
| 93 |
-
For more info on video decoding, see `benchmark/video/README.md`
|
| 94 |
-
|
| 95 |
-
See torchvision doc for more info on these two backends:
|
| 96 |
-
https://pytorch.org/vision/0.18/index.html?highlight=backend#torchvision.set_video_backend
|
| 97 |
-
|
| 98 |
-
Note: Video benefits from inter-frame compression. Instead of storing every frame individually,
|
| 99 |
-
the encoder stores a reference frame (or a key frame) and subsequent frames as differences relative to
|
| 100 |
-
that key frame. As a consequence, to access a requested frame, we need to load the preceding key frame,
|
| 101 |
-
and all subsequent frames until reaching the requested frame. The number of key frames in a video
|
| 102 |
-
can be adjusted during encoding to take into account decoding time and video size in bytes.
|
| 103 |
-
"""
|
| 104 |
-
video_path = str(video_path)
|
| 105 |
-
|
| 106 |
-
# set backend
|
| 107 |
-
keyframes_only = False
|
| 108 |
-
torchvision.set_video_backend(backend)
|
| 109 |
-
if backend == "pyav":
|
| 110 |
-
keyframes_only = True # pyav doesn't support accurate seek
|
| 111 |
-
|
| 112 |
-
# set a video stream reader
|
| 113 |
-
# TODO(rcadene): also load audio stream at the same time
|
| 114 |
-
reader = torchvision.io.VideoReader(video_path, "video")
|
| 115 |
-
|
| 116 |
-
# set the first and last requested timestamps
|
| 117 |
-
# Note: previous timestamps are usually loaded, since we need to access the previous key frame
|
| 118 |
-
first_ts = min(timestamps)
|
| 119 |
-
last_ts = max(timestamps)
|
| 120 |
-
|
| 121 |
-
# access closest key frame of the first requested frame
|
| 122 |
-
# Note: closest key frame timestamp is usually smaller than `first_ts` (e.g. key frame can be the first frame of the video)
|
| 123 |
-
# for details on what `seek` is doing see: https://pyav.basswood-io.com/docs/stable/api/container.html?highlight=inputcontainer#av.container.InputContainer.seek
|
| 124 |
-
reader.seek(first_ts, keyframes_only=keyframes_only)
|
| 125 |
-
|
| 126 |
-
# load all frames until last requested frame
|
| 127 |
-
loaded_frames = []
|
| 128 |
-
loaded_ts = []
|
| 129 |
-
for frame in reader:
|
| 130 |
-
current_ts = frame["pts"]
|
| 131 |
-
if log_loaded_timestamps:
|
| 132 |
-
logging.info(f"frame loaded at timestamp={current_ts:.4f}")
|
| 133 |
-
loaded_frames.append(frame["data"])
|
| 134 |
-
loaded_ts.append(current_ts)
|
| 135 |
-
if current_ts >= last_ts:
|
| 136 |
-
break
|
| 137 |
-
|
| 138 |
-
if backend == "pyav":
|
| 139 |
-
reader.container.close()
|
| 140 |
-
|
| 141 |
-
reader = None
|
| 142 |
-
|
| 143 |
-
# Use float32 for timestamp distance computation (torch.cdist doesn't support bfloat16).
|
| 144 |
-
query_ts = torch.tensor(timestamps, dtype=torch.float32)
|
| 145 |
-
loaded_ts = torch.tensor(loaded_ts, dtype=torch.float32)
|
| 146 |
-
|
| 147 |
-
# compute distances between each query timestamp and timestamps of all loaded frames
|
| 148 |
-
dist = torch.cdist(query_ts[:, None], loaded_ts[:, None], p=1)
|
| 149 |
-
min_, argmin_ = dist.min(1)
|
| 150 |
-
|
| 151 |
-
is_within_tol = min_ < tolerance_s
|
| 152 |
-
assert is_within_tol.all(), (
|
| 153 |
-
f"One or several query timestamps unexpectedly violate the tolerance ({min_[~is_within_tol]} > {tolerance_s=})."
|
| 154 |
-
"It means that the closest frame that can be loaded from the video is too far away in time."
|
| 155 |
-
"This might be due to synchronization issues with timestamps during data collection."
|
| 156 |
-
"To be safe, we advise to ignore this item during training."
|
| 157 |
-
f"\nqueried timestamps: {query_ts}"
|
| 158 |
-
f"\nloaded timestamps: {loaded_ts}"
|
| 159 |
-
f"\nvideo: {video_path}"
|
| 160 |
-
f"\nbackend: {backend}"
|
| 161 |
-
)
|
| 162 |
-
|
| 163 |
-
# get closest frames to the query timestamps
|
| 164 |
-
closest_frames = torch.stack([loaded_frames[idx] for idx in argmin_])
|
| 165 |
-
closest_ts = loaded_ts[argmin_]
|
| 166 |
-
|
| 167 |
-
if log_loaded_timestamps:
|
| 168 |
-
logging.info(f"{closest_ts=}")
|
| 169 |
-
|
| 170 |
-
# convert to the pytorch format which is float32 in [0,1] range (and channel first)
|
| 171 |
-
closest_frames = closest_frames.type(torch.float32) / 255
|
| 172 |
-
|
| 173 |
-
assert len(timestamps) == len(closest_frames)
|
| 174 |
-
return closest_frames
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
def decode_video_frames_torchcodec(
|
| 178 |
-
video_path: Path | str,
|
| 179 |
-
timestamps: list[float],
|
| 180 |
-
tolerance_s: float,
|
| 181 |
-
device: str = "cpu",
|
| 182 |
-
log_loaded_timestamps: bool = False,
|
| 183 |
-
) -> torch.Tensor:
|
| 184 |
-
"""Loads frames associated with the requested timestamps of a video using torchcodec.
|
| 185 |
-
|
| 186 |
-
Note: Setting device="cuda" outside the main process, e.g. in data loader workers, will lead to CUDA initialization errors.
|
| 187 |
-
|
| 188 |
-
Note: Video benefits from inter-frame compression. Instead of storing every frame individually,
|
| 189 |
-
the encoder stores a reference frame (or a key frame) and subsequent frames as differences relative to
|
| 190 |
-
that key frame. As a consequence, to access a requested frame, we need to load the preceding key frame,
|
| 191 |
-
and all subsequent frames until reaching the requested frame. The number of key frames in a video
|
| 192 |
-
can be adjusted during encoding to take into account decoding time and video size in bytes.
|
| 193 |
-
"""
|
| 194 |
-
|
| 195 |
-
if importlib.util.find_spec("torchcodec"):
|
| 196 |
-
from torchcodec.decoders import VideoDecoder
|
| 197 |
-
else:
|
| 198 |
-
raise ImportError("torchcodec is required but not available.")
|
| 199 |
-
|
| 200 |
-
# initialize video decoder
|
| 201 |
-
decoder = VideoDecoder(video_path, device=device, seek_mode="approximate")
|
| 202 |
-
loaded_frames = []
|
| 203 |
-
loaded_ts = []
|
| 204 |
-
# get metadata for frame information
|
| 205 |
-
metadata = decoder.metadata
|
| 206 |
-
average_fps = metadata.average_fps
|
| 207 |
-
|
| 208 |
-
# convert timestamps to frame indices
|
| 209 |
-
frame_indices = [round(ts * average_fps) for ts in timestamps]
|
| 210 |
-
|
| 211 |
-
# retrieve frames based on indices
|
| 212 |
-
frames_batch = decoder.get_frames_at(indices=frame_indices)
|
| 213 |
-
|
| 214 |
-
for frame, pts in zip(frames_batch.data, frames_batch.pts_seconds, strict=False):
|
| 215 |
-
loaded_frames.append(frame)
|
| 216 |
-
loaded_ts.append(pts.item())
|
| 217 |
-
if log_loaded_timestamps:
|
| 218 |
-
logging.info(f"Frame loaded at timestamp={pts:.4f}")
|
| 219 |
-
|
| 220 |
-
# Use float32 for timestamp distance computation (torch.cdist doesn't support bfloat16).
|
| 221 |
-
query_ts = torch.tensor(timestamps, dtype=torch.float32)
|
| 222 |
-
loaded_ts = torch.tensor(loaded_ts, dtype=torch.float32)
|
| 223 |
-
|
| 224 |
-
# compute distances between each query timestamp and loaded timestamps
|
| 225 |
-
dist = torch.cdist(query_ts[:, None], loaded_ts[:, None], p=1)
|
| 226 |
-
min_, argmin_ = dist.min(1)
|
| 227 |
-
|
| 228 |
-
is_within_tol = min_ < tolerance_s
|
| 229 |
-
assert is_within_tol.all(), (
|
| 230 |
-
f"One or several query timestamps unexpectedly violate the tolerance ({min_[~is_within_tol]} > {tolerance_s=})."
|
| 231 |
-
"It means that the closest frame that can be loaded from the video is too far away in time."
|
| 232 |
-
"This might be due to synchronization issues with timestamps during data collection."
|
| 233 |
-
"To be safe, we advise to ignore this item during training."
|
| 234 |
-
f"\nqueried timestamps: {query_ts}"
|
| 235 |
-
f"\nloaded timestamps: {loaded_ts}"
|
| 236 |
-
f"\nvideo: {video_path}"
|
| 237 |
-
)
|
| 238 |
-
|
| 239 |
-
# get closest frames to the query timestamps
|
| 240 |
-
closest_frames = torch.stack([loaded_frames[idx] for idx in argmin_])
|
| 241 |
-
closest_ts = loaded_ts[argmin_]
|
| 242 |
-
|
| 243 |
-
if log_loaded_timestamps:
|
| 244 |
-
logging.info(f"{closest_ts=}")
|
| 245 |
-
|
| 246 |
-
# convert to float32 in [0,1] range (channel first)
|
| 247 |
-
closest_frames = closest_frames.type(torch.float32) / 255
|
| 248 |
-
|
| 249 |
-
assert len(timestamps) == len(closest_frames)
|
| 250 |
-
return closest_frames
|
| 251 |
-
|
| 252 |
-
def encode_video_frames(
|
| 253 |
-
imgs_dir: Path | str,
|
| 254 |
-
video_path: Path | str,
|
| 255 |
-
fps: int,
|
| 256 |
-
vcodec: str = "libsvtav1",
|
| 257 |
-
pix_fmt: str = "yuv420p",
|
| 258 |
-
g: int | None = 2,
|
| 259 |
-
crf: int | None = 30,
|
| 260 |
-
fast_decode: int = 0,
|
| 261 |
-
log_level: int | None = av.logging.ERROR,
|
| 262 |
-
overwrite: bool = False,
|
| 263 |
-
) -> None:
|
| 264 |
-
"""More info on ffmpeg arguments tuning on `benchmark/video/README.md`"""
|
| 265 |
-
# Check encoder availability
|
| 266 |
-
if vcodec == "h264_nvenc" :
|
| 267 |
-
return encode_video_frames_ffmpeg(
|
| 268 |
-
imgs_dir, video_path, fps, pix_fmt = pix_fmt, overwrite=overwrite
|
| 269 |
-
)
|
| 270 |
-
|
| 271 |
-
if vcodec not in ["h264", "hevc", "libsvtav1"]:
|
| 272 |
-
raise ValueError(f"Unsupported video codec: {vcodec}. Supported codecs are: h264, hevc, libsvtav1.")
|
| 273 |
-
|
| 274 |
-
video_path = Path(video_path)
|
| 275 |
-
imgs_dir = Path(imgs_dir)
|
| 276 |
-
|
| 277 |
-
video_path.parent.mkdir(parents=True, exist_ok=overwrite)
|
| 278 |
-
|
| 279 |
-
# Encoders/pixel formats incompatibility check
|
| 280 |
-
if (vcodec == "libsvtav1" or vcodec == "hevc") and pix_fmt == "yuv444p":
|
| 281 |
-
logging.warning(
|
| 282 |
-
f"Incompatible pixel format 'yuv444p' for codec {vcodec}, auto-selecting format 'yuv420p'"
|
| 283 |
-
)
|
| 284 |
-
pix_fmt = "yuv420p"
|
| 285 |
-
|
| 286 |
-
# Get input frames
|
| 287 |
-
template = "frame_" + ("[0-9]" * 6) + ".jpeg"
|
| 288 |
-
input_list = sorted(
|
| 289 |
-
glob.glob(str(imgs_dir / template)), key=lambda x: int(x.split("_")[-1].split(".")[0])
|
| 290 |
-
)
|
| 291 |
-
|
| 292 |
-
# Define video output frame size (assuming all input frames are the same size)
|
| 293 |
-
if len(input_list) == 0:
|
| 294 |
-
raise FileNotFoundError(f"No images found in {imgs_dir}.")
|
| 295 |
-
dummy_image = Image.open(input_list[0])
|
| 296 |
-
width, height = dummy_image.size
|
| 297 |
-
|
| 298 |
-
# Define video codec options
|
| 299 |
-
video_options = {}
|
| 300 |
-
|
| 301 |
-
if g is not None:
|
| 302 |
-
video_options["g"] = str(g)
|
| 303 |
-
|
| 304 |
-
if crf is not None:
|
| 305 |
-
video_options["crf"] = str(crf)
|
| 306 |
-
|
| 307 |
-
if fast_decode:
|
| 308 |
-
key = "svtav1-params" if vcodec == "libsvtav1" else "tune"
|
| 309 |
-
value = f"fast-decode={fast_decode}" if vcodec == "libsvtav1" else "fastdecode"
|
| 310 |
-
video_options[key] = value
|
| 311 |
-
|
| 312 |
-
# Set logging level
|
| 313 |
-
if log_level is not None:
|
| 314 |
-
# "While less efficient, it is generally preferable to modify logging with Python’s logging"
|
| 315 |
-
logging.getLogger("libav").setLevel(log_level)
|
| 316 |
-
|
| 317 |
-
# Create and open output file (overwrite by default)
|
| 318 |
-
with av.open(str(video_path), "w") as output:
|
| 319 |
-
output_stream = output.add_stream(vcodec, fps, options=video_options)
|
| 320 |
-
output_stream.pix_fmt = pix_fmt
|
| 321 |
-
output_stream.width = width
|
| 322 |
-
output_stream.height = height
|
| 323 |
-
|
| 324 |
-
# Loop through input frames and encode them
|
| 325 |
-
for input_data in input_list:
|
| 326 |
-
input_image = Image.open(input_data).convert("RGB")
|
| 327 |
-
input_frame = av.VideoFrame.from_image(input_image)
|
| 328 |
-
packet = output_stream.encode(input_frame)
|
| 329 |
-
if packet:
|
| 330 |
-
output.mux(packet)
|
| 331 |
-
|
| 332 |
-
# Flush the encoder
|
| 333 |
-
packet = output_stream.encode()
|
| 334 |
-
if packet:
|
| 335 |
-
output.mux(packet)
|
| 336 |
-
|
| 337 |
-
# Reset logging level
|
| 338 |
-
if log_level is not None:
|
| 339 |
-
av.logging.restore_default_callback()
|
| 340 |
-
|
| 341 |
-
if not video_path.exists():
|
| 342 |
-
raise OSError(f"Video encoding did not work. File not found: {video_path}.")
|
| 343 |
-
|
| 344 |
-
# GPU speed up video encoding
|
| 345 |
-
def encode_video_frames_ffmpeg(
|
| 346 |
-
imgs_dir: Path | str,
|
| 347 |
-
video_path: Path | str,
|
| 348 |
-
fps: int,
|
| 349 |
-
vcodec: str = "h264_nvenc",
|
| 350 |
-
pix_fmt: str = "yuv420p",
|
| 351 |
-
g: int | None = 4,
|
| 352 |
-
crf: int | None = 30,
|
| 353 |
-
overwrite: bool = False,
|
| 354 |
-
) -> None:
|
| 355 |
-
import subprocess
|
| 356 |
-
import shutil
|
| 357 |
-
|
| 358 |
-
video_path = Path(video_path)
|
| 359 |
-
imgs_dir = Path(imgs_dir)
|
| 360 |
-
|
| 361 |
-
video_path.parent.mkdir(parents=True, exist_ok=True)
|
| 362 |
-
|
| 363 |
-
# Check if ffmpeg is available
|
| 364 |
-
ffmpeg_path = shutil.which("ffmpeg")
|
| 365 |
-
if ffmpeg_path is None:
|
| 366 |
-
raise RuntimeError("ffmpeg is not installed or not in system PATH")
|
| 367 |
-
|
| 368 |
-
# Build ffmpeg command
|
| 369 |
-
cmd = [
|
| 370 |
-
ffmpeg_path,
|
| 371 |
-
"-y" if overwrite else "-n",
|
| 372 |
-
"-framerate", str(fps),
|
| 373 |
-
"-pattern_type", "sequence",
|
| 374 |
-
"-i", str(imgs_dir / "frame_%06d.jpeg"),
|
| 375 |
-
"-vcodec", vcodec,
|
| 376 |
-
"-pix_fmt", pix_fmt,
|
| 377 |
-
]
|
| 378 |
-
|
| 379 |
-
if g is not None:
|
| 380 |
-
cmd.extend(["-g", str(g)])
|
| 381 |
-
|
| 382 |
-
if crf is not None:
|
| 383 |
-
cmd.extend(["-crf", str(crf)])
|
| 384 |
-
|
| 385 |
-
cmd.append(str(video_path))
|
| 386 |
-
|
| 387 |
-
try:
|
| 388 |
-
result = subprocess.run(
|
| 389 |
-
cmd,
|
| 390 |
-
capture_output=True,
|
| 391 |
-
text=True,
|
| 392 |
-
check=True
|
| 393 |
-
)
|
| 394 |
-
except subprocess.CalledProcessError as e:
|
| 395 |
-
error_msg = f"FFmpeg failed:\nCommand: {' '.join(cmd)}\nStdout: {e.stdout}\nStderr: {e.stderr}"
|
| 396 |
-
logging.error(error_msg)
|
| 397 |
-
logging.error(video_path)
|
| 398 |
-
logging.error(vcodec)
|
| 399 |
-
print(f"ffmpeg {' '.join(cmd)}")
|
| 400 |
-
raise RuntimeError(error_msg)
|
| 401 |
-
except Exception as e:
|
| 402 |
-
error_msg = f"Failed to run FFmpeg command: {' '.join(cmd)}\nError: {str(e)}"
|
| 403 |
-
logging.error(error_msg)
|
| 404 |
-
raise RuntimeError(error_msg)
|
| 405 |
-
|
| 406 |
-
|
| 407 |
-
@dataclass
|
| 408 |
-
class VideoFrame:
|
| 409 |
-
# TODO(rcadene, lhoestq): move to Hugging Face `datasets` repo
|
| 410 |
-
"""
|
| 411 |
-
Provides a type for a dataset containing video frames.
|
| 412 |
-
|
| 413 |
-
Example:
|
| 414 |
-
|
| 415 |
-
```python
|
| 416 |
-
data_dict = [{"image": {"path": "videos/episode_0.mp4", "timestamp": 0.3}}]
|
| 417 |
-
features = {"image": VideoFrame()}
|
| 418 |
-
Dataset.from_dict(data_dict, features=Features(features))
|
| 419 |
-
```
|
| 420 |
-
"""
|
| 421 |
-
|
| 422 |
-
pa_type: ClassVar[Any] = pa.struct({"path": pa.string(), "timestamp": pa.float32()})
|
| 423 |
-
_type: str = field(default="VideoFrame", init=False, repr=False)
|
| 424 |
-
|
| 425 |
-
def __call__(self):
|
| 426 |
-
return self.pa_type
|
| 427 |
-
|
| 428 |
-
|
| 429 |
-
with warnings.catch_warnings():
|
| 430 |
-
warnings.filterwarnings(
|
| 431 |
-
"ignore",
|
| 432 |
-
"'register_feature' is experimental and might be subject to breaking changes in the future.",
|
| 433 |
-
category=UserWarning,
|
| 434 |
-
)
|
| 435 |
-
# to make VideoFrame available in HuggingFace `datasets`
|
| 436 |
-
register_feature(VideoFrame, "VideoFrame")
|
| 437 |
-
|
| 438 |
-
|
| 439 |
-
def get_audio_info(video_path: Path | str) -> dict:
|
| 440 |
-
# Set logging level
|
| 441 |
-
logging.getLogger("libav").setLevel(av.logging.ERROR)
|
| 442 |
-
|
| 443 |
-
# Getting audio stream information
|
| 444 |
-
audio_info = {}
|
| 445 |
-
with av.open(str(video_path), "r") as audio_file:
|
| 446 |
-
try:
|
| 447 |
-
audio_stream = audio_file.streams.audio[0]
|
| 448 |
-
except IndexError:
|
| 449 |
-
# Reset logging level
|
| 450 |
-
av.logging.restore_default_callback()
|
| 451 |
-
return {"has_audio": False}
|
| 452 |
-
|
| 453 |
-
audio_info["audio.channels"] = audio_stream.channels
|
| 454 |
-
audio_info["audio.codec"] = audio_stream.codec.canonical_name
|
| 455 |
-
# In an ideal loseless case : bit depth x sample rate x channels = bit rate.
|
| 456 |
-
# In an actual compressed case, the bit rate is set according to the compression level : the lower the bit rate, the more compression is applied.
|
| 457 |
-
audio_info["audio.bit_rate"] = audio_stream.bit_rate
|
| 458 |
-
audio_info["audio.sample_rate"] = audio_stream.sample_rate # Number of samples per second
|
| 459 |
-
# In an ideal loseless case : fixed number of bits per sample.
|
| 460 |
-
# In an actual compressed case : variable number of bits per sample (often reduced to match a given depth rate).
|
| 461 |
-
audio_info["audio.bit_depth"] = audio_stream.format.bits
|
| 462 |
-
audio_info["audio.channel_layout"] = audio_stream.layout.name
|
| 463 |
-
audio_info["has_audio"] = True
|
| 464 |
-
|
| 465 |
-
# Reset logging level
|
| 466 |
-
av.logging.restore_default_callback()
|
| 467 |
-
|
| 468 |
-
return audio_info
|
| 469 |
-
|
| 470 |
-
|
| 471 |
-
def get_video_info(video_path: Path | str) -> dict:
|
| 472 |
-
# Set logging level
|
| 473 |
-
logging.getLogger("libav").setLevel(av.logging.ERROR)
|
| 474 |
-
|
| 475 |
-
# Getting video stream information
|
| 476 |
-
video_info = {}
|
| 477 |
-
with av.open(str(video_path), "r") as video_file:
|
| 478 |
-
try:
|
| 479 |
-
video_stream = video_file.streams.video[0]
|
| 480 |
-
except IndexError:
|
| 481 |
-
# Reset logging level
|
| 482 |
-
av.logging.restore_default_callback()
|
| 483 |
-
return {}
|
| 484 |
-
|
| 485 |
-
video_info["video.height"] = video_stream.height
|
| 486 |
-
video_info["video.width"] = video_stream.width
|
| 487 |
-
video_info["video.codec"] = video_stream.codec.canonical_name
|
| 488 |
-
video_info["video.pix_fmt"] = video_stream.pix_fmt
|
| 489 |
-
video_info["video.is_depth_map"] = False
|
| 490 |
-
|
| 491 |
-
# Calculate fps from r_frame_rate
|
| 492 |
-
video_info["video.fps"] = int(video_stream.base_rate)
|
| 493 |
-
|
| 494 |
-
pixel_channels = get_video_pixel_channels(video_stream.pix_fmt)
|
| 495 |
-
video_info["video.channels"] = pixel_channels
|
| 496 |
-
|
| 497 |
-
# Reset logging level
|
| 498 |
-
av.logging.restore_default_callback()
|
| 499 |
-
|
| 500 |
-
# Adding audio stream information
|
| 501 |
-
video_info.update(**get_audio_info(video_path))
|
| 502 |
-
|
| 503 |
-
return video_info
|
| 504 |
-
|
| 505 |
-
|
| 506 |
-
def get_video_pixel_channels(pix_fmt: str) -> int:
|
| 507 |
-
if "gray" in pix_fmt or "depth" in pix_fmt or "monochrome" in pix_fmt:
|
| 508 |
-
return 1
|
| 509 |
-
elif "rgba" in pix_fmt or "yuva" in pix_fmt:
|
| 510 |
-
return 4
|
| 511 |
-
elif "rgb" in pix_fmt or "yuv" in pix_fmt:
|
| 512 |
-
return 3
|
| 513 |
-
else:
|
| 514 |
-
raise ValueError("Unknown format")
|
| 515 |
-
|
| 516 |
-
|
| 517 |
-
def get_image_pixel_channels(image: Image):
|
| 518 |
-
if image.mode == "L":
|
| 519 |
-
return 1 # Grayscale
|
| 520 |
-
elif image.mode == "LA":
|
| 521 |
-
return 2 # Grayscale + Alpha
|
| 522 |
-
elif image.mode == "RGB":
|
| 523 |
-
return 3 # RGB
|
| 524 |
-
elif image.mode == "RGBA":
|
| 525 |
-
return 4 # RGBA
|
| 526 |
-
else:
|
| 527 |
-
raise ValueError("Unknown format")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/lerobot/lerobot_dataset.py
DELETED
|
@@ -1,1404 +0,0 @@
|
|
| 1 |
-
#!/usr/bin/env python
|
| 2 |
-
|
| 3 |
-
# Copyright 2024 The HuggingFace Inc. team. All rights reserved.
|
| 4 |
-
#
|
| 5 |
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 6 |
-
# you may not use this file except in compliance with the License.
|
| 7 |
-
# You may obtain a copy of the License at
|
| 8 |
-
#
|
| 9 |
-
# http://www.apache.org/licenses/LICENSE-2.0
|
| 10 |
-
#
|
| 11 |
-
# Unless required by applicable law or agreed to in writing, software
|
| 12 |
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 13 |
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 14 |
-
# See the License for the specific language governing permissions and
|
| 15 |
-
# limitations under the License.
|
| 16 |
-
import contextlib
|
| 17 |
-
import logging
|
| 18 |
-
import shutil
|
| 19 |
-
from pathlib import Path
|
| 20 |
-
from typing import Callable, List, Literal
|
| 21 |
-
import warnings
|
| 22 |
-
|
| 23 |
-
import datasets
|
| 24 |
-
import numpy as np
|
| 25 |
-
import packaging.version
|
| 26 |
-
import PIL.Image
|
| 27 |
-
import torch
|
| 28 |
-
import torch.utils
|
| 29 |
-
import pyarrow.parquet as pq
|
| 30 |
-
from datasets import concatenate_datasets, load_dataset
|
| 31 |
-
from huggingface_hub import HfApi, snapshot_download
|
| 32 |
-
from huggingface_hub.constants import REPOCARD_NAME
|
| 33 |
-
from huggingface_hub.errors import RevisionNotFoundError
|
| 34 |
-
|
| 35 |
-
# adapte to own path
|
| 36 |
-
from ..constants import HF_LEROBOT_HOME
|
| 37 |
-
from .datasets.compute_stats import aggregate_stats, compute_episode_stats
|
| 38 |
-
from .datasets.utils import (
|
| 39 |
-
DEFAULT_FEATURES,
|
| 40 |
-
DEFAULT_IMAGE_PATH,
|
| 41 |
-
DEFAULT_DATA_PATH_V30,
|
| 42 |
-
DEFAULT_VIDEO_PATH_V30,
|
| 43 |
-
INFO_PATH,
|
| 44 |
-
TASKS_PATH,
|
| 45 |
-
_validate_feature_names,
|
| 46 |
-
append_jsonlines,
|
| 47 |
-
backward_compatible_episodes_stats,
|
| 48 |
-
check_delta_timestamps,
|
| 49 |
-
check_timestamps_sync,
|
| 50 |
-
# check_version_compatibility,
|
| 51 |
-
create_empty_dataset_info,
|
| 52 |
-
create_lerobot_dataset_card,
|
| 53 |
-
embed_images,
|
| 54 |
-
get_delta_indices,
|
| 55 |
-
get_episode_data_index,
|
| 56 |
-
get_hf_features_from_features,
|
| 57 |
-
# get_safe_version,
|
| 58 |
-
hf_transform_to_torch,
|
| 59 |
-
is_valid_version,
|
| 60 |
-
load_episodes,
|
| 61 |
-
load_episodes_stats,
|
| 62 |
-
load_episodes_v30,
|
| 63 |
-
load_info,
|
| 64 |
-
load_stats,
|
| 65 |
-
load_tasks,
|
| 66 |
-
load_tasks_v30,
|
| 67 |
-
load_annotations,
|
| 68 |
-
validate_episode_buffer,
|
| 69 |
-
validate_frame,
|
| 70 |
-
write_episode,
|
| 71 |
-
write_episode_stats,
|
| 72 |
-
write_info,
|
| 73 |
-
write_json,
|
| 74 |
-
)
|
| 75 |
-
from .datasets.video_utils import (
|
| 76 |
-
VideoFrame,
|
| 77 |
-
decode_video_frames,
|
| 78 |
-
encode_video_frames,
|
| 79 |
-
get_safe_default_codec,
|
| 80 |
-
get_video_info,
|
| 81 |
-
)
|
| 82 |
-
import traceback
|
| 83 |
-
|
| 84 |
-
CODEBASE_VERSION = "v2.1"
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
def dataset_dir_to_repo_id(dataset_dir: str | Path) -> str:
|
| 88 |
-
"""Return a valid repo id while preserving local paths as dataset roots.
|
| 89 |
-
|
| 90 |
-
LeRobot accepts a local ``root`` and a Hub-style ``repo_id``. Several local
|
| 91 |
-
training configs pass paths such as ``./data/libero_...`` as
|
| 92 |
-
``dataset_dirs``; using that path string as ``repo_id`` trips HuggingFace
|
| 93 |
-
validation even though the dataset is local. For local paths, use the leaf
|
| 94 |
-
directory name as a stable, valid dataset id while keeping the original path
|
| 95 |
-
for ``root``.
|
| 96 |
-
"""
|
| 97 |
-
ds_path = Path(dataset_dir)
|
| 98 |
-
ds_str = str(dataset_dir)
|
| 99 |
-
if ds_path.is_absolute() or ds_str.startswith(".") or ds_path.exists():
|
| 100 |
-
return ds_path.name
|
| 101 |
-
return ds_str
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
class LeRobotDatasetMetadata:
|
| 105 |
-
def __init__(
|
| 106 |
-
self,
|
| 107 |
-
repo_id: str,
|
| 108 |
-
root: str | Path | None = None,
|
| 109 |
-
revision: str | None = None,
|
| 110 |
-
force_cache_sync: bool = False,
|
| 111 |
-
):
|
| 112 |
-
self.repo_id = repo_id
|
| 113 |
-
self.revision = revision if revision else CODEBASE_VERSION
|
| 114 |
-
self.root = Path(root) if root is not None else HF_LEROBOT_HOME / repo_id
|
| 115 |
-
|
| 116 |
-
try:
|
| 117 |
-
if force_cache_sync:
|
| 118 |
-
raise FileNotFoundError
|
| 119 |
-
self.load_metadata()
|
| 120 |
-
except (FileNotFoundError, NotADirectoryError):
|
| 121 |
-
# if is_valid_version(self.revision):
|
| 122 |
-
# self.revision = get_safe_version(self.repo_id, self.revision)
|
| 123 |
-
|
| 124 |
-
(self.root / "meta").mkdir(exist_ok=True, parents=True)
|
| 125 |
-
self.pull_from_repo(allow_patterns="meta/")
|
| 126 |
-
self.load_metadata()
|
| 127 |
-
|
| 128 |
-
def load_metadata(self):
|
| 129 |
-
self.info = load_info(self.root)
|
| 130 |
-
# TODO add new check
|
| 131 |
-
# check_version_compatibility(self.repo_id, self._version, CODEBASE_VERSION)
|
| 132 |
-
if self._version >= packaging.version.parse("v3.0"):
|
| 133 |
-
self.tasks, self.task_to_task_index = load_tasks_v30(self.root)
|
| 134 |
-
self.episodes = load_episodes_v30(self.root)
|
| 135 |
-
self.episodes_stats = {}
|
| 136 |
-
self.stats = load_stats(self.root) or {}
|
| 137 |
-
elif self._version < packaging.version.parse("v2.1"):
|
| 138 |
-
self.tasks, self.task_to_task_index = load_tasks(self.root)
|
| 139 |
-
if (self.root / "annotations").exists():
|
| 140 |
-
self.annotations = load_annotations(self.root)
|
| 141 |
-
self.episodes = load_episodes(self.root)
|
| 142 |
-
self.stats = load_stats(self.root)
|
| 143 |
-
self.episodes_stats = backward_compatible_episodes_stats(self.stats, self.episodes)
|
| 144 |
-
else:
|
| 145 |
-
self.tasks, self.task_to_task_index = load_tasks(self.root)
|
| 146 |
-
if (self.root / "annotations").exists():
|
| 147 |
-
self.annotations = load_annotations(self.root)
|
| 148 |
-
self.episodes = load_episodes(self.root)
|
| 149 |
-
self.episodes_stats = load_episodes_stats(self.root)
|
| 150 |
-
self.stats = aggregate_stats(list(self.episodes_stats.values()))
|
| 151 |
-
|
| 152 |
-
def pull_from_repo(
|
| 153 |
-
self,
|
| 154 |
-
allow_patterns: list[str] | str | None = None,
|
| 155 |
-
ignore_patterns: list[str] | str | None = None,
|
| 156 |
-
) -> None:
|
| 157 |
-
snapshot_download(
|
| 158 |
-
self.repo_id,
|
| 159 |
-
repo_type="dataset",
|
| 160 |
-
revision=self.revision,
|
| 161 |
-
local_dir=self.root,
|
| 162 |
-
allow_patterns=allow_patterns,
|
| 163 |
-
ignore_patterns=ignore_patterns,
|
| 164 |
-
)
|
| 165 |
-
|
| 166 |
-
@property
|
| 167 |
-
def _version(self) -> packaging.version.Version:
|
| 168 |
-
"""Codebase version used to create this dataset."""
|
| 169 |
-
return packaging.version.parse(self.info["codebase_version"])
|
| 170 |
-
|
| 171 |
-
def get_data_file_path(self, ep_index: int) -> Path:
|
| 172 |
-
if self._version >= packaging.version.parse("v3.0"):
|
| 173 |
-
ep = self.episodes[ep_index]
|
| 174 |
-
fpath = DEFAULT_DATA_PATH_V30.format(
|
| 175 |
-
chunk_index=int(ep["data/chunk_index"]),
|
| 176 |
-
file_index=int(ep["data/file_index"]),
|
| 177 |
-
)
|
| 178 |
-
else:
|
| 179 |
-
ep_chunk = self.get_episode_chunk(ep_index)
|
| 180 |
-
fpath = self.data_path.format(episode_chunk=ep_chunk, episode_index=ep_index)
|
| 181 |
-
return Path(fpath)
|
| 182 |
-
|
| 183 |
-
def get_video_file_path(self, ep_index: int, vid_key: str) -> Path:
|
| 184 |
-
if self._version >= packaging.version.parse("v3.0"):
|
| 185 |
-
ep = self.episodes[ep_index]
|
| 186 |
-
fpath = DEFAULT_VIDEO_PATH_V30.format(
|
| 187 |
-
video_key=vid_key,
|
| 188 |
-
chunk_index=int(ep[f"videos/{vid_key}/chunk_index"]),
|
| 189 |
-
file_index=int(ep[f"videos/{vid_key}/file_index"]),
|
| 190 |
-
)
|
| 191 |
-
else:
|
| 192 |
-
ep_chunk = self.get_episode_chunk(ep_index)
|
| 193 |
-
fpath = self.video_path.format(episode_chunk=ep_chunk, video_key=vid_key, episode_index=ep_index)
|
| 194 |
-
return Path(fpath)
|
| 195 |
-
|
| 196 |
-
def get_episode_chunk(self, ep_index: int) -> int:
|
| 197 |
-
return ep_index // self.chunks_size
|
| 198 |
-
|
| 199 |
-
@property
|
| 200 |
-
def data_path(self) -> str:
|
| 201 |
-
"""Formattable string for the parquet files."""
|
| 202 |
-
return self.info["data_path"]
|
| 203 |
-
|
| 204 |
-
@property
|
| 205 |
-
def video_path(self) -> str | None:
|
| 206 |
-
"""Formattable string for the video files."""
|
| 207 |
-
return self.info["video_path"]
|
| 208 |
-
|
| 209 |
-
@property
|
| 210 |
-
def robot_type(self) -> str | None:
|
| 211 |
-
"""Robot type used in recording this dataset."""
|
| 212 |
-
return self.info["robot_type"]
|
| 213 |
-
|
| 214 |
-
@property
|
| 215 |
-
def fps(self) -> int:
|
| 216 |
-
"""Frames per second used during data collection."""
|
| 217 |
-
return self.info["fps"]
|
| 218 |
-
|
| 219 |
-
@property
|
| 220 |
-
def features(self) -> dict[str, dict]:
|
| 221 |
-
"""All features contained in the dataset."""
|
| 222 |
-
return self.info["features"]
|
| 223 |
-
|
| 224 |
-
@property
|
| 225 |
-
def image_keys(self) -> list[str]:
|
| 226 |
-
"""Keys to access visual modalities stored as images."""
|
| 227 |
-
return [key for key, ft in self.features.items() if ft["dtype"] == "image"]
|
| 228 |
-
|
| 229 |
-
@property
|
| 230 |
-
def video_keys(self) -> list[str]:
|
| 231 |
-
"""Keys to access visual modalities stored as videos."""
|
| 232 |
-
return [key for key, ft in self.features.items() if ft["dtype"] == "video"]
|
| 233 |
-
|
| 234 |
-
@property
|
| 235 |
-
def camera_keys(self) -> list[str]:
|
| 236 |
-
"""Keys to access visual modalities (regardless of their storage method)."""
|
| 237 |
-
return [key for key, ft in self.features.items() if ft["dtype"] in ["video", "image"]]
|
| 238 |
-
|
| 239 |
-
@property
|
| 240 |
-
def names(self) -> dict[str, list | dict]:
|
| 241 |
-
"""Names of the various dimensions of vector modalities."""
|
| 242 |
-
return {key: ft["names"] for key, ft in self.features.items()}
|
| 243 |
-
|
| 244 |
-
@property
|
| 245 |
-
def shapes(self) -> dict:
|
| 246 |
-
"""Shapes for the different features."""
|
| 247 |
-
return {key: tuple(ft["shape"]) for key, ft in self.features.items()}
|
| 248 |
-
|
| 249 |
-
@property
|
| 250 |
-
def total_episodes(self) -> int:
|
| 251 |
-
"""Total number of episodes available."""
|
| 252 |
-
return self.info["total_episodes"]
|
| 253 |
-
|
| 254 |
-
@property
|
| 255 |
-
def total_frames(self) -> int:
|
| 256 |
-
"""Total number of frames saved in this dataset."""
|
| 257 |
-
return self.info["total_frames"]
|
| 258 |
-
|
| 259 |
-
@property
|
| 260 |
-
def total_tasks(self) -> int:
|
| 261 |
-
"""Total number of different tasks performed in this dataset."""
|
| 262 |
-
return self.info["total_tasks"]
|
| 263 |
-
|
| 264 |
-
@property
|
| 265 |
-
def total_chunks(self) -> int:
|
| 266 |
-
"""Total number of chunks (groups of episodes)."""
|
| 267 |
-
return self.info["total_chunks"]
|
| 268 |
-
|
| 269 |
-
@property
|
| 270 |
-
def chunks_size(self) -> int:
|
| 271 |
-
"""Max number of episodes per chunk."""
|
| 272 |
-
return self.info["chunks_size"]
|
| 273 |
-
|
| 274 |
-
def get_task_index(self, task: str) -> int | None:
|
| 275 |
-
"""
|
| 276 |
-
Given a task in natural language, returns its task_index if the task already exists in the dataset,
|
| 277 |
-
otherwise return None.
|
| 278 |
-
"""
|
| 279 |
-
return self.task_to_task_index.get(task, None)
|
| 280 |
-
|
| 281 |
-
def add_task(self, task: str):
|
| 282 |
-
"""
|
| 283 |
-
Given a task in natural language, add it to the dictionary of tasks.
|
| 284 |
-
"""
|
| 285 |
-
if task in self.task_to_task_index:
|
| 286 |
-
raise ValueError(f"The task '{task}' already exists and can't be added twice.")
|
| 287 |
-
|
| 288 |
-
task_index = self.info["total_tasks"]
|
| 289 |
-
self.task_to_task_index[task] = task_index
|
| 290 |
-
self.tasks[task_index] = task
|
| 291 |
-
self.info["total_tasks"] += 1
|
| 292 |
-
|
| 293 |
-
task_dict = {
|
| 294 |
-
"task_index": task_index,
|
| 295 |
-
"task": task,
|
| 296 |
-
}
|
| 297 |
-
append_jsonlines(task_dict, self.root / TASKS_PATH)
|
| 298 |
-
|
| 299 |
-
def save_episode(
|
| 300 |
-
self,
|
| 301 |
-
episode_index: int,
|
| 302 |
-
episode_length: int,
|
| 303 |
-
episode_tasks: list[str],
|
| 304 |
-
episode_stats: dict[str, dict],
|
| 305 |
-
raw_file_name: str | None = None,
|
| 306 |
-
) -> None:
|
| 307 |
-
self.info["total_episodes"] += 1
|
| 308 |
-
self.info["total_frames"] += episode_length
|
| 309 |
-
|
| 310 |
-
chunk = self.get_episode_chunk(episode_index)
|
| 311 |
-
if chunk >= self.total_chunks:
|
| 312 |
-
self.info["total_chunks"] += 1
|
| 313 |
-
|
| 314 |
-
self.info["splits"] = {"train": f"0:{self.info['total_episodes']}"}
|
| 315 |
-
self.info["total_videos"] += len(self.video_keys)
|
| 316 |
-
if len(self.video_keys) > 0:
|
| 317 |
-
self.update_video_info()
|
| 318 |
-
|
| 319 |
-
write_info(self.info, self.root)
|
| 320 |
-
|
| 321 |
-
episode_dict = {
|
| 322 |
-
"episode_index": episode_index,
|
| 323 |
-
"tasks": episode_tasks,
|
| 324 |
-
"length": episode_length,
|
| 325 |
-
}
|
| 326 |
-
if raw_file_name is not None:
|
| 327 |
-
episode_dict["raw_file_name"] = raw_file_name
|
| 328 |
-
|
| 329 |
-
self.episodes[episode_index] = episode_dict
|
| 330 |
-
write_episode(episode_dict, self.root)
|
| 331 |
-
|
| 332 |
-
self.episodes_stats[episode_index] = episode_stats
|
| 333 |
-
self.stats = aggregate_stats([self.stats, episode_stats]) if self.stats else episode_stats
|
| 334 |
-
write_episode_stats(episode_index, episode_stats, self.root)
|
| 335 |
-
|
| 336 |
-
def update_video_info(self) -> None:
|
| 337 |
-
"""
|
| 338 |
-
Warning: this function writes info from first episode videos, implicitly assuming that all videos have
|
| 339 |
-
been encoded the same way. Also, this means it assumes the first episode exists.
|
| 340 |
-
"""
|
| 341 |
-
for key in self.video_keys:
|
| 342 |
-
if not self.features[key].get("info", None):
|
| 343 |
-
video_path = self.root / self.get_video_file_path(ep_index=0, vid_key=key)
|
| 344 |
-
self.info["features"][key]["info"] = get_video_info(video_path)
|
| 345 |
-
|
| 346 |
-
def __repr__(self):
|
| 347 |
-
feature_keys = list(self.features)
|
| 348 |
-
return (
|
| 349 |
-
f"{self.__class__.__name__}({{\n"
|
| 350 |
-
f" Repository ID: '{self.repo_id}',\n"
|
| 351 |
-
f" Total episodes: '{self.total_episodes}',\n"
|
| 352 |
-
f" Total frames: '{self.total_frames}',\n"
|
| 353 |
-
f" Features: '{feature_keys}',\n"
|
| 354 |
-
"})',\n"
|
| 355 |
-
)
|
| 356 |
-
|
| 357 |
-
@classmethod
|
| 358 |
-
def create(
|
| 359 |
-
cls,
|
| 360 |
-
repo_id: str,
|
| 361 |
-
fps: int,
|
| 362 |
-
features: dict,
|
| 363 |
-
robot_type: str | None = None,
|
| 364 |
-
root: str | Path | None = None,
|
| 365 |
-
use_videos: bool = True,
|
| 366 |
-
) -> "LeRobotDatasetMetadata":
|
| 367 |
-
"""Creates metadata for a LeRobotDataset."""
|
| 368 |
-
obj = cls.__new__(cls)
|
| 369 |
-
obj.repo_id = repo_id
|
| 370 |
-
obj.root = Path(root) if root is not None else HF_LEROBOT_HOME / repo_id
|
| 371 |
-
|
| 372 |
-
obj.root.mkdir(parents=True, exist_ok=False)
|
| 373 |
-
|
| 374 |
-
# TODO(aliberts, rcadene): implement sanity check for features
|
| 375 |
-
features = {**features, **DEFAULT_FEATURES}
|
| 376 |
-
_validate_feature_names(features)
|
| 377 |
-
|
| 378 |
-
obj.tasks, obj.task_to_task_index = {}, {}
|
| 379 |
-
obj.episodes_stats, obj.stats, obj.episodes = {}, {}, {}
|
| 380 |
-
obj.info = create_empty_dataset_info(CODEBASE_VERSION, fps, features, use_videos, robot_type)
|
| 381 |
-
if len(obj.video_keys) > 0 and not use_videos:
|
| 382 |
-
raise ValueError()
|
| 383 |
-
write_json(obj.info, obj.root / INFO_PATH)
|
| 384 |
-
obj.revision = None
|
| 385 |
-
return obj
|
| 386 |
-
|
| 387 |
-
|
| 388 |
-
class LeRobotDataset(torch.utils.data.Dataset):
|
| 389 |
-
def __init__(
|
| 390 |
-
self,
|
| 391 |
-
repo_id: str,
|
| 392 |
-
root: str | Path | None = None,
|
| 393 |
-
episodes: list[int] | None = None,
|
| 394 |
-
image_transforms: Callable | None = None,
|
| 395 |
-
delta_timestamps: dict[list[float]] | None = None,
|
| 396 |
-
tolerance_s: float = 1e-4,
|
| 397 |
-
revision: str | None = None,
|
| 398 |
-
force_cache_sync: bool = False,
|
| 399 |
-
download_videos: bool = True,
|
| 400 |
-
video_backend: str | None = None,
|
| 401 |
-
video_codec: Literal["h264", "hevc", "libsvtav1", "h264_nvenc"] = "libsvtav1",
|
| 402 |
-
is_compute_episode_stats_image: bool = True,
|
| 403 |
-
):
|
| 404 |
-
"""
|
| 405 |
-
2 modes are available for instantiating this class, depending on 2 different use cases:
|
| 406 |
-
|
| 407 |
-
1. Your dataset already exists:
|
| 408 |
-
- On your local disk in the 'root' folder. This is typically the case when you recorded your
|
| 409 |
-
dataset locally and you may or may not have pushed it to the hub yet. Instantiating this class
|
| 410 |
-
with 'root' will load your dataset directly from disk. This can happen while you're offline (no
|
| 411 |
-
internet connection).
|
| 412 |
-
|
| 413 |
-
- On the Hugging Face Hub at the address https://huggingface.co/datasets/{repo_id} and not on
|
| 414 |
-
your local disk in the 'root' folder. Instantiating this class with this 'repo_id' will download
|
| 415 |
-
the dataset from that address and load it, pending your dataset is compliant with
|
| 416 |
-
codebase_version v2.0. If your dataset has been created before this new format, you will be
|
| 417 |
-
prompted to convert it using our conversion script from v1.6 to v2.0, which you can find at
|
| 418 |
-
lerobot/datasets/v2/convert_dataset_v1_to_v2.py.
|
| 419 |
-
|
| 420 |
-
|
| 421 |
-
2. Your dataset doesn't already exists (either on local disk or on the Hub): you can create an empty
|
| 422 |
-
LeRobotDataset with the 'create' classmethod. This can be used for recording a dataset or port an
|
| 423 |
-
existing dataset to the LeRobotDataset format.
|
| 424 |
-
|
| 425 |
-
|
| 426 |
-
In terms of files, LeRobotDataset encapsulates 3 main things:
|
| 427 |
-
- metadata:
|
| 428 |
-
- info contains various information about the dataset like shapes, keys, fps etc.
|
| 429 |
-
- stats stores the dataset statistics of the different modalities for normalization
|
| 430 |
-
- tasks contains the prompts for each task of the dataset, which can be used for
|
| 431 |
-
task-conditioned training.
|
| 432 |
-
- hf_dataset (from datasets.Dataset), which will read any values from parquet files.
|
| 433 |
-
- videos (optional) from which frames are loaded to be synchronous with data from parquet files.
|
| 434 |
-
|
| 435 |
-
A typical LeRobotDataset looks like this from its root path:
|
| 436 |
-
.
|
| 437 |
-
├── data
|
| 438 |
-
│ ├── chunk-000
|
| 439 |
-
│ │ ├── episode_000000.parquet
|
| 440 |
-
│ │ ├── episode_000001.parquet
|
| 441 |
-
│ │ ├── episode_000002.parquet
|
| 442 |
-
│ │ └── ...
|
| 443 |
-
│ ├── chunk-001
|
| 444 |
-
│ │ ├── episode_001000.parquet
|
| 445 |
-
│ │ ├── episode_001001.parquet
|
| 446 |
-
│ │ ├── episode_001002.parquet
|
| 447 |
-
│ │ └── ...
|
| 448 |
-
│ └── ...
|
| 449 |
-
├── meta
|
| 450 |
-
│ ├── episodes.jsonl
|
| 451 |
-
│ ├── info.json
|
| 452 |
-
│ ├── stats.json
|
| 453 |
-
│ └── tasks.jsonl
|
| 454 |
-
└── videos
|
| 455 |
-
├── chunk-000
|
| 456 |
-
│ ├── observation.images.laptop
|
| 457 |
-
│ │ ├── episode_000000.mp4
|
| 458 |
-
│ │ ├── episode_000001.mp4
|
| 459 |
-
│ │ ├── episode_000002.mp4
|
| 460 |
-
│ │ └── ...
|
| 461 |
-
│ ├── observation.images.phone
|
| 462 |
-
│ │ ├── episode_000000.mp4
|
| 463 |
-
│ │ ├── episode_000001.mp4
|
| 464 |
-
│ │ ├── episode_000002.mp4
|
| 465 |
-
│ │ └── ...
|
| 466 |
-
├── chunk-001
|
| 467 |
-
└── ...
|
| 468 |
-
|
| 469 |
-
Note that this file-based structure is designed to be as versatile as possible. The files are split by
|
| 470 |
-
episodes which allows a more granular control over which episodes one wants to use and download. The
|
| 471 |
-
structure of the dataset is entirely described in the info.json file, which can be easily downloaded
|
| 472 |
-
or viewed directly on the hub before downloading any actual data. The type of files used are very
|
| 473 |
-
simple and do not need complex tools to be read, it only uses .parquet, .json and .mp4 files (and .md
|
| 474 |
-
for the README).
|
| 475 |
-
|
| 476 |
-
Args:
|
| 477 |
-
repo_id (str): This is the repo id that will be used to fetch the dataset. Locally, the dataset
|
| 478 |
-
will be stored under root/repo_id.
|
| 479 |
-
root (Path | None, optional): Local directory to use for downloading/writing files. You can also
|
| 480 |
-
set the LEROBOT_HOME environment variable to point to a different location. Defaults to
|
| 481 |
-
'~/.cache/huggingface/lerobot'.
|
| 482 |
-
episodes (list[int] | None, optional): If specified, this will only load episodes specified by
|
| 483 |
-
their episode_index in this list. Defaults to None.
|
| 484 |
-
image_transforms (Callable | None, optional): You can pass standard v2 image transforms from
|
| 485 |
-
torchvision.transforms.v2 here which will be applied to visual modalities (whether they come
|
| 486 |
-
from videos or images). Defaults to None.
|
| 487 |
-
delta_timestamps (dict[list[float]] | None, optional): _description_. Defaults to None.
|
| 488 |
-
tolerance_s (float, optional): Tolerance in seconds used to ensure data timestamps are actually in
|
| 489 |
-
sync with the fps value. It is used at the init of the dataset to make sure that each
|
| 490 |
-
timestamps is separated to the next by 1/fps +/- tolerance_s. This also applies to frames
|
| 491 |
-
decoded from video files. It is also used to check that `delta_timestamps` (when provided) are
|
| 492 |
-
multiples of 1/fps. Defaults to 1e-4.
|
| 493 |
-
revision (str, optional): An optional Git revision id which can be a branch name, a tag, or a
|
| 494 |
-
commit hash. Defaults to current codebase version tag.
|
| 495 |
-
sync_cache_first (bool, optional): Flag to sync and refresh local files first. If True and files
|
| 496 |
-
are already present in the local cache, this will be faster. However, files loaded might not
|
| 497 |
-
be in sync with the version on the hub, especially if you specified 'revision'. Defaults to
|
| 498 |
-
False.
|
| 499 |
-
download_videos (bool, optional): Flag to download the videos. Note that when set to True but the
|
| 500 |
-
video files are already present on local disk, they won't be downloaded again. Defaults to
|
| 501 |
-
True.
|
| 502 |
-
video_backend (str | None, optional): Video backend to use for decoding videos. Defaults to torchcodec when available int the platform; otherwise, defaults to 'pyav'.
|
| 503 |
-
You can also use the 'pyav' decoder used by Torchvision, which used to be the default option, or 'video_reader' which is another decoder of Torchvision.
|
| 504 |
-
"""
|
| 505 |
-
super().__init__()
|
| 506 |
-
self.repo_id = repo_id
|
| 507 |
-
self.root = Path(root) if root else HF_LEROBOT_HOME / repo_id
|
| 508 |
-
self.image_transforms = image_transforms
|
| 509 |
-
self.delta_timestamps = delta_timestamps
|
| 510 |
-
self.episodes = episodes
|
| 511 |
-
self.tolerance_s = tolerance_s
|
| 512 |
-
self.revision = revision if revision else CODEBASE_VERSION
|
| 513 |
-
self.video_backend = video_backend if video_backend else get_safe_default_codec()
|
| 514 |
-
self.video_codec = video_codec
|
| 515 |
-
self.is_compute_episode_stats_image = is_compute_episode_stats_image
|
| 516 |
-
self.delta_indices = None
|
| 517 |
-
self.during_training = True
|
| 518 |
-
|
| 519 |
-
# Unused attributes
|
| 520 |
-
self.image_writer = None
|
| 521 |
-
self.episode_buffer = None
|
| 522 |
-
|
| 523 |
-
self.root.mkdir(exist_ok=True, parents=True)
|
| 524 |
-
|
| 525 |
-
# Load metadata
|
| 526 |
-
self.meta = LeRobotDatasetMetadata(
|
| 527 |
-
self.repo_id, self.root, self.revision, force_cache_sync=force_cache_sync
|
| 528 |
-
)
|
| 529 |
-
# v3.0 RoboTwin task shards keep global episode ids. When episodes is None,
|
| 530 |
-
# range(total_episodes) is wrong for every shard after the first and also
|
| 531 |
-
# disables parquet filtering. Default to the ids declared by this shard.
|
| 532 |
-
if self.episodes is None and self.meta._version >= packaging.version.parse("v3.0"):
|
| 533 |
-
self.episodes = sorted(self.meta.episodes.keys())
|
| 534 |
-
if (self.episodes is not None
|
| 535 |
-
and self.meta._version >= packaging.version.parse("v2.1")
|
| 536 |
-
and self.meta._version < packaging.version.parse("v3.0")):
|
| 537 |
-
episodes_stats = [self.meta.episodes_stats[ep_idx] for ep_idx in self.episodes]
|
| 538 |
-
self.stats = aggregate_stats(episodes_stats)
|
| 539 |
-
|
| 540 |
-
# v3.0: Dataset.from_parquet with isin() returns rows in parquet storage order
|
| 541 |
-
# (episode_index order), regardless of the order in self.episodes. Sort episodes
|
| 542 |
-
# so episode_data_index aligns with the HF dataset row ordering.
|
| 543 |
-
if self.episodes is not None and self.meta._version >= packaging.version.parse("v3.0"):
|
| 544 |
-
self.episodes = sorted(self.episodes)
|
| 545 |
-
|
| 546 |
-
# Load actual data
|
| 547 |
-
try:
|
| 548 |
-
if force_cache_sync:
|
| 549 |
-
raise FileNotFoundError
|
| 550 |
-
assert all((self.root / fpath).is_file() for fpath in self.get_episodes_file_paths())
|
| 551 |
-
self.hf_dataset = self.load_hf_dataset()
|
| 552 |
-
except (AssertionError, FileNotFoundError, NotADirectoryError):
|
| 553 |
-
# self.revision = get_safe_version(self.repo_id, self.revision)
|
| 554 |
-
self.revision = CODEBASE_VERSION
|
| 555 |
-
self.download_episodes(download_videos)
|
| 556 |
-
self.hf_dataset = self.load_hf_dataset()
|
| 557 |
-
|
| 558 |
-
self.episode_data_index = get_episode_data_index(self.meta.episodes, self.episodes)
|
| 559 |
-
|
| 560 |
-
# check_timestamps_sync skipped (requires decoded column access not compatible with set_transform)
|
| 561 |
-
|
| 562 |
-
# Setup delta_indices
|
| 563 |
-
if self.delta_timestamps is not None:
|
| 564 |
-
# check_delta_timestamps(self.delta_timestamps, self.fps, self.tolerance_s)
|
| 565 |
-
self.delta_indices = get_delta_indices(self.delta_timestamps, self.fps)
|
| 566 |
-
|
| 567 |
-
def push_to_hub(
|
| 568 |
-
self,
|
| 569 |
-
branch: str | None = None,
|
| 570 |
-
tags: list | None = None,
|
| 571 |
-
license: str | None = "apache-2.0",
|
| 572 |
-
tag_version: bool = True,
|
| 573 |
-
push_videos: bool = True,
|
| 574 |
-
private: bool = False,
|
| 575 |
-
allow_patterns: list[str] | str | None = None,
|
| 576 |
-
upload_large_folder: bool = False,
|
| 577 |
-
**card_kwargs,
|
| 578 |
-
) -> None:
|
| 579 |
-
ignore_patterns = ["images/"]
|
| 580 |
-
if not push_videos:
|
| 581 |
-
ignore_patterns.append("videos/")
|
| 582 |
-
|
| 583 |
-
hub_api = HfApi()
|
| 584 |
-
hub_api.create_repo(
|
| 585 |
-
repo_id=self.repo_id,
|
| 586 |
-
private=private,
|
| 587 |
-
repo_type="dataset",
|
| 588 |
-
exist_ok=True,
|
| 589 |
-
)
|
| 590 |
-
if branch:
|
| 591 |
-
hub_api.create_branch(
|
| 592 |
-
repo_id=self.repo_id,
|
| 593 |
-
branch=branch,
|
| 594 |
-
revision=self.revision,
|
| 595 |
-
repo_type="dataset",
|
| 596 |
-
exist_ok=True,
|
| 597 |
-
)
|
| 598 |
-
|
| 599 |
-
upload_kwargs = {
|
| 600 |
-
"repo_id": self.repo_id,
|
| 601 |
-
"folder_path": self.root,
|
| 602 |
-
"repo_type": "dataset",
|
| 603 |
-
"revision": branch,
|
| 604 |
-
"allow_patterns": allow_patterns,
|
| 605 |
-
"ignore_patterns": ignore_patterns,
|
| 606 |
-
}
|
| 607 |
-
if upload_large_folder:
|
| 608 |
-
hub_api.upload_large_folder(**upload_kwargs)
|
| 609 |
-
else:
|
| 610 |
-
hub_api.upload_folder(**upload_kwargs)
|
| 611 |
-
|
| 612 |
-
if not hub_api.file_exists(self.repo_id, REPOCARD_NAME, repo_type="dataset", revision=branch):
|
| 613 |
-
card = create_lerobot_dataset_card(
|
| 614 |
-
tags=tags, dataset_info=self.meta.info, license=license, **card_kwargs
|
| 615 |
-
)
|
| 616 |
-
card.push_to_hub(repo_id=self.repo_id, repo_type="dataset", revision=branch)
|
| 617 |
-
|
| 618 |
-
if tag_version:
|
| 619 |
-
with contextlib.suppress(RevisionNotFoundError):
|
| 620 |
-
hub_api.delete_tag(self.repo_id, tag=CODEBASE_VERSION, repo_type="dataset")
|
| 621 |
-
hub_api.create_tag(self.repo_id, tag=CODEBASE_VERSION, revision=branch, repo_type="dataset")
|
| 622 |
-
|
| 623 |
-
def pull_from_repo(
|
| 624 |
-
self,
|
| 625 |
-
allow_patterns: list[str] | str | None = None,
|
| 626 |
-
ignore_patterns: list[str] | str | None = None,
|
| 627 |
-
) -> None:
|
| 628 |
-
snapshot_download(
|
| 629 |
-
self.repo_id,
|
| 630 |
-
repo_type="dataset",
|
| 631 |
-
revision=self.revision,
|
| 632 |
-
local_dir=self.root,
|
| 633 |
-
allow_patterns=allow_patterns,
|
| 634 |
-
ignore_patterns=ignore_patterns,
|
| 635 |
-
)
|
| 636 |
-
|
| 637 |
-
def download_episodes(self, download_videos: bool = True) -> None:
|
| 638 |
-
"""Downloads the dataset from the given 'repo_id' at the provided version. If 'episodes' is given, this
|
| 639 |
-
will only download those episodes (selected by their episode_index). If 'episodes' is None, the whole
|
| 640 |
-
dataset will be downloaded. Thanks to the behavior of snapshot_download, if the files are already present
|
| 641 |
-
in 'local_dir', they won't be downloaded again.
|
| 642 |
-
"""
|
| 643 |
-
# TODO(rcadene, aliberts): implement faster transfer
|
| 644 |
-
# https://huggingface.co/docs/huggingface_hub/en/guides/download#faster-downloads
|
| 645 |
-
files = None
|
| 646 |
-
ignore_patterns = None if download_videos else "videos/"
|
| 647 |
-
if self.episodes is not None:
|
| 648 |
-
files = self.get_episodes_file_paths()
|
| 649 |
-
|
| 650 |
-
self.pull_from_repo(allow_patterns=files, ignore_patterns=ignore_patterns)
|
| 651 |
-
|
| 652 |
-
def get_episodes_file_paths(self) -> list[Path]:
|
| 653 |
-
episodes = (
|
| 654 |
-
self.episodes
|
| 655 |
-
if self.episodes is not None
|
| 656 |
-
else sorted(self.meta.episodes.keys())
|
| 657 |
-
)
|
| 658 |
-
fpaths = [str(self.meta.get_data_file_path(ep_idx)) for ep_idx in episodes]
|
| 659 |
-
if len(self.meta.video_keys) > 0:
|
| 660 |
-
video_files = [
|
| 661 |
-
str(self.meta.get_video_file_path(ep_idx, vid_key))
|
| 662 |
-
for vid_key in self.meta.video_keys
|
| 663 |
-
for ep_idx in episodes
|
| 664 |
-
]
|
| 665 |
-
fpaths += video_files
|
| 666 |
-
# v3.0 multi-episode files: many episodes share one file — deduplicate
|
| 667 |
-
return list(dict.fromkeys(fpaths))
|
| 668 |
-
|
| 669 |
-
def load_hf_dataset(self) -> datasets.Dataset:
|
| 670 |
-
"""hf_dataset contains all the observations, states, actions, rewards, etc."""
|
| 671 |
-
if self.meta._version >= packaging.version.parse("v3.0"):
|
| 672 |
-
return self._load_hf_dataset_v30()
|
| 673 |
-
if self.episodes is None:
|
| 674 |
-
path = str(self.root / "data")
|
| 675 |
-
hf_dataset = load_dataset("parquet", data_dir=path, split="train")
|
| 676 |
-
else:
|
| 677 |
-
files = [str(self.root / self.meta.get_data_file_path(ep_idx)) for ep_idx in self.episodes]
|
| 678 |
-
hf_dataset = load_dataset("parquet", data_files=files, split="train")
|
| 679 |
-
|
| 680 |
-
# TODO(aliberts): hf_dataset.set_format("torch")
|
| 681 |
-
hf_dataset.set_transform(hf_transform_to_torch)
|
| 682 |
-
return hf_dataset
|
| 683 |
-
|
| 684 |
-
def _load_hf_dataset_v30(self) -> datasets.Dataset:
|
| 685 |
-
"""v3.0 loader: multi-episode parquet files with predicate pushdown filtering."""
|
| 686 |
-
import pyarrow.dataset as pa_ds
|
| 687 |
-
features = get_hf_features_from_features(self.meta.features)
|
| 688 |
-
paths = sorted((self.root / "data").glob("*/*.parquet"))
|
| 689 |
-
if not paths:
|
| 690 |
-
raise FileNotFoundError(f"No parquet files found in {self.root / 'data'}")
|
| 691 |
-
filters = pa_ds.field("episode_index").isin(self.episodes) if self.episodes is not None else None
|
| 692 |
-
hf_dataset = datasets.Dataset.from_parquet(
|
| 693 |
-
[str(p) for p in paths], filters=filters, features=features
|
| 694 |
-
)
|
| 695 |
-
hf_dataset.set_transform(hf_transform_to_torch)
|
| 696 |
-
return hf_dataset
|
| 697 |
-
|
| 698 |
-
def create_hf_dataset(self) -> datasets.Dataset:
|
| 699 |
-
features = get_hf_features_from_features(self.features)
|
| 700 |
-
ft_dict = {col: [] for col in features}
|
| 701 |
-
hf_dataset = datasets.Dataset.from_dict(ft_dict, features=features, split="train")
|
| 702 |
-
|
| 703 |
-
# TODO(aliberts): hf_dataset.set_format("torch")
|
| 704 |
-
hf_dataset.set_transform(hf_transform_to_torch)
|
| 705 |
-
return hf_dataset
|
| 706 |
-
|
| 707 |
-
@property
|
| 708 |
-
def fps(self) -> int:
|
| 709 |
-
"""Frames per second used during data collection."""
|
| 710 |
-
return self.meta.fps
|
| 711 |
-
|
| 712 |
-
@property
|
| 713 |
-
def num_frames(self) -> int:
|
| 714 |
-
"""Number of frames in selected episodes."""
|
| 715 |
-
return len(self.hf_dataset) if self.hf_dataset is not None else self.meta.total_frames
|
| 716 |
-
|
| 717 |
-
@property
|
| 718 |
-
def num_episodes(self) -> int:
|
| 719 |
-
"""Number of episodes selected."""
|
| 720 |
-
return len(self.episodes) if self.episodes is not None else self.meta.total_episodes
|
| 721 |
-
|
| 722 |
-
@property
|
| 723 |
-
def features(self) -> dict[str, dict]:
|
| 724 |
-
return self.meta.features
|
| 725 |
-
|
| 726 |
-
@property
|
| 727 |
-
def hf_features(self) -> datasets.Features:
|
| 728 |
-
"""Features of the hf_dataset."""
|
| 729 |
-
if self.hf_dataset is not None:
|
| 730 |
-
return self.hf_dataset.features
|
| 731 |
-
else:
|
| 732 |
-
return get_hf_features_from_features(self.features)
|
| 733 |
-
|
| 734 |
-
def _get_query_indices(self, idx: int, ep_idx: int) -> tuple[dict[str, list[int | bool]]]:
|
| 735 |
-
ep_start = self.episode_data_index["from"][ep_idx]
|
| 736 |
-
ep_end = self.episode_data_index["to"][ep_idx]
|
| 737 |
-
query_indices = {
|
| 738 |
-
key: [max(ep_start.item(), min(ep_end.item() - 1, idx + delta)) for delta in delta_idx]
|
| 739 |
-
for key, delta_idx in self.delta_indices.items()
|
| 740 |
-
}
|
| 741 |
-
padding = { # Pad values outside of current episode range
|
| 742 |
-
f"{key}_is_pad": torch.BoolTensor(
|
| 743 |
-
[(idx + delta < ep_start.item()) | (idx + delta >= ep_end.item()) for delta in delta_idx]
|
| 744 |
-
)
|
| 745 |
-
for key, delta_idx in self.delta_indices.items()
|
| 746 |
-
}
|
| 747 |
-
return query_indices, padding
|
| 748 |
-
|
| 749 |
-
def _get_query_timestamps(
|
| 750 |
-
self,
|
| 751 |
-
current_ts: float,
|
| 752 |
-
query_indices: dict[str, list[int]] | None = None,
|
| 753 |
-
) -> dict[str, list[float]]:
|
| 754 |
-
query_timestamps = {}
|
| 755 |
-
for key in self.meta.video_keys:
|
| 756 |
-
if query_indices is not None and key in query_indices:
|
| 757 |
-
timestamps = self.hf_dataset.select(query_indices[key])["timestamp"]
|
| 758 |
-
query_timestamps[key] = torch.stack(timestamps).tolist()
|
| 759 |
-
else:
|
| 760 |
-
query_timestamps[key] = [current_ts]
|
| 761 |
-
|
| 762 |
-
return query_timestamps
|
| 763 |
-
|
| 764 |
-
def _query_hf_dataset(self, query_indices: dict[str, list[int]]) -> dict:
|
| 765 |
-
return {
|
| 766 |
-
key: torch.stack(self.hf_dataset.select(q_idx)[key])
|
| 767 |
-
for key, q_idx in query_indices.items()
|
| 768 |
-
if key not in self.meta.video_keys
|
| 769 |
-
}
|
| 770 |
-
|
| 771 |
-
def _query_hf_dataset_fast(self, query_indices: dict[str, list[int]]) -> dict:
|
| 772 |
-
result = {}
|
| 773 |
-
processed_indices = set()
|
| 774 |
-
index_to_selected = {}
|
| 775 |
-
for key, q_idx in query_indices.items():
|
| 776 |
-
if key not in self.meta.video_keys :
|
| 777 |
-
if 'images' in key and not self.during_training:
|
| 778 |
-
continue
|
| 779 |
-
q_idx_tuple = tuple(q_idx)
|
| 780 |
-
if q_idx_tuple not in processed_indices:
|
| 781 |
-
# List-index access triggers set_transform and returns a batch dict.
|
| 782 |
-
# .select() returns a Dataset whose column access bypasses the transform.
|
| 783 |
-
selected_data = self.hf_dataset[list(q_idx)]
|
| 784 |
-
index_to_selected[q_idx_tuple] = selected_data
|
| 785 |
-
processed_indices.add(q_idx_tuple)
|
| 786 |
-
else:
|
| 787 |
-
selected_data = index_to_selected[q_idx_tuple]
|
| 788 |
-
col = selected_data[key]
|
| 789 |
-
result[key] = col if isinstance(col, torch.Tensor) else torch.stack(col)
|
| 790 |
-
return result
|
| 791 |
-
|
| 792 |
-
# no videos
|
| 793 |
-
def get_episode_data(self, episode_id: int) -> dict:
|
| 794 |
-
ep_start = self.episode_data_index["from"][episode_id].item()
|
| 795 |
-
ep_end = self.episode_data_index["to"][episode_id].item()
|
| 796 |
-
q_idx = list(range(ep_start, ep_end))
|
| 797 |
-
# selected_data = self.hf_dataset.select(q_idx)
|
| 798 |
-
selected_data = self.hf_dataset[q_idx]
|
| 799 |
-
res_keys = self.meta.features.keys() - set(self.meta.video_keys)
|
| 800 |
-
res = {key : torch.stack(selected_data[key]) for key in res_keys}
|
| 801 |
-
return res
|
| 802 |
-
|
| 803 |
-
def _query_videos(self, query_timestamps: dict[str, list[float]], ep_idx: int) -> dict[str, torch.Tensor]:
|
| 804 |
-
"""Note: When using data workers (e.g. DataLoader with num_workers>0), do not call this function
|
| 805 |
-
in the main process (e.g. by using a second Dataloader with num_workers=0). It will result in a
|
| 806 |
-
Segmentation Fault. This probably happens because a memory reference to the video loader is created in
|
| 807 |
-
the main process and a subprocess fails to access it.
|
| 808 |
-
"""
|
| 809 |
-
item = {}
|
| 810 |
-
for vid_key, query_ts in query_timestamps.items():
|
| 811 |
-
video_path = self.root / self.meta.get_video_file_path(ep_idx, vid_key)
|
| 812 |
-
if self.meta._version >= packaging.version.parse("v3.0"):
|
| 813 |
-
# In v3.0, episodes are concatenated into shared video files.
|
| 814 |
-
# Timestamps in the parquet are episode-relative; shift by from_timestamp
|
| 815 |
-
# to get the seek position within the concatenated file.
|
| 816 |
-
from_ts = float(self.meta.episodes[ep_idx][f"videos/{vid_key}/from_timestamp"])
|
| 817 |
-
query_ts = [from_ts + ts for ts in query_ts]
|
| 818 |
-
frames = decode_video_frames(video_path, query_ts, self.tolerance_s, self.video_backend)
|
| 819 |
-
item[vid_key] = frames.squeeze(0)
|
| 820 |
-
|
| 821 |
-
return item
|
| 822 |
-
|
| 823 |
-
def _add_padding_keys(self, item: dict, padding: dict[str, list[bool]]) -> dict:
|
| 824 |
-
for key, val in padding.items():
|
| 825 |
-
item[key] = torch.BoolTensor(val)
|
| 826 |
-
return item
|
| 827 |
-
|
| 828 |
-
def __len__(self):
|
| 829 |
-
return self.num_frames
|
| 830 |
-
|
| 831 |
-
def __getitem__(self, idx) -> dict:
|
| 832 |
-
item = self.hf_dataset[idx]
|
| 833 |
-
ep_idx = item["episode_index"].item()
|
| 834 |
-
|
| 835 |
-
query_indices = None
|
| 836 |
-
if self.delta_indices is not None:
|
| 837 |
-
current_ep_idx = self.episodes.index(ep_idx) if self.episodes is not None else ep_idx
|
| 838 |
-
query_indices, padding = self._get_query_indices(idx, current_ep_idx)
|
| 839 |
-
query_result = self._query_hf_dataset_fast(query_indices)
|
| 840 |
-
item = {**item, **padding}
|
| 841 |
-
for key, val in query_result.items():
|
| 842 |
-
item[key] = val
|
| 843 |
-
|
| 844 |
-
if len(self.meta.video_keys) > 0 and self.during_training:
|
| 845 |
-
current_ts = item["timestamp"].item()
|
| 846 |
-
query_timestamps = self._get_query_timestamps(current_ts, query_indices)
|
| 847 |
-
video_frames = self._query_videos(query_timestamps, ep_idx)
|
| 848 |
-
item = {**video_frames, **item}
|
| 849 |
-
|
| 850 |
-
if self.image_transforms is not None:
|
| 851 |
-
image_keys = self.meta.camera_keys
|
| 852 |
-
for cam in image_keys:
|
| 853 |
-
item[cam] = self.image_transforms(item[cam])
|
| 854 |
-
|
| 855 |
-
# Add task as a string
|
| 856 |
-
task_idx = item["task_index"].item()
|
| 857 |
-
item["task"] = self.meta.tasks[task_idx]
|
| 858 |
-
if "coarse_task_index" in item:
|
| 859 |
-
coarse_task_index = item["coarse_task_index"].item()
|
| 860 |
-
item["coarse_task"] = self.meta.tasks[coarse_task_index]
|
| 861 |
-
|
| 862 |
-
if "operating_hand_index" in item:
|
| 863 |
-
operating_hand_index = item["operating_hand_index"].item()
|
| 864 |
-
item["operating_hand"] = self.meta.tasks[operating_hand_index]
|
| 865 |
-
|
| 866 |
-
if "subtask_annotation" in item and hasattr(self.meta, "annotations"):
|
| 867 |
-
index = item["subtask_annotation"][0].item()
|
| 868 |
-
item["subtask"] = self.meta.annotations["subtask"][index]
|
| 869 |
-
|
| 870 |
-
if "atomic_task_index" in item and item["atomic_task_index"] is not None:
|
| 871 |
-
atomic_task_index = item["atomic_task_index"].item()
|
| 872 |
-
item["subtask"] = self.meta.tasks[int(atomic_task_index)]
|
| 873 |
-
|
| 874 |
-
return item
|
| 875 |
-
|
| 876 |
-
def __repr__(self):
|
| 877 |
-
feature_keys = list(self.features)
|
| 878 |
-
return (
|
| 879 |
-
f"{self.__class__.__name__}({{\n"
|
| 880 |
-
f" Repository ID: '{self.repo_id}',\n"
|
| 881 |
-
f" Number of selected episodes: '{self.num_episodes}',\n"
|
| 882 |
-
f" Number of selected samples: '{self.num_frames}',\n"
|
| 883 |
-
f" Features: '{feature_keys}',\n"
|
| 884 |
-
"})',\n"
|
| 885 |
-
)
|
| 886 |
-
|
| 887 |
-
def create_episode_buffer(self, episode_index: int | None = None) -> dict:
|
| 888 |
-
current_ep_idx = self.meta.total_episodes if episode_index is None else episode_index
|
| 889 |
-
ep_buffer = {}
|
| 890 |
-
# size and task are special cases that are not in self.features
|
| 891 |
-
ep_buffer["size"] = 0
|
| 892 |
-
ep_buffer["task"] = []
|
| 893 |
-
for key in self.features:
|
| 894 |
-
ep_buffer[key] = current_ep_idx if key == "episode_index" else []
|
| 895 |
-
return ep_buffer
|
| 896 |
-
|
| 897 |
-
def _get_image_file_path(self, episode_index: int, image_key: str, frame_index: int) -> Path:
|
| 898 |
-
fpath = DEFAULT_IMAGE_PATH.format(
|
| 899 |
-
image_key=image_key, episode_index=episode_index, frame_index=frame_index
|
| 900 |
-
)
|
| 901 |
-
return self.root / fpath
|
| 902 |
-
|
| 903 |
-
# def _save_image(self, image: torch.Tensor | np.ndarray | PIL.Image.Image | bytes, fpath: Path) -> None:
|
| 904 |
-
# if self.image_writer is None:
|
| 905 |
-
# if isinstance(image, torch.Tensor):
|
| 906 |
-
# image = image.cpu().numpy()
|
| 907 |
-
# write_image(image, fpath)
|
| 908 |
-
# else:
|
| 909 |
-
# self.image_writer.save_image(image=image, fpath=fpath)
|
| 910 |
-
|
| 911 |
-
def add_frame(self, frame: dict, task: List[str], timestamp: float | None = None) -> None:
|
| 912 |
-
"""
|
| 913 |
-
This function only adds the frame to the episode_buffer. Apart from images — which are written in a
|
| 914 |
-
temporary directory — nothing is written to disk. To save those frames, the 'save_episode()' method
|
| 915 |
-
then needs to be called.
|
| 916 |
-
"""
|
| 917 |
-
# Convert torch to numpy if needed
|
| 918 |
-
assert len(task) == 4, "Task frame must be of two elements"
|
| 919 |
-
for name in frame:
|
| 920 |
-
if isinstance(frame[name], torch.Tensor):
|
| 921 |
-
frame[name] = frame[name].numpy()
|
| 922 |
-
|
| 923 |
-
validate_frame(frame, self.features)
|
| 924 |
-
|
| 925 |
-
if self.episode_buffer is None:
|
| 926 |
-
self.episode_buffer = self.create_episode_buffer()
|
| 927 |
-
|
| 928 |
-
# Automatically add frame_index and timestamp to episode buffer
|
| 929 |
-
frame_index = self.episode_buffer["size"]
|
| 930 |
-
if timestamp is None:
|
| 931 |
-
timestamp = frame_index / self.fps
|
| 932 |
-
self.episode_buffer["frame_index"].append(frame_index)
|
| 933 |
-
self.episode_buffer["timestamp"].append(timestamp)
|
| 934 |
-
self.episode_buffer["task"].append(task)
|
| 935 |
-
|
| 936 |
-
# Add frame features to episode_buffer
|
| 937 |
-
for key in frame:
|
| 938 |
-
if key not in self.features:
|
| 939 |
-
raise ValueError(
|
| 940 |
-
f"An element of the frame is not in the features. '{key}' not in '{self.features.keys()}'."
|
| 941 |
-
)
|
| 942 |
-
|
| 943 |
-
if self.features[key]["dtype"] in ["image", "video"]:
|
| 944 |
-
img_path = self._get_image_file_path(
|
| 945 |
-
episode_index=self.episode_buffer["episode_index"], image_key=key, frame_index=frame_index
|
| 946 |
-
)
|
| 947 |
-
if frame_index == 0:
|
| 948 |
-
img_path.parent.mkdir(parents=True, exist_ok=True)
|
| 949 |
-
# self._save_image(frame[key], img_path)
|
| 950 |
-
self.episode_buffer[key].append(str(img_path))
|
| 951 |
-
else:
|
| 952 |
-
self.episode_buffer[key].append(frame[key])
|
| 953 |
-
|
| 954 |
-
self.episode_buffer["size"] += 1
|
| 955 |
-
|
| 956 |
-
def save_episode(self, episode_data: dict | None = None, raw_file_name: str | None = None) -> None:
|
| 957 |
-
"""
|
| 958 |
-
This will save to disk the current episode in self.episode_buffer.
|
| 959 |
-
|
| 960 |
-
Args:
|
| 961 |
-
episode_data (dict | None, optional): Dict containing the episode data to save. If None, this will
|
| 962 |
-
save the current episode in self.episode_buffer, which is filled with 'add_frame'. Defaults to
|
| 963 |
-
None.
|
| 964 |
-
"""
|
| 965 |
-
if not episode_data:
|
| 966 |
-
episode_buffer = self.episode_buffer
|
| 967 |
-
|
| 968 |
-
validate_episode_buffer(episode_buffer, self.meta.total_episodes, self.features)
|
| 969 |
-
|
| 970 |
-
# size and task are special cases that won't be added to hf_dataset
|
| 971 |
-
episode_length = episode_buffer.pop("size")
|
| 972 |
-
tasks = episode_buffer.pop("task")
|
| 973 |
-
episode_tasks = list(set([item for sublist in tasks for item in sublist]))
|
| 974 |
-
episode_index = episode_buffer["episode_index"]
|
| 975 |
-
|
| 976 |
-
episode_buffer["index"] = np.arange(self.meta.total_frames, self.meta.total_frames + episode_length)
|
| 977 |
-
episode_buffer["episode_index"] = np.full((episode_length,), episode_index)
|
| 978 |
-
|
| 979 |
-
# Add new tasks to the tasks dictionary
|
| 980 |
-
for task in episode_tasks:
|
| 981 |
-
task_index = self.meta.get_task_index(task)
|
| 982 |
-
if task_index is None:
|
| 983 |
-
self.meta.add_task(task)
|
| 984 |
-
|
| 985 |
-
# Given tasks in natural language, find their corresponding task indices
|
| 986 |
-
episode_buffer["coarse_task_index"] = np.array([self.meta.get_task_index(task[0]) for task in tasks])
|
| 987 |
-
episode_buffer["task_index"] = np.array([self.meta.get_task_index(task[1]) for task in tasks])
|
| 988 |
-
episode_buffer["coarse_quality_index"] = np.array([self.meta.get_task_index(task[2]) for task in tasks])
|
| 989 |
-
episode_buffer["quality_index"] = np.array([self.meta.get_task_index(task[3]) for task in tasks])
|
| 990 |
-
|
| 991 |
-
for key, ft in self.features.items():
|
| 992 |
-
# index, episode_index, task_index are already processed above, and image and video
|
| 993 |
-
# are processed separately by storing image path and frame info as meta data
|
| 994 |
-
if key in ["index", "episode_index", "coarse_task_index", "task_index", "coarse_quality_index", "quality_index"] or ft["dtype"] in ["image", "video"]:
|
| 995 |
-
continue
|
| 996 |
-
episode_buffer[key] = np.stack(episode_buffer[key])
|
| 997 |
-
|
| 998 |
-
self._wait_image_writer()
|
| 999 |
-
self._save_episode_table(episode_buffer, episode_index)
|
| 1000 |
-
ep_stats = compute_episode_stats(episode_buffer, self.features, self.is_compute_episode_stats_image)
|
| 1001 |
-
|
| 1002 |
-
if len(self.meta.video_keys) > 0:
|
| 1003 |
-
video_paths = self.encode_episode_videos(episode_index)
|
| 1004 |
-
for key in self.meta.video_keys:
|
| 1005 |
-
episode_buffer[key] = video_paths[key]
|
| 1006 |
-
|
| 1007 |
-
# `meta.save_episode` be executed after encoding the videos
|
| 1008 |
-
self.meta.save_episode(episode_index, episode_length, episode_tasks, ep_stats, raw_file_name)
|
| 1009 |
-
|
| 1010 |
-
ep_data_index = get_episode_data_index(self.meta.episodes, [episode_index])
|
| 1011 |
-
ep_data_index_np = {k: t.numpy() for k, t in ep_data_index.items()}
|
| 1012 |
-
check_timestamps_sync(
|
| 1013 |
-
episode_buffer["timestamp"],
|
| 1014 |
-
episode_buffer["episode_index"],
|
| 1015 |
-
ep_data_index_np,
|
| 1016 |
-
self.fps,
|
| 1017 |
-
self.tolerance_s,
|
| 1018 |
-
)
|
| 1019 |
-
|
| 1020 |
-
video_files = list(self.root.rglob("*.mp4"))
|
| 1021 |
-
assert len(video_files) == self.num_episodes * len(self.meta.video_keys)
|
| 1022 |
-
|
| 1023 |
-
parquet_files = list(self.root.rglob("*.parquet"))
|
| 1024 |
-
assert len(parquet_files) == self.num_episodes
|
| 1025 |
-
|
| 1026 |
-
# delete images
|
| 1027 |
-
img_dir = self.root / "images"
|
| 1028 |
-
if img_dir.is_dir():
|
| 1029 |
-
shutil.rmtree(self.root / "images")
|
| 1030 |
-
|
| 1031 |
-
if not episode_data: # Reset the buffer
|
| 1032 |
-
self.episode_buffer = self.create_episode_buffer()
|
| 1033 |
-
|
| 1034 |
-
def _save_episode_table(self, episode_buffer: dict, episode_index: int) -> None:
|
| 1035 |
-
episode_dict = {key: episode_buffer[key] for key in self.hf_features}
|
| 1036 |
-
ep_dataset = datasets.Dataset.from_dict(episode_dict, features=self.hf_features, split="train")
|
| 1037 |
-
ep_dataset = embed_images(ep_dataset)
|
| 1038 |
-
self.hf_dataset = concatenate_datasets([self.hf_dataset, ep_dataset])
|
| 1039 |
-
self.hf_dataset.set_transform(hf_transform_to_torch)
|
| 1040 |
-
ep_data_path = self.root / self.meta.get_data_file_path(ep_index=episode_index)
|
| 1041 |
-
ep_data_path.parent.mkdir(parents=True, exist_ok=True)
|
| 1042 |
-
ep_dataset.to_parquet(ep_data_path)
|
| 1043 |
-
|
| 1044 |
-
def clear_episode_buffer(self) -> None:
|
| 1045 |
-
episode_index = self.episode_buffer["episode_index"]
|
| 1046 |
-
if self.image_writer is not None:
|
| 1047 |
-
for cam_key in self.meta.camera_keys:
|
| 1048 |
-
img_dir = self._get_image_file_path(
|
| 1049 |
-
episode_index=episode_index, image_key=cam_key, frame_index=0
|
| 1050 |
-
).parent
|
| 1051 |
-
if img_dir.is_dir():
|
| 1052 |
-
shutil.rmtree(img_dir)
|
| 1053 |
-
|
| 1054 |
-
# Reset the buffer
|
| 1055 |
-
self.episode_buffer = self.create_episode_buffer()
|
| 1056 |
-
|
| 1057 |
-
# def start_image_writer(self, num_processes: int = 0, num_threads: int = 4) -> None:
|
| 1058 |
-
# if isinstance(self.image_writer, AsyncImageWriter):
|
| 1059 |
-
# logging.warning(
|
| 1060 |
-
# "You are starting a new AsyncImageWriter that is replacing an already existing one in the dataset."
|
| 1061 |
-
# )
|
| 1062 |
-
|
| 1063 |
-
# self.image_writer = AsyncImageWriter(
|
| 1064 |
-
# num_processes=num_processes,
|
| 1065 |
-
# num_threads=num_threads,
|
| 1066 |
-
# )
|
| 1067 |
-
|
| 1068 |
-
def stop_image_writer(self) -> None:
|
| 1069 |
-
"""
|
| 1070 |
-
Whenever wrapping this dataset inside a parallelized DataLoader, this needs to be called first to
|
| 1071 |
-
remove the image_writer in order for the LeRobotDataset object to be picklable and parallelized.
|
| 1072 |
-
"""
|
| 1073 |
-
if self.image_writer is not None:
|
| 1074 |
-
self.image_writer.stop()
|
| 1075 |
-
self.image_writer = None
|
| 1076 |
-
|
| 1077 |
-
def _wait_image_writer(self) -> None:
|
| 1078 |
-
"""Wait for asynchronous image writer to finish."""
|
| 1079 |
-
if self.image_writer is not None:
|
| 1080 |
-
self.image_writer.wait_until_done()
|
| 1081 |
-
|
| 1082 |
-
def encode_videos(self) -> None:
|
| 1083 |
-
"""
|
| 1084 |
-
Use ffmpeg to convert frames stored as png into mp4 videos.
|
| 1085 |
-
Note: `encode_video_frames` is a blocking call. Making it asynchronous shouldn't speedup encoding,
|
| 1086 |
-
since video encoding with ffmpeg is already using multithreading.
|
| 1087 |
-
"""
|
| 1088 |
-
for ep_idx in range(self.meta.total_episodes):
|
| 1089 |
-
self.encode_episode_videos(ep_idx)
|
| 1090 |
-
|
| 1091 |
-
def encode_episode_videos(self, episode_index: int) -> dict:
|
| 1092 |
-
"""
|
| 1093 |
-
Use ffmpeg to convert frames stored as png into mp4 videos.
|
| 1094 |
-
Note: `encode_video_frames` is a blocking call. Making it asynchronous shouldn't speedup encoding,
|
| 1095 |
-
since video encoding with ffmpeg is already using multithreading.
|
| 1096 |
-
"""
|
| 1097 |
-
video_paths = {}
|
| 1098 |
-
for key in self.meta.video_keys:
|
| 1099 |
-
video_path = self.root / self.meta.get_video_file_path(episode_index, key)
|
| 1100 |
-
video_paths[key] = str(video_path)
|
| 1101 |
-
if video_path.is_file():
|
| 1102 |
-
# Skip if video is already encoded. Could be the case when resuming data recording.
|
| 1103 |
-
continue
|
| 1104 |
-
img_dir = self._get_image_file_path(
|
| 1105 |
-
episode_index=episode_index, image_key=key, frame_index=0
|
| 1106 |
-
).parent
|
| 1107 |
-
encode_video_frames(img_dir, video_path, self.fps, overwrite=True, vcodec=self.video_codec)
|
| 1108 |
-
|
| 1109 |
-
return video_paths
|
| 1110 |
-
|
| 1111 |
-
@classmethod
|
| 1112 |
-
def create(
|
| 1113 |
-
cls,
|
| 1114 |
-
repo_id: str,
|
| 1115 |
-
fps: int,
|
| 1116 |
-
features: dict,
|
| 1117 |
-
root: str | Path | None = None,
|
| 1118 |
-
robot_type: str | None = None,
|
| 1119 |
-
use_videos: bool = True,
|
| 1120 |
-
tolerance_s: float = 1e-4,
|
| 1121 |
-
image_writer_processes: int = 0,
|
| 1122 |
-
image_writer_threads: int = 0,
|
| 1123 |
-
video_backend: str | None = None,
|
| 1124 |
-
video_codec: Literal["h264", "hevc", "libsvtav1", "h264_nvenc"] = "libsvtav1",
|
| 1125 |
-
is_compute_episode_stats_image = True,
|
| 1126 |
-
) -> "LeRobotDataset":
|
| 1127 |
-
"""Create a LeRobot Dataset from scratch in order to record data."""
|
| 1128 |
-
obj = cls.__new__(cls)
|
| 1129 |
-
obj.meta = LeRobotDatasetMetadata.create(
|
| 1130 |
-
repo_id=repo_id,
|
| 1131 |
-
fps=fps,
|
| 1132 |
-
robot_type=robot_type,
|
| 1133 |
-
features=features,
|
| 1134 |
-
root=root,
|
| 1135 |
-
use_videos=use_videos,
|
| 1136 |
-
)
|
| 1137 |
-
obj.repo_id = obj.meta.repo_id
|
| 1138 |
-
obj.root = obj.meta.root
|
| 1139 |
-
obj.revision = None
|
| 1140 |
-
obj.tolerance_s = tolerance_s
|
| 1141 |
-
obj.image_writer = None
|
| 1142 |
-
|
| 1143 |
-
# if image_writer_processes or image_writer_threads:
|
| 1144 |
-
# obj.start_image_writer(image_writer_processes, image_writer_threads)
|
| 1145 |
-
|
| 1146 |
-
# TODO(aliberts, rcadene, alexander-soare): Merge this with OnlineBuffer/DataBuffer
|
| 1147 |
-
obj.episode_buffer = obj.create_episode_buffer()
|
| 1148 |
-
|
| 1149 |
-
obj.episodes = None
|
| 1150 |
-
obj.hf_dataset = obj.create_hf_dataset()
|
| 1151 |
-
obj.image_transforms = None
|
| 1152 |
-
obj.delta_timestamps = None
|
| 1153 |
-
obj.delta_indices = None
|
| 1154 |
-
obj.episode_data_index = None
|
| 1155 |
-
obj.video_backend = video_backend if video_backend is not None else get_safe_default_codec()
|
| 1156 |
-
obj.video_codec = video_codec
|
| 1157 |
-
obj.is_compute_episode_stats_image = is_compute_episode_stats_image
|
| 1158 |
-
return obj
|
| 1159 |
-
|
| 1160 |
-
|
| 1161 |
-
class MultiLeRobotDataset(torch.utils.data.Dataset):
|
| 1162 |
-
"""A dataset consisting of multiple underlying `LeRobotDataset`s.
|
| 1163 |
-
|
| 1164 |
-
The underlying `LeRobotDataset`s are effectively concatenated, and this class adopts much of the API
|
| 1165 |
-
structure of `LeRobotDataset`.
|
| 1166 |
-
"""
|
| 1167 |
-
|
| 1168 |
-
def __init__(
|
| 1169 |
-
self,
|
| 1170 |
-
dataset_dirs: list[str],
|
| 1171 |
-
episodes: dict | None = None,
|
| 1172 |
-
image_transforms: Callable | None = None,
|
| 1173 |
-
delta_timestamps: dict[list[float]] | None = None,
|
| 1174 |
-
tolerances_s: dict | None = None,
|
| 1175 |
-
download_videos: bool = True,
|
| 1176 |
-
video_backend: str | None = None,
|
| 1177 |
-
):
|
| 1178 |
-
super().__init__()
|
| 1179 |
-
self.dataset_dirs = dataset_dirs
|
| 1180 |
-
ds_roots = [Path(ds_dir) for ds_dir in dataset_dirs]
|
| 1181 |
-
ds_names = [dataset_dir_to_repo_id(ds_dir) for ds_dir in dataset_dirs]
|
| 1182 |
-
self.ds_names = ds_names
|
| 1183 |
-
self.ds_roots = ds_roots
|
| 1184 |
-
self.tolerances_s = tolerances_s if tolerances_s else dict.fromkeys(ds_names, 0.0001)
|
| 1185 |
-
# Construct the underlying datasets passing everything but `transform` and `delta_timestamps` which
|
| 1186 |
-
# are handled by this class.
|
| 1187 |
-
self._datasets = []
|
| 1188 |
-
for ds_root, ds_name in zip(ds_roots, ds_names, strict=True):
|
| 1189 |
-
try:
|
| 1190 |
-
_dataset = LeRobotDataset(
|
| 1191 |
-
ds_name,
|
| 1192 |
-
root=ds_root,
|
| 1193 |
-
episodes=episodes[ds_name] if episodes else None,
|
| 1194 |
-
image_transforms=image_transforms,
|
| 1195 |
-
delta_timestamps=delta_timestamps,
|
| 1196 |
-
tolerance_s=self.tolerances_s[ds_name],
|
| 1197 |
-
download_videos=download_videos,
|
| 1198 |
-
video_backend=video_backend,
|
| 1199 |
-
)
|
| 1200 |
-
self._datasets.append(_dataset)
|
| 1201 |
-
except Exception as e:
|
| 1202 |
-
# logging.error(e)
|
| 1203 |
-
logging.error(f"Exception while process ds_root: {ds_root}, ds_name: {ds_name}")
|
| 1204 |
-
traceback.print_exc()
|
| 1205 |
-
raise e
|
| 1206 |
-
|
| 1207 |
-
# Disable any data keys that are not common across all of the datasets. Note: we may relax this
|
| 1208 |
-
# restriction in future iterations of this class. For now, this is necessary at least for being able
|
| 1209 |
-
# to use PyTorch's default DataLoader collate function.
|
| 1210 |
-
self.disabled_features = set()
|
| 1211 |
-
intersection_features = set(self._datasets[0].features)
|
| 1212 |
-
for ds in self._datasets:
|
| 1213 |
-
intersection_features.intersection_update(ds.features)
|
| 1214 |
-
if len(intersection_features) == 0:
|
| 1215 |
-
raise RuntimeError(
|
| 1216 |
-
"Multiple datasets were provided but they had no keys common to all of them. "
|
| 1217 |
-
"The multi-dataset functionality currently only keeps common keys."
|
| 1218 |
-
)
|
| 1219 |
-
for ds_name, ds in zip(self.ds_names, self._datasets, strict=True):
|
| 1220 |
-
# Disable warning of empty extra keys do
|
| 1221 |
-
extra_keys = set(ds.features).difference(intersection_features)
|
| 1222 |
-
if extra_keys:
|
| 1223 |
-
logging.warning(
|
| 1224 |
-
f"keys {extra_keys} of {ds_name} were disabled as they are not contained in all the "
|
| 1225 |
-
"other datasets."
|
| 1226 |
-
)
|
| 1227 |
-
self.disabled_features.update(extra_keys)
|
| 1228 |
-
|
| 1229 |
-
self.image_transforms = image_transforms
|
| 1230 |
-
self.delta_timestamps = delta_timestamps
|
| 1231 |
-
# TODO(rcadene, aliberts): We should not perform this aggregation for datasets
|
| 1232 |
-
# with multiple robots of different ranges. Instead we should have one normalization
|
| 1233 |
-
# per robot.
|
| 1234 |
-
try:
|
| 1235 |
-
self.stats = aggregate_stats([dataset.meta.stats for dataset in self._datasets])
|
| 1236 |
-
except ValueError as err:
|
| 1237 |
-
logging.warning(
|
| 1238 |
-
"Failed to aggregate metadata stats across datasets; using the first "
|
| 1239 |
-
"dataset stats instead. Error: %s",
|
| 1240 |
-
err,
|
| 1241 |
-
)
|
| 1242 |
-
self.stats = self._datasets[0].meta.stats
|
| 1243 |
-
|
| 1244 |
-
def set_during_training(self, during_training: bool):
|
| 1245 |
-
for dataset in self._datasets:
|
| 1246 |
-
dataset.during_training = during_training
|
| 1247 |
-
|
| 1248 |
-
@property
|
| 1249 |
-
def repo_id_to_index(self):
|
| 1250 |
-
"""Return a mapping from dataset repo_id to a dataset index automatically created by this class.
|
| 1251 |
-
|
| 1252 |
-
This index is incorporated as a data key in the dictionary returned by `__getitem__`.
|
| 1253 |
-
"""
|
| 1254 |
-
return {repo_id: i for i, repo_id in enumerate(self.ds_names)}
|
| 1255 |
-
|
| 1256 |
-
@property
|
| 1257 |
-
def repo_index_to_id(self):
|
| 1258 |
-
"""Return the inverse mapping if repo_id_to_index."""
|
| 1259 |
-
return {v: k for k, v in self.repo_id_to_index}
|
| 1260 |
-
|
| 1261 |
-
@property
|
| 1262 |
-
def fps(self) -> int:
|
| 1263 |
-
"""Frames per second used during data collection.
|
| 1264 |
-
|
| 1265 |
-
NOTE: Fow now, this relies on a check in __init__ to make sure all sub-datasets have the same info.
|
| 1266 |
-
"""
|
| 1267 |
-
return self._datasets[0].meta.info["fps"]
|
| 1268 |
-
|
| 1269 |
-
@property
|
| 1270 |
-
def video(self) -> bool:
|
| 1271 |
-
"""Returns True if this dataset loads video frames from mp4 files.
|
| 1272 |
-
|
| 1273 |
-
Returns False if it only loads images from png files.
|
| 1274 |
-
|
| 1275 |
-
NOTE: Fow now, this relies on a check in __init__ to make sure all sub-datasets have the same info.
|
| 1276 |
-
"""
|
| 1277 |
-
return self._datasets[0].meta.info.get("video", False)
|
| 1278 |
-
|
| 1279 |
-
@property
|
| 1280 |
-
def features(self) -> datasets.Features:
|
| 1281 |
-
features = {}
|
| 1282 |
-
for dataset in self._datasets:
|
| 1283 |
-
features.update({k: v for k, v in dataset.hf_features.items() if k not in self.disabled_features})
|
| 1284 |
-
return features
|
| 1285 |
-
|
| 1286 |
-
@property
|
| 1287 |
-
def camera_keys(self) -> list[str]:
|
| 1288 |
-
"""Keys to access image and video stream from cameras."""
|
| 1289 |
-
keys = []
|
| 1290 |
-
for key, feats in self.features.items():
|
| 1291 |
-
if isinstance(feats, (datasets.Image, VideoFrame)):
|
| 1292 |
-
keys.append(key)
|
| 1293 |
-
return keys
|
| 1294 |
-
|
| 1295 |
-
@property
|
| 1296 |
-
def video_frame_keys(self) -> list[str]:
|
| 1297 |
-
"""Keys to access video frames that requires to be decoded into images.
|
| 1298 |
-
|
| 1299 |
-
Note: It is empty if the dataset contains images only,
|
| 1300 |
-
or equal to `self.cameras` if the dataset contains videos only,
|
| 1301 |
-
or can even be a subset of `self.cameras` in a case of a mixed image/video dataset.
|
| 1302 |
-
"""
|
| 1303 |
-
video_frame_keys = []
|
| 1304 |
-
for key, feats in self.features.items():
|
| 1305 |
-
if isinstance(feats, VideoFrame):
|
| 1306 |
-
video_frame_keys.append(key)
|
| 1307 |
-
return video_frame_keys
|
| 1308 |
-
|
| 1309 |
-
@property
|
| 1310 |
-
def num_frames(self) -> int:
|
| 1311 |
-
"""Number of samples/frames."""
|
| 1312 |
-
return sum(d.num_frames for d in self._datasets)
|
| 1313 |
-
|
| 1314 |
-
@property
|
| 1315 |
-
def num_episodes(self) -> int:
|
| 1316 |
-
"""Number of episodes."""
|
| 1317 |
-
return sum(d.num_episodes for d in self._datasets)
|
| 1318 |
-
|
| 1319 |
-
@property
|
| 1320 |
-
def tolerance_s(self) -> float:
|
| 1321 |
-
"""Tolerance in seconds used to discard loaded frames when their timestamps
|
| 1322 |
-
are not close enough from the requested frames. It is only used when `delta_timestamps`
|
| 1323 |
-
is provided or when loading video frames from mp4 files.
|
| 1324 |
-
"""
|
| 1325 |
-
# 1e-4 to account for possible numerical error
|
| 1326 |
-
return 1 / self.fps - 1e-4
|
| 1327 |
-
|
| 1328 |
-
def get_episode_data(self, episode_idx: int) -> dict:
|
| 1329 |
-
for dataset in self._datasets:
|
| 1330 |
-
if episode_idx < dataset.num_episodes:
|
| 1331 |
-
actual_ep_idx = (
|
| 1332 |
-
dataset.episodes[episode_idx]
|
| 1333 |
-
if dataset.episodes is not None
|
| 1334 |
-
else sorted(dataset.meta.episodes.keys())[episode_idx]
|
| 1335 |
-
)
|
| 1336 |
-
file = str(dataset.root / dataset.meta.get_data_file_path(actual_ep_idx))
|
| 1337 |
-
if dataset.meta._version >= packaging.version.parse("v3.0"):
|
| 1338 |
-
# v3.0: shared files contain multiple episodes; filter to this one
|
| 1339 |
-
table = pq.read_table(file, filters=[("episode_index", "=", actual_ep_idx)])
|
| 1340 |
-
else:
|
| 1341 |
-
table = pq.read_table(file)
|
| 1342 |
-
|
| 1343 |
-
result_dict = {}
|
| 1344 |
-
for col_name in table.column_names:
|
| 1345 |
-
col = table[col_name]
|
| 1346 |
-
try:
|
| 1347 |
-
np_arr = col.to_numpy(zero_copy_only=True)
|
| 1348 |
-
except Exception:
|
| 1349 |
-
raw = col.to_numpy()
|
| 1350 |
-
np_arr = np.stack(raw) if raw.dtype == object else raw
|
| 1351 |
-
with warnings.catch_warnings():
|
| 1352 |
-
warnings.filterwarnings(
|
| 1353 |
-
"ignore",
|
| 1354 |
-
message="The given NumPy array is not writable",
|
| 1355 |
-
category=UserWarning,
|
| 1356 |
-
)
|
| 1357 |
-
# deal with string in parquet file
|
| 1358 |
-
if np_arr.dtype == 'O':
|
| 1359 |
-
result_dict[col_name] = np_arr
|
| 1360 |
-
else:
|
| 1361 |
-
result_dict[col_name] = torch.from_numpy(np_arr)
|
| 1362 |
-
return result_dict
|
| 1363 |
-
else:
|
| 1364 |
-
episode_idx -= dataset.num_episodes
|
| 1365 |
-
raise IndexError(f"Episode index {episode_idx} out of bounds.")
|
| 1366 |
-
|
| 1367 |
-
def __len__(self):
|
| 1368 |
-
return self.num_frames
|
| 1369 |
-
|
| 1370 |
-
def __getitem__(self, idx: int) -> dict[str, torch.Tensor]:
|
| 1371 |
-
if idx >= len(self):
|
| 1372 |
-
raise IndexError(f"Index {idx} out of bounds.")
|
| 1373 |
-
# Determine which dataset to get an item from based on the index.
|
| 1374 |
-
start_idx = 0
|
| 1375 |
-
dataset_idx = 0
|
| 1376 |
-
for dataset in self._datasets:
|
| 1377 |
-
if idx >= start_idx + dataset.num_frames:
|
| 1378 |
-
start_idx += dataset.num_frames
|
| 1379 |
-
dataset_idx += 1
|
| 1380 |
-
continue
|
| 1381 |
-
break
|
| 1382 |
-
else:
|
| 1383 |
-
raise AssertionError("We expect the loop to break out as long as the index is within bounds.")
|
| 1384 |
-
item = self._datasets[dataset_idx][idx - start_idx]
|
| 1385 |
-
item["dataset_index"] = torch.tensor(dataset_idx)
|
| 1386 |
-
for data_key in self.disabled_features:
|
| 1387 |
-
if data_key in item:
|
| 1388 |
-
del item[data_key]
|
| 1389 |
-
|
| 1390 |
-
return item
|
| 1391 |
-
|
| 1392 |
-
def __repr__(self):
|
| 1393 |
-
return (
|
| 1394 |
-
f"{self.__class__.__name__}(\n"
|
| 1395 |
-
f" Dataset Names: '{self.ds_names}',\n"
|
| 1396 |
-
f" Number of Samples: {self.num_frames},\n"
|
| 1397 |
-
f" Number of Episodes: {self.num_episodes},\n"
|
| 1398 |
-
f" Type: {'video (.mp4)' if self.video else 'image (.png)'},\n"
|
| 1399 |
-
f" Recorded Frames per Second: {self.fps},\n"
|
| 1400 |
-
f" Camera Keys: {self.camera_keys},\n"
|
| 1401 |
-
f" Video Frame Keys: {self.video_frame_keys if self.video else 'N/A'},\n"
|
| 1402 |
-
f" Transformations: {self.image_transforms},\n"
|
| 1403 |
-
f")"
|
| 1404 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/processors/base_processor.py
DELETED
|
@@ -1,263 +0,0 @@
|
|
| 1 |
-
from abc import ABC, abstractmethod
|
| 2 |
-
from typing import Dict, Any, Optional, List, Literal
|
| 3 |
-
|
| 4 |
-
import torch
|
| 5 |
-
import numpy as np
|
| 6 |
-
from copy import deepcopy
|
| 7 |
-
from ..utils.normalizer import LinearNormalizer, NormMode
|
| 8 |
-
from fastwam.utils.pytorch_utils import dict_apply
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
class BaseProcessor(ABC):
|
| 12 |
-
def __init__(
|
| 13 |
-
self,
|
| 14 |
-
# keys
|
| 15 |
-
shape_meta: Dict[str, Any],
|
| 16 |
-
num_obs_steps: int,
|
| 17 |
-
num_output_cameras: int,
|
| 18 |
-
action_output_dim: int,
|
| 19 |
-
proprio_output_dim: int,
|
| 20 |
-
|
| 21 |
-
action_state_transforms: Optional[List[Any]],
|
| 22 |
-
|
| 23 |
-
# action & state normalization
|
| 24 |
-
use_stepwise_action_norm: bool,
|
| 25 |
-
norm_default_mode: NormMode,
|
| 26 |
-
norm_exception_mode: Dict[str, Dict[str, NormMode]],
|
| 27 |
-
|
| 28 |
-
action_state_merger,
|
| 29 |
-
|
| 30 |
-
# image transform
|
| 31 |
-
train_transforms: Dict[str, List[Any]] | None,
|
| 32 |
-
val_transforms: Dict[str, List[Any]] | None,
|
| 33 |
-
|
| 34 |
-
# instruction transform
|
| 35 |
-
drop_high_level_prob: float,
|
| 36 |
-
use_zh_instruction: bool,
|
| 37 |
-
|
| 38 |
-
tokenizer: Any
|
| 39 |
-
):
|
| 40 |
-
self.shape_meta = shape_meta
|
| 41 |
-
self.num_obs_steps = num_obs_steps
|
| 42 |
-
self.num_output_cameras = num_output_cameras
|
| 43 |
-
self.action_output_dim = action_output_dim
|
| 44 |
-
self.proprio_output_dim = proprio_output_dim
|
| 45 |
-
|
| 46 |
-
self.drop_high_level_prob = drop_high_level_prob
|
| 47 |
-
self.use_zh_instruction = use_zh_instruction
|
| 48 |
-
|
| 49 |
-
# image
|
| 50 |
-
self.train_transforms = train_transforms
|
| 51 |
-
self.val_transforms = val_transforms
|
| 52 |
-
|
| 53 |
-
self._is_train = None
|
| 54 |
-
|
| 55 |
-
self.action_state_transforms = action_state_transforms
|
| 56 |
-
self.action_state_merger = action_state_merger
|
| 57 |
-
self.action_state_merger.set_shape_meta(self.shape_meta)
|
| 58 |
-
|
| 59 |
-
self.use_stepwise_action_norm = use_stepwise_action_norm
|
| 60 |
-
self.norm_default_mode = norm_default_mode
|
| 61 |
-
self.norm_exception_mode = norm_exception_mode
|
| 62 |
-
self._normalizer = None
|
| 63 |
-
|
| 64 |
-
self.tokenizer = tokenizer
|
| 65 |
-
|
| 66 |
-
@property
|
| 67 |
-
def is_train(self):
|
| 68 |
-
if self._is_train is None:
|
| 69 |
-
raise ValueError("is_train has not been set. Please call train() and eval() first.")
|
| 70 |
-
return self._is_train
|
| 71 |
-
|
| 72 |
-
@property
|
| 73 |
-
def normalizer(self) -> LinearNormalizer:
|
| 74 |
-
if self._normalizer is None:
|
| 75 |
-
raise ValueError("normalizer has not been set. Please call set_normalizer_from_stats() first.")
|
| 76 |
-
return self._normalizer
|
| 77 |
-
|
| 78 |
-
def train(self):
|
| 79 |
-
self._is_train = True
|
| 80 |
-
return self
|
| 81 |
-
|
| 82 |
-
def eval(self):
|
| 83 |
-
self._is_train = False
|
| 84 |
-
return self
|
| 85 |
-
|
| 86 |
-
def set_normalizer_from_stats(self, dataset_stats: Dict[str, Any] = None):
|
| 87 |
-
self._normalizer = LinearNormalizer(
|
| 88 |
-
use_stepwise_action_norm=self.use_stepwise_action_norm,
|
| 89 |
-
shape_meta=self.shape_meta,
|
| 90 |
-
default_mode=self.norm_default_mode,
|
| 91 |
-
exception_mode=self.norm_exception_mode,
|
| 92 |
-
stats=dataset_stats,
|
| 93 |
-
)
|
| 94 |
-
|
| 95 |
-
def augment_instruction(self, data: Dict[str, str] | List[str]) -> List[str]:
|
| 96 |
-
"""
|
| 97 |
-
Args:
|
| 98 |
-
data: Dict[str, str] | List[str], lerobot sample in raw mcap
|
| 99 |
-
|
| 100 |
-
Returns:
|
| 101 |
-
List[str], processed instructions
|
| 102 |
-
"""
|
| 103 |
-
# if single instruction, convert to list
|
| 104 |
-
if "coarse_task" in data:
|
| 105 |
-
high_level_instruction = data["coarse_task"]
|
| 106 |
-
else:
|
| 107 |
-
high_level_instruction = ""
|
| 108 |
-
if "task" not in data:
|
| 109 |
-
return f"[high] {high_level_instruction}"
|
| 110 |
-
|
| 111 |
-
low_level_instruction = data["task"]
|
| 112 |
-
# Galaxea lerobot use @ to split Chinese and English instruction
|
| 113 |
-
if "@" in low_level_instruction:
|
| 114 |
-
zh, eng = low_level_instruction.split("@")
|
| 115 |
-
low_level_instruction = zh if self.use_zh_instruction else eng
|
| 116 |
-
|
| 117 |
-
if np.random.rand() < self.drop_high_level_prob:
|
| 118 |
-
instruction = f"[Low]: {low_level_instruction}"
|
| 119 |
-
else:
|
| 120 |
-
instruction = f"[High]: {high_level_instruction}, [Low]: {low_level_instruction}"
|
| 121 |
-
|
| 122 |
-
return instruction
|
| 123 |
-
|
| 124 |
-
def action_state_transform(self, batch):
|
| 125 |
-
if "action" in batch:
|
| 126 |
-
for meta in self.shape_meta["action"]:
|
| 127 |
-
k, meta_shape = meta["key"], meta["raw_shape"]
|
| 128 |
-
actual_shape = batch["action"][k].shape[-1]
|
| 129 |
-
assert actual_shape == meta_shape, \
|
| 130 |
-
f"Action key {k} actual raw shape {actual_shape} mismatch with meta raw shape {meta_shape}."
|
| 131 |
-
|
| 132 |
-
for meta in self.shape_meta["state"]:
|
| 133 |
-
k, meta_shape = meta["key"], meta["raw_shape"]
|
| 134 |
-
actual_shape = batch["state"][k].shape[-1]
|
| 135 |
-
assert actual_shape == meta_shape, \
|
| 136 |
-
f"State key {k} actual raw shape {actual_shape} mismatch with meta raw shape{meta_shape}."
|
| 137 |
-
|
| 138 |
-
if self.action_state_transforms is not None:
|
| 139 |
-
for trans in self.action_state_transforms:
|
| 140 |
-
batch = trans.forward(batch)
|
| 141 |
-
|
| 142 |
-
if "action" in batch:
|
| 143 |
-
for meta in self.shape_meta["action"]:
|
| 144 |
-
k, meta_shape = meta["key"], meta["shape"]
|
| 145 |
-
actual_shape = batch["action"][k].shape[-1]
|
| 146 |
-
assert actual_shape == meta_shape, \
|
| 147 |
-
f"Action key {k} actual transformed shape {actual_shape} mismatch with meta shape {meta_shape}."
|
| 148 |
-
|
| 149 |
-
for meta in self.shape_meta["state"]:
|
| 150 |
-
k, meta_shape = meta["key"], meta["shape"]
|
| 151 |
-
actual_shape = batch["state"][k].shape[-1]
|
| 152 |
-
assert actual_shape == meta_shape, \
|
| 153 |
-
f"State key {k} actual transformed shape {actual_shape} mismatch with meta raw shape {meta_shape}."
|
| 154 |
-
|
| 155 |
-
return batch
|
| 156 |
-
|
| 157 |
-
def preprocess(self, data: Dict[str, Any]) -> Dict[str, Any]:
|
| 158 |
-
"""
|
| 159 |
-
Preprocess the data for the policy model.
|
| 160 |
-
|
| 161 |
-
Args:
|
| 162 |
-
Data: Dict[str, Any], lerobot sample in raw mcap obtained from dataset __getitem__:
|
| 163 |
-
- "action": Optional, Dict[str, torch.Tensor] -> [action_horizon, action_dim]
|
| 164 |
-
- "state": Dict[str, torch.Tensor] -> [num_obs_steps, state_dim]
|
| 165 |
-
- "images": Dict[str, torch.Tensor] -> [num_obs_steps, C, H, W]
|
| 166 |
-
- "action_is_pad": Optional, torch.Tensor -> [action_horizon,]
|
| 167 |
-
- "state_is_pad": torch.Tensor -> [num_obs_steps,]
|
| 168 |
-
- "image_is_pad": torch.Tensor -> [num_obs_steps,]
|
| 169 |
-
- "idx": int, sample index
|
| 170 |
-
|
| 171 |
-
Returns:
|
| 172 |
-
Sample: Dict[str, Any], which can collated:
|
| 173 |
-
- "input_ids": torch.Tensor -> [max_image_text_tokens,]
|
| 174 |
-
- "attention_mask": torch.Tensor -> [max_image_text_tokens,]
|
| 175 |
-
- "pixel_values": torch.Tensor -> [num_input_cameras, C, H, W]
|
| 176 |
-
- "image_is_pad": torch.Tensor -> [num_obs_steps,]
|
| 177 |
-
- "proprio": torch.Tensor -> [num_obs_steps, proprio_dim]
|
| 178 |
-
- "state_is_pad": torch.Tensor -> [num_obs_steps,]
|
| 179 |
-
- "action": Optional, torch.Tensor -> [action_horizon, action_dim]
|
| 180 |
-
- "action_is_pad": Optional, torch.Tensor -> [action_horizon,]
|
| 181 |
-
- "gt_action: Optional, deepcopy of input action for open loop eval, which is left untouched
|
| 182 |
-
- "idx": int, sample index
|
| 183 |
-
"""
|
| 184 |
-
sample = {}
|
| 185 |
-
# 1. instruction
|
| 186 |
-
sample["instruction"] = self.augment_instruction(data)
|
| 187 |
-
sample["image_is_pad"] = data["image_is_pad"]
|
| 188 |
-
|
| 189 |
-
# 2. image
|
| 190 |
-
processed_images = []
|
| 191 |
-
for meta in self.shape_meta["images"]:
|
| 192 |
-
key, shape = meta["key"], meta["shape"]
|
| 193 |
-
image = data["images"][key] # [num_obs_steps, C, H, W]
|
| 194 |
-
assert image.ndim == 4, f"Expected 4 dimensions (num_obs_steps, C, H, W), got shape {image.shape}"
|
| 195 |
-
|
| 196 |
-
# Apply transforms efficiently on the merged batch
|
| 197 |
-
transforms = self.train_transforms if self.is_train else self.val_transforms
|
| 198 |
-
for trans in transforms[key]:
|
| 199 |
-
image = trans(image)
|
| 200 |
-
|
| 201 |
-
meta_shape = [self.num_obs_steps] + shape
|
| 202 |
-
assert image.shape == meta_shape, \
|
| 203 |
-
f"Expected shape {meta_shape}, got {image.shape} after transforms for key {key}"
|
| 204 |
-
|
| 205 |
-
processed_images.append(image)
|
| 206 |
-
|
| 207 |
-
pixel_values = torch.cat(processed_images, dim=0) # [num_input_cameras, C, H, W]
|
| 208 |
-
if self.num_output_cameras > pixel_values.shape[0]:
|
| 209 |
-
out = torch.zeros((self.num_output_cameras,) + pixel_values.shape[1:], device=pixel_values.device, dtype=pixel_values.dtype)
|
| 210 |
-
out[0: pixel_values.shape[0]] = pixel_values
|
| 211 |
-
sample["pixel_values"] = out
|
| 212 |
-
else:
|
| 213 |
-
sample["pixel_values"] = pixel_values
|
| 214 |
-
|
| 215 |
-
# Copy action before transform for open-loop evaluation,
|
| 216 |
-
# disabled for training dataset as it may cause collating key problem.
|
| 217 |
-
if not self.is_train and "action" in data:
|
| 218 |
-
sample["gt_action"] = deepcopy(data["action"])
|
| 219 |
-
|
| 220 |
-
# 3. action & state
|
| 221 |
-
data = self.action_state_transform(data)
|
| 222 |
-
data = self.normalizer.forward(data)
|
| 223 |
-
data = self.action_state_merger.forward(data)
|
| 224 |
-
|
| 225 |
-
if "action" in data:
|
| 226 |
-
sample["action"] = data["action"] # [action_horizon, action_dim]
|
| 227 |
-
sample["action_is_pad"] = data["action_is_pad"] # [action_horizon,]
|
| 228 |
-
sample["action_dim_is_pad"] = data["action_dim_is_pad"] # [action_dim,]
|
| 229 |
-
assert sample["action"].shape[-1] == self.action_output_dim
|
| 230 |
-
|
| 231 |
-
# TODO: rename all "state" into "proprio"
|
| 232 |
-
sample["proprio"] = data["state"] # [num_obs_steps, proprio_dim]
|
| 233 |
-
sample["proprio_is_pad"] = data["state_is_pad"] # [num_obs_steps,]
|
| 234 |
-
sample["proprio_dim_is_pad"] = data["state_dim_is_pad"] # [proprio_dim,]
|
| 235 |
-
assert sample["proprio"].shape[-1] == self.proprio_output_dim
|
| 236 |
-
|
| 237 |
-
sample["idx"] = data["idx"]
|
| 238 |
-
|
| 239 |
-
sample = self.tokenizer(sample)
|
| 240 |
-
|
| 241 |
-
return sample
|
| 242 |
-
|
| 243 |
-
def postprocess(self, data: Dict[str, Any]) -> Dict[str, Any]:
|
| 244 |
-
"""
|
| 245 |
-
Postprocess the data for the policy model.
|
| 246 |
-
|
| 247 |
-
Args:
|
| 248 |
-
data: Dict[str, Any], lerobot sample in raw mcap
|
| 249 |
-
|
| 250 |
-
Returns:
|
| 251 |
-
data: Dict[str, Any], processed data including unnormalized action
|
| 252 |
-
"""
|
| 253 |
-
assert "action" in data, "Action is required in postprocess"
|
| 254 |
-
data["state"] = data.pop("proprio")
|
| 255 |
-
data = self.action_state_merger.backward(data)
|
| 256 |
-
data = self.normalizer.backward(data)
|
| 257 |
-
if self.action_state_transforms is not None:
|
| 258 |
-
for trans in reversed(self.action_state_transforms):
|
| 259 |
-
data = trans.backward(data)
|
| 260 |
-
|
| 261 |
-
start_obs_step = self.num_obs_steps - 1
|
| 262 |
-
data["action"] = dict_apply(data["action"], lambda x: x[:, start_obs_step:, :])
|
| 263 |
-
return data
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/processors/fastwam_processor.py
DELETED
|
@@ -1,362 +0,0 @@
|
|
| 1 |
-
# Author: Rui Heng Yang
|
| 2 |
-
|
| 3 |
-
from abc import ABC, abstractmethod
|
| 4 |
-
from typing import Dict, Any, Optional, List, Literal
|
| 5 |
-
|
| 6 |
-
import torch
|
| 7 |
-
import numpy as np
|
| 8 |
-
from copy import deepcopy
|
| 9 |
-
from ..utils.normalizer import LinearNormalizer, NormMode
|
| 10 |
-
from fastwam.utils.pytorch_utils import dict_apply
|
| 11 |
-
from fastwam.utils.logging_config import get_logger
|
| 12 |
-
from .base_processor import BaseProcessor
|
| 13 |
-
|
| 14 |
-
logger = get_logger(__name__)
|
| 15 |
-
|
| 16 |
-
# Sample-identity keys that `preprocess()` forwards untouched. Consumers that
|
| 17 |
-
# need to know *which* episode/frame a sample came from (e.g. the EEF-anchor
|
| 18 |
-
# lookup in `RobotVideoDataset`) must read them off the returned sample, since
|
| 19 |
-
# both resample paths mean the requested index is not the delivered one.
|
| 20 |
-
IDENTITY_KEYS = ("dataset_index", "episode_index", "frame_index")
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
class FastWAMProcessor(BaseProcessor):
|
| 24 |
-
def __init__(
|
| 25 |
-
self,
|
| 26 |
-
# keys
|
| 27 |
-
shape_meta: Dict[str, Any],
|
| 28 |
-
num_obs_steps: int,
|
| 29 |
-
num_output_cameras: int,
|
| 30 |
-
action_output_dim: int,
|
| 31 |
-
proprio_output_dim: int,
|
| 32 |
-
|
| 33 |
-
action_state_transforms: Optional[List[Any]],
|
| 34 |
-
|
| 35 |
-
# action & state normalization
|
| 36 |
-
use_stepwise_action_norm: bool,
|
| 37 |
-
norm_default_mode: NormMode,
|
| 38 |
-
norm_exception_mode: Dict[str, Dict[str, NormMode]],
|
| 39 |
-
|
| 40 |
-
action_state_merger,
|
| 41 |
-
|
| 42 |
-
# image transform
|
| 43 |
-
train_transforms: Dict[str, List[Any]] | None,
|
| 44 |
-
val_transforms: Dict[str, List[Any]] | None,
|
| 45 |
-
|
| 46 |
-
# instruction transform
|
| 47 |
-
drop_high_level_prob: float = 1.0,
|
| 48 |
-
use_zh_instruction: bool = False,
|
| 49 |
-
|
| 50 |
-
tokenizer: Optional[Any] = None,
|
| 51 |
-
delta_action_dim_mask: Optional[Dict[str, List[bool]]] = None,
|
| 52 |
-
):
|
| 53 |
-
self.shape_meta = shape_meta
|
| 54 |
-
self.num_obs_steps = num_obs_steps
|
| 55 |
-
self.num_output_cameras = num_output_cameras
|
| 56 |
-
self.action_output_dim = action_output_dim
|
| 57 |
-
self.proprio_output_dim = proprio_output_dim
|
| 58 |
-
|
| 59 |
-
self.drop_high_level_prob = drop_high_level_prob
|
| 60 |
-
self.use_zh_instruction = use_zh_instruction
|
| 61 |
-
|
| 62 |
-
# image
|
| 63 |
-
self.train_transforms = train_transforms
|
| 64 |
-
self.val_transforms = val_transforms
|
| 65 |
-
|
| 66 |
-
self._is_train = None
|
| 67 |
-
|
| 68 |
-
self.action_state_transforms = action_state_transforms
|
| 69 |
-
self.action_state_merger = action_state_merger
|
| 70 |
-
self.action_state_merger.set_shape_meta(self.shape_meta)
|
| 71 |
-
|
| 72 |
-
self.use_stepwise_action_norm = use_stepwise_action_norm
|
| 73 |
-
self.norm_default_mode = norm_default_mode
|
| 74 |
-
self.norm_exception_mode = norm_exception_mode
|
| 75 |
-
self._normalizer = None
|
| 76 |
-
|
| 77 |
-
self.tokenizer = tokenizer
|
| 78 |
-
if delta_action_dim_mask is None:
|
| 79 |
-
self.delta_action_dim_mask = None
|
| 80 |
-
else:
|
| 81 |
-
action_meta = self.shape_meta["action"]
|
| 82 |
-
expected_keys = [m["key"] for m in action_meta]
|
| 83 |
-
provided_keys = list(delta_action_dim_mask.keys())
|
| 84 |
-
if set(provided_keys) != set(expected_keys):
|
| 85 |
-
raise ValueError(
|
| 86 |
-
f"`delta_action_dim_mask` keys mismatch. Expected {expected_keys}, got {provided_keys}."
|
| 87 |
-
)
|
| 88 |
-
|
| 89 |
-
self.delta_action_dim_mask = {}
|
| 90 |
-
for meta in action_meta:
|
| 91 |
-
key = meta["key"]
|
| 92 |
-
expected_dim = meta["shape"]
|
| 93 |
-
mask = delta_action_dim_mask[key]
|
| 94 |
-
if len(mask) != expected_dim:
|
| 95 |
-
raise ValueError(
|
| 96 |
-
f"`delta_action_dim_mask[{key}]` length must be {expected_dim}, got {len(mask)}."
|
| 97 |
-
)
|
| 98 |
-
self.delta_action_dim_mask[key] = torch.as_tensor(mask, dtype=torch.bool)
|
| 99 |
-
|
| 100 |
-
@property
|
| 101 |
-
def is_train(self):
|
| 102 |
-
if self._is_train is None:
|
| 103 |
-
raise ValueError("is_train has not been set. Please call train() and eval() first.")
|
| 104 |
-
return self._is_train
|
| 105 |
-
|
| 106 |
-
@property
|
| 107 |
-
def normalizer(self) -> LinearNormalizer:
|
| 108 |
-
if self._normalizer is None:
|
| 109 |
-
raise ValueError("normalizer has not been set. Please call set_normalizer_from_stats() first.")
|
| 110 |
-
return self._normalizer
|
| 111 |
-
|
| 112 |
-
def train(self):
|
| 113 |
-
self._is_train = True
|
| 114 |
-
return self
|
| 115 |
-
|
| 116 |
-
def eval(self):
|
| 117 |
-
self._is_train = False
|
| 118 |
-
return self
|
| 119 |
-
|
| 120 |
-
def set_normalizer_from_stats(self, dataset_stats: Dict[str, Any] = None):
|
| 121 |
-
self._normalizer = LinearNormalizer(
|
| 122 |
-
use_stepwise_action_norm=self.use_stepwise_action_norm,
|
| 123 |
-
shape_meta=self.shape_meta,
|
| 124 |
-
default_mode=self.norm_default_mode,
|
| 125 |
-
exception_mode=self.norm_exception_mode,
|
| 126 |
-
stats=dataset_stats,
|
| 127 |
-
)
|
| 128 |
-
|
| 129 |
-
def augment_instruction(self, data: Dict[str, str] | List[str]) -> List[str]:
|
| 130 |
-
"""
|
| 131 |
-
Args:
|
| 132 |
-
data: Dict[str, str] | List[str], lerobot sample in raw mcap
|
| 133 |
-
|
| 134 |
-
Returns:
|
| 135 |
-
List[str], processed instructions
|
| 136 |
-
"""
|
| 137 |
-
# if single instruction, convert to list
|
| 138 |
-
if "coarse_task" in data:
|
| 139 |
-
high_level_instruction = data["coarse_task"]
|
| 140 |
-
else:
|
| 141 |
-
high_level_instruction = ""
|
| 142 |
-
if "task" not in data:
|
| 143 |
-
return f"[high] {high_level_instruction}"
|
| 144 |
-
|
| 145 |
-
low_level_instruction = data["task"]
|
| 146 |
-
# Galaxea lerobot use @ to split Chinese and English instruction
|
| 147 |
-
if "@" in low_level_instruction:
|
| 148 |
-
zh, eng = low_level_instruction.split("@")
|
| 149 |
-
low_level_instruction = zh if self.use_zh_instruction else eng
|
| 150 |
-
|
| 151 |
-
if np.random.rand() < self.drop_high_level_prob:
|
| 152 |
-
instruction = f"{low_level_instruction}"
|
| 153 |
-
else:
|
| 154 |
-
instruction = f"[High]: {high_level_instruction}, [Low]: {low_level_instruction}"
|
| 155 |
-
|
| 156 |
-
return instruction
|
| 157 |
-
|
| 158 |
-
def action_state_transform(self, batch):
|
| 159 |
-
if "action" in batch:
|
| 160 |
-
for meta in self.shape_meta["action"]:
|
| 161 |
-
k, meta_shape = meta["key"], meta["raw_shape"]
|
| 162 |
-
actual_shape = batch["action"][k].shape[-1]
|
| 163 |
-
assert actual_shape == meta_shape, \
|
| 164 |
-
f"Action key {k} actual raw shape {actual_shape} mismatch with meta raw shape {meta_shape}."
|
| 165 |
-
|
| 166 |
-
for meta in self.shape_meta["state"]:
|
| 167 |
-
k, meta_shape = meta["key"], meta["raw_shape"]
|
| 168 |
-
actual_shape = batch["state"][k].shape[-1]
|
| 169 |
-
assert actual_shape == meta_shape, \
|
| 170 |
-
f"State key {k} actual raw shape {actual_shape} mismatch with meta raw shape {meta_shape}."
|
| 171 |
-
|
| 172 |
-
if self.action_state_transforms is not None:
|
| 173 |
-
for trans in self.action_state_transforms:
|
| 174 |
-
batch = trans.forward(batch)
|
| 175 |
-
|
| 176 |
-
if "action" in batch:
|
| 177 |
-
for meta in self.shape_meta["action"]:
|
| 178 |
-
k, meta_shape = meta["key"], meta["shape"]
|
| 179 |
-
actual_shape = batch["action"][k].shape[-1]
|
| 180 |
-
assert actual_shape == meta_shape, \
|
| 181 |
-
f"Action key {k} actual transformed shape {actual_shape} mismatch with meta shape {meta_shape}."
|
| 182 |
-
|
| 183 |
-
for meta in self.shape_meta["state"]:
|
| 184 |
-
k, meta_shape = meta["key"], meta["shape"]
|
| 185 |
-
actual_shape = batch["state"][k].shape[-1]
|
| 186 |
-
assert actual_shape == meta_shape, \
|
| 187 |
-
f"State key {k} actual transformed shape {actual_shape} mismatch with meta raw shape {meta_shape}."
|
| 188 |
-
|
| 189 |
-
return batch
|
| 190 |
-
|
| 191 |
-
def preprocess_images(
|
| 192 |
-
self,
|
| 193 |
-
images: Dict[str, torch.Tensor],
|
| 194 |
-
*,
|
| 195 |
-
expected_num_obs_steps: Optional[int] = None,
|
| 196 |
-
) -> torch.Tensor:
|
| 197 |
-
"""Transform and stack camera images without processing action or state.
|
| 198 |
-
|
| 199 |
-
Parameters
|
| 200 |
-
----------
|
| 201 |
-
images:
|
| 202 |
-
Mapping from configured camera key to ``[T,C,H,W]`` uint8 tensors.
|
| 203 |
-
expected_num_obs_steps:
|
| 204 |
-
Expected temporal length. Defaults to the training dataset's full
|
| 205 |
-
observation horizon; precompute uses the nine VAE-sampled frames.
|
| 206 |
-
|
| 207 |
-
Returns
|
| 208 |
-
-------
|
| 209 |
-
torch.Tensor
|
| 210 |
-
Camera-major tensor ``[num_output_cameras,T,C,H,W]``.
|
| 211 |
-
"""
|
| 212 |
-
|
| 213 |
-
num_obs_steps = (
|
| 214 |
-
self.num_obs_steps
|
| 215 |
-
if expected_num_obs_steps is None
|
| 216 |
-
else int(expected_num_obs_steps)
|
| 217 |
-
)
|
| 218 |
-
processed_images = []
|
| 219 |
-
for meta in self.shape_meta["images"]:
|
| 220 |
-
key, shape = meta["key"], meta["shape"]
|
| 221 |
-
image = images[key]
|
| 222 |
-
if image.ndim != 4:
|
| 223 |
-
raise ValueError(
|
| 224 |
-
"Expected image dimensions [T,C,H,W], "
|
| 225 |
-
f"got {tuple(image.shape)} for key {key}"
|
| 226 |
-
)
|
| 227 |
-
|
| 228 |
-
transforms = self.train_transforms if self.is_train else self.val_transforms
|
| 229 |
-
current_transforms = transforms[key] if isinstance(transforms, dict) else transforms
|
| 230 |
-
for transform in current_transforms:
|
| 231 |
-
image = transform(image)
|
| 232 |
-
|
| 233 |
-
expected_shape = [num_obs_steps] + shape
|
| 234 |
-
if list(image.shape) != expected_shape:
|
| 235 |
-
raise ValueError(
|
| 236 |
-
f"Expected shape {expected_shape}, got {tuple(image.shape)} "
|
| 237 |
-
f"after transforms for key {key}"
|
| 238 |
-
)
|
| 239 |
-
processed_images.append(image)
|
| 240 |
-
|
| 241 |
-
pixel_values = torch.stack(processed_images, dim=0)
|
| 242 |
-
if self.num_output_cameras > pixel_values.shape[0]:
|
| 243 |
-
output = torch.zeros(
|
| 244 |
-
(self.num_output_cameras,) + pixel_values.shape[1:],
|
| 245 |
-
device=pixel_values.device,
|
| 246 |
-
dtype=pixel_values.dtype,
|
| 247 |
-
)
|
| 248 |
-
output[: pixel_values.shape[0]] = pixel_values
|
| 249 |
-
return output
|
| 250 |
-
if self.num_output_cameras < pixel_values.shape[0]:
|
| 251 |
-
logger.warning(
|
| 252 |
-
"num_output_cameras %d is less than input cameras %d; truncating.",
|
| 253 |
-
self.num_output_cameras,
|
| 254 |
-
pixel_values.shape[0],
|
| 255 |
-
)
|
| 256 |
-
return pixel_values[: self.num_output_cameras]
|
| 257 |
-
return pixel_values
|
| 258 |
-
|
| 259 |
-
def preprocess(self, data: Dict[str, Any]) -> Dict[str, Any]:
|
| 260 |
-
"""
|
| 261 |
-
Preprocess the data for the policy model.
|
| 262 |
-
|
| 263 |
-
Args:
|
| 264 |
-
Data: Dict[str, Any], lerobot sample in raw mcap obtained from dataset __getitem__:
|
| 265 |
-
- "action": Optional, Dict[str, torch.Tensor] -> [action_horizon, action_dim]
|
| 266 |
-
- "state": Dict[str, torch.Tensor] -> [num_obs_steps, state_dim]
|
| 267 |
-
- "images": Dict[str, torch.Tensor] -> [num_obs_steps, C, H, W]
|
| 268 |
-
- "action_is_pad": Optional, torch.Tensor -> [action_horizon,]
|
| 269 |
-
- "state_is_pad": torch.Tensor -> [num_obs_steps,]
|
| 270 |
-
- "image_is_pad": torch.Tensor -> [num_obs_steps,]
|
| 271 |
-
- "idx": int, sample index
|
| 272 |
-
|
| 273 |
-
Returns:
|
| 274 |
-
Sample: Dict[str, Any], which can collated:
|
| 275 |
-
- "input_ids": torch.Tensor -> [max_image_text_tokens,]
|
| 276 |
-
- "attention_mask": torch.Tensor -> [max_image_text_tokens,]
|
| 277 |
-
- "pixel_values": torch.Tensor -> [num_input_cameras, C, H, W]
|
| 278 |
-
- "image_is_pad": torch.Tensor -> [num_obs_steps,]
|
| 279 |
-
- "proprio": torch.Tensor -> [num_obs_steps, proprio_dim]
|
| 280 |
-
- "state_is_pad": torch.Tensor -> [num_obs_steps,]
|
| 281 |
-
- "action": Optional, torch.Tensor -> [action_horizon, action_dim]
|
| 282 |
-
- "action_is_pad": Optional, torch.Tensor -> [action_horizon,]
|
| 283 |
-
- "gt_action: Optional, deepcopy of input action for open loop eval, which is left untouched
|
| 284 |
-
- "idx": int, sample index
|
| 285 |
-
"""
|
| 286 |
-
sample = {}
|
| 287 |
-
# 1. instruction
|
| 288 |
-
sample["instruction"] = self.augment_instruction(data)
|
| 289 |
-
sample["image_is_pad"] = data["image_is_pad"]
|
| 290 |
-
|
| 291 |
-
# 2. image
|
| 292 |
-
if data["images"]:
|
| 293 |
-
sample["pixel_values"] = self.preprocess_images(data["images"])
|
| 294 |
-
|
| 295 |
-
# Copy action before transform for open-loop evaluation,
|
| 296 |
-
# disabled for training dataset as it may cause collating key problem.
|
| 297 |
-
if not self.is_train and "action" in data:
|
| 298 |
-
sample["gt_action"] = deepcopy(data["action"])
|
| 299 |
-
|
| 300 |
-
# 3. action & state
|
| 301 |
-
if "action" in data and self.delta_action_dim_mask is not None:
|
| 302 |
-
action_is_pad = torch.as_tensor(data["action_is_pad"], dtype=torch.bool)
|
| 303 |
-
if bool(action_is_pad.any().item()):
|
| 304 |
-
for key, dim_mask in self.delta_action_dim_mask.items():
|
| 305 |
-
cur_action = data["action"][key]
|
| 306 |
-
cur_action_is_pad = action_is_pad.to(device=cur_action.device)
|
| 307 |
-
cur_dim_mask = dim_mask.to(device=cur_action.device)
|
| 308 |
-
pad_delta_mask = cur_action_is_pad.unsqueeze(1) & cur_dim_mask.unsqueeze(0)
|
| 309 |
-
cur_action[pad_delta_mask] = 0.0
|
| 310 |
-
data = self.action_state_transform(data)
|
| 311 |
-
data = self.normalizer.forward(data)
|
| 312 |
-
data = self.action_state_merger.forward(data)
|
| 313 |
-
|
| 314 |
-
if "action" in data:
|
| 315 |
-
sample["action"] = data["action"] # [action_horizon, action_dim]
|
| 316 |
-
sample["action_is_pad"] = data["action_is_pad"] # [action_horizon,]
|
| 317 |
-
sample["action_dim_is_pad"] = data["action_dim_is_pad"] # [action_dim,]
|
| 318 |
-
assert sample["action"].shape[-1] == self.action_output_dim
|
| 319 |
-
# sample["action"][sample["action_is_pad"], :-1] = 0.0 # NOTE: we assume use delta_eef_pose + gripper, so pad action is 0
|
| 320 |
-
|
| 321 |
-
|
| 322 |
-
# TODO: rename all "state" into "proprio"
|
| 323 |
-
sample["proprio"] = data["state"] # [num_obs_steps, proprio_dim]
|
| 324 |
-
sample["proprio_is_pad"] = data["state_is_pad"] # [num_obs_steps,]
|
| 325 |
-
sample["proprio_dim_is_pad"] = data["state_dim_is_pad"] # [proprio_dim,]
|
| 326 |
-
assert sample["proprio"].shape[-1] == self.proprio_output_dim
|
| 327 |
-
|
| 328 |
-
sample["idx"] = data["idx"]
|
| 329 |
-
|
| 330 |
-
# Episode/frame identity, forwarded verbatim. `preprocess` builds a fresh
|
| 331 |
-
# dict, so anything not copied here is dropped before the caller sees it.
|
| 332 |
-
# `RobotVideoDataset` keys its EEF-anchor lookup off these and consumes
|
| 333 |
-
# them, so they never reach the collater.
|
| 334 |
-
for key in IDENTITY_KEYS:
|
| 335 |
-
if key in data:
|
| 336 |
-
sample[key] = data[key]
|
| 337 |
-
|
| 338 |
-
# sample = self.tokenizer(sample)
|
| 339 |
-
|
| 340 |
-
return sample
|
| 341 |
-
|
| 342 |
-
def postprocess(self, data: Dict[str, Any]) -> Dict[str, Any]:
|
| 343 |
-
"""
|
| 344 |
-
Postprocess the data for the policy model.
|
| 345 |
-
|
| 346 |
-
Args:
|
| 347 |
-
data: Dict[str, Any], lerobot sample in raw mcap
|
| 348 |
-
|
| 349 |
-
Returns:
|
| 350 |
-
data: Dict[str, Any], processed data including unnormalized action
|
| 351 |
-
"""
|
| 352 |
-
assert "action" in data, "Action is required in postprocess"
|
| 353 |
-
data["state"] = data.pop("proprio")
|
| 354 |
-
data = self.action_state_merger.backward(data)
|
| 355 |
-
data = self.normalizer.backward(data)
|
| 356 |
-
if self.action_state_transforms is not None:
|
| 357 |
-
for trans in reversed(self.action_state_transforms):
|
| 358 |
-
data = trans.backward(data)
|
| 359 |
-
|
| 360 |
-
start_obs_step = self.num_obs_steps - 1
|
| 361 |
-
data["action"] = dict_apply(data["action"], lambda x: x[:, start_obs_step:, :])
|
| 362 |
-
return data
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/robot_video_dataset.py
DELETED
|
@@ -1,446 +0,0 @@
|
|
| 1 |
-
# Author: Rui Heng Yang
|
| 2 |
-
|
| 3 |
-
import hashlib
|
| 4 |
-
import os
|
| 5 |
-
from pathlib import Path
|
| 6 |
-
from typing import Any, Optional
|
| 7 |
-
import numpy as np
|
| 8 |
-
import traceback
|
| 9 |
-
import torch
|
| 10 |
-
import torchvision.transforms.functional as transforms_F
|
| 11 |
-
|
| 12 |
-
from omegaconf import DictConfig, OmegaConf
|
| 13 |
-
|
| 14 |
-
from hydra.utils import instantiate
|
| 15 |
-
from .base_lerobot_dataset import BaseLerobotDataset
|
| 16 |
-
from ..video_latent_cache import VideoLatentCache, build_video_preprocess_spec
|
| 17 |
-
from .utils.normalizer import save_dataset_stats_to_json, load_dataset_stats_from_json
|
| 18 |
-
from ..dataset_utils import ResizeSmallestSideAspectPreserving, CenterCrop, Normalize
|
| 19 |
-
from fastwam.utils.logging_config import get_logger
|
| 20 |
-
from fastwam.utils import misc, pytorch_utils
|
| 21 |
-
logger = get_logger(__name__)
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
DEFAULT_PROMPT = "A video recorded from a robot's point of view executing the following instruction: {task}"
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
def _is_main_process_without_init() -> bool:
|
| 28 |
-
return pytorch_utils._resolve_global_rank() == 0
|
| 29 |
-
|
| 30 |
-
class RobotVideoDataset(torch.utils.data.Dataset):
|
| 31 |
-
def __init__(
|
| 32 |
-
self,
|
| 33 |
-
dataset_dirs,
|
| 34 |
-
shape_meta,
|
| 35 |
-
num_frames=33,
|
| 36 |
-
video_size=[384, 640],
|
| 37 |
-
camera_key=None,
|
| 38 |
-
processor=None,
|
| 39 |
-
text_embedding_cache_dir=None,
|
| 40 |
-
context_len=128,
|
| 41 |
-
pretrained_norm_stats=None,
|
| 42 |
-
val_set_proportion=0.05,
|
| 43 |
-
is_training_set=False,
|
| 44 |
-
episode_indices=None,
|
| 45 |
-
episode_indices_path=None,
|
| 46 |
-
episode_indices_key=None,
|
| 47 |
-
global_sample_stride=1,
|
| 48 |
-
action_video_freq_ratio: int = 1,
|
| 49 |
-
skip_padding_as_possible: bool = False,
|
| 50 |
-
max_padding_retry: int = 3,
|
| 51 |
-
concat_multi_camera: str = "horizontal", # "horizontal", "vertical", "robotwin", or None
|
| 52 |
-
video_backend: Optional[str] = None,
|
| 53 |
-
video_latent_cache_dir: Optional[str] = None,
|
| 54 |
-
video_latent_cache_vae_identity: Optional[dict[str, str]] = None,
|
| 55 |
-
strict_getitem: bool = False,
|
| 56 |
-
precompute_video_only: bool = False,
|
| 57 |
-
override_instruction: Optional[str] = None, # whether to hardcode a specific instruction for all samples, for debugging
|
| 58 |
-
eef_anchor_calibration_path: Optional[str] = None,
|
| 59 |
-
eef_anchor_raw_resolution: int = 512,
|
| 60 |
-
):
|
| 61 |
-
if video_latent_cache_dir is not None and not strict_getitem:
|
| 62 |
-
raise ValueError(
|
| 63 |
-
"`strict_getitem=true` is required with `video_latent_cache_dir` "
|
| 64 |
-
"to prevent latent/action sample misalignment."
|
| 65 |
-
)
|
| 66 |
-
if video_latent_cache_dir is not None and video_backend is None:
|
| 67 |
-
raise ValueError(
|
| 68 |
-
"`video_backend` must be explicitly pinned when using a video latent cache."
|
| 69 |
-
)
|
| 70 |
-
if video_latent_cache_dir is not None and video_latent_cache_vae_identity is None:
|
| 71 |
-
raise ValueError(
|
| 72 |
-
"`video_latent_cache_vae_identity` is required with a video latent cache."
|
| 73 |
-
)
|
| 74 |
-
if strict_getitem and skip_padding_as_possible:
|
| 75 |
-
raise ValueError(
|
| 76 |
-
"`skip_padding_as_possible` must be false in strict/cache mode because "
|
| 77 |
-
"padding retries substitute a random global sample index."
|
| 78 |
-
)
|
| 79 |
-
if precompute_video_only and (not strict_getitem or video_latent_cache_dir is not None):
|
| 80 |
-
raise ValueError(
|
| 81 |
-
"`precompute_video_only` requires strict_getitem=true and no latent cache."
|
| 82 |
-
)
|
| 83 |
-
|
| 84 |
-
if (num_frames - 1) % action_video_freq_ratio != 0:
|
| 85 |
-
raise ValueError(
|
| 86 |
-
"num_frames-1 must be divisible by action_video_freq_ratio, got "
|
| 87 |
-
f"{num_frames - 1} and {action_video_freq_ratio}"
|
| 88 |
-
)
|
| 89 |
-
if ((num_frames - 1) // action_video_freq_ratio) % 4 != 0:
|
| 90 |
-
raise ValueError(
|
| 91 |
-
"video transitions must be divisible by 4 for tokenization, got "
|
| 92 |
-
f"{(num_frames - 1) // action_video_freq_ratio}"
|
| 93 |
-
)
|
| 94 |
-
video_sample_indices = list(range(0, num_frames, action_video_freq_ratio))
|
| 95 |
-
|
| 96 |
-
shape_meta_container = OmegaConf.to_container(shape_meta, resolve=True)
|
| 97 |
-
processor_config: dict[str, Any] | None = None
|
| 98 |
-
if isinstance(processor, DictConfig):
|
| 99 |
-
processor_config = OmegaConf.to_container(processor, resolve=True)
|
| 100 |
-
|
| 101 |
-
self.lerobot_dataset = BaseLerobotDataset(
|
| 102 |
-
dataset_dirs=dataset_dirs,
|
| 103 |
-
shape_meta=shape_meta_container,
|
| 104 |
-
obs_size=num_frames,
|
| 105 |
-
action_size=num_frames - 1,
|
| 106 |
-
val_set_proportion=val_set_proportion,
|
| 107 |
-
is_training_set=is_training_set,
|
| 108 |
-
episode_indices=episode_indices,
|
| 109 |
-
episode_indices_path=episode_indices_path,
|
| 110 |
-
episode_indices_key=episode_indices_key,
|
| 111 |
-
global_sample_stride=global_sample_stride,
|
| 112 |
-
video_backend=video_backend,
|
| 113 |
-
strict_getitem=strict_getitem,
|
| 114 |
-
image_only=precompute_video_only,
|
| 115 |
-
image_sample_indices=(video_sample_indices if precompute_video_only else None),
|
| 116 |
-
)
|
| 117 |
-
|
| 118 |
-
self.num_frames = num_frames
|
| 119 |
-
self.action_video_freq_ratio = action_video_freq_ratio
|
| 120 |
-
|
| 121 |
-
self.video_sample_indices = video_sample_indices
|
| 122 |
-
|
| 123 |
-
self.camera_key = camera_key
|
| 124 |
-
self.video_latent_cache_dir = video_latent_cache_dir
|
| 125 |
-
self.strict_getitem = bool(strict_getitem)
|
| 126 |
-
self.precompute_video_only = bool(precompute_video_only)
|
| 127 |
-
self.lerobot_dataset._set_return_images(video_latent_cache_dir is None)
|
| 128 |
-
|
| 129 |
-
self.video_size = video_size
|
| 130 |
-
self.text_embedding_cache_dir = text_embedding_cache_dir
|
| 131 |
-
self.context_len = context_len
|
| 132 |
-
self.skip_padding_as_possible = skip_padding_as_possible
|
| 133 |
-
self.max_padding_retry = max_padding_retry
|
| 134 |
-
self.concat_multi_camera = concat_multi_camera
|
| 135 |
-
self.override_instruction = override_instruction
|
| 136 |
-
|
| 137 |
-
resolved_episode_indices_path = None
|
| 138 |
-
episode_indices_path_sha256 = None
|
| 139 |
-
if episode_indices_path is not None:
|
| 140 |
-
resolved_path = Path(episode_indices_path).expanduser().resolve()
|
| 141 |
-
if not resolved_path.is_file():
|
| 142 |
-
raise FileNotFoundError(f"Episode split file not found: {resolved_path}")
|
| 143 |
-
resolved_episode_indices_path = str(resolved_path)
|
| 144 |
-
episode_indices_path_sha256 = hashlib.sha256(resolved_path.read_bytes()).hexdigest()
|
| 145 |
-
|
| 146 |
-
preprocess_spec = build_video_preprocess_spec(
|
| 147 |
-
dataset_dirs=dataset_dirs,
|
| 148 |
-
shape_meta=shape_meta_container,
|
| 149 |
-
processor_config=processor_config,
|
| 150 |
-
num_frames=num_frames,
|
| 151 |
-
action_video_freq_ratio=action_video_freq_ratio,
|
| 152 |
-
video_size=video_size,
|
| 153 |
-
concat_multi_camera=concat_multi_camera,
|
| 154 |
-
video_backend=str(video_backend),
|
| 155 |
-
global_sample_stride=global_sample_stride,
|
| 156 |
-
sample_selection={
|
| 157 |
-
"val_set_proportion": float(val_set_proportion),
|
| 158 |
-
"is_training_set": bool(is_training_set),
|
| 159 |
-
"episode_indices": (
|
| 160 |
-
None if episode_indices is None else [int(value) for value in episode_indices]
|
| 161 |
-
),
|
| 162 |
-
"episode_indices_path": (
|
| 163 |
-
resolved_episode_indices_path
|
| 164 |
-
),
|
| 165 |
-
"episode_indices_path_sha256": episode_indices_path_sha256,
|
| 166 |
-
"episode_indices_key": episode_indices_key,
|
| 167 |
-
},
|
| 168 |
-
)
|
| 169 |
-
self.video_preprocess_spec = preprocess_spec
|
| 170 |
-
self.video_latent_cache = None
|
| 171 |
-
if video_latent_cache_dir is not None:
|
| 172 |
-
expected_vae_identity = OmegaConf.to_container(
|
| 173 |
-
video_latent_cache_vae_identity, resolve=True
|
| 174 |
-
) if isinstance(video_latent_cache_vae_identity, DictConfig) else dict(
|
| 175 |
-
video_latent_cache_vae_identity
|
| 176 |
-
)
|
| 177 |
-
self.video_latent_cache = VideoLatentCache(
|
| 178 |
-
video_latent_cache_dir,
|
| 179 |
-
expected_sample_count=len(self.lerobot_dataset),
|
| 180 |
-
expected_preprocess_spec=preprocess_spec,
|
| 181 |
-
expected_vae_identity=expected_vae_identity,
|
| 182 |
-
)
|
| 183 |
-
|
| 184 |
-
self.resize_transform = ResizeSmallestSideAspectPreserving(
|
| 185 |
-
args={"img_w": self.video_size[1], "img_h": self.video_size[0]},
|
| 186 |
-
)
|
| 187 |
-
self.crop_transform = CenterCrop(
|
| 188 |
-
args={"img_w": self.video_size[1], "img_h": self.video_size[0]},
|
| 189 |
-
)
|
| 190 |
-
self.normalize_transform = Normalize(
|
| 191 |
-
args={"mean": 0.5, "std": 0.5},
|
| 192 |
-
)
|
| 193 |
-
if processor is not None:
|
| 194 |
-
if isinstance(processor, DictConfig):
|
| 195 |
-
processor = instantiate(processor)
|
| 196 |
-
if not pretrained_norm_stats:
|
| 197 |
-
if not is_training_set:
|
| 198 |
-
raise ValueError("pretrained_norm_stats must be provided for validation/test sets since we don't want to calculate stats on them.")
|
| 199 |
-
dist_initialized = (
|
| 200 |
-
torch.distributed.is_available() and torch.distributed.is_initialized()
|
| 201 |
-
)
|
| 202 |
-
if _is_main_process_without_init() or not dist_initialized:
|
| 203 |
-
logger.info("Calculating dataset stats for normalization...")
|
| 204 |
-
dataset_stats = self.lerobot_dataset.get_dataset_stats(processor)
|
| 205 |
-
work_dir = misc.get_work_dir()
|
| 206 |
-
if _is_main_process_without_init():
|
| 207 |
-
save_dataset_stats_to_json(dataset_stats, os.path.join(work_dir, "dataset_stats.json"))
|
| 208 |
-
else:
|
| 209 |
-
dataset_stats = None
|
| 210 |
-
if dist_initialized:
|
| 211 |
-
obj_list = [dataset_stats]
|
| 212 |
-
torch.distributed.broadcast_object_list(obj_list, src=0)
|
| 213 |
-
dataset_stats = obj_list[0]
|
| 214 |
-
else:
|
| 215 |
-
dataset_stats = load_dataset_stats_from_json(pretrained_norm_stats)
|
| 216 |
-
logger.info(f"Using dataset stats: {pretrained_norm_stats}")
|
| 217 |
-
if _is_main_process_without_init():
|
| 218 |
-
work_dir = misc.get_work_dir()
|
| 219 |
-
save_dataset_stats_to_json(dataset_stats, os.path.join(work_dir, "dataset_stats.json"))
|
| 220 |
-
|
| 221 |
-
processor.set_normalizer_from_stats(dataset_stats)
|
| 222 |
-
self.lerobot_dataset.set_processor(processor)
|
| 223 |
-
|
| 224 |
-
# EEF-relative camera RoPE: resolve every episode's anchors once, here,
|
| 225 |
-
# and hold them in RAM. No sidecar exists (plan Section 15). Disabled
|
| 226 |
-
# unless a calibration path is configured, so every other mode keeps its
|
| 227 |
-
# existing sample keys and behavior byte for byte.
|
| 228 |
-
self.eef_anchor_index = None
|
| 229 |
-
if eef_anchor_calibration_path:
|
| 230 |
-
from fastwam.datasets.eef_anchors import EpisodeAnchorIndex
|
| 231 |
-
from fastwam.geometry import EEFProjector, load_calibration
|
| 232 |
-
|
| 233 |
-
calibration = load_calibration(eef_anchor_calibration_path)
|
| 234 |
-
self.eef_anchor_index = EpisodeAnchorIndex.build(
|
| 235 |
-
[str(d) for d in dataset_dirs],
|
| 236 |
-
calibration_path=eef_anchor_calibration_path,
|
| 237 |
-
projector=EEFProjector(calibration, int(eef_anchor_raw_resolution)),
|
| 238 |
-
)
|
| 239 |
-
|
| 240 |
-
def __len__(self):
|
| 241 |
-
return len(self.lerobot_dataset)
|
| 242 |
-
|
| 243 |
-
def _get(self, idx):
|
| 244 |
-
sample_idx = idx
|
| 245 |
-
sample = None
|
| 246 |
-
for attempt in range(self.max_padding_retry + 1):
|
| 247 |
-
sample = self.lerobot_dataset[sample_idx]
|
| 248 |
-
|
| 249 |
-
if not self.skip_padding_as_possible:
|
| 250 |
-
break
|
| 251 |
-
|
| 252 |
-
action_is_pad = sample["action_is_pad"]
|
| 253 |
-
image_is_pad = sample["image_is_pad"]
|
| 254 |
-
proprio_is_pad = sample["proprio_is_pad"]
|
| 255 |
-
has_pad = False
|
| 256 |
-
if bool(action_is_pad.any().item()):
|
| 257 |
-
has_pad = True
|
| 258 |
-
if bool(image_is_pad.any().item()):
|
| 259 |
-
has_pad = True
|
| 260 |
-
if bool(proprio_is_pad.any().item()):
|
| 261 |
-
has_pad = True
|
| 262 |
-
|
| 263 |
-
if not has_pad or attempt >= self.max_padding_retry:
|
| 264 |
-
break
|
| 265 |
-
|
| 266 |
-
sample_idx = np.random.randint(len(self.lerobot_dataset))
|
| 267 |
-
|
| 268 |
-
image_is_pad = sample["image_is_pad"]
|
| 269 |
-
|
| 270 |
-
if not self.precompute_video_only:
|
| 271 |
-
image_is_pad = image_is_pad[self.video_sample_indices]
|
| 272 |
-
video = None
|
| 273 |
-
video_latents = None
|
| 274 |
-
if self.video_latent_cache is None:
|
| 275 |
-
video = sample["pixel_values"] # [T, C, H, W] or [num_cameras, T, C, H, W]
|
| 276 |
-
num_cameras = 1
|
| 277 |
-
if video.ndim == 5:
|
| 278 |
-
if not self.precompute_video_only:
|
| 279 |
-
video = video[:, self.video_sample_indices, :, :, :]
|
| 280 |
-
num_cameras, T_video, C, H, W = video.shape
|
| 281 |
-
else:
|
| 282 |
-
assert video.ndim == 4, f"Expected video to have shape [T, C, H, W], but got {video.shape}"
|
| 283 |
-
if not self.precompute_video_only:
|
| 284 |
-
video = video[self.video_sample_indices, :, :, :]
|
| 285 |
-
T_video, C, H, W = video.shape
|
| 286 |
-
|
| 287 |
-
video = video.view(num_cameras, T_video, C, H, W) # [num_cameras, T_video, C, H, W]
|
| 288 |
-
if self.concat_multi_camera == "robotwin":
|
| 289 |
-
if num_cameras != 3:
|
| 290 |
-
raise ValueError(
|
| 291 |
-
f"`concat_multi_camera='robotwin'` requires exactly 3 cameras, got {num_cameras}"
|
| 292 |
-
)
|
| 293 |
-
cam_top = transforms_F.resize(
|
| 294 |
-
video[0],
|
| 295 |
-
size=[256, 320],
|
| 296 |
-
interpolation=transforms_F.InterpolationMode.BILINEAR,
|
| 297 |
-
antialias=True,
|
| 298 |
-
) # [T_video, C, 256, 320]
|
| 299 |
-
cam_left = transforms_F.resize(
|
| 300 |
-
video[1],
|
| 301 |
-
size=[128, 160],
|
| 302 |
-
interpolation=transforms_F.InterpolationMode.BILINEAR,
|
| 303 |
-
antialias=True,
|
| 304 |
-
) # [T_video, C, 128, 160]
|
| 305 |
-
cam_right = transforms_F.resize(
|
| 306 |
-
video[2],
|
| 307 |
-
size=[128, 160],
|
| 308 |
-
interpolation=transforms_F.InterpolationMode.BILINEAR,
|
| 309 |
-
antialias=True,
|
| 310 |
-
) # [T_video, C, 128, 160]
|
| 311 |
-
bottom = torch.cat([cam_left, cam_right], dim=-1) # [T_video, C, 128, 320]
|
| 312 |
-
video = torch.cat([cam_top, bottom], dim=-2) # [T_video, C, 384, 320]
|
| 313 |
-
elif num_cameras > 1:
|
| 314 |
-
if self.concat_multi_camera == "horizontal":
|
| 315 |
-
video = torch.cat([video[i] for i in range(num_cameras)], dim=-1) # [T_video, C, H, num_cameras*W]
|
| 316 |
-
elif self.concat_multi_camera == "vertical":
|
| 317 |
-
video = torch.cat([video[i] for i in range(num_cameras)], dim=-2) # [T_video, C, num_cameras*H, W]
|
| 318 |
-
else:
|
| 319 |
-
raise ValueError(
|
| 320 |
-
f"Invalid concat_multi_camera: {self.concat_multi_camera}. "
|
| 321 |
-
"Expected one of: horizontal, vertical, robotwin."
|
| 322 |
-
)
|
| 323 |
-
else:
|
| 324 |
-
video = video.squeeze(0) # [T_video, C, H, W]
|
| 325 |
-
|
| 326 |
-
# final resize and normalization
|
| 327 |
-
video = self.resize_transform(video)
|
| 328 |
-
video = self.crop_transform(video)
|
| 329 |
-
video = self.normalize_transform(video) # [T_video, C, H, W]
|
| 330 |
-
|
| 331 |
-
video = video.permute(1, 0, 2, 3) # [C, T_video, H, W], range [-1, 1]
|
| 332 |
-
else:
|
| 333 |
-
returned_index = int(sample["idx"])
|
| 334 |
-
video_latents = self.video_latent_cache[returned_index]
|
| 335 |
-
|
| 336 |
-
if self.precompute_video_only:
|
| 337 |
-
if video is None:
|
| 338 |
-
raise RuntimeError("precompute_video_only unexpectedly resolved cached latents.")
|
| 339 |
-
return {"video": video}
|
| 340 |
-
|
| 341 |
-
# Proxy (from lerobot):
|
| 342 |
-
# action: [num_frames-1, action_dim] # start from t0, except the last frame
|
| 343 |
-
# proprio: [num_frames, proprio_dim] # start from t0 to the last frame, aligned with video frames
|
| 344 |
-
action = sample["action"] # [T-1, action_dim]
|
| 345 |
-
proprio = sample["proprio"][:-1, :] # [T-1, state_dim], to align with action
|
| 346 |
-
sampled_video_frames = len(self.video_sample_indices)
|
| 347 |
-
if sampled_video_frames <= 1:
|
| 348 |
-
raise ValueError(f"At least two sampled video frames are required, got {sampled_video_frames}")
|
| 349 |
-
if action.shape[0] % (sampled_video_frames - 1) != 0:
|
| 350 |
-
raise ValueError(
|
| 351 |
-
f"`action` horizon must be divisible by `video` transitions, got {action.shape[0]} and {sampled_video_frames - 1}"
|
| 352 |
-
)
|
| 353 |
-
|
| 354 |
-
task = sample["instruction"]
|
| 355 |
-
|
| 356 |
-
# FIXME
|
| 357 |
-
if self.override_instruction is not None:
|
| 358 |
-
task = self.override_instruction
|
| 359 |
-
instruction = DEFAULT_PROMPT.format(task=task)
|
| 360 |
-
|
| 361 |
-
context, context_mask = self._get_cached_text_context(instruction)
|
| 362 |
-
# NOTE: to keep consistent with wan2.2's behavior
|
| 363 |
-
context[~context_mask] = 0.0
|
| 364 |
-
context_mask = torch.ones_like(context_mask)
|
| 365 |
-
|
| 366 |
-
data = {
|
| 367 |
-
"action": action,
|
| 368 |
-
"proprio": proprio,
|
| 369 |
-
"prompt": instruction,
|
| 370 |
-
"context": context,
|
| 371 |
-
"context_mask": context_mask,
|
| 372 |
-
"image_is_pad": image_is_pad,
|
| 373 |
-
"action_is_pad": sample["action_is_pad"],
|
| 374 |
-
"proprio_is_pad": sample["proprio_is_pad"],
|
| 375 |
-
}
|
| 376 |
-
if video is not None:
|
| 377 |
-
data["video"] = video
|
| 378 |
-
else:
|
| 379 |
-
data["video_latents"] = video_latents
|
| 380 |
-
data["source_video_shape"] = torch.tensor(
|
| 381 |
-
[3, sampled_video_frames, int(self.video_size[0]), int(self.video_size[1])],
|
| 382 |
-
dtype=torch.int64,
|
| 383 |
-
)
|
| 384 |
-
if self.eef_anchor_index is not None:
|
| 385 |
-
# Key off the RETURNED sample, never the requested idx. Both the
|
| 386 |
-
# padding retry above and __getitem__'s exception handler resample
|
| 387 |
-
# to a random global index, so an idx-keyed lookup would pair these
|
| 388 |
-
# frames with another episode's gripper position -- silently.
|
| 389 |
-
# Indexed, not `.get(..., 0)`: a missing `dataset_index` would
|
| 390 |
-
# silently key every directory of a concatenated MultiLeRobotDataset
|
| 391 |
-
# to directory 0, serving one suite's geometry for another's frames.
|
| 392 |
-
data["eef_anchor_token"] = torch.from_numpy(
|
| 393 |
-
self.eef_anchor_index.lookup(
|
| 394 |
-
dataset_index=int(sample["dataset_index"]),
|
| 395 |
-
episode_index=int(sample["episode_index"]),
|
| 396 |
-
frame_index=int(sample["frame_index"]),
|
| 397 |
-
).copy()
|
| 398 |
-
)
|
| 399 |
-
return data
|
| 400 |
-
|
| 401 |
-
def _get_cached_text_context(self, prompt: str):
|
| 402 |
-
if self.text_embedding_cache_dir is None:
|
| 403 |
-
raise ValueError("text_embedding_cache_dir is not set.")
|
| 404 |
-
cache_dir = self.text_embedding_cache_dir
|
| 405 |
-
os.makedirs(cache_dir, exist_ok=True)
|
| 406 |
-
hashed = hashlib.sha256(prompt.encode("utf-8")).hexdigest()
|
| 407 |
-
cache_path = os.path.join(cache_dir, f"{hashed}.t5_len{self.context_len}.wan22ti2v5b.pt")
|
| 408 |
-
if not os.path.exists(cache_path):
|
| 409 |
-
raise FileNotFoundError(
|
| 410 |
-
f"Missing text embedding cache: {cache_path}. "
|
| 411 |
-
"Run scripts/precompute_text_embeds.py first."
|
| 412 |
-
)
|
| 413 |
-
payload = torch.load(cache_path, map_location="cpu")
|
| 414 |
-
context = payload["context"]
|
| 415 |
-
context_mask = payload["mask"].bool()
|
| 416 |
-
if context.ndim != 2:
|
| 417 |
-
raise ValueError(
|
| 418 |
-
f"Cached `context` must be 2D [L, D], got shape {tuple(context.shape)} in {cache_path}"
|
| 419 |
-
)
|
| 420 |
-
if context_mask.ndim != 1:
|
| 421 |
-
raise ValueError(
|
| 422 |
-
f"Cached `mask` must be 1D [L], got shape {tuple(context_mask.shape)} in {cache_path}"
|
| 423 |
-
)
|
| 424 |
-
if context.shape[0] != self.context_len:
|
| 425 |
-
raise ValueError(
|
| 426 |
-
f"Cached context_len mismatch: expected {self.context_len}, got {context.shape[0]} in {cache_path}"
|
| 427 |
-
)
|
| 428 |
-
if context_mask.shape[0] != self.context_len:
|
| 429 |
-
raise ValueError(
|
| 430 |
-
f"Cached mask_len mismatch: expected {self.context_len}, got {context_mask.shape[0]} in {cache_path}"
|
| 431 |
-
)
|
| 432 |
-
|
| 433 |
-
return context, context_mask
|
| 434 |
-
|
| 435 |
-
def __getitem__(self, idx):
|
| 436 |
-
if self.strict_getitem:
|
| 437 |
-
return self._get(idx)
|
| 438 |
-
try:
|
| 439 |
-
data = self._get(idx)
|
| 440 |
-
except Exception as e:
|
| 441 |
-
print(f"Error processing sample idx {idx}: {e}. Returning a random sample instead.")
|
| 442 |
-
# trace back
|
| 443 |
-
print(traceback.format_exc())
|
| 444 |
-
random_idx = np.random.randint(len(self))
|
| 445 |
-
data = self._get(random_idx)
|
| 446 |
-
return data
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joint/fasterwam/train90_joint_job4247/training_code/fastwam/src/fastwam/datasets/lerobot/transforms/action_state_merger.py
DELETED
|
@@ -1,78 +0,0 @@
|
|
| 1 |
-
from typing import Dict
|
| 2 |
-
|
| 3 |
-
import torch
|
| 4 |
-
from torch.nn.functional import pad
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
class ConcatLeftAlign:
|
| 8 |
-
def __init__(
|
| 9 |
-
self,
|
| 10 |
-
action_target_dim: int | None = None,
|
| 11 |
-
state_target_dim: int | None = None
|
| 12 |
-
):
|
| 13 |
-
self.action_target_dim = action_target_dim
|
| 14 |
-
self.state_target_dim = state_target_dim
|
| 15 |
-
|
| 16 |
-
def set_shape_meta(self, shape_meta):
|
| 17 |
-
self.action_meta = shape_meta["action"]
|
| 18 |
-
self.state_meta = shape_meta["state"]
|
| 19 |
-
|
| 20 |
-
def forward(self, batch):
|
| 21 |
-
if "action" in batch:
|
| 22 |
-
batch["action"] = self._concat(batch["action"], self.action_meta)
|
| 23 |
-
batch["action"], batch["action_dim_is_pad"] = self._pad(batch["action"], self.action_target_dim)
|
| 24 |
-
|
| 25 |
-
batch["state"] = self._concat(batch["state"], self.state_meta)
|
| 26 |
-
batch["state"], batch["state_dim_is_pad"] = self._pad(batch["state"], self.state_target_dim)
|
| 27 |
-
|
| 28 |
-
return batch
|
| 29 |
-
|
| 30 |
-
def backward(self, batch):
|
| 31 |
-
if self.state_target_dim is not None:
|
| 32 |
-
assert batch["state"].shape[-1] == self.state_target_dim
|
| 33 |
-
batch["state"] = self._crop(batch["state"], self.state_meta)
|
| 34 |
-
batch["state"] = self._split(batch["state"], self.state_meta)
|
| 35 |
-
|
| 36 |
-
if self.action_target_dim is not None:
|
| 37 |
-
assert batch["action"].shape[-1] == self.action_target_dim
|
| 38 |
-
batch["action"] = self._crop(batch["action"], self.action_meta)
|
| 39 |
-
batch["action"] = self._split(batch["action"], self.action_meta)
|
| 40 |
-
|
| 41 |
-
return batch
|
| 42 |
-
|
| 43 |
-
@staticmethod
|
| 44 |
-
def _pad(x: torch.Tensor, dim: int):
|
| 45 |
-
if dim is None:
|
| 46 |
-
dim = x.shape[-1]
|
| 47 |
-
|
| 48 |
-
assert x.ndim == 2 and x.shape[-1] <= dim
|
| 49 |
-
pad_dim = dim - x.shape[-1]
|
| 50 |
-
x_padded = pad(x, (0, pad_dim))
|
| 51 |
-
mask = torch.zeros_like(x[0]).bool()
|
| 52 |
-
mask = pad(mask, (0, pad_dim), value=True)
|
| 53 |
-
return x_padded, mask
|
| 54 |
-
|
| 55 |
-
@staticmethod
|
| 56 |
-
def _crop(x: torch.Tensor, meta: int):
|
| 57 |
-
assert x.ndim == 3
|
| 58 |
-
dim = sum([m["shape"] for m in meta])
|
| 59 |
-
x = x[:, :, :dim]
|
| 60 |
-
return x
|
| 61 |
-
|
| 62 |
-
@staticmethod
|
| 63 |
-
def _concat(x: Dict[str, torch.Tensor], meta: Dict[str, Dict]):
|
| 64 |
-
x = torch.cat([x[m["key"]] for m in meta], dim=-1)
|
| 65 |
-
assert x.ndim == 2
|
| 66 |
-
return x
|
| 67 |
-
|
| 68 |
-
@staticmethod
|
| 69 |
-
def _split(x: torch.Tensor, meta: Dict[str, Dict]):
|
| 70 |
-
assert x.ndim == 3
|
| 71 |
-
y = {}
|
| 72 |
-
idx = 0
|
| 73 |
-
for m in meta:
|
| 74 |
-
key, dim = m["key"], m["shape"]
|
| 75 |
-
y[key] = x[:, :, idx: idx + dim]
|
| 76 |
-
idx += dim
|
| 77 |
-
|
| 78 |
-
return y
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|