Downloads · 30 days
0
arashakb/IMAGEWAM-Unitree-G1
IMAGEWAM-Unitree-G1 is a robotics model from arashakb. 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 pytorch. The card lists the license as mit.
The ImageWAM-FLUX.2-4B Unitree-G1 two-task fine-tune (LGG100/imagewam-sc-10k, step 10000) quantised to INT4, group 32 for GPUs with 4-bit tensor cores, by two methods calibrated identically and packed identically — so…
Downloads · 30 days
0
Access
Public
Updated Aug 31, 2026
Repo size
5.3 GB
Likes
0
Public
Click a slice to open those files.
.pt5.3 GB · 100%
From the Hugging Face model README
The ImageWAM-FLUX.2-4B Unitree-G1 two-task fine-tune (LGG100/imagewam-sc-10k, step 10000)
quantised to INT4, group 32 for GPUs with 4-bit tensor cores, by two methods calibrated
identically and packed identically — so they differ in their mathematics, not their plumbing.
Real quantisation, not a simulation of it. The weight ships PACKED at 4 bits, two output
channels per byte, in the [K, N/2] layout the fused Triton kernels contract on — the same packing
the FastWAM Unitree-G1 checkpoints use, so the arms are comparable across models.
sc_step10000_asp_w4a4_g32.pt | sc_step10000_svdquant_w4a4_g32.pt | |
|---|---|---|
| method | AFQ / ASP, deflated form | SVDQuant (Li et al., ICLR 2025) |
| rotation | block Hadamard | none |
| low-rank branch | rank 32 on the action expert, from the action metric | rank 32 on every layer, from the quantisation residual |
| BPW | 4.5789 | 4.7523 |
| resident weights | 2.637 GiB (3.25x less than bf16) | 2.716 GiB (3.16x) |
| vs bf16, mean | 0.00326 | 0.00623 |
| vs bf16, worst frame | 0.01291 | 0.01485 |
| vs recorded teleoperation | 0.06588 | 0.06523 |
bf16's own distance to the demonstrator is 0.06592. ASP tracks the unquantised model to 0.00326 — half SVDQuant's movement — and lands within 4e-5 of bf16's own gap to the demonstrator, while spending 0.173 fewer bits per weight. (Both arms sitting either side of bf16 on the last row is noise; the row that separates them is movement against bf16.)
Both quantise the same 153 of 156 MoT Linears, 4.498 B parameters.
The same 30 episodes as the FastWAM Unitree-G1 arms — 15 per task from
item-classification-new and sort-tools-new, seed 42, all frames, 14,469 observations — so
the two models' quantised rows are comparable. Activation absmax feeds SmoothQuant; an
800-row-per-layer reservoir of real layer inputs feeds the smoothing search, whose objective is
SVDQuant's own OutputsError with the INT4 quantiser and the refitted low-rank branch inside the
scored loop.
SVDQuant: 124 layers chose (alpha, 0), 30 (alpha, 1-alpha); split-half 69.5%; searching the
smoothing is worth 1.076x over a fixed alpha = 0.5 and the rank-32 branch 1.061x over no branch.
ASP searches the smoothing and the subspace jointly, because the protected subspace is the top eigenspace of the metric in the coordinates being quantised and those coordinates move with the smoothing: split-half 77.3%, and its branch is worth 1.574x — half again as much as SVDQuant's, on the same model and the same activations.
G_l = E[J_l^T J_l], J_l = d(action chunk)/d(x_l) differentiated through all ten denoising steps,
estimated with random probes over 905 frames x 12 probes. 97.9% of tr(G) sits in six layers,
and none is a transformer block: single_stream_modulation 37.8%, double_stream_modulation_img
34.0%, action_encoder 15.7%, time_in.out_layer 8.0%, the two head layers 2.5%. Top-32
eigenvectors capture 99.93% of tr(G) on the dominant layer.
mixtures.action.time_in.in_layer gets rank 0, not rank 32: it consumes the timestep, not the
action latents, so its Jacobian to the action is genuinely empty and a "protected subspace" there
would be 32 directions chosen by LAPACK out of a zero matrix. 65 layers carry a subspace, 88 do not.
REAL — 153 packed Linears, all torch.int8 at [K, N/2]; 2413.1 MiB for 4.498 B weights is
4.50 bits/weight exactly (4 plus 16/32 for the per-group scale); zero dequantised weight
copies anywhere in the module.
PACKING — per layer, on random inputs, against each method's own fake-quant formula written out directly. SVDQuant: worst layer 1.1e-2, 0.086% of codes differ by exactly 1 LSB, scales bit-identical. A wrong nibble pairing or a transposed scale shows up here and nowhere else, because at the model level it would still emit a plausible action chunk.
For ASP the criterion has to change, and the reason is worth stating. Bit-identical scales are achievable for SVDQuant, whose prologue is an elementwise multiply a fp32 reference reproduces exactly, and are not achievable for ASP, whose prologue is a tensor-core Hadamard: the rotated activation rounds differently, so its per-group amax does too. The honest criterion is distance to the unquantised layer, and ASP's kernel is at worst +0.8% further from the true bf16 layer than a fp32 reference — on layers where both sit at ~1.5e-1, because that is W4A4's own error. Codes are still within 1 LSB and scales within 5%.
ACCURATE — on episodes disjoint from the calibration selection: the table at the top. The model's own distance to the demonstrator is ~20x what ASP moved and ~10x what SVDQuant moved.
No closed-loop success rate has been measured. Open-loop agreement is necessary and not sufficient.
153 of 156 MoT Linears, 4.498 B weights — 99.6% of mot's parameters. Three stay bf16 and the
checkpoint records them:
| layer | shape | why |
|---|---|---|
mixtures.action.action_encoder | (1024, 16) | K = 16 is below the kernel's group granularity of 32 |
mixtures.video.transformer.final_layer.linear | (128, 3072) | the video output head predicts the next frame; it never runs during action inference, so it has no calibration |
…final_layer.adaLN_modulation.1 | (6144, 3072) | same |
Needs triton and a GPU with INT4-on-INT8 tensor cores (built and verified on sm_89 and H100). The
file is self-contained — the quantised Linears, every unquantised mot tensor and the proprio
encoder — so the source checkpoint is not needed at inference. You still need the FLUX.2
klein-base-4B backbone and autoencoder, dataset_stats.json, and the pre-encoded prompt.
from iw_w4a4_runtime import load_quantized_model
model, cfg = load_quantized_model("sc_step10000_svdquant_w4a4_g32.pt", build_model=my_builder)
install_iw_w4a4 raises unless every name resolves to an nn.Linear, and dispatches on
lowrank_mode: SVDQuant and deflated ASP produce the same shapes, so nothing else tells them
apart, and running one through the other's class gives a well-formed GEMM of the wrong bilinear
form that still emits a plausible action chunk.
The runtime files here are standalone copies of the in-repo versions, checked on real exported layers (see the note on reproducibility below).
mot carries ...base.weight, ...lora_A and
...lora_B for every adapted video Linear, and only load_checkpoint merges them. Read the
weights straight out of the file and you quantise the pretrain and silently drop the
fine-tune — a checkpoint that loads, runs, emits plausible actions, and is the wrong model. This
export reads module.weight.data off the live model after the merge, and turns
load_checkpoint's missing/unexpected report (which it only logs at INFO) into an exception.mixtures.video.X and
mixtures.video.transformer.X are the same tensor — 140 of 267 storages carry two names.
Deduplicate by storage or a "quantised" export comes out larger than the bf16 original.compact_288x256): cam_left_high at 256x192 on top, the two wrists
at 128x96 side by side below, order [high, left, right], pixels mapped to (-1, 1). Actions are
16-D and are not padded or un-padded — this robot is natively 16-D, unlike the UR3 ImageWAM
checkpoints which pad 14 to 16.Both recorded on Unitree_G1_Dex1_Sim, 100 episodes each, 30 fps, three cameras at 480x640, and
both declaring the same instruction "pick up cube." in their own metadata.