Ngseo commited on
Commit
0802db9
·
verified ·
1 Parent(s): 26c70e4

Stage 3 UR5 current-view — final checkpoint epoch_6 (60k steps)

Browse files
Files changed (3) hide show
  1. README.md +108 -0
  2. config.yaml +80 -0
  3. epoch_6.pt +3 -0
README.md ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ base_model: Qwen/Qwen2.5-VL-3B-Instruct
4
+ datasets:
5
+ - Ngseo/ur5_teleop_multitask
6
+ tags:
7
+ - robotics
8
+ - vision-language-action
9
+ - vla
10
+ - qwen2_5_vl
11
+ - lerobot
12
+ - spurious-correlation
13
+ ---
14
+
15
+ # Stage 3 — UR5 teleop VLA (Qwen2.5-VL-3B), current-view variant
16
+
17
+ Training run **complete**: 60,000 steps. This is the ablation partner of
18
+ [`Ngseo/stage3-ur5-actheavy`](https://huggingface.co/Ngseo/stage3-ur5-actheavy):
19
+ same objective, same data, same hyper-parameters — the frozen V-JEPA2 targets
20
+ are computed on the **current** frame instead of on **future** frames.
21
+
22
+ ```
23
+ act-heavy : V-JEPA sees frames t+4 … t+32 (1.07 s ahead)
24
+ current-view : V-JEPA sees frame t, repeated 8x ← this model
25
+ ```
26
+
27
+ Both branches move together: the task branch that `z_a` is aligned to *and* the
28
+ domain branch that `z_b` is decorrelated from. Nothing in this model's loss
29
+ looks ahead in time.
30
+
31
+ **The question it answers:** does the V-JEPA target have to predict the future,
32
+ or is shaping the representation against the current frame enough?
33
+
34
+ ## The setup this was trained for
35
+
36
+ Each of the 7 tasks in [`Ngseo/ur5_teleop_multitask`](https://huggingface.co/datasets/Ngseo/ur5_teleop_multitask)
37
+ is only ever shown from **one** of the 4 cameras, so viewpoint alone almost
38
+ determines the task. Object colour is deliberately crossed between the two task
39
+ families so that "colour ⇒ camera" is not a valid shortcut on its own:
40
+
41
+ | camera | tasks |
42
+ |---|---|
43
+ | `camera_0` | Point at the **red** cup · Pick up the **blue** die → basket |
44
+ | `camera_1` | Pull a tissue out of the box · Close the laptop · Stand the shoe upright |
45
+ | `camera_2` | Point at the **blue** cup · Pick up the **red** die → basket |
46
+
47
+ ## Architecture
48
+
49
+ ```
50
+ Qwen2.5-VL-3B + LoRA ─ forward_full_hidden ─┬─ Head A → z_a ─┐
51
+ └─ Head B → z_b ─┴─ concat(8192) → ResNetActionHead → 30×7
52
+
53
+ L = 1.0·L1(action) + 0.02·InfoNCE(z_a, z_task_CURRENT) + 0.002·SIGReg([z_domain_CURRENT ; z_b])
54
+ ```
55
+
56
+ Frozen target encoder: [`Ngseo/stage1`](https://huggingface.co/Ngseo/stage1)
57
+ disentangled V-JEPA2 ViT-L. Both heads are `AttentiveLatentHead`
58
+ (proj 4096, 8 queries, depth 2, 167.8M each).
59
+
60
+ | | |
61
+ |---|---|
62
+ | LoRA | r=32, α=64 — LLM `q_proj`/`v_proj` (7.4M) **and** vision tower `qkv` (5.2M) |
63
+ | Trainable | 386M of 3.77B |
64
+ | Inputs | 1 RGB frame @224 + task string + 7-D joint state |
65
+ | Output | 30-step action chunk (absolute joint positions, 1.0 s @ 30 fps) |
66
+ | Optimiser | AdamW, lr 1e-4, 1000-step warmup + cosine to 0, batch 32, bf16 |
67
+ | Augmentation | ColorJitter/SharpnessJitter ×2 + DomainRandomization p=0.7 |
68
+
69
+ ## Final metrics vs. the future-frame variant
70
+
71
+ | | current-view (this) | act-heavy (future) |
72
+ |---|---|---|
73
+ | action L1 @ 10k | 0.0826 | 0.0836 |
74
+ | @ 30k | 0.0438 | 0.0442 |
75
+ | @ 50k | 0.0326 | 0.0305 |
76
+ | **@ 60k (final)** | **0.0319** | **0.0300** |
77
+ | InfoNCE (chance 3.466) | 1.86 | 1.79 |
78
+ | cos(z_a, z_target) | 0.233 | 0.292 |
79
+ | cos(z_b, z_domain) | −0.002 | −0.000 |
80
+
81
+ On in-distribution action accuracy the two are within ~6% of each other, i.e.
82
+ looking ahead buys almost nothing here. That is expected: the InfoNCE term
83
+ carries weight 0.02, so it barely competes with the action loss.
84
+
85
+ Reference points on the same normalised scale, none of which use vision or
86
+ language: dataset mean **0.834**, copying the input state across all 30 steps
87
+ **0.155**. The per-step copy error grows from 0.019 at k=0 to 0.291 at k=29.
88
+
89
+ > **Not evaluated on a robot.** Everything above is a training-set loss. The
90
+ > question this study is actually about — what happens when a task is requested
91
+ > from a camera it was never trained on — is not answered by these numbers, and
92
+ > is exactly where the two variants might diverge.
93
+ >
94
+ > **Caveat specific to this variant:** the current-view clip is built from the
95
+ > *same augmented context frame* the VLM is shown, so its InfoNCE aligns two
96
+ > encodings of identical pixels. The future-frame variant aligns against a
97
+ > different, independently-augmented clip. The two therefore differ in more
98
+ > than just "future vs current", and the comparison should be read with that in
99
+ > mind.
100
+ >
101
+ > The 7-D joint state is also an input, and a probe on that state alone recovers
102
+ > which of the 7 tasks is running with 94% accuracy (chance 14%).
103
+
104
+ ## Contents
105
+
106
+ `epoch_6.pt` holds `model_state_dict` (full VLM incl. LoRA), `latent_head_state_dict`
107
+ (Head A), `free_latent_head_state_dict` (Head B), `stage2_action_head_state_dict`,
108
+ optimiser state, and the run config. `config.yaml` is the exact training config.
config.yaml ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Stage 3 — UR5 teleop, CURRENT-VIEW variant (GPU 0).
2
+ # Identical to stage3-ur5-qwen25vl-actheavy.yaml except BOTH V-JEPA branches
3
+ # read the CURRENT view (context frame repeated to fill the 8-frame clip)
4
+ # instead of the future frames. The objective keeps its full shape — align z_a
5
+ # to the stage-1 task space, decorrelate z_b from the stage-1 domain space —
6
+ # but no future frame enters it anywhere.
7
+ #
8
+ # loss = 1.0*L1(action)
9
+ # + 0.02*InfoNCE(z_a, z_task_CURRENT)
10
+ # + 0.002*SIGReg([z_domain_CURRENT ; z_b])
11
+ #
12
+ # Pairs with act-heavy, which is the same objective computed on future frames.
13
+ # The two isolate one question: does the V-JEPA target have to look AHEAD, or
14
+ # is shaping the representation against the current frame enough?
15
+ data_root: /data3/ngseo/lerobot/ur5_teleop_multitask
16
+ inmem_frame_dir: /data3/ngseo/cache/frames_ur5_teleop
17
+ vjepa_cache_dir: null # null -> run V-JEPA online every step
18
+ cams: cam0,cam1,cam2
19
+
20
+ # Stage 1 frozen target encoder (online mode)
21
+ vjepa_checkpoint: /data3/ngseo/experiments/disentangle-stage1/hf-Ngseo-stage1/e4.pt
22
+ vjepa_arch: vit_large
23
+ vjepa_img_size: 256
24
+ vjepa_pooler_depth: 2
25
+ vjepa_num_queries: 8
26
+ vjepa_mlp_proj: true
27
+ vjepa_lora_rank: 32
28
+ vjepa_lora_alpha: 32
29
+ vjepa_lora_dropout: 0.05
30
+ aug_future: true # independent aug on future frames (online only)
31
+ vjepa_task_input: current # task branch sees the current view, not the future
32
+ vjepa_domain_input: current # domain branch too — nothing in the loss looks ahead
33
+
34
+ # Must match the caches
35
+ chunk_size: 30 # 1.0 s at 30 fps
36
+ num_future_frames: 8
37
+ future_stride: 4 # 8x4 = 32 frames = 1.07 s lookahead
38
+
39
+ # Backbone
40
+ vlm_model: Qwen/Qwen2.5-VL-3B-Instruct
41
+ image_size: 224
42
+ pooling_type: last
43
+ lora_rank: 32
44
+ # Qwen2.5-VL splits attention differently per tower: the LLM has q_proj/v_proj,
45
+ # the vision tower has a single fused qkv. Listing all three puts LoRA on BOTH
46
+ # (LLM 7.37M + vision 5.24M). Drop `qkv` and the vision encoder trains nothing.
47
+ lora_target_modules: q_proj,v_proj,qkv
48
+
49
+ # Heads (match stage1 e4.pt: proj_dim 4096, 8 queries, depth 2)
50
+ stage2_proj_dim: 4096
51
+ stage2_pooler_num_queries: 8
52
+ stage2_pooler_depth: 2
53
+ stage2_pooler_num_heads: 16
54
+ stage2_action_head_hidden_dim: 2048
55
+ stage2_action_head_num_blocks: 2
56
+
57
+ # Loss
58
+ lambda_action: 1.0
59
+ latent_loss_type: none # InfoNCE carries the alignment; no L1/cosine term
60
+ latent_infonce_weight: 0.02
61
+ latent_infonce_temperature: 0.1
62
+ latent_infonce_negatives: teacher
63
+ dual_head: true
64
+ sigreg_weight: 0.002
65
+
66
+ # Inputs
67
+ use_state: true # state[t] 1 frame in; the 30-step chunk still has to be predicted
68
+ no_aug: false
69
+
70
+ # Training
71
+ batch_size: 32 # throughput is flat vs bs; 31 InfoNCE negatives per anchor
72
+ lr: 1.0e-4
73
+ steps_per_epoch: 10000
74
+ num_epochs: 6 # 60k steps = 1.92M samples = 15 passes over the data
75
+ num_workers: 10
76
+ seed: 42
77
+ log_freq: 50
78
+ lr_scaling_mode: none
79
+ output_dir: /data3/ngseo/experiments/stage3_ur5_qwen25vl_taskcurrent
80
+ resume_checkpoint: null
epoch_6.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9b1cdbc090e2ab191de94cc9c19087ff4dc2a77a7e6e841c6f3a4a6a85bca49f
3
+ size 9947159527