Instructions to use chomeed/rewind_state_dexmg_two_arm_threading with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LeRobot
How to use chomeed/rewind_state_dexmg_two_arm_threading with LeRobot:
# No code snippets available yet for this library. # To use this model, check the repository files and the library's documentation. # Want to help? PRs adding snippets are welcome at: # https://github.com/huggingface/huggingface.js
- Notebooks
- Google Colab
- Kaggle
Add model card (FARM reward modeling collection)
Browse files
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.
|