irene-mobile / README.md
franch's picture
README: minimal set now from 256 base
912087b verified
|
Raw
History Blame Contribute Delete
4.31 kB
---
license: bsd-2-clause
base_model: it4lia/irene
tags:
- executorch
- android
- weather
- nowcasting
- precipitation
- radar
---
# IRENE on-device — ExecuTorch per-step cells (fp16, XNNPACK)
Mobile inference graphs for [IRENE](https://huggingface.co/it4lia/irene), the
ConvGRU ensemble precipitation-nowcasting model (64M params, © FBK DSIP,
BSD-2-Clause). Exported from the released `model.ckpt` as **per-timestep
cells**: the caller drives both recurrences in a loop, carrying the five
per-block ConvGRU hidden states — so the forecast rollout length and the
input-history length are loop counts, not export parameters. One
encoder/decoder pair per domain size.
Produced by `export_executorch.py --cells --fp16` in the irene-android repo
(wrappers and the full I/O contract in its `export/common.py`; parity gate in
`export/parity_step.py`).
## Graph contract (num_blocks=5 ⇒ divisor 32)
| graph | inputs | outputs |
|---|---|---|
| `encoder_step` | `frame (1,1,H,W)` normalized reflectivity + states `e1 (1,1,H,W) … e5 (1,256,H/16,W/16)` (zeros at t=0) | `e1'..e5'` + `h1..h5` (downsampled block outputs, deepest first — the **last** step's are the decoder's initial states) |
| `decoder_step` | `noise_t (1,1024,H/32,W/32)` ~N(0,1) + states `h1..h5` | `frame_t (1,1,H,W)` normalized, unclamped + `h1'..h5'` |
All I/O is **fp16** (no in-graph casts). Pre/post-processing lives in the
caller: pad to /32 → NaN→0 → Marshall–Palmer `dBZ = 10·log10(200·R^1.6+1e-16)`
clip [0,60] → `/30−1`; inverse + crop on the way out. Per ensemble member:
re-seed the decoder states from the encoder skips and draw fresh noise per
step. Trained config: 6 input frames, 12 forecast steps (5-min cadence);
longer rollouts run mechanically but are beyond the trained horizon.
Two integration warnings (cost us a day each):
- On Android, `Module.forward` output tensors alias the runtime's memory
arena — **copy every carried state** before the next call.
- Pin the ExecuTorch runtime to the exporting version: **1.4.0**
(delegate blobs do not cross versions).
## Files
| file | raw | zst |
|---|---|---|
| `encoder_step_{256x256,512x512,1024x1024,1408x1216}_fp16.pte` | 15.1 MB each | 7.9 MB each |
| `decoder_step_{256x256,512x512,1024x1024,1408x1216}_fp16.pte` | 241.6 MB each | 122.1 MB each |
`1408x1216` is the full Italian DPC mosaic (1400×1200, padded to /32); the
others are crop sizes in km (1 km cells).
Note on size: the weights inside every file are the *same* 64M fp16
parameters; they occupy 2× their fp16 bytes because ExecuTorch ≤1.4
serializes convolution filters as fp32 for XNNPACK (`op_conv2d.py`
`force_fp32=True` — the f16 conv API takes fp32 filters and packs at load).
That's also why zstd compresses them almost exactly 2:1 (the upcast halves
have zero low-mantissa bits), and why the per-size **patches** below are
tiny: the weight bytes are identical across sizes, only the graph skeleton
differs.
## Getting the files
Each `.pte.zst` is standalone:
```bash
zstd -d decoder_step_512x512_fp16.pte.zst
sha256sum -c SHA256SUMS.pte
```
Minimal-bandwidth set (~130 MB for all four sizes): download the two 256
files + `patches-from-256/`, then reconstruct:
```bash
zstd -d --long=28 --patch-from=decoder_step_256x256_fp16.pte \
decoder_step_1024x1024_fp16.pte.zst-patch -o decoder_step_1024x1024_fp16.pte
```
(decoder patches ~218 KB, encoder patches ~2 KB; all reconstructions are
byte-identical, verify with `SHA256SUMS.pte`.)
`patches-from-512/` is the same idea against the 512 base — kept for
irene-android ≤0.5.9, whose in-app updater patches from 512.
## Validation
- Eager cells ≡ the monolithic export ≡ `RadarLightningModel.predict()`
**bit-exact** (fixed noise, rain-rate space).
- ExecuTorch fp32 cells vs eager: ~1e-4 mm/h mean abs.
- These fp16 cells produce output **bit-identical** to the monolithic fp16
export; fp16-vs-fp32 error measured on-device at 0.079 mm/h mean against a
7.2 mm/h ensemble spread.
- Measured on a Snapdragon 8 Gen 2 (4 threads, mmap): 512² ≈ 206 ms/step,
full grid ≈ 1.3 s/step — a 10-member 1-hour ensemble in ~25 s, a full-grid
2-hour member in ~40 s.
## License
BSD-2-Clause, © Fondazione Bruno Kessler (DSIP) — same as the IRENE model
these are derived from.