This repository implements a domain-adaptive radio fingerprinting framework that uses standard-compliant MIMO beamforming feedback matrices to learn client-discriminative embeddings for fingerprinting radios (Network Interface Cards).
If you use this code, please cite:
@inproceedings{haque2026beamid,
title={BeamID: Domain-Adaptive Radio Fingerprinting with MIMO Beamforming Feedback},
author={Haque, Khandaker Foysal and Meneghello, Francesca and Restuccia, Francesco},
booktitle={IEEE International Conference on Network Softwarization (NetSoft)},
year={2026}
}model.py— encoder / projector / classifier network definitions.datagen.py— dataset loader forDataset/vmatrices/*.npy.loss.py— supervised contrastive loss implementation.train.py— source-domain training using supervised contrastive learning (SupCon) and optional classifier loss.viz_cosine_gap_v3.py— generate 3-panel cosine-gap plots for same-domain vs cross-domain before/after domain adaptation.
BeamID learns radio fingerprints from MIMO beamforming feedback. It trains on a source domain and then adapts with a few labeled target-domain samples directly in embedding space, restoring cross-environment client identification accuracy.
Please download the dataset from HuggingFace Repo
First Install the Hugging Face CLI:
pip install -U "huggingface_hub[cli]"
Download the vmatrices folder:
hf download foysalhaque/BeamID \
--repo-type dataset \
--include "vmatrices/*" \
--local-dir Dataset
The files will be stored under:
Dataset/vmatrices/
- Expected filenames are of the form
<mac>_<loc>.npy. - Each
.npycontains complex-valued beamforming feedback samples. datagen.pyconverts them to real-valued tensors of shape(16, 250)for model input.
- Train a source-domain model:
python train.py Dataset/vmatrices \
--source 1 2 3 4 5 6 \
--target 7 8 9 \
--k 15 \
--epochs 30 \
--batch 128 \
--lr 1e-3 \
--save checkpoints/checkpoint.pt- Generate the cross-domain adaptation plot:
python viz_cosine_gap_v3.py Dataset/vmatrices \
--ckpt checkpoints/checkpoint.pt \
--source 1 2 3 \
--target 4 \
--k 15 \
--pairs 50000 \
--ft_steps 800 \
--ft_lr 5e-4 \
--unfreeze_last \
--out cosine_gap.png- If you already have cached cosine-gap data:
python viz_cosine_gap_v3.py Dataset/vmatrices \
--cache cosine_gap_cache_v3.npz \
--plot_only \
--out cosine_gap.pngFor any further information, please contact K Foysal Haque at haque.k@northeastern.edu