chomeed commited on
Commit
f2c2e16
·
verified ·
1 Parent(s): 9d73fa8

Add model card (FARM reward modeling collection)

Browse files
Files changed (1) hide show
  1. README.md +168 -0
README.md ADDED
@@ -0,0 +1,168 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ library_name: lerobot
4
+ pipeline_tag: robotics
5
+ tags:
6
+ - lerobot
7
+ - reward-model
8
+ - rewind
9
+ - progress-reward
10
+ - dexmimicgen
11
+ - bimanual
12
+ - robotics
13
+ datasets:
14
+ - chomeed/dexmg_two_arm_threading
15
+ base_model: facebook/dinov2-base
16
+ ---
17
+
18
+ # ReWiND-state reward model -- DexMimicGen Two-Arm Threading
19
+
20
+ Progress reward model (ReWiND-state, LeRobot plugin type `rewind_state`) for the bimanual task **Pick up the needle
21
+ and thread it through the hole in the tripod.** It predicts task progress in [0, 1] per frame from 3 cameras, the
22
+ robot state and the instruction. It was trained on successful demos only, so it never sees a failure.
23
+
24
+ This exact file is the progress-only baseline of the FARM comparison, the starting point of the failure-aware
25
+ companion [`chomeed/farm_rewind_state_dexmg_two_arm_threading`](https://huggingface.co/chomeed/farm_rewind_state_dexmg_two_arm_threading),
26
+ and the dense reward of the "ReWiND" RL runs summarised under Evaluation. On fresh rollouts, a failed attempt that
27
+ looks like progress keeps a high reward: failed episodes end at 0.92, successful ones at 0.94.
28
+
29
+ ## Training data
30
+
31
+ [`chomeed/dexmg_two_arm_threading`](https://huggingface.co/datasets/chomeed/dexmg_two_arm_threading): all 1,025
32
+ DexMimicGen-generated success demos (218,858 frames, 20 fps; the normalizer statistics count every frame). There is
33
+ no validation split and there are no failures.
34
+
35
+ **Objective (ReWiND).** Per-frame MSE between the sigmoid output and the progress label
36
+ (i - clip start) / (episode end - clip start - 1). Clips are random contiguous segments of random demos. Half of them
37
+ are "rewound": a forward segment from the first half of the episode into the second half, followed by a reversed
38
+ tail whose labels decrease. Clips are uniformly subsampled or padded to 16 frames. No negatives, no language
39
+ perturbation, no image augmentation.
40
+
41
+ ## Model and configuration
42
+
43
+ Inputs per frame: 3 RGB cameras at 84x84 (`agentview`, `robot0_eye_in_hand`, `robot1_eye_in_hand`), the 18-d
44
+ `observation.state` (mean/std normalised with the demo statistics) and the task string. DINOv2-base encodes each
45
+ camera at its native 84x84 (a 6x6 patch grid), pooled with the last layer's CLS attention; its last 2 blocks and final
46
+ LayerNorm are fine-tuned, the rest is frozen. The instruction goes through a frozen
47
+ `sentence-transformers/all-MiniLM-L12-v2` inside the preprocessor (not stored in this repo). Per-modality MLPs, with
48
+ the state added to every token, feed a 4-layer Transformer (512-d, 8 heads) over a 16-frame window; the head is
49
+ LayerNorm -> MLP -> sigmoid. 102,945,537 parameters, 30,545,409 trainable.
50
+
51
+ | setting | value |
52
+ | --- | --- |
53
+ | checkpoint | final step 50,000 (`checkpoints/last`); `model.safetensors` sha256 `8dad424e31cfb3e6a0b896cf1e00459137684a906505fb781019f390f47a3bdc` |
54
+ | batch | 16 clips of 16 frames |
55
+ | optimiser | AdamW (0.9, 0.95), weight decay 1e-10, grad clip 10, bf16 mixed precision, seed 1000, 1 GPU |
56
+ | learning rate | 1e-4 for all non-DINOv2 parameters (MLPs, Transformer, head), 1e-5 for the fine-tuned DINOv2 blocks and final LayerNorm; 1,000-step warmup, cosine decay over 50k steps to 5 % of the base rate |
57
+
58
+ `scheduler_peak_lr: 5e-5` in the config does not set the peak: LeRobot's cosine schedule scales the optimizer LR and
59
+ uses `peak_lr` only for the 5 % floor ratio.
60
+
61
+ ## Evaluation
62
+
63
+ **Causal window (`hybrid8`).** For t >= 16, the reward at frame t is the last output of a 16-frame window:
64
+ `np.linspace(0, t-8, 8).astype(int)` followed by frames t-7..t. Only frames <= t are used. This is also the window of
65
+ the RL reward shaper (`RewindRewardShaper`, `trajectory_mode="hybrid"`, `window_recent_n=8`).
66
+
67
+ **Protocol.** Episode score = mean of the last 3 per-frame rewards, threshold 0.5. Failures caught = failure score
68
+ < 0.5; successes recognised = success score >= 0.5; balanced accuracy = the mean of the two. AUROC = probability that
69
+ a random success outscores a random failure.
70
+
71
+ **Fresh held-out rollouts (headline).** 100 new rollouts of the frozen base Diffusion Policy with env seeds
72
+ 20000-20099, disjoint from every seed used for training, RL or earlier evaluation: 57 successes (8.8-13.85 s long) and
73
+ 43 failures (all 25 s time-outs). No reward model saw them.
74
+
75
+ | model | success score | failure score (lower is better) | failures caught | successes recognised | balanced acc. | AUROC |
76
+ | --- | --- | --- | --- | --- | --- | --- |
77
+ | **ReWiND-state (this model)** | **0.94** | **0.92** | **1/43** | **57/57** | **0.51** | **0.33** |
78
+ | FARM, step 5k (companion) | 0.98 | 0.003 | 43/43 | 56/57 | 0.99 | 1.00 |
79
+
80
+ - An AUROC of 0.33 means failures outrank successes more often than not. On a fresh failure the reward climbs to a
81
+ per-episode peak of 0.97 on average and stays near it.
82
+ - In-sample reference, not out-of-sample: the last 50 demos (975-1024, in this model's training data) and failed
83
+ rollouts 150-199 (never seen by this model, but mined by FARM): 0.98 / 0.92 / 1/50 / 50/50 / 0.51 / 0.38.
84
+ - **As an RL reward** (ResFit-TD3, same window): 76.6 % mean evaluation success over 730-780k steps, against 40.3 %
85
+ with the sparse environment reward, 56.6 % with a ReWiND variant trained with failures labelled 0, and 71.3 % with
86
+ FARM v6, an earlier failure-aware checkpoint (its value is digitised from a plot of its best replicates, so it is
87
+ optimistic). At most 3 seeds; one 96-episode evaluation has an SD of about 5 points, and the evaluated sparse runs
88
+ are the weaker replicate. In a separate 400k-step sweep, step 2,000 of the FARM v7 run was within seed noise of
89
+ this model (training success 0.54 vs 0.51 at reward scale 0.5, 3 seeds each).
90
+
91
+ ## How the FARM companion lowers the failure reward
92
+
93
+ FARM fine-tunes this checkpoint for 5,000 steps with 200 failed rollouts. On each failure it finds the critical point
94
+ t\*, the peak of this model's 7-frame-smoothed reward (the furthest the attempt got), scored with a 16-frame uniform
95
+ window (frames `linspace(0, t, 16)`) rather than the `hybrid8` window above; the two windows give different t\* in
96
+ 46 of 50 checked failures. A hinge on the reward logits then penalises the reward unless it falls by at least 0.2
97
+ logits from each of 16 anchors to the next over frames t\*-5..t\*+60, each anchor scored in the causal `hybrid8`
98
+ window. Successes are protected by this model's progress loss plus a no-decrease hinge and a progress MSE on matched
99
+ success windows. Failures never get a "0" label, so the progress credit before t\* is kept. Details are on the
100
+ [FARM card](https://huggingface.co/chomeed/farm_rewind_state_dexmg_two_arm_threading).
101
+
102
+ ## Loading
103
+
104
+ A sketch of the evaluation path (reference implementation: `load_rewind_reward_model` +
105
+ `compute_rewind_reward_for_episode`); this exact snippet was not run on its own.
106
+
107
+ ```python
108
+ import lerobot_policy_rewind_state # registers `rewind_state` (local plugin, see caveats)
109
+ from huggingface_hub import snapshot_download
110
+ from lerobot.configs.policies import PreTrainedConfig
111
+ from lerobot.datasets.lerobot_dataset import LeRobotDatasetMetadata
112
+ from lerobot.policies.factory import make_policy, make_pre_post_processors
113
+ from lerobot_policy_rewind_state.common.eval_rewind_reward_visualization_dense import dense_predict_per_frame
114
+
115
+ path = snapshot_download("chomeed/rewind_state_dexmg_two_arm_threading")
116
+ cfg = PreTrainedConfig.from_pretrained(path)
117
+ cfg.pretrained_path = path # required: config.json has pretrained_path = null (make_policy would build a random head)
118
+ cfg.device = "cuda"
119
+ meta = LeRobotDatasetMetadata("chomeed/dexmg_two_arm_threading")
120
+ policy = make_policy(cfg=cfg, ds_meta=meta).eval()
121
+ pre, _ = make_pre_post_processors(policy_cfg=cfg, pretrained_path=None, dataset_stats=meta.stats)
122
+
123
+ # cams: {"observation.images.agentview", "...robot0_eye_in_hand", "...robot1_eye_in_hand"} -> float (1, T, 3, 84, 84) in [0, 1]
124
+ # state: raw observation.state, shape (1, T, 18)
125
+ batch = pre({**cams, "observation.state": state,
126
+ "task": ["Pick up the needle and thread it through the hole in the tripod"]})
127
+ reward = dense_predict_per_frame(policy, {k: batch[k] for k in cams}, batch["task.minilm"],
128
+ state=batch["observation.state"], max_window=16, sampling="hybrid", n_recent=8)
129
+ ```
130
+
131
+ ## Caveats
132
+
133
+ **Progress only.** The model never saw a failure, so a failed attempt that looks like progress keeps a high reward;
134
+ fresh failures end at 0.92.
135
+
136
+ **Window layout differs between training and use.** Training clips were contiguous segments, uniformly subsampled
137
+ or padded to 16 frames. The `hybrid8` window used for evaluation and RL (8 sparse history frames + 8 consecutive
138
+ recent frames) was never seen in training.
139
+
140
+ **Causal only through the window.** The trunk lays tokens out stream-major, masks them with `triu` and regroups them
141
+ with `h.view(B, T, -1)`, so early output positions inside a window see later frames. Read only the last output of a
142
+ window that ends at t. `dense_predict_per_frame` scores frames 0-15 from one pass over frames 0-15 (outputs 0-14 see
143
+ later frames, up to frame 15); for strictly causal online use, feed the prefix 0..t and read its last output, as the
144
+ RL shaper does. Episode scores (last 3 frames) are unaffected.
145
+
146
+ **Episode length is a confound** in every DexMimicGen evaluation: all failures are 25 s time-outs, while successes
147
+ end after 8.8-13.85 s.
148
+
149
+ **In-sample is not held out.** There is no train/val split, so the evaluator's "validation" slice (the last 50
150
+ demos) is training data. In-sample successes are generated demos; fresh successes are policy rollouts.
151
+
152
+ **Loading.** Needs the LeRobot plugin package `lerobot_policy_rewind_state`, which has no public code location yet.
153
+ The results were produced with a locally modified LeRobot 0.4.4, and the snippet is untested on stock LeRobot:
154
+ config.json loads through the plugin, but train_config.json contains fork-only fields (`dataset.cf_aug`, `val`,
155
+ `test`) that stock LeRobot may not parse. Set `cfg.pretrained_path` before `make_policy`. config.json's `repo_id`
156
+ (`chomeed/rewind_state_dexmg_threading_v1`) is the internal run name, not this repo. The 14-d `action` output and the
157
+ postprocessor exist for LeRobot compatibility only; use `predict_reward` (`select_action` raises
158
+ `NotImplementedError`).
159
+
160
+ ## Companion artifacts
161
+
162
+ - Failure-aware fine-tune of this model:
163
+ [`chomeed/farm_rewind_state_dexmg_two_arm_threading`](https://huggingface.co/chomeed/farm_rewind_state_dexmg_two_arm_threading)
164
+ - Same baseline on Three-Piece Assembly:
165
+ [`chomeed/rewind_state_dexmg_two_arm_three_piece_assembly`](https://huggingface.co/chomeed/rewind_state_dexmg_two_arm_three_piece_assembly)
166
+ - Datasets, base policies and the MimicGen models are in the
167
+ [MimicGen & DexMimicGen Reward Modeling](https://huggingface.co/collections/chomeed/mimicgen-and-dexmimicgen-reward-modeling-6ad45df2fafcb692ae6f37b1)
168
+ collection.