Downloads · 30 days
14
19% of all-time downloads
maskjp/pi05-relative-eef-bagplace-memrtc-full-ft-43k
pi05-relative-eef-bagplace-memrtc-full-ft-43k 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
19% of all-time downloads
All-time downloads
73
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 43K of a 100K-step run. The run had not finished when this was published — it was still training, at step 43K of 100K. This is a mid-run snapshot, and held-out loss here is 101% above the run's minimum so far: on this curve it is the worst checkpoint yet, not the best. It is published as a snapshot of where the run had got to, nothing more. If you want the best weights, take the 4K checkpoint instead.
5% of episodes are held out (10 of 200; 190 train).
| step | eval_loss |
|---|---|
| 1K | 0.0278 |
| 2K | 0.0215 |
| 3K | 0.0186 |
| 4K | 0.0180 min |
| 5K | 0.0186 |
| 6K | 0.0184 |
| 7K | 0.0187 |
| 8K | 0.0191 |
| 9K | 0.0191 |
| 10K | 0.0196 |
| 11K | 0.0208 |
| 12K | 0.0205 |
| 13K | 0.0215 |
| 14K | 0.0210 |
| 15K | 0.0225 |
| 16K | 0.0226 |
| 17K | 0.0231 |
| 18K | 0.0223 |
| 19K | 0.0234 |
| 20K | 0.0232 |
| 21K | 0.0239 |
| 22K | 0.0255 |
| 23K | 0.0243 |
| 24K | 0.0254 |
| 25K | 0.0255 |
| 26K | 0.0266 |
| 27K | 0.0278 |
| 28K | 0.0288 |
| 29K | 0.0273 |
| 30K | 0.0281 |
| 31K | 0.0290 |
| 32K | 0.0313 |
| 33K | 0.0305 |
| 34K | 0.0293 |
| 35K | 0.0306 |
| 36K | 0.0309 |
| 37K | 0.0310 |
| 38K | 0.0327 |
| 39K | 0.0320 |
| 40K | 0.0345 |
| 41K | 0.0332 |
| 42K | 0.0351 |
| 43K | 0.0361 <- this repo |
The minimum is at 4K (0.0180). 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. The table above stops where the run had reached when this was published; it was still training and the curve was still climbing.
This round enables two things the other bag-place rounds do not, so its numbers are not on the same scale as theirs.
use_visual_memory | True — MEM (arXiv:2603.03596) section III-C |
memory_frames / memory_stride | 6 / 50 frames = 1.0 s spacing at 50 fps |
memory_temporal_attention_every | 4 — every Nth SigLIP layer uses composed space-time attention |
use_proprioceptive_memory | False — see below |
rtc_training_max_delay | 10 controller steps |
memory_stride is counted in dataset frames, and MEM pretrains on six observations one second
apart. The stock default of 30 encodes one second only at 30 fps; this dataset is 50 fps, so the
value above is derived from the dataset rather than defaulted.
With rtc_training_max_delay non-zero, each example gets a clean ground-truth action prefix of
0–10 steps, and the flow loss is averaged over the remaining postfix only
(_reduce_training_rtc_loss). Evaluation runs the same forward path, so the model is scored
while conditioned on part of the answer, over fewer positions. That makes the number smaller for
reasons unrelated to how well the policy generalises. Comparing it against a round trained without
RTC measures the scoring change as much as the model.
Batch is also 32 effective here against 64 in the other rounds — MEM puts memory_frames x cameras images through SigLIP per sample instead of one set — so at equal steps this run has seen fewer samples.
Enabling MEM on lerobot/pi05_base, pretrained without it, is the paper's weaker
MEM-Posttrain-Only ablation; MEM's headline results come from pretraining the video encoder on a
large robot+non-robot video mixture that no public pi05 checkpoint provides. MEM's long-horizon
language memory (section III-B) is not implemented. Proprioceptive memory (III-D) is off because
it is incompatible with relative actions: it gives observation.state a time axis, which
to_relative_actions does not accept.
--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]} |
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-memrtc-full-ft-43k")
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-memrtc-full-ft-4k — the same arm at 4K.maskjp/pi05-relative-eef-all10-full-ft-100k — the all-10 generalist, which includes this
task. Different training data; not a drop-in replacement.