|
Download README.md from arashakb/FastWAM_UR3: direct link, hf CLI and curl.
- Browser
- Download file 8.73 kB
-
https://huggingface.co/arashakb/FastWAM_UR3/resolve/main/README.md
- Command line
-
hf download hf://arashakb/FastWAM_UR3/README.md
-
curl -L -o README.md https://huggingface.co/arashakb/FastWAM_UR3/resolve/main/README.md
8.73 kB
| license: apache-2.0 | |
| library_name: pytorch | |
| tags: | |
| - robotics | |
| - quantization | |
| - nvfp4 | |
| - fp4 | |
| - w4a4 | |
| - svdquant | |
| - world-action-model | |
| - fastwam | |
| base_model: armanakbari4/fastwam-ur3-3task-10k | |
| datasets: | |
| - armanakbari4/ur3-3task-lerobot | |
| # FastWAM UR3 3-task — 4-bit quantisations | |
| Two post-training 4-bit quantisations of the UR3 3-task FastWAM fine-tune (step 7000). Both store | |
| the weight **packed at 4 bits** and contract it on 4-bit or integer tensor cores. Neither is a | |
| fake-quant checkpoint that keeps 4-bit values inside 16-bit tensors. | |
| | | `ur3_step7000_asp_nvfp4.pt` | `ur3_step7000_svdquant_w4a4.pt` | | |
| |---|---|---| | |
| | method | **ĀFQ / ASP, deflated form** | SVDQuant (Li et al., ICLR 2025) | | |
| | numeric format | **NVFP4** — E2M1 elements, block 16, E4M3 block scales | INT4, group 64 | | |
| | weights / activations | W4A4, both at block 16 | W4A4, both at group 64 | | |
| | tensor cores | **FP4** (`torch._scaled_mm_v2`, recipe `BlockWise1x16`) | INT8 (exact for 4-bit codes) | | |
| | size | 4.6117 BPW, **3.38 GiB** | 4.5798 BPW, 3.36 GiB | | |
| | quantised-vs-bf16 action NRMSE | **0.0006** | 0.0010 | | |
| | target GPU | **RTX 5090 / Blackwell** (sm_100, sm_103, sm_120) | L40S / Ada, Hopper (sm_89 tuned) | | |
| The NVFP4 checkpoint is the one to run on an RTX 5090. | |
| Both quantise the same 600 Linears — the two experts' 2 × 30 blocks × {`self_attn` q/k/v/o, | |
| `cross_attn` q/k/v/o, `ffn.0`, `ffn.2`}, **5.914 B parameters**. Patch/text/time embeddings, heads, | |
| the action encoder, norms, modulation and the proprio encoder stay in bf16. Both are | |
| **self-contained**: the quantised Linears *and* every unquantised `mot` tensor *and* the proprio | |
| encoder are inside the file, so the 11.2 GiB bf16 checkpoint is not needed at inference. | |
| Both were calibrated on `armanakbari4/ur3-3task-lerobot` with **10 episodes per task × 3 tasks, | |
| every frame, seed 42 — 9 908 observations**. | |
| ## What ASP is, and what the deflated form means | |
| Action-Subspace Protection keeps a rank-32 subspace of each action-expert layer out of the 4-bit | |
| grid. The subspace is not chosen by activation magnitude: it is the top eigenspace of the **action | |
| metric** `G = E_o[JᵀJ]`, `J = ∂action/∂x`, differentiated through all ten denoising steps, so it is | |
| the set of directions the *emitted action* is most sensitive to rather than the ones that happen to | |
| be large. | |
| Per layer, with `s` the smoothing vector, `H` a block Hadamard, `V` the rank-32 basis and | |
| `W̃ = W·diag(s)` the smoothed weight, the deflated contract is | |
| ``` | |
| x̃ = (x / s) H | |
| y = (x̃ V)(W̃V)ᵀ + NVFP4GEMM( (I − VVᵀ) x̃ , W̃(I − VVᵀ) ) + bias | |
| ``` | |
| **Deflated** means the protected subspace is subtracted from the 4-bit path on *both* sides: the | |
| low-rank branch carries the exact `W̃V` and the FP4 weight holds `W̃(I − VVᵀ)`. The cheaper | |
| shared-weight variant, which quantises one weight and stores `V` alone, is a different arm and a | |
| measurably worse one at these group sizes. The rank-32 branch stays in bf16 by design — it carries | |
| the directions the action depends on, which is the point of protecting them. | |
| The per-layer smoothing `(α, β)` is not a fixed 0.5. It comes from a 39-candidate grid search | |
| (`α ∈ {0, 0.05…0.95}`, `β ∈ {0, 1−α}`, per SVDQuant's protocol) scored on **real calibration | |
| activations** with the objective being this layer's own deflated-ASP NVFP4 output MSE — the same | |
| objective the deployed arm minimises, at the same granularity it is applied. | |
| ## Files | |
| | file | size | | | |
| |---|---|---| | |
| | `ur3_step7000_asp_nvfp4.pt` | 3.38 GiB | **NVFP4 deflated-ASP checkpoint.** Weights E2M1 packed, E4M3 block scales pre-swizzled to `SWIZZLE_32_4_4` | | |
| | `ur3_step7000_svdquant_w4a4.pt` | 3.36 GiB | INT4 SVDQuant checkpoint | | |
| | `nvfp4.py` | 8 KB | the NVFP4 quantiser and `_scaled_mm_v2` wrapper — quantise, dequantise, scale swizzle, GEMM | | |
| | `asp_nvfp4_runtime.py` | 9.6 KB | `ASPNVFP4Linear`, `install_asp_nvfp4`, `load_quantized_asp_model`. Self-contained; imports only torch and `nvfp4.py` | | |
| | `ur3_3task_10k_dataset_stats.json` | 170 KB | proprio z-scoring and action denormalisation — **the checkpoint cannot be run correctly without it** | | |
| | `ur3_prompt_embeddings.pt` | 3.0 MiB | the three task instructions, pre-encoded, so the 11 GB umT5-XXL text encoder is not needed at inference | | |
| Besides these you need the Wan2.2 VAE (`Wan2.2_VAE.pth`, 2.7 GiB) to encode the camera image to the | |
| video latent. You do not need the bf16 checkpoint, the text encoder, or the Wan2.2 DiT weights. | |
| ## Running the NVFP4 checkpoint | |
| Requires a GPU with **FP4 tensor cores** — RTX 5090 (sm_120), B200/B300 (sm_100/sm_103) — and a | |
| PyTorch with `torch._scaled_mm_v2`. Verified on torch 2.12.0+cu130. | |
| ```python | |
| from asp_nvfp4_runtime import load_quantized_asp_model | |
| model, cfg = load_quantized_asp_model( | |
| "ur3_step7000_asp_nvfp4.pt", | |
| build_model, # your own bf16 FastWAM constructor -> (model, cfg) | |
| ) | |
| ``` | |
| `build_model` supplies the module graph only; every tensor comes from the checkpoint. To quantise a | |
| model you already built, call `install_asp_nvfp4(model, ckpt_path)` instead — it raises rather than | |
| swapping a subset, because a partial swap is not a defined arm. | |
| Full pipeline, kernels and the deployment guide: **https://github.com/arashakb/QuantWAM** | |
| (`adapters/fastwam/`, `quantwam/kernels/nvfp4.py`, `adapters/fastwam/README_ur3_5090.md`). The | |
| `UR3QuantPolicy` wrapper there takes **raw** `HxWx3` uint8 frames and the **raw** 14-d state and | |
| applies the whole observation contract itself (top → 320×256, wrists → 160×128, | |
| `[top ; [left|right]]` → 384×320, `*2/255 − 1`; state z-scored and clamped to ±5), so a caller | |
| cannot get the preprocessing subtly wrong. | |
| ## Verification — NVFP4 deflated ASP | |
| Everything below is measured on **held-out** episodes; the calibration episodes are excluded, | |
| because a check run on fitted data cannot detect the failure it exists to detect. | |
| **It is really 4-bit, not a simulation.** Read off the loaded model: | |
| | | | | |
| |---|---| | |
| | `wq` dtype, all 600 layers | `torch.float4_e2m1fn_x2` | | |
| | weight bytes resident | 2 820 MiB for 5.914 B weights = **4.00 bits/weight** (bf16 would be 16.00) | | |
| | E4M3 block scales | 352.5 MiB | | |
| | any dequantised weight copy anywhere | **none** | | |
| | `torch._scaled_mm_v2` calls in one full inference | **3 300** = 300 video prefill × 1 + 300 action × 10 steps | | |
| | recipes those calls used | `BlockWise1x16` only — i.e. NVFP4 | | |
| **It computes the intended contract.** Recomputing each layer independently from the stored | |
| transforms and comparing against the runtime: worst relative error **1.7e-3** across sampled action | |
| and video layers, which is the bf16 output cast and not a form mismatch. | |
| **The actions are right.** Twelve held-out observations spanning all three tasks: | |
| | | NRMSE | | |
| |---|---| | |
| | **NVFP4 ASP vs bf16, action chunk** | **0.0006** | | |
| | bf16 vs recorded actions | 0.0068 ← the ceiling | | |
| | **NVFP4 ASP vs recorded actions** | **0.0066** (corr 0.9997) | | |
| The quantised model sits as close to the recorded actions as the bf16 model does — marginally | |
| closer on these frames, which is noise, not an improvement. | |
| **Not yet measured: real-robot success rate.** The bf16 model has been evaluated on the physical | |
| UR3; neither quantised checkpoint has. Everything above is open-loop agreement with recorded | |
| trajectories, which is necessary but not sufficient. | |
| ## Verification — INT4 SVDQuant | |
| | check | result | | |
| |---|---| | |
| | base bf16 model vs recorded actions | NRMSE 0.0055, corr 0.9998 | | |
| | packed kernels vs the reference SVDQuant formula, per layer | activation scales bit-identical; ≤ 0.10 % of 4-bit codes differ, every one by exactly 1 LSB | | |
| | weight repacking fidelity at export | 0.0000 % of codes off by 1 LSB | | |
| | quantised vs bf16, action chunk | NRMSE 0.0010 | | |
| | quantised vs recorded actions | NRMSE 0.0064 — the same as bf16's own 0.0064 | | |
| | end-to-end from raw camera frames | NRMSE 0.0061, corr 0.9997 | | |
| Its Triton launch configurations are tuned per compute capability and only `sm_89` ships; on other | |
| architectures the kernel prints `no tuned config for M=… K=… N=…` and falls back to an occupancy | |
| heuristic — correct, but roughly 2× off the tuned optimum on narrow shapes. Run | |
| `analysis/iw_gemm_tune.py` once on the target GPU to fix it. This does not apply to the NVFP4 | |
| checkpoint, which calls cuBLAS through `_scaled_mm_v2` rather than a hand-tuned Triton kernel. | |
| ## Tasks | |
| * `blue_basket` — put the medicine then the measuring tape inside the blue basket | |
| * `drawer` — open the drawer, put the white box inside the drawer then close the drawer | |
| * `stacking_cubes` — put the green cube on top of the black cube and put the red cube on top of the green cube | |