YAML Metadata Warning:empty or missing yaml metadata in repo card

Check out the documentation for more information.

belt_assembly β€” real-robot CCIL checkpoints (2026-09-11)

Diffusion-policy checkpoints for belt_assembly, a DROID real-robot manipulation task, trained with the CCIL-in-visual-observation-spaces pipeline (baseline BC β†’ sequential CCIL β†’ end-to-end CCIL).

Read the caveats before using these numbers. Two of the three arms are snapshots of work in progress, not finished results. See Status below.

Data

source DROID capture, belt_assembly/success/2026-09-10
episodes 50 recorded, 49 used
transitions 12,804
cameras agentview_image, robot0_eye_in_hand_image @ 140Γ—140 uint8
state robot0_eef_pos (3) + robot0_eef_quat (4) + robot0_gripper_qpos (2) = 9
actions 7-dim absolute (pos 3, axis-angle 3, gripper 1) β†’ rotation_6d β†’ 10-dim

demo_3 is excluded by the episode-quality labels. Every other episode starts and ends at the same home pose (cohort median end-distance 0.1 mm); demo_3 ends 10.5 cm away, ranked 50/50. The protocol is home β†’ task β†’ home, and it never returns β€” a truncated recording. The grasp itself did occur (all 50 episodes contain exactly one gripper close).

Model selection β€” no simulator

This is real-robot data: there is no robosuite environment and /data carries no env_args, so there is no rollout success rate. Every arm runs with eval_every=0 and selects best.pt by executed-chunk action MSE on a held-out split (select_best_by_val_loss=true).

The validation split is 5 episodes. Treat small differences with suspicion: in the e2e arm the spread between 1st and 5th place in the top-k heap is ~7%.

Contents

path arm best epoch val action MSE
baseline/ BC baseline 60 0.003426
seq_be/ sequential CCIL, clean dynamics 10 0.003401
e2e/ end-to-end CCIL 10 0.003215
e2e_fix_stepscale/ e2e, aug_step_scale=1.6 10 0.003260
e2e_fix_lossweight/ e2e, loss_normalization=fixed, lambda_aug=0.3 10 0.003258
e2e_fix_combined/ e2e, all of the above + aug_q_threshold=0.8, phase1=120 10 0.003258

Every arm carries *_best.pt (validation-selected) and final_epoch300.pt (last epoch). They differ: best is typically epoch 10, final is epoch 300.

Each directory holds *_best.pt, val_top_k.json (the full top-k selection record), and where available the hydra overrides.yaml.

Status β€” what these checkpoints actually are

baseline/ β€” complete and valid. 300 epochs, finished.

seq_be/ β€” now the clean-dynamics rerun (this replaces the earlier upload). The first attempt was built on a dynamics model that had stalled: correct_il's trainer had no guard against non-finite gradients, so on these 6921-dim latents it diverged, kept training on NaN, and saved an all-NaN model (72/72 tensors). After the guards were ported it survived but every gradient step was skipped from ~epoch 450, so training froze. That version scored 0.003440 β€” worse than the baseline it fine-tuned from β€” and is preserved for comparison as the wandb run belt_assembly_dynamics_earlystop_e426.

What is published here is the rerun on dynamics capped at 400 epochs, which logged a loss in all 400 epochs, skipped 59 of ~4,000 steps (1.5%), and ended with 0 non-finite parameters. It scores 0.003401, marginally better than the baseline β€” but by 0.7%, on a 5-episode validation split whose 1st-to-5th spread is ~7%. Treat that as "no measurable difference", not a win.

Note the dynamics prediction error barely moved between the stalled and clean models (per_dim_rmse 0.1215 vs 0.1219), so there was little headroom for the seq result to change β€” the stall was not what was holding it back.

e2e/ β€” complete (300/300 epochs), but the augmentation branch never helped. Across the full run no checkpoint ever beat epoch 10, which sits inside the warmup phase (e2e_phase1_epochs=50) where the augmentation branch is not yet active. So best.pt is effectively the baseline lightly fine-tuned, and 0.003215 should not be read as e2e beating the baseline. The top-5 by validation:

epoch val action MSE
10 0.003215 (best; pre-augmentation)
150 0.003411
50 0.003412
140 0.003427
160 0.003449

Epochs 140-160 land on the baseline's 0.003426, while training BC loss more than halved (0.0239 -> 0.0112) β€” an overfitting signature on 44 training episodes. final_epoch300.pt is included alongside best.pt so the gap between last-epoch and val-selected weights is inspectable.

Why augmentation never helped β€” the measured cause

The latent dynamics head barely models the dynamics. fwd_image_nmse is the normalized one-step prediction error, where 1.0 means no better than predicting "no change":

epoch 10 50 100 150 200 299
e2e 0.968 0.852 0.779 0.696 0.631 0.549

At epoch 50, when augmentation switches on, the head explains roughly 15% of the latent displacement variance; even after 300 epochs it reaches only ~45%. Backward-Euler synthesizes z_g = z_prev - step * fwd_head(z_prev, a_t) and then trains the policy to emit a_t at z_g. When fwd_head is that wrong, z_g is largely noise and the policy is taught incorrect state-action associations. CCIL assumes the dynamics model is good enough to place a corrective label; on 44 training episodes in a 6921-dim latent space, it is not.

Three tuning arms confirm this and rule out hyperparameters as the cause. Each was run for a full 300 epochs from the same baseline checkpoint:

arm best top-5 epochs post-augmentation checkpoints in top-5
original 0.003215 10, 150, 50, 140, 160 150, 140, 160
stepscale 0.003260 10, 20, 40, 50, 30 none
lossweight 0.003258 10, 20, 40, 50, 30 none
combined 0.003258 10, 20, 40, 50, 70 none

The arm with the weakest augmentation β€” the original β€” is the only one whose post-augmentation checkpoints placed at all. Correcting the displacement (aug_step_scale=1.6, bringing effective displacement from 0.645 to ~0.98 of true), relaxing the mask (aug_q_threshold=0.8, verified: mask_ratio 0.500 -> 0.797), reducing the augmentation weight, and delaying warmup to epoch 120 each made post-augmentation checkpoints less competitive, not more. Amplifying a mostly-wrong displacement amplifies the error.

Meanwhile training BC loss more than halved in every arm β€” the policy is overfitting 44 episodes, and augmentation does not counteract it.

Secondary issues, real but downstream. Three advertised quality gates are inert in this code path: aug_cycle_threshold (its cycle_error_mean is assigned to zero and never computed), aug_hardness_min (hard_ratio is hardcoded to 1.0), and the mask's quantile filter, which keeps exactly 50% by construction regardless of absolute quality β€” and since label_err is the novelty metric, it keeps the least-displaced half, selecting against novelty. Worth fixing, but they are not why the method fails here.

What would actually change the result: gate augmentation on measured fwd_image_nmse rather than an epoch count (e.g. require < 0.3), and give the dynamics head materially more data. A 100-episode session exists and is being evaluated separately.

Reproducing

Pipeline lives on the caiyi_real_robot branch of personalrobotics/image_ccil.

# 1. preprocess + quality labels
./prepare_real_robot_data.sh RAW.hdf5 PROCESSED.hdf5 QUALITY.json
# 2. inspect trajectories; flag geometric outliers
python plot_real_wrist_trajectories.py PROCESSED.hdf5 --output wrist.png
# 3. mark bad episodes
python create_episode_quality_labels.py PROCESSED.hdf5 QUALITY.json --set-zero demo_3 --force
# 4. baseline -> seq -> e2e
REAL_TASK=belt_assembly DATASET_TASK=belt_assembly TASK_TAG=real_belt_assembly_50 \
CCIL_ENV_NAME=BeltAssembly-v0 \
  bash run_real_hang_cup_baseline.sh all -1

Shared settings: DINOv2-small encoder, patch_hw=[3,3], crop 128 from 140, pred_horizon=16, action_horizon=8, obs_horizon=1, batch 64, seed 42, val_ratio=0.1. Latent dim = 2 Γ— 3 Γ— 3 Γ— 384 + 9 = 6921.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support