Downloads · 30 days
14
32% of all-time downloads
maskjp/pi05-relative-eef-bagplace-aug100k-full-ft-100k
pi05-relative-eef-bagplace-aug100k-full-ft-100k is a robotics model from maskjp. Use it for the robotics task on the model card, and read the license before you ship it in a product. It is set up for lerobot. The card lists the license as apache-2.0.
Full fine-tune of lerobot/pi05base on a single task — "pick up the bag on the ground and place it on the table" — with actions expressed relative to the observation state at the start of each chunk, and with photometr…
Downloads · 30 days
14
32% of all-time downloads
All-time downloads
44
Public
Parameters
4.1B
9.4 GB on disk
Likes
0
Public
Click a slice to open those files.
.safetensors9.4 GB · 100%
How the weights are stored.
BF163.6B · 87%
From the Hugging Face model README
Full fine-tune of lerobot/pi05_base on a single
task — "pick up the bag on the ground and place it on the table" — with actions expressed relative to the observation state at the start of
each chunk, and with photometric image augmentation enabled.
This is step 100K of a 100K-step run. Held-out loss here is 298% above the run's minimum, so these are not the best weights; they are published for step-matched comparison against the non-augmented run and the all-10 releases.
5% of episodes are held out (10 of 200; 190 train).
| step | eval_loss |
|---|---|
| 1K | 0.0357 |
| 2K | 0.0315 min |
| 3K | 0.0315 |
| 4K | 0.0324 |
| 5K | 0.0343 |
| 6K | 0.0370 |
| 7K | 0.0377 |
| 8K | 0.0393 |
| 9K | 0.0395 |
| 10K | 0.0414 |
| 11K | 0.0420 |
| 12K | 0.0449 |
| 13K | 0.0462 |
| 14K | 0.0471 |
| 15K | 0.0476 |
| 16K | 0.0475 |
| 17K | 0.0484 |
| 18K | 0.0491 |
| 19K | 0.0521 |
| 20K | 0.0518 |
| 21K | 0.0520 |
| 22K | 0.0514 |
| 23K | 0.0536 |
| 24K | 0.0555 |
| 25K | 0.0545 |
| 26K | 0.0569 |
| 27K | 0.0586 |
| 28K | 0.0557 |
| 29K | 0.0595 |
| 30K | 0.0606 |
| 31K | 0.0625 |
| 32K | 0.0632 |
| 33K | 0.0630 |
| 34K | 0.0646 |
| 35K | 0.0649 |
| 36K | 0.0654 |
| 37K | 0.0689 |
| 38K | 0.0691 |
| 39K | 0.0699 |
| 40K | 0.0699 |
| 41K | 0.0741 |
| 42K | 0.0732 |
| 43K | 0.0765 |
| 44K | 0.0763 |
| 45K | 0.0747 |
| 46K | 0.0800 |
| 47K | 0.0788 |
| 48K | 0.0814 |
| 49K | 0.0838 |
| 50K | 0.0858 |
| 51K | 0.0853 |
| 52K | 0.0872 |
| 53K | 0.0860 |
| 54K | 0.0882 |
| 55K | 0.0924 |
| 56K | 0.0918 |
| 57K | 0.0926 |
| 58K | 0.0936 |
| 59K | 0.0954 |
| 60K | 0.0962 |
| 61K | 0.0946 |
| 62K | 0.0987 |
| 63K | 0.1006 |
| 64K | 0.1025 |
| 65K | 0.1034 |
| 66K | 0.1043 |
| 67K | 0.1052 |
| 68K | 0.1058 |
| 69K | 0.1058 |
| 70K | 0.1086 |
| 71K | 0.1072 |
| 72K | 0.1098 |
| 73K | 0.1128 |
| 74K | 0.1127 |
| 75K | 0.1104 |
| 76K | 0.1111 |
| 77K | 0.1144 |
| 78K | 0.1141 |
| 79K | 0.1173 |
| 80K | 0.1174 |
| 81K | 0.1165 |
| 82K | 0.1206 |
| 83K | 0.1169 |
| 84K | 0.1184 |
| 85K | 0.1188 |
| 86K | 0.1215 |
| 87K | 0.1231 |
| 88K | 0.1239 |
| 89K | 0.1211 |
| 90K | 0.1239 |
| 91K | 0.1223 |
| 92K | 0.1239 |
| 93K | 0.1269 |
| 94K | 0.1265 |
| 95K | 0.1283 |
| 96K | 0.1252 |
| 97K | 0.1272 |
| 98K | 0.1251 |
| 99K | 0.1219 |
| 100K | 0.1254 <- this repo |
The minimum is at 2K (0.0315). The curve rises after it: more steps make this model worse on held-out data, which is why the minimum rather than the endpoint is the checkpoint to prefer.
--dataset.image_transforms.enable=true, at most 3 of the following sampled per example.
All are photometric; there is no geometric transform, so the image-to-action geometry the policy
learns is untouched.
| transform | type | range |
|---|---|---|
brightness | ColorJitter | {"brightness": [0.8, 1.2]} |
contrast | ColorJitter | {"contrast": [0.8, 1.2]} |
saturation | ColorJitter | {"saturation": [0.5, 1.5]} |
hue | ColorJitter | {"hue": [-0.05, 0.05]} |
sharpness | SharpnessJitter | {"sharpness": [0.5, 1.5]} |
There is a nearest counterpart — same data, same relative-action scheme, same init, same 2.5e-5 peak lr, same batch — run without augmentation. It is not a clean ablation, because the augmentation switch is not the only thing that differs:
| non-augmented run | this run | |
|---|---|---|
| image transforms | off | on (above) |
| steps / cosine decay horizon | 20K | 100K |
The cosine horizons differ, so the two runs sit at different learning rates from warmup onward and the gap widens with step: by 20K this run's lr is 9.1x the other's. Any difference measured there (eef at 20K: 0.0518 here, 0.0728 there) therefore confounds augmentation with the schedule and should not be read as an augmentation effect.
The minima are more comparable: both arrive at 2K, where the two schedules are still close (lr differs by 2.2%), giving 0.0315 here against 0.0317 there. That is a ~1% gap from a single seed per arm — not enough to claim an effect in either direction.
No claim is made here that augmentation helped. Settling that would need the two runs at a matched decay horizon and more than one seed. The non-augmented run is not published.
use_relative_actions=true with relative_exclude_joints=["gripper"]. This is a processor
transform, not a data rewrite: RelativeActionsProcessorStep subtracts the anchor state at batch
time and AbsoluteActionsProcessorStep adds it back on the way out, so the policy emits absolute
actions and the conversion is identical in training, evaluation and inference.
action[t+k] -= observation.state[anchor] for all dims EXCEPT gripper
gripper absolute (it is a command, not a pose)
Action dim 13: eef_x, eef_y, eef_z, eef_xx, eef_xy, eef_xz, eef_yx, eef_yy, eef_yz, gripper, base_x, base_y, base_yaw — 12 of 13 dims relative, gripper absolute.
Normalisation is QUANTILES, computed from the relative offsets over chunks of 50
(meta/relative_action_provenance.json records this), not from the absolute targets. Absolute
statistics would put most targets far outside [-1, 1].
The end-effector rotation is the stored continuous 6D form (first two rotation-matrix
columns), not axis-angle. On this robot the gripper points down, so |rotvec| sits near pi where
the sign flips arbitrarily; a built axis-angle view carries frame-to-frame jumps of 2*pi.
One language-conditioned task, 200 episodes, 477,058 frames (2.65 h at 50 fps), one u850 arm on a mobile base, three cameras (left / right / wrist).
| task | episodes | frames |
|---|---|---|
| pick up the bag on the ground and place it on the table | 200 | 477,058 |
bag-place is also ~7% of the all-10 mixture, so maskjp/pi05-relative-eef-all10-full-ft-100k
has already trained on this task. Initialising from lerobot/pi05_base instead makes this a
single-task specialist — the clean counterpart to that generalist.
| init | lerobot/pi05_base |
| regime | full fine-tune (vision + language + action expert) |
| batch | 16/rank x 4 ranks = 64 effective |
| lr | 2.5e-5, cosine to 2.5e-6 over 100K, 1000 warmup; vision tower at 0.1x |
| chunk_size / n_action_steps | 50 / 10 |
| precision | bfloat16 policy dtype, gradient checkpointing on |
| augmentation | photometric, <=3 per sample (above) |
| seed | 1000 |
config.json here has had vision_encoder_lr_multiplier and state_in_prompt removed: both are
training-only fields from the fork this was trained in, and stock LeRobot rejects unknown config
keys. Inference is unaffected.
from lerobot.policies.pi05.modeling_pi05 import PI05Policy
policy = PI05Policy.from_pretrained("maskjp/pi05-relative-eef-bagplace-aug100k-full-ft-100k")
meta/ ships the dataset metadata for deployments that want it. Its info.json has
per-dimension names flattened to a plain list; the training datasets store them grouped as
{"motors": [...]}, which stock LeRobot resolves to the single key "motors" and which would
silently relativise the gripper.
maskjp/pi05-relative-eef-bagplace-aug100k-full-ft-2k — the same arm at 2K.maskjp/pi05-relative-eef-all10-full-ft-100k — the all-10 generalist, which includes this
task. Different training data; not a drop-in replacement.