Jeff Mixon / Wi-Fi as a sensor: reproducing WhoFi and getting the rigor right

Created Sun, 15 Feb 2026 00:00:00 -0800 Modified Mon, 22 Jun 2026 16:04:57 -0700

What Wi-Fi can see through a wall

When a Wi-Fi access point and a client exchange frames, the radio reports — per subcarrier, per antenna pair — how the channel between them is behaving. That report is called Channel State Information, or CSI. A body moving through the room perturbs the channel; a body standing still still perturbs the channel; an empty room perturbs it differently again. Treat CSI as a time series and you have a sensor that needs no camera, no microphone, and nothing on the person you are sensing.

That is the field this post is about. I have been chewing on it as a personal research line for a couple of years now, and 2025–2026 was when it finally produced two artifacts I am willing to point at.

Two artifacts

The first is a reproduction of WhoFi — the recent “Deep Person Re-Identification via Wi-Fi Channel Signal Encoding” paper (arXiv:2507.12869) — implemented as a metric-learning retrieval system: encode a CSI clip into an embedding, ask whether the closest embedding in a gallery belongs to the same person, score retrieval. The paper provides the architecture and the framing; the pipeline from raw capture to retrieval metrics is mine.

The second is an arXiv-style preprint of my own on a graduated occupancy task: detect whether a room is empty or not, then count occupants in three buckets, then estimate the exact count (0–3 under one of the standard multi-channel scenarios). It is not the model that makes the preprint interesting. It is the scaffolding around the model.

The rigor that’s easy to skip

CSI sensing has a methodology problem the field has been candid about: it is extremely easy to publish numbers that do not survive contact with a new environment, a new device, or a new day. The leading cause is packet-level leakage in the train/test split. If consecutive CSI packets from the same capture session show up on both sides of the split, the model isn’t learning “how Person A perturbs the channel” — it is learning “what Tuesday afternoon at 4:13 PM looked like.” The literature puts the inflation at 20–40% accuracy.

So:

  • Splits are strictly by session. No packet from any capture session appears on both sides of the line.
  • I ran a leakage-quantification experiment rather than asserting the effect by reference: split packet-randomly and session-strictly on the same data, report both numbers, watch the gap.
  • Leave-one-set-out (LOSO) cross-validation across seven capture sessions sits next to a fixed-split baseline. Both numbers are reported so the cross-session generalization gap is visible, not hidden by a single cherry-pickable split.
  • Multi-seed × multi-fold confidence intervals decompose seed variance from fold variance. A single number is a story; an interval is a result.
  • A preprocessing ablation grid (TSFR phase reconstruction, subcarrier removal, background subtraction, temporal high-pass) is reported as a grid, not as a sentence beginning “we found that…”
  • Classical baselines (RBF SVM, random forest, gradient boosting on hand-crafted features) run against the CNN, with paired significance tests under Holm–Bonferroni correction. If the deep model isn’t beating the classical baseline at p<0.05 after multiple-comparison correction, that is the result, and I write that down.
  • Calibration as a first-class artifact — Expected Calibration Error and reliability diagrams alongside accuracy. A 92% accurate model that is systematically overconfident is not a 92% useful model.
  • The cross-session-shift fold gets called out by name as the natural target for follow-up domain-adaptation work, rather than buried in the appendix.

None of this is novel methodology. All of it is supposed to be how the field works. Doing it consistently is the work.

The engineering scaffolding

A research codebase that you actually re-run is a different artifact from one you wrote once and shoved up on GitHub. Some pieces that paid for themselves:

  • Independent experiment drivers sit behind a single resumable sweep, each producing canonical artifacts that downstream drivers consume. You can rerun the calibration stage without retraining; you can rerun the significance stage without recomputing calibration; the determinism is in the file layout, not in remembering what you did.
  • An offline preprocessing cache so cross-validation never re-decodes the raw multi-tens-of-GB capture. The first run pays the cost. Every run after that runs at the speed of the model.
  • uv for env management, with per-machine CUDA-wheel pinning (cu130 / cu124 / cpu) as the only line that changes per host. Same lockfile, same code, three machines.
  • A Makefile wraps the drivers with overridable DATA_ROOT and pass-through ARGS. The same incantation works on the laptop with a toy slice and on the GPU box with the full corpus.
  • Headline figures are generated from canonical sidecars, not redrawn by hand. If the underlying numbers shift, the figures shift with them, and I notice.

The lesson, generalized to anyone doing applied-ML research solo: the time you spend making the experimental harness boring is time you do not later spend wondering whether a number is real.

Closer

Wi-Fi sensing is a small-enough field that you can read most of the seminal papers in a season and a big-enough field that there is still room for an unaffiliated practitioner to contribute reproductions and methodological hardening. That is the slot I have been working in. The next strand — domain-adaptation across the cross-session-shift fold the calibration work already flagged — is the obvious follow-up, and is what I am chewing on now.