Restructure package: descriptive study documentation and clean layout

This commit is contained in:
Ki-Ho Lee
2026-08-25 20:25:46 +09:00
parent 7e831474af
commit 1fc9cad834
38 changed files with 397 additions and 2262 deletions
+43 -36
View File
@@ -2,60 +2,67 @@
Simulation code, raw results, and figure sources for the manuscript Simulation code, raw results, and figure sources for the manuscript
"Relevance-Aware Semantic Multiple Access via Meta-Learned User-Wise "Relevance-Aware Semantic Multiple Access via Meta-Learned User-Wise
Cross-Attention" (submitted to IEEE Transactions on Wireless Communications). Cross-Attention" (submitted to the IEEE Transactions on Communications).
The package contains everything needed to regenerate every number and
figure in the manuscript: one script per study, the raw JSON/CSV results
each script produced, and a single plotting script that rebuilds the figure
PDFs from the stored results without rerunning any experiment.
**Detailed per-study documentation (question, setup, procedure, metrics,
key results): [docs/EXPERIMENTS.md](docs/EXPERIMENTS.md).**
## Requirements ## Requirements
- Python 3.10+ with `torch` (CUDA optional; results generated on an NVIDIA - Python 3.10+ with `torch` (results generated on an NVIDIA RTX A4500,
RTX A4500, PyTorch 2.10, CUDA 12.8), `numpy`, `matplotlib`, and PyTorch 2.10, CUDA 12.8; CPU fallback works), `numpy`, `matplotlib`, and
`scikit-learn` (real-data study only). `scikit-learn` (real-data study only).
- All experiments use fixed seed 42 (auxiliary generators seeded as noted in - All experiments use fixed seed 42 (auxiliary generators seeded as noted
each script). in each script).
## Layout ## Layout
- `rev2/lib.py` — shared library: single-superimposed-signal channel - `experiments/lib.py` — shared library: the single-superimposed-signal
(Rayleigh / Rician / Nakagami fading, complex phase residuals, timing uplink of the manuscript (Rayleigh / Rician / Nakagami fading, complex
offsets, CSI error), UWCA decoder (active-set masking, top-k masking, phase residuals, timing offsets, CSI error; fixed disjoint transmit block
I/Q input), closed-form LMMSE receivers, training loops (multi-task masks), the UWCA decoder (learned soft masks, active-set masking, top-k
meta-training and first-order MAML), evaluation metrics. masking, optional I/Q input), closed-form LMMSE reference receivers,
- `rev2/e1_fair_baselines.py``rev2/e9_topk_online.py` — one script per training loops, and evaluation metrics.
experiment (see the table below). `*_v2/_v3` scripts supersede their - `experiments/e1_fair_baselines.py``experiments/e9_topk_online.py`
earlier versions where present. one self-contained script per study (see the table below).
- `rev2/data/` — raw JSON results behind every quoted number. - `experiments/data/` — raw JSON results behind every quoted number.
- `rev2/plot_rev2.py` — regenerates every new figure from `rev2/data/` - `experiments/make_figures.py` — regenerates the figure PDFs from
without rerunning experiments. `experiments/data/` only.
- `legacy/` — scripts for the pre-revision figures (synthetic three-scenario - `simulation/` — the three-scenario synthetic study, hyperparameter
study, attention maps, beta sweep, real-data study). ablations, threshold sweeps, and the real-data study.
- `fig/` — figure PDFs as included in the manuscript. - `fig/` — figure PDFs as included in the manuscript.
**Detailed per-experiment documentation (setup, procedure, metrics, key results, reviewer-concern map): [docs/EXPERIMENTS.md](docs/EXPERIMENTS.md).** ## Study → script → data map
## Figure/number → script → data map
| Manuscript item | Script | Data | | Manuscript item | Script | Data |
|---|---|---| |---|---|---|
| Fig. SER vs SNR (3 scenarios) | `legacy/semantic_correlation_sim.py`, `legacy/maml_semantic.py` | `legacy/results/` | | SER vs SNR, three scenarios (Fig. 2) | `simulation/semantic_correlation_sim.py`, `simulation/maml_semantic.py` | `simulation/results/` |
| Fig. fairness vs optimal linear receivers | `rev2/e1_fair_baselines.py` | `rev2/data/e1_fair_baselines.json` | | Optimal-linear-receiver fairness (Fig. 3) | `experiments/e1_fair_baselines.py` | `experiments/data/e1_fair_baselines.json` |
| Fig. residual orthogonality | `rev2/e6_residual_orth.py` | `rev2/data/e6_residual_orth.json` | | Residual orthogonality (Fig. 4) | `experiments/e6_residual_orth.py` | `experiments/data/e6_residual_orth.json` |
| Phase-error robustness (complex model, CSI error) | `rev2/e2_phase_iui.py` | `rev2/data/e2_phase_iui.json` | | Complex phase-error model, CSI error | `experiments/e2_phase_iui.py` | `experiments/data/e2_phase_iui.json` |
| Timing-offset robustness | `rev2/e4_v3_async.py` | `rev2/data/e4_v3_async.json` | | Timing offsets and realignment | `experiments/e4_async.py` | `experiments/data/e4_async.json` |
| Dynamic user population | `rev2/e3_dynamic_users.py` | `rev2/data/e3_dynamic_users.json` | | Dynamic user population | `experiments/e3_dynamic_users.py` | `experiments/data/e3_dynamic_users.json` |
| Nonlinear view-network study | `rev2/e5_nonlinear.py` | `rev2/data/e5_nonlinear.json` | | Nonlinear view-network study | `experiments/e5_nonlinear.py` | `experiments/data/e5_nonlinear.json` |
| Meta-adaptation beyond SNR (OOD) | `rev2/e7_v2_meta.py` | `rev2/data/e7_v2_meta.json` | | Adaptation across fading families | `experiments/e7_meta.py` | `experiments/data/e7_meta.json` |
| End-to-end anti-collapse study | `rev2/e8_v2_e2e.py` | `rev2/data/e8_v2_e2e.json` | | End-to-end training with anti-collapse | `experiments/e8_e2e.py` | `experiments/data/e8_e2e.json` |
| Online top-k acquisition and timing | `rev2/e9_topk_online.py` | `rev2/data/e9_topk_online.json` | | Online top-k acquisition and timing | `experiments/e9_topk_online.py` | `experiments/data/e9_topk_online.json` |
| Real-data validation | `legacy/revision_realdata_train.py`, `legacy/revision_realdata_plot.py` | `legacy/results/` | | beta sweep, attention maps, ablations | `simulation/revision_*.py`, `simulation/plot_figures.py` | `simulation/results/` |
| Real-data validation (Fig. 5) | `simulation/revision_realdata_train.py`, `simulation/revision_realdata_plot.py` | `simulation/results/` |
## Running ## Running
```bash ```bash
python rev2/e1_fair_baselines.py # writes rev2/data/e1_fair_baselines.json python experiments/e1_fair_baselines.py # writes experiments/data/e1_fair_baselines.json
python rev2/plot_rev2.py # regenerates the new figure PDFs python experiments/make_figures.py # rebuilds the figure PDFs from data/
``` ```
Each experiment script is self-contained and writes its JSON into Each study script is self-contained and writes its JSON into
`rev2/data/`. `experiments/data/`.
## Citation and license ## Citation and license
+172 -178
View File
@@ -1,20 +1,21 @@
# Experiment Documentation # Study Documentation
Detailed description of every experiment behind the manuscript Detailed description of every study behind the manuscript
"Relevance-Aware Semantic Multiple Access via Meta-Learned User-Wise "Relevance-Aware Semantic Multiple Access via Meta-Learned User-Wise
Cross-Attention." Each entry states the reviewer concern it addresses, the Cross-Attention": the question each study answers, the exact setup, the
exact setup, the procedure, the metrics, the key results, and the artifact procedure, the metrics, the key results, and the artifact paths. All
paths. All experiments run on a single NVIDIA RTX A4500 (PyTorch 2.10, CUDA studies run on a single NVIDIA RTX A4500 (PyTorch 2.10, CUDA 12.8), seed
12.8), seed 42, and write raw JSON results consumed only by 42, and write raw JSON results consumed only by
`rev2/plot_rev2.py`. `experiments/make_figures.py`.
**Common system model** (all rev2 experiments, matching manuscript Eq. (7)): **Common system model** (all `experiments/` studies, matching the
single superimposed uplink y = sum_v |h_v| e^{j dphi_v} (e_v (.) m_v) + n over manuscript's received-signal model): single superimposed uplink
one d=64-dimensional frame; fixed {0,1} disjoint transmit block masks y = sum_v |h_v| e^{j dphi_v} (e_v (.) m_v) + n over one d=64-dimensional
(d/U coordinates per user, identical for every compared scheme); per-rail frame; fixed {0,1} disjoint transmit block masks (d/U coordinates per user,
noise std = sqrt(mean|y_tx|^2 / SNR); U=4 users, HIGH/LOW/MIX scenarios of identical for every compared scheme); per-rail noise
Table II unless stated. The decoder-side masks are separate learned soft std = sqrt(mean|y_tx|^2 / SNR); U=4 users and the HIGH/LOW/MIX scenarios of
masks in [0,1]^d initialized at the block pattern. Training is the the manuscript unless stated. The decoder-side masks are separate learned
soft masks in [0,1]^d initialized at the block pattern. Training is the
manuscript's first-order meta-training aggregated over SNR tasks manuscript's first-order meta-training aggregated over SNR tasks
{0,4,...,20} dB, Adam 1e-3 (mask logits 0.1), 250-300 epochs, batch 64; {0,4,...,20} dB, Adam 1e-3 (mask logits 0.1), 250-300 epochs, batch 64;
evaluation uses 150-200 Monte Carlo batches of 64 per point. evaluation uses 150-200 Monte Carlo batches of 64 per point.
@@ -22,225 +23,218 @@ evaluation uses 150-200 Monte Carlo batches of 64 per point.
--- ---
## E1 — Comparison fairness against optimal linear receivers ## E1 — Comparison fairness against optimal linear receivers
*Reviewer concerns: R1-10, R3-7 (d/U comparison "mathematically unfair");
editor point 4.*
- **Question.** Is the OFDMA/SFDMA subspace ceiling an artifact of weak - **Question.** Is the d/U subspace ceiling of orthogonal access an
baselines, and how much of the UWCA gain is mere dimensionality? artifact of weak comparison schemes, and how much of the UWCA gain is
mere dimensionality rather than relevance exploitation?
- **Setup.** For each scenario the true relevance matrix B (B_uv = - **Setup.** For each scenario the true relevance matrix B (B_uv =
beta_u beta_v for shared scene, else 0) and the per-realization channel beta_u beta_v for a shared scene, else 0) and the per-realization channel
magnitudes are formed. Receivers evaluated on the *same* received frame: magnitudes are formed. Receivers evaluated on the *same* received frame:
`uwca` (trained), `ofdma`, `sfdma`, `noma` (full-band power-domain SIC, `uwca` (trained), `ofdma`, `sfdma`, `noma` (full-band power-domain SIC,
powers 0.40/0.30/0.20/0.10), `lmmse_blind` (closed-form Wiener with powers 0.40/0.30/0.20/0.10), `lmmse_blind` (closed-form Wiener with
cross-covariances zeroed), `lmmse_genie` (closed form with true B and cross-covariances zeroed), `lmmse_genie` (closed form with true B and
channel gains, manuscript Eq. (23)), `tdma_proj` (random orthonormal channel gains, the manuscript's Proposition on optimal linear receivers),
16-dim projection per user — an arbitrary orthogonal partition). and `tdma_proj` (random orthonormal 16-dim projection per user — an
arbitrary orthogonal partition).
- **Key results.** lmmse_blind = OFDMA at every SNR in all scenarios - **Key results.** lmmse_blind = OFDMA at every SNR in all scenarios
(SER 0.509 vs 0.508 @10 dB HIGH), tdma_proj and SFDMA coincide with them; (SER 0.509 vs 0.508 @10 dB HIGH), and tdma_proj and SFDMA coincide with
HIGH @20 dB: blind 0.327 -> UWCA 0.110 -> genie 0.044 (UWCA recovers 77% them — the ceiling binds every correlation-blind receiver. HIGH @20 dB:
of the blind-to-genie gap); LOW: genie = blind (nothing to exploit), blind 0.327 -> UWCA 0.110 -> genie 0.044, so UWCA recovers 77% of the
UWCA within 0.02 SER. blind-to-genie gap without side information. LOW: genie = blind (nothing
- **Artifacts.** `rev2/e1_fair_baselines.py` -> to exploit), UWCA within 0.02 SER.
`rev2/data/e1_fair_baselines.json` -> `fig/fig_fair.pdf` (manuscript - **Artifacts.** `experiments/e1_fair_baselines.py` ->
Fig. 3). Trained checkpoints `e1_uwca_{HIGH,LOW,MIX}.pt` (reused by E4/E6). `experiments/data/e1_fair_baselines.json` -> `fig/fig_fair.pdf`
(manuscript Fig. 3). Trained checkpoints `e1_uwca_{HIGH,LOW,MIX}.pt`
(reused by E4/E6).
## E2 — Full complex-baseband phase errors and CSI error ## E2 — Full complex-baseband phase errors and CSI error
*Reviewer concerns: R1-1 (phase model underestimates IUI), R2-3 (CSI).*
- **Question.** Does the multi-user superposition amplify residual phase - **Question.** Does the multi-user superposition amplify residual phase
errors into severe inter-user interference once nothing is absorbed into a errors into severe inter-user interference once every leakage path is
noise term? simulated explicitly?
- **Setup.** Complex channel with per-user residual dphi_u ~ N(0, sigma^2), - **Setup.** Complex channel with per-user residual dphi_u ~ N(0, sigma^2),
sigma in {0,5,10,15,20,30} deg; both rails simulated so every leakage path sigma in {0,5,10,15,20,30} deg; both rails simulated. Three decoders:
exists. Three decoders: mismatch-trained (never saw phase errors), mismatch-trained (never saw phase errors), phase-augmented (trained with
phase-augmented (trained with sigma ~ U[0,20] deg), and a two-rail variant sigma ~ U[0,20] deg), and a two-rail variant whose keys/values read
whose keys/values read [Re;Im] (2d input). CSI sweep: amplitude error [Re;Im]. CSI sweep: amplitude error h_hat = h(1+eps),
h_hat = h(1+eps), eps ~ N(0, sigma_h^2), sigma_h up to 0.2, at 10 deg. eps ~ N(0, sigma_h^2), sigma_h up to 0.2, at 10 deg. The learned-mask
Learned-mask overlap (mean pairwise cosine) is also measured. overlap (mean pairwise cosine) is also measured.
- **Key results.** Mismatch-trained @10 dB: SER 0.270 -> 0.291 (20 deg) -> - **Key results.** Mismatch-trained @10 dB: SER 0.270 -> 0.291 (20 deg) ->
0.332 (30 deg); @20 dB 0.110 -> 0.127; augmentation and I/Q reading change 0.332 (30 deg); @20 dB 0.110 -> 0.127; augmentation and I/Q reading
curves by less than Monte Carlo spread -> leakage is second order because change the curves by less than the Monte Carlo spread. The leakage is
it scales with sin(dphi) x mask overlap (measured 0.26). CSI: UWCA second order because it scales with sin(dphi) times the mask overlap
unchanged within 0.004 (uses no explicit CSI). (measured 0.26). CSI: UWCA unchanged within 0.004 (it uses no explicit
- **Artifacts.** `rev2/e2_phase_iui.py` -> `rev2/data/e2_phase_iui.json`; CSI).
`fig/fig_phase2.pdf` (repo; numbers narrated in manuscript Sec. VII-E). - **Artifacts.** `experiments/e2_phase_iui.py` ->
`experiments/data/e2_phase_iui.json`; `fig/fig_phase2.pdf`.
## E3 — Dynamic user population ## E3 — Dynamic user population
*Reviewer concerns: R1-6 (fixed U, costly retraining), R2-3 (fixed
identities).*
- **Setup.** U_max = 8 mask slots (d=64, 8 dims/slot), HIGH-type correlation - **Question.** Does a decoder provisioned for U_max users need retraining
(beta_u = 0.6, one scene). Active set resampled per frame; inactive users when users arrive and depart?
transmit nothing and their softmax scores are masked to -inf (the - **Setup.** U_max = 8 mask slots (d=64, 8 dims/slot), high-correlation
scheduler announces the active set). Compared: one model trained with the scenario (beta_u = 0.6, one scene). The active set is resampled per
full population always active (never retrained), an activity-sampled frame; inactive users transmit nothing and their softmax scores are
model, and per-count oracle models retrained from scratch for masked out (the scheduler announces the active set). Compared: one model
trained with the full population always active (never retrained), an
activity-sampled model, and per-count models retrained from scratch for
|A| in {2,4,6,8}. Metric: mean cosine (the sqrt(1/8)=0.35 subspace |A| in {2,4,6,8}. Metric: mean cosine (the sqrt(1/8)=0.35 subspace
ceiling saturates the binary SER at this scale). ceiling saturates the binary SER at this scale).
- **Key results.** The single full-population model sustains fidelity over - **Key results.** The single full-population model sustains fidelity over
every active count (c 0.34 -> 0.39 for |A| = 2 -> 8 @10 dB) and matches or every active count (c 0.34 -> 0.39 for |A| = 2 -> 8 @10 dB) and matches
exceeds the per-count retrained models (0.33/0.32/0.36/0.39); per-count or exceeds the per-count retrained models (0.33/0.32/0.36/0.39);
retraining is counterproductive (sparse populations train each slot on a per-count retraining is counterproductive, since sparse populations train
fraction of the traffic). each slot on a fraction of the traffic.
- **Artifacts.** `rev2/e3_dynamic_users.py` -> - **Artifacts.** `experiments/e3_dynamic_users.py` ->
`rev2/data/e3_dynamic_users.json`; `fig/fig_dynusers.pdf` (repo). `experiments/data/e3_dynamic_users.json`; `fig/fig_dynusers.pdf`.
## E4 — Symbol-timing offsets (v3 = block-wise realignment) ## E4 — Symbol-timing offsets and receiver-side realignment
*Reviewer concern: R1-8 (asynchronous reception / ISI).*
- **Question.** How does the decoder behave under asynchronous reception,
and what does the standard timing-correction chain restore?
- **Setup.** Per-user integer offsets delta_u ~ U{0..Delta} symbols, - **Setup.** Per-user integer offsets delta_u ~ U{0..Delta} symbols,
Delta in {0,1,2,4,8}, shift each user's transmitted block within the Delta in {0,1,2,4,8}, shift each user's transmitted block within the
frame (edge energy lost). Conditions: uncorrected (UWCA and OFDMA), frame (edge energy lost). Conditions: uncorrected reception (UWCA and
corrected by block-wise realignment using pilot-estimated offsets OFDMA), block-wise realignment using pilot-estimated offsets (each
(each user's block region shifted back individually), and corrected with user's block region shifted back individually), and realignment with a
a deliberately impaired estimator (+-1 symbol on 20% of users). deliberately impaired estimator (+-1 symbol on 20% of users).
v1 (`e4_async` results in json) showed offset-augmented *training* cannot
repair unknown shifts; v2 showed whole-frame realignment breaks
cross-block alignment — both superseded by v3.
- **Key results.** Uncorrected offsets are catastrophic for *every* - **Key results.** Uncorrected offsets are catastrophic for *every*
embedding-level scheme (one symbol: UWCA 0.26 -> 0.73, OFDMA 0.51 -> embedding-level scheme (one symbol: UWCA 0.26 -> 0.73, OFDMA 0.51 ->
0.76) because i.i.d. embedding coordinates fully decorrelate under a 0.76), because i.i.d. embedding coordinates fully decorrelate under a
one-symbol misalignment. With realignment the degradation is gradual one-symbol misalignment — synchronization is a shared physical-layer
(0.266 -> 0.304 @Delta=1, 0.455 @Delta=8) and realigned UWCA stays below prerequisite, not a property of the multiple-access mechanism. With
realigned OFDMA (0.536-0.638) at every offset. The impaired estimator realignment the degradation is gradual (0.266 -> 0.304 @Delta=1, 0.455
costs 0.14 SER — whole-symbol residuals sacrifice the affected block, so @Delta=8) and realigned UWCA stays below realigned OFDMA (0.536-0.638)
timing must be sub-symbol (standard timing advance). at every offset. The impaired estimator costs 0.14 SER: whole-symbol
- **Artifacts.** `rev2/e4_v3_async.py` -> `rev2/data/e4_v3_async.json`; residuals sacrifice the affected block, so timing must be held to
`fig/fig_async.pdf` (repo). sub-symbol accuracy (which the closed-loop timing advance provides).
- **Artifacts.** `experiments/e4_async.py` ->
`experiments/data/e4_async.json`; `fig/fig_async.pdf`.
## E5 — Nonlinear inter-user semantic structure ## E5 — Nonlinear inter-user semantic structure
*Reviewer concerns: R1-7, R2-5, R3-2 (linear scalar model too restrictive).*
- **Question.** Does the mechanism survive when no scalar or linear
description of the inter-user dependence exists?
- **Setup.** Embeddings e_u = normalize(g_u([s; p_u])) with fixed random - **Setup.** Embeddings e_u = normalize(g_u([s; p_u])) with fixed random
two-layer tanh view networks g_u per user (seed 7): users share the scene two-layer tanh view networks g_u per user (seed 7): users share the
s only through independent nonlinear transformations. Cases: shared scene scene s only through independent nonlinear transformations. Cases:
vs independent scenes (control). Schemes: trained UWCA, OFDMA, NOMA-SIC, shared scene vs independent scenes (control). Schemes: trained UWCA,
and the scalar-parameterized genie LMMSE fed the *measured* mean pairwise OFDMA, NOMA-SIC, and the scalar-parameterized genie LMMSE fed the
cosine. *measured* mean pairwise cosine.
- **Key results.** Linear correlation is destroyed (mean cosine 0.006), so - **Key results.** The linear correlation is destroyed (mean cosine
the genie LMMSE collapses onto the ceiling (0.515 vs OFDMA 0.518 @10 dB) 0.006), so the genie LMMSE collapses onto the ceiling (0.515 vs OFDMA
— no scalar/linear receiver can represent the shared structure. UWCA 0.518 @10 dB) — no scalar or linear receiver can represent the shared
still attains 0.363 @10 dB / 0.220 @20 dB. The independent-scene control structure. UWCA still attains 0.363 @10 dB / 0.220 @20 dB. The
(UWCA 0.441) isolates the manifold-prior share, so the further reduction independent-scene control (UWCA 0.441) isolates the manifold-prior
to 0.363 is pure nonlinear cross-user structure. share, so the further reduction to 0.363 is pure nonlinear cross-user
- **Artifacts.** `rev2/e5_nonlinear.py` -> `rev2/data/e5_nonlinear.json` structure.
(numbers narrated in manuscript Sec. VII-G). - **Artifacts.** `experiments/e5_nonlinear.py` ->
`experiments/data/e5_nonlinear.json`.
## E6 — Residual orthogonality vs content preservation ## E6 — Residual orthogonality vs content preservation
*Reviewer concerns: R1-4, R2-2, R3-3 (semantic-orthogonality
self-contradiction).*
- **Question.** What exactly decorrelates at the decoder output: the
delivered content, or the errors?
- **Setup.** E1's trained HIGH decoder; per-sample Pearson correlation - **Setup.** E1's trained HIGH decoder; per-sample Pearson correlation
across the 64 dimensions, averaged over user pairs and 100x64 samples per across the 64 dimensions, averaged over user pairs and 100x64 samples
SNR, for: input embeddings, decoded embeddings, decoding residuals per SNR, for: input embeddings, decoded embeddings, and decoding
r_u = e_hat_u - e_u; OFDMA decoded correlation as reference. residuals r_u = e_hat_u - e_u; OFDMA decoded correlation as reference.
- **Key results.** Decoded-embedding correlation rises with SNR from 0.31 - **Key results.** The decoded-embedding correlation rises with SNR from
toward the 0.39 input level (shared content preserved, not stripped); 0.31 toward the 0.39 input level (the shared content is delivered, not
residual correlation falls 0.23 -> 0.14 (2.8x below input) — the stripped), while the residual correlation falls 0.23 -> 0.14 (2.8x below
emergent residual orthogonality. OFDMA's decoded correlation is 0.00 at the input level) — the emergent residual orthogonality. OFDMA's decoded
every SNR: orthogonal access erases the inter-user semantic structure. correlation is 0.00 at every SNR: orthogonal access erases the
- **Artifacts.** `rev2/e6_residual_orth.py` -> inter-user semantic structure from the delivered embeddings.
`rev2/data/e6_residual_orth.json` -> `fig/fig_resorth.pdf` (manuscript - **Artifacts.** `experiments/e6_residual_orth.py` ->
Fig. 4). `experiments/data/e6_residual_orth.json` -> `fig/fig_resorth.pdf`
(manuscript Fig. 4).
## E7 — Meta-adaptation beyond the SNR axis (v2) ## E7 — Adaptation across fading families
*Reviewer concerns: R1-3, R3-4, R3-5 (MAML overkill for a 1-D lookup);
R1-9 (eta stability).*
- **Question.** Does the meta-trained initialization cover a
multi-dimensional space of operating conditions that a one-dimensional
per-SNR model bank cannot, and is the sharpness scalar stable?
- **Setup.** Task family = 6 SNRs x {Rayleigh, Rician K=5 dB, K=10 dB} x - **Setup.** Task family = 6 SNRs x {Rayleigh, Rician K=5 dB, K=10 dB} x
phase residual {0,10} deg (36 tasks). Systems: one initialization phase residual {0,10} deg (36 tasks). Systems: one initialization
meta-trained over the full family (300 epochs, eta and outer-gradient meta-trained over the full family (300 epochs, eta and outer-gradient
norm logged every epoch); per-SNR specialist bank trained on norm logged every epoch); a per-SNR specialist bank trained on
Rayleigh/no-phase (the 1-D lookup, nearest-SNR index). Held-out tests: Rayleigh/no-phase and indexed by nearest SNR. Held-out tests: Rician
Rician K=20 dB + 15 deg (10/18 dB), Nakagami m=3 + 5 deg (a fading law in K=20 dB + 15 deg (10/18 dB), Nakagami m=3 + 5 deg (a fading law in no
no training task), Rayleigh + 20 deg @6 dB, plus an in-distribution training task), Rayleigh + 20 deg @6 dB, plus an in-distribution check;
check; zero-shot and after S in {1,5,10,20} inner steps (SGD 0.02, one zero-shot and after S in {1,5,10,20} inner steps (SGD 0.02, one
64-sample support batch). 64-sample support batch).
- **Key results.** Family initialization transfers zero-shot with 9-46% - **Key results.** The family initialization transfers zero-shot with
lower SER than the lookup on every held-out condition (e.g. 0.114 vs 9-46% lower SER than the specialist bank on every held-out condition
0.158 Rician-K20-15deg @10 dB; 0.139 vs 0.190 unseen Nakagami); inner-loop (e.g. 0.114 vs 0.158 Rician-K20-15deg @10 dB; 0.139 vs 0.190 under the
adaptation is stable (within 0.005 over 20 steps). eta converges to 0.94 unseen Nakagami law); inner-loop adaptation is stable (within 0.005 over
(max 1.00), outer gradient norm <= 0.024 vs clip bound 5 — no softmax 20 steps). eta converges to 0.94 (max 1.00) and the outer gradient norm
saturation or divergence. stays below 0.024 against a clipping bound of 5 — no softmax saturation
- **Artifacts.** `rev2/e7_v2_meta.py` -> `rev2/data/e7_v2_meta.json` or divergence.
(includes eta/gradient trajectories). - **Artifacts.** `experiments/e7_meta.py` ->
`experiments/data/e7_meta.json` (includes eta/gradient trajectories).
## E8 — End-to-end training with anti-collapse (v2) ## E8 — End-to-end training with anti-collapse regularization
*Reviewer concern: R1-5 (representation collapse prevents joint JSCC).*
- **Question.** Can the encoder be trained jointly with the decoder
without representation collapse, and what causes the collapse when it
occurs?
- **Setup.** Four configurations on HIGH: frozen encoder (reference); - **Setup.** Four configurations on HIGH: frozen encoder (reference);
naive end-to-end with the distortion measured against the encoder's own naive end-to-end with the distortion measured against the encoder's own
output (the collapse-prone moving target); source-anchored end-to-end output (a moving target); source-anchored end-to-end (distortion vs
(distortion vs normalize(x)); moving target + VICReg-style normalize(x)); moving target + a VICReg-style variance-covariance
variance-covariance regularizer (hinge at 1/sqrt(d) per-dim std, 25x regularizer (hinge at 1/sqrt(d) per-dim std, 25x variance + 100/d
variance + 100/d covariance weights). Collapse-proof metric: batch covariance weights). Collapse-proof metric: batch nearest-neighbor
nearest-neighbor retrieval accuracy over the *encoded* gallery, plus the retrieval accuracy over the *encoded* gallery, plus the effective rank
effective rank of the encoder-output covariance. of the encoder-output covariance.
- **Key results.** Naive collapses exactly as the reviewers expect: - **Key results.** The naive configuration collapses (retrieval falls to
retrieval falls to chance (0.005 vs 0.536 frozen @10 dB) the pathology chance, 0.005 vs 0.536 frozen @10 dB), locating the pathology in the
is the moving-target objective, not the cross-attention. Source anchoring moving-target objective rather than the cross-attention. Source
keeps effective rank 59.6/64 and lands within 0.04 SER of frozen; VICReg anchoring keeps effective rank 59.6 of 64 and lands within 0.04 SER of
restores retrieval to 0.509 with a learned task-specific code. E2E the frozen reference; the variance-covariance regularizer restores
training is therefore demonstrated, and the frozen encoder in the main retrieval to 0.509 with a learned task-specific code. The frozen encoder
experiments is a controlled-isolation choice. in the main experiments is therefore a controlled-isolation choice.
- **Artifacts.** `rev2/e8_v2_e2e.py` -> `rev2/data/e8_v2_e2e.json`. - **Artifacts.** `experiments/e8_e2e.py` ->
`experiments/data/e8_e2e.json`.
## E9 — Online top-k relevance acquisition and measured overhead ## E9 — Online top-k relevance acquisition and measured overhead
*Reviewer concerns: R1-2, R3-6 (circular dependency), R2-4 (cost at large
populations).*
- **Question.** How does sparse top-k attention obtain the relevance
ranking it needs, starting from no knowledge, and what does the
acquisition cost?
- **Setup.** U=32, eight relevance clusters of four, k=4, briefly trained - **Setup.** U=32, eight relevance clusters of four, k=4, briefly trained
full-attention model. Protocol: frames 1-3 full attention (needs no full-attention model. Protocol: frames 1-3 run full attention (which
relevance) while the BS accumulates beta_hat by EWMA (zeta=0.5) of needs no relevance knowledge) while the BS accumulates beta_hat by EWMA
decoded-embedding cosines; from frame 4, per-row top-k via argpartition (zeta=0.5) of decoded-embedding cosines; from frame 4, per-row top-k via
on beta_hat. References: oracle top-k (peers selected from the true argpartition on beta_hat. References: an oracle whose peers are selected
clusters) and permanent full attention. Timing: decoder forward vs from the true clusters, and permanent full attention. Timing: decoder
EWMA-update + selection wall-clock for U in {8,16,32,64,128} forward vs EWMA-update-plus-selection wall-clock for
(256-sample frames, GPU, 20-run averages). U in {8,16,32,64,128} (256-sample frames, GPU, 20-run averages).
- **Key results.** From the first post-warm-up frame the online selection - **Key results.** From the first post-warm-up frame the online selection
matches the oracle exactly and slightly exceeds full attention matches the oracle exactly and slightly exceeds full attention
(discarding irrelevant peers discards their noise); ranking needs far (discarding irrelevant peers discards their noise); ranking needs far
less accuracy than estimation because intra-cluster (~0.42) and less accuracy than estimation because intra-cluster (~0.42) and
inter-cluster (~0) cosines are well separated. Estimation + selection inter-cluster (~0) cosines are well separated. Estimation plus selection
cost 0.02-0.04 ms vs the 0.3-5.4 ms decoder pass, incurred once per cost 0.02-0.04 ms against the 0.3-5.4 ms decoder pass, incurred once per
relevance coherence interval. relevance coherence interval.
- **Artifacts.** `rev2/e9_topk_online.py` -> - **Artifacts.** `experiments/e9_topk_online.py` ->
`rev2/data/e9_topk_online.json` (trajectory + timing). `experiments/data/e9_topk_online.json` (trajectory + timing).
--- ---
## Legacy experiments (retained from the original study) ## Simulation studies (`simulation/`)
- **Three-scenario SER study** (manuscript Fig. 2): analytical simulation - **Three-scenario SER study** (manuscript Fig. 2): analytical simulation
`legacy/semantic_correlation_sim.py` + trained decoder-only overlay `simulation/semantic_correlation_sim.py` with the trained decoder-only
`legacy/maml_semantic.py --decoder_only`; threshold sweep tau in overlay from `simulation/maml_semantic.py --decoder_only`; threshold
[0.30,0.50] and mean-cosine table in `legacy/revision_experiments.py`. sweep tau in [0.30,0.50] and the mean-cosine comparison in
- **beta sweep** (monotone gain law): `legacy/revision_betasweep.py` `simulation/revision_experiments.py`.
(figure `fig/fig4_beta_sweep.pdf`, narrated in Sec. VII-C). - **beta sweep** (monotone gain law): `simulation/revision_betasweep.py`
- **Attention heatmaps**: `legacy/plot_figures.py` (figure `fig/fig4_beta_sweep.pdf`).
(figure `fig/fig6_hlm.pdf`, narrated in Sec. VII-C). - **Attention heatmaps**: `simulation/plot_figures.py`
- **Hyperparameter ablations** (S, lambda, d, H, K): (figure `fig/fig6_hlm.pdf`).
`legacy/revision_ablation.py`, `legacy/revision_dsweep.py`, - **Hyperparameter studies** (S, lambda, d, H, K):
`legacy/revision_e2e.py` (Sec. VII-D). `simulation/revision_ablation.py`, `simulation/revision_dsweep.py`,
`simulation/revision_e2e.py`.
- **Real-data study** (manuscript Fig. 5): UCI optical-recognition digits - **Real-data study** (manuscript Fig. 5): UCI optical-recognition digits
(8x8=64 dims), `legacy/revision_realdata_train.py` + (8x8=64 dimensions), `simulation/revision_realdata_train.py` +
`legacy/revision_realdata_plot.py` (Sec. VII-G). `simulation/revision_realdata_plot.py`.
## Reviewer-concern -> experiment map
| Concern | Experiment(s) | Manuscript |
|---|---|---|
| R1-1 phase IUI | E2 | Sec. III-A, VII-E |
| R1-2 / R3-6 top-k circularity | E9 | Sec. V-E, VII-H |
| R1-3 / R3-4 / R3-5 MAML vs lookup | E7 | Sec. V-E, VII-F |
| R1-4 / R2-2 / R3-3 orthogonality contradiction | E6 | Def. 3, Prop. 4, Fig. 4 |
| R1-5 representation collapse | E8 | Sec. VI-B |
| R1-6 dynamic U | E3 | Sec. IV-B, VII-E |
| R1-7 / R2-5 / R3-2 linear scalar model | E5 (+ real data) | Sec. III-B, VII-G |
| R1-8 asynchrony | E4 | Sec. III-A, VII-E |
| R1-9 eta stability | E7 logs | Sec. IV-A, VII-F |
| R1-10 / R3-7 d/U fairness | E1 | Prop. 3, Fig. 3, VII-B |
| R2-1 idealized proofs | assumption block + E1/E5/real data | Sec. V |
| R2-3 sync / CSI / identities / encoder | E4 / E2 / E3 / E8+E5 | Sec. III, VI-B, VII-E |
| R2-4 large-population cost | E9 timing | Sec. VII-H |
| R3-1 DSC novelty | (positioning) | Sec. II-A |
@@ -1,4 +1,4 @@
"""E1 — Degrees-of-freedom fairness (R1.10, R3.7). """E1 — Degrees-of-freedom fairness study.
Adds full-dimensional receivers on the SAME received signal: Adds full-dimensional receivers on the SAME received signal:
- lmmse_blind : optimal linear receiver with cross-user correlation set to 0 - lmmse_blind : optimal linear receiver with cross-user correlation set to 0
@@ -1,5 +1,5 @@
"""E2 — Full complex-baseband phase-error model with inter-user leakage (R1.1) """E2 — Full complex-baseband phase-error model with inter-user leakage,
plus CSI amplitude-error robustness (R2.3). plus CSI amplitude-error robustness.
Three evaluation models on HIGH: Three evaluation models on HIGH:
scalar : real channel, per-user cos(dphi) attenuation only (old model) scalar : real channel, per-user cos(dphi) attenuation only (old model)
@@ -1,4 +1,4 @@
"""E3 — Dynamic user arrivals/departures (R1.6, R2.3). """E3 — Dynamic user arrivals and departures.
U_max = 8 mask slots, d = 64. Activity-aware meta-training samples a random U_max = 8 mask slots, d = 64. Activity-aware meta-training samples a random
active subset each batch; at inference the attention softmax is restricted to active subset each batch; at inference the attention softmax is restricted to
@@ -1,4 +1,4 @@
"""E4 v3 — Timing offsets with BLOCK-WISE receiver realignment (R1.8). """E4 — Symbol-timing offsets with block-wise receiver realignment.
The BS knows the per-user timing estimates (pilot-based) and realigns each The BS knows the per-user timing estimates (pilot-based) and realigns each
user's block region individually inside the single received frame: user's block region individually inside the single received frame:
@@ -88,7 +88,7 @@ for label, mode, ep in [("uwca_uncorrected", "uwca_unc", 0.0),
for snr in out["snr_eval"]: for snr in out["snr_eval"]:
cur[str(snr)] = [evaluate(mode, dm, snr, ep) for dm in dgrid] cur[str(snr)] = [evaluate(mode, dm, snr, ep) for dm in dgrid]
out["curves"][label] = cur out["curves"][label] = cur
print(f"[E4v3] {label} 10dB SER: " print(f"[E4] {label} 10dB SER: "
f"{[round(a[0],3) for a in cur['10.0']]}", flush=True) f"{[round(a[0],3) for a in cur['10.0']]}", flush=True)
save_json("e4_v3_async.json", out) save_json("e4_async.json", out)
@@ -1,4 +1,4 @@
"""E5 — Nonlinear inter-user semantic structure (R1.7, R2.5, R3.2). """E5 — Nonlinear inter-user semantic structure.
Embeddings are produced by fixed random per-user nonlinear view networks Embeddings are produced by fixed random per-user nonlinear view networks
e_u = normalize(g_u([kappa*s ; p_u])), so the inter-user dependence is e_u = normalize(g_u([kappa*s ; p_u])), so the inter-user dependence is
@@ -1,4 +1,4 @@
"""E6 — Residual (error) orthogonality vs. content preservation (R1.4, R3.3, R2.2). """E6 — Residual (error) orthogonality vs. content preservation.
Resolves the claimed contradiction: the decoded embeddings PRESERVE the shared Resolves the claimed contradiction: the decoded embeddings PRESERVE the shared
scene correlation (rho(e_hat_u, e_hat_v) tracks beta_uv), while the decoding scene correlation (rho(e_hat_u, e_hat_v) tracks beta_uv), while the decoding
@@ -1,5 +1,5 @@
"""E7 v2 — Meta-training over the multi-dimensional task family, OOD transfer, """E7 — Meta-training over a multi-dimensional task family: held-out
adaptation sweep, and eta/gradient logging. transfer, adaptation sweep, and eta/gradient logging.
meta : the paper's first-order meta-training aggregated over the FULL meta : the paper's first-order meta-training aggregated over the FULL
36-task family (SNR x {Rayleigh, Rician K=5,10 dB} x phase {0,10 deg}) 36-task family (SNR x {Rayleigh, Rician K=5,10 dB} x phase {0,10 deg})
@@ -35,15 +35,15 @@ family = [{"snr_db": s, "phase_sigma_deg": p, **f}
eta_log = [] eta_log = []
m_meta = UWCA(d, U, H).to(DEVICE) m_meta = UWCA(d, U, H).to(DEVICE)
train_multitask(m_meta, gen, family, epochs=300, tag="E7v2-meta", train_multitask(m_meta, gen, family, epochs=300, tag="E7-meta",
log_state=eta_log) log_state=eta_log)
torch.save(m_meta.state_dict(), lib.DATA / "e7v2_meta.pt") torch.save(m_meta.state_dict(), lib.DATA / "e7_meta.pt")
specialists = {} specialists = {}
for s in snrs: for s in snrs:
m = UWCA(d, U, H).to(DEVICE) m = UWCA(d, U, H).to(DEVICE)
train_multitask(m, gen, [{"snr_db": s}], epochs=150, train_multitask(m, gen, [{"snr_db": s}], epochs=150,
tag=f"E7v2-spec{int(s)}") tag=f"E7-spec{int(s)}")
specialists[s] = m specialists[s] = m
@@ -78,7 +78,7 @@ for name, t in test_tasks.items():
sers.append({"ser": s, "cos": c}) sers.append({"ser": s, "cos": c})
row[label] = sers row[label] = sers
out["results"][name] = row out["results"][name] = row
print(f"[E7v2] {name}: meta={[round(x['ser'],3) for x in row['meta']]} " print(f"[E7] {name}: meta={[round(x['ser'],3) for x in row['meta']]} "
f"lookup={[round(x['ser'],3) for x in row['lookup']]}", flush=True) f"lookup={[round(x['ser'],3) for x in row['lookup']]}", flush=True)
etas = [e["eta"] for e in eta_log] etas = [e["eta"] for e in eta_log]
@@ -87,7 +87,7 @@ out["eta_traj"] = etas[::5]
out["gnorm_traj"] = gns[::5] out["gnorm_traj"] = gns[::5]
out["eta_final"], out["eta_max"] = etas[-1], max(etas) out["eta_final"], out["eta_max"] = etas[-1], max(etas)
out["gnorm_max"] = max(gns) out["gnorm_max"] = max(gns)
print(f"[E7v2] eta final={etas[-1]:.3f} max={max(etas):.3f} " print(f"[E7] eta final={etas[-1]:.3f} max={max(etas):.3f} "
f"gnorm max={max(gns):.3f}", flush=True) f"gnorm max={max(gns):.3f}", flush=True)
save_json("e7_v2_meta.json", out) save_json("e7_meta.json", out)
+4 -4
View File
@@ -1,4 +1,4 @@
"""E8 v2 — End-to-end joint encoder-decoder training (R1.5), source-anchored. """E8 — End-to-end joint encoder-decoder training, source-anchored metrics.
All fidelity metrics are measured against the SOURCE embedding normalize(x), All fidelity metrics are measured against the SOURCE embedding normalize(x),
never against the trainable encoder output (a moving target that makes never against the trainable encoder output (a moving target that makes
@@ -69,7 +69,7 @@ def train(mode, epochs=300):
torch.nn.utils.clip_grad_norm_(model.parameters(), 5.0) torch.nn.utils.clip_grad_norm_(model.parameters(), 5.0)
opt.step() opt.step()
if ep % 75 == 0: if ep % 75 == 0:
print(f" [E8v2-{mode}] ep {ep}/{epochs} " print(f" [E8-{mode}] ep {ep}/{epochs} "
f"loss={float(loss)/len(snrs):.4f}", flush=True) f"loss={float(loss)/len(snrs):.4f}", flush=True)
return model, enc return model, enc
@@ -119,7 +119,7 @@ for mode in ["frozen", "e2e_moving", "e2e_anchored", "e2e_vicreg"]:
erank = collapse_metrics(enc) erank = collapse_metrics(enc)
ss, cc, rr = curves(model, enc) ss, cc, rr = curves(model, enc)
out["configs"][mode] = {"ser": ss, "cos": cc, "retr": rr, "erank": erank} out["configs"][mode] = {"ser": ss, "cos": cc, "retr": rr, "erank": erank}
print(f"[E8v2] {mode}: erank={erank:.1f} SER@10={ss[5]:.3f} " print(f"[E8] {mode}: erank={erank:.1f} SER@10={ss[5]:.3f} "
f"cos@10={cc[5]:.3f} retr@10={rr[5]:.3f}", flush=True) f"cos@10={cc[5]:.3f} retr@10={rr[5]:.3f}", flush=True)
save_json("e8_v2_e2e.json", out) save_json("e8_e2e.json", out)
@@ -1,5 +1,5 @@
"""E9 — Online relevance acquisition for sparse top-k attention (R1.2, R3.6) """E9 — Online relevance acquisition for sparse top-k attention and measured
and measured selection/sorting overhead (R2.4). selection overhead.
Protocol (U=32, 8 clusters of 4, k=4): Protocol (U=32, 8 clusters of 4, k=4):
frames 1..3 : full attention; the BS estimates beta_hat from the decoded frames 1..3 : full attention; the BS estimates beta_hat from the decoded
+1 -1
View File
@@ -1,5 +1,5 @@
""" """
Shared library for TWC revision-2 experiments (new submission). Shared library for the UWCA semantic multiple access studies.
Single-signal uplink model matching the manuscript: Single-signal uplink model matching the manuscript:
y = sum_v g_v (e_v m_v) + n, g_v = |h_v| e^{jΔφ_v} y = sum_v g_v (e_v m_v) + n, g_v = |h_v| e^{jΔφ_v}
All experiments import from here. Seed fixed = 42. All experiments import from here. Seed fixed = 42.
+158 -158
View File
@@ -1,158 +1,158 @@
"""Generate the five new revision figures from data/*.json into ../Relevance_TWCOM_R2/fig/. """Regenerate the figure PDFs from data/*.json into ../fig/.
Uniform geometry: 8:6 axes box, shared rcParams, no tight bounding box. Uniform geometry: 8:6 axes box, shared rcParams, no tight bounding box.
""" """
import json import json
from pathlib import Path from pathlib import Path
import matplotlib import matplotlib
matplotlib.use("Agg") matplotlib.use("Agg")
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import numpy as np import numpy as np
HERE = Path(__file__).resolve().parent HERE = Path(__file__).resolve().parent
DATA = HERE / "data" DATA = HERE / "data"
FIG = HERE.parent / "Relevance_TWCOM_R2" / "fig" FIG = HERE.parent / "fig"
FIG.mkdir(exist_ok=True) FIG.mkdir(exist_ok=True)
plt.rcParams.update({ plt.rcParams.update({
"font.size": 9, "axes.labelsize": 10, "axes.titlesize": 10, "font.size": 9, "axes.labelsize": 10, "axes.titlesize": 10,
"legend.fontsize": 7.5, "xtick.labelsize": 8.5, "ytick.labelsize": 8.5, "legend.fontsize": 7.5, "xtick.labelsize": 8.5, "ytick.labelsize": 8.5,
"lines.linewidth": 1.4, "lines.markersize": 4.5, "lines.linewidth": 1.4, "lines.markersize": 4.5,
"figure.dpi": 200, "savefig.dpi": 300, "figure.dpi": 200, "savefig.dpi": 300,
"grid.alpha": 0.35, "axes.grid": True, "grid.alpha": 0.35, "axes.grid": True,
}) })
AXRECT = [0.17, 0.165, 0.79, 0.80] # single panel 8:6-ish AXRECT = [0.17, 0.165, 0.79, 0.80] # single panel 8:6-ish
FSIZE = (3.5, 2.75) FSIZE = (3.5, 2.75)
def newfig(): def newfig():
f = plt.figure(figsize=FSIZE) f = plt.figure(figsize=FSIZE)
ax = f.add_axes(AXRECT) ax = f.add_axes(AXRECT)
return f, ax return f, ax
def save(f, name, axes=None): def save(f, name, axes=None):
f.canvas.draw() f.canvas.draw()
if axes: if axes:
for ax in axes: for ax in axes:
for lbl in [ax.xaxis.label, ax.yaxis.label]: for lbl in [ax.xaxis.label, ax.yaxis.label]:
bb = lbl.get_window_extent() bb = lbl.get_window_extent()
fw, fh = f.canvas.get_width_height() fw, fh = f.canvas.get_width_height()
assert bb.x0 >= -1 and bb.y0 >= -1 and bb.x1 <= fw + 1 \ assert bb.x0 >= -1 and bb.y0 >= -1 and bb.x1 <= fw + 1 \
and bb.y1 <= fh + 1, f"label clipped in {name}" and bb.y1 <= fh + 1, f"label clipped in {name}"
f.savefig(FIG / name) f.savefig(FIG / name)
plt.close(f) plt.close(f)
print("saved", FIG / name) print("saved", FIG / name)
C = {"ofdma": "#546E7A", "blind": "#8D6E63", "noma": "#E65100", C = {"ofdma": "#546E7A", "blind": "#8D6E63", "noma": "#E65100",
"uwca": "#1565C0", "genie": "#2E7D32", "extra": "#C62828", "uwca": "#1565C0", "genie": "#2E7D32", "extra": "#C62828",
"aux": "#6A1B9A"} "aux": "#6A1B9A"}
# ---------------------------------------------------------------- fig_fair -- # ---------------------------------------------------------------- fig_fair --
# axes box kept at 2.59 x 2.12 in; panel tags "(a)"/"(b)" BELOW the panels # axes box kept at 2.59 x 2.12 in; panel tags "(a)"/"(b)" BELOW the panels
d = json.load(open(DATA / "e1_fair_baselines.json")) d = json.load(open(DATA / "e1_fair_baselines.json"))
snr = d["snr"] snr = d["snr"]
FH = 3.10 # taller canvas for below-axis tags FH = 3.10 # taller canvas for below-axis tags
AXH = 2.12 / FH AXH = 2.12 / FH
AXB = 0.86 / FH AXB = 0.86 / FH
f = plt.figure(figsize=(7.1, FH)) f = plt.figure(figsize=(7.1, FH))
axs = [f.add_axes([0.115, AXB, 0.365, AXH]), axs = [f.add_axes([0.115, AXB, 0.365, AXH]),
f.add_axes([0.615, AXB, 0.365, AXH])] f.add_axes([0.615, AXB, 0.365, AXH])]
for ax, sc, ttl in zip(axs, ["HIGH", "MIX"], ["(a) HIGH", "(b) MIX"]): for ax, sc, ttl in zip(axs, ["HIGH", "MIX"], ["(a) HIGH", "(b) MIX"]):
v = d["scenarios"][sc] v = d["scenarios"][sc]
ax.semilogy(snr, v["ofdma"]["ser"], "s--", color=C["ofdma"], label="OFDMA") ax.semilogy(snr, v["ofdma"]["ser"], "s--", color=C["ofdma"], label="OFDMA")
ax.semilogy(snr, v["lmmse_blind"]["ser"], "v-", color=C["blind"], ax.semilogy(snr, v["lmmse_blind"]["ser"], "v-", color=C["blind"],
markevery=(1, 2), label="LMMSE-blind") markevery=(1, 2), label="LMMSE-blind")
ax.semilogy(snr, v["noma"]["ser"], "^-.", color=C["noma"], label="NOMA-SIC") ax.semilogy(snr, v["noma"]["ser"], "^-.", color=C["noma"], label="NOMA-SIC")
ax.semilogy(snr, v["uwca"]["ser"], "o-", color=C["uwca"], label="UWCA (prop.)") ax.semilogy(snr, v["uwca"]["ser"], "o-", color=C["uwca"], label="UWCA (prop.)")
ax.semilogy(snr, v["lmmse_genie"]["ser"], "d:", color=C["genie"], ax.semilogy(snr, v["lmmse_genie"]["ser"], "d:", color=C["genie"],
label="LMMSE-genie") label="LMMSE-genie")
ax.set_xlabel("SNR (dB)") ax.set_xlabel("SNR (dB)")
ax.set_ylabel("SER") ax.set_ylabel("SER")
ax.set_xlim(0, 20) ax.set_xlim(0, 20)
ax.text(0.5, -0.31, ttl, transform=ax.transAxes, ax.text(0.5, -0.31, ttl, transform=ax.transAxes,
ha="center", va="top", fontsize=10) ha="center", va="top", fontsize=10)
axs[1].legend(loc="lower left", framealpha=0.9, fontsize=7) axs[1].legend(loc="lower left", framealpha=0.9, fontsize=7)
save(f, "fig_fair.pdf", axs) save(f, "fig_fair.pdf", axs)
# -------------------------------------------------------------- fig_resorth -- # -------------------------------------------------------------- fig_resorth --
d = json.load(open(DATA / "e6_residual_orth.json")) d = json.load(open(DATA / "e6_residual_orth.json"))
snr = d["snr"] snr = d["snr"]
f, ax = newfig() f, ax = newfig()
ax.plot(snr, d["uwca"]["rho_input"], "k--", label=r"input $\rho(\mathbf{e}_u,\mathbf{e}_v)$") ax.plot(snr, d["uwca"]["rho_input"], "k--", label=r"input $\rho(\mathbf{e}_u,\mathbf{e}_v)$")
ax.plot(snr, d["uwca"]["rho_decoded"], "o-", color=C["uwca"], ax.plot(snr, d["uwca"]["rho_decoded"], "o-", color=C["uwca"],
label=r"UWCA decoded $\rho(\hat{\mathbf{e}}_u,\hat{\mathbf{e}}_v)$") label=r"UWCA decoded $\rho(\hat{\mathbf{e}}_u,\hat{\mathbf{e}}_v)$")
ax.plot(snr, d["uwca"]["rho_residual"], "s-", color=C["extra"], ax.plot(snr, d["uwca"]["rho_residual"], "s-", color=C["extra"],
label=r"UWCA residual $\rho(\mathbf{r}_u,\mathbf{r}_v)$") label=r"UWCA residual $\rho(\mathbf{r}_u,\mathbf{r}_v)$")
ax.plot(snr, d["ofdma"]["rho_decoded"], "^:", color=C["ofdma"], ax.plot(snr, d["ofdma"]["rho_decoded"], "^:", color=C["ofdma"],
label=r"OFDMA decoded") label=r"OFDMA decoded")
ax.set_xlabel("SNR (dB)") ax.set_xlabel("SNR (dB)")
ax.set_ylabel("Pearson correlation") ax.set_ylabel("Pearson correlation")
ax.set_xlim(0, 20) ax.set_xlim(0, 20)
ax.set_ylim(-0.05, 0.62) ax.set_ylim(-0.05, 0.62)
ax.legend(loc="upper right", framealpha=0.9, fontsize=6.8) ax.legend(loc="upper right", framealpha=0.9, fontsize=6.8)
save(f, "fig_resorth.pdf", [ax]) save(f, "fig_resorth.pdf", [ax])
# --------------------------------------------------------------- fig_phase2 -- # --------------------------------------------------------------- fig_phase2 --
d = json.load(open(DATA / "e2_phase_iui.json")) d = json.load(open(DATA / "e2_phase_iui.json"))
sg = d["sigma_phi_deg"] sg = d["sigma_phi_deg"]
f, ax = newfig() f, ax = newfig()
sty = {"complexI_zerotrain": ("o-", C["uwca"], "mismatch-trained"), sty = {"complexI_zerotrain": ("o-", C["uwca"], "mismatch-trained"),
"complexI_augtrain": ("s--", C["genie"], "phase-augmented"), "complexI_augtrain": ("s--", C["genie"], "phase-augmented"),
"complexIQ_iqtrain": ("^:", C["extra"], "two-rail (I/Q)")} "complexIQ_iqtrain": ("^:", C["extra"], "two-rail (I/Q)")}
for key, (mk, col, lab) in sty.items(): for key, (mk, col, lab) in sty.items():
ax.plot(sg, d["curves"][key]["10.0"]["ser"], mk, color=col, label=lab) ax.plot(sg, d["curves"][key]["10.0"]["ser"], mk, color=col, label=lab)
for key, (mk, col, lab) in sty.items(): for key, (mk, col, lab) in sty.items():
ax.plot(sg, d["curves"][key]["20.0"]["ser"], mk, color=col, alpha=0.45, ax.plot(sg, d["curves"][key]["20.0"]["ser"], mk, color=col, alpha=0.45,
label="_nolegend_") label="_nolegend_")
ax.annotate("10 dB", xy=(1.5, 0.29), fontsize=8) ax.annotate("10 dB", xy=(1.5, 0.29), fontsize=8)
ax.annotate("20 dB", xy=(1.5, 0.135), fontsize=8) ax.annotate("20 dB", xy=(1.5, 0.135), fontsize=8)
ax.set_xlabel(r"phase residual $\sigma_\varphi$ (deg)") ax.set_xlabel(r"phase residual $\sigma_\varphi$ (deg)")
ax.set_ylabel("SER") ax.set_ylabel("SER")
ax.set_ylim(0.0, 0.45) ax.set_ylim(0.0, 0.45)
ax.legend(loc="upper left", framealpha=0.9, fontsize=7) ax.legend(loc="upper left", framealpha=0.9, fontsize=7)
save(f, "fig_phase2.pdf", [ax]) save(f, "fig_phase2.pdf", [ax])
# ---------------------------------------------------------------- fig_async -- # ---------------------------------------------------------------- fig_async --
d = json.load(open(DATA / "e4_v3_async.json")) d = json.load(open(DATA / "e4_async.json"))
dm = d["dmax"] dm = d["dmax"]
f, ax = newfig() f, ax = newfig()
cur = d["curves"] cur = d["curves"]
ax.plot(dm, [a[0] for a in cur["uwca_uncorrected"]["10.0"]], "o--", ax.plot(dm, [a[0] for a in cur["uwca_uncorrected"]["10.0"]], "o--",
color=C["uwca"], alpha=0.5, label="UWCA, uncorrected") color=C["uwca"], alpha=0.5, label="UWCA, uncorrected")
ax.plot(dm, [a[0] for a in cur["ofdma_uncorrected"]["10.0"]], "s--", ax.plot(dm, [a[0] for a in cur["ofdma_uncorrected"]["10.0"]], "s--",
color=C["ofdma"], alpha=0.5, label="OFDMA, uncorrected") color=C["ofdma"], alpha=0.5, label="OFDMA, uncorrected")
ax.plot(dm, [a[0] for a in cur["uwca_corrected"]["10.0"]], "o-", ax.plot(dm, [a[0] for a in cur["uwca_corrected"]["10.0"]], "o-",
color=C["uwca"], label="UWCA, realigned") color=C["uwca"], label="UWCA, realigned")
ax.plot(dm, [a[0] for a in cur["ofdma_corrected"]["10.0"]], "s-", ax.plot(dm, [a[0] for a in cur["ofdma_corrected"]["10.0"]], "s-",
color=C["ofdma"], label="OFDMA, realigned") color=C["ofdma"], label="OFDMA, realigned")
ax.plot(dm, [a[0] for a in cur["uwca_corrected_err20"]["10.0"]], "^-.", ax.plot(dm, [a[0] for a in cur["uwca_corrected_err20"]["10.0"]], "^-.",
color=C["extra"], label="UWCA, realigned (20% est. err.)") color=C["extra"], label="UWCA, realigned (20% est. err.)")
ax.set_xlabel(r"maximum timing offset $\Delta$ (symbols)") ax.set_xlabel(r"maximum timing offset $\Delta$ (symbols)")
ax.set_ylabel("SER") ax.set_ylabel("SER")
ax.set_ylim(0, 1.05) ax.set_ylim(0, 1.05)
ax.legend(loc="lower right", ncol=2, framealpha=0.9, fontsize=6.0) ax.legend(loc="lower right", ncol=2, framealpha=0.9, fontsize=6.0)
save(f, "fig_async.pdf", [ax]) save(f, "fig_async.pdf", [ax])
# ------------------------------------------------------------- fig_dynusers -- # ------------------------------------------------------------- fig_dynusers --
d = json.load(open(DATA / "e3_dynamic_users.json")) d = json.load(open(DATA / "e3_dynamic_users.json"))
ks = d["k"] ks = d["k"]
f = plt.figure(figsize=FSIZE) f = plt.figure(figsize=FSIZE)
ax = f.add_axes([0.20, 0.165, 0.76, 0.80]) ax = f.add_axes([0.20, 0.165, 0.76, 0.80])
ax.plot(ks, [a[1] for a in d["fixed8"]["10.0"]], "o-", color=C["uwca"], ax.plot(ks, [a[1] for a in d["fixed8"]["10.0"]], "o-", color=C["uwca"],
label="single model, 10 dB") label="single model, 10 dB")
ax.plot(ks, [a[1] for a in d["fixed8"]["20.0"]], "o--", color=C["uwca"], ax.plot(ks, [a[1] for a in d["fixed8"]["20.0"]], "o--", color=C["uwca"],
alpha=0.5, label="single model, 20 dB") alpha=0.5, label="single model, 20 dB")
ok = sorted(int(k) for k in d["oracle"]) ok = sorted(int(k) for k in d["oracle"])
ax.plot(ok, [d["oracle"][str(k)]["10.0"][1] for k in ok], "s", ls="none", ax.plot(ok, [d["oracle"][str(k)]["10.0"][1] for k in ok], "s", ls="none",
color=C["extra"], label="per-count retrained, 10 dB") color=C["extra"], label="per-count retrained, 10 dB")
ax.plot(ok, [d["oracle"][str(k)]["20.0"][1] for k in ok], "s", ls="none", ax.plot(ok, [d["oracle"][str(k)]["20.0"][1] for k in ok], "s", ls="none",
mfc="none", color=C["extra"], label="per-count retrained, 20 dB") mfc="none", color=C["extra"], label="per-count retrained, 20 dB")
ax.set_xlabel(r"number of active users $|\mathcal{A}|$") ax.set_xlabel(r"number of active users $|\mathcal{A}|$")
ax.set_ylabel(r"mean cosine $\bar{c}$") ax.set_ylabel(r"mean cosine $\bar{c}$")
ax.set_ylim(0.28, 0.47) ax.set_ylim(0.28, 0.47)
ax.legend(loc="upper left", framealpha=0.9, fontsize=6.8) ax.legend(loc="upper left", framealpha=0.9, fontsize=6.8)
save(f, "fig_dynusers.pdf", [ax]) save(f, "fig_dynusers.pdf", [ax])
print("ALL FIGURES DONE") print("ALL FIGURES DONE")
-151
View File
@@ -1,151 +0,0 @@
{
"dmax": [
0,
1,
2,
4,
8
],
"snr_eval": [
10.0,
20.0
],
"sync_trained": {
"10.0": [
[
0.2683203125,
0.49533248856663703
],
[
0.7208984375,
0.242251892760396
],
[
0.83734375,
0.15587599329650403
],
[
0.91517578125,
0.09062198633328081
],
[
0.95876953125,
0.0465814154734835
]
],
"20.0": [
[
0.10884765625,
0.5421956545114517
],
[
0.65294921875,
0.2639770006388426
],
[
0.79462890625,
0.1728138119354844
],
[
0.8930859375,
0.09787379436194897
],
[
0.94958984375,
0.048505370183847846
]
]
},
"aug_trained": {
"10.0": [
[
0.61974609375,
0.4028245759010315
],
[
0.80044921875,
0.20371038138866424
],
[
0.8644921875,
0.14209178265184164
],
[
0.91814453125,
0.08969146355986596
],
[
0.95642578125,
0.05853485576808452
]
],
"20.0": [
[
0.50931640625,
0.4357883331179619
],
[
0.7403515625,
0.22275549590587615
],
[
0.82765625,
0.15037441711872815
],
[
0.8998046875,
0.09680132243782281
],
[
0.94701171875,
0.06260592238977551
]
]
},
"ofdma": {
"10.0": [
[
0.508203125,
0.4361314806342125
],
[
0.76318359375,
0.21654599383473397
],
[
0.84802734375,
0.14174282837659122
],
[
0.91091796875,
0.08382582331076265
],
[
0.9557421875,
0.043560955775901675
]
],
"20.0": [
[
0.32919921875,
0.48276128739118573
],
[
0.68083984375,
0.23667482212185859
],
[
0.79951171875,
0.15432738859206438
],
[
0.88361328125,
0.09289443053305149
],
[
0.94376953125,
0.04812081384472549
]
]
}
}
-245
View File
@@ -1,245 +0,0 @@
{
"dmax": [
0,
1,
2,
4,
8
],
"snr_eval": [
10.0,
20.0
],
"curves": {
"uwca_uncorrected": {
"10.0": [
[
0.26302734375,
0.49663727134466173
],
[
0.72521484375,
0.24080994725227356
],
[
0.83720703125,
0.1565597005933523
],
[
0.9140234375,
0.09298811599612236
],
[
0.95828125,
0.045774847799912095
]
],
"20.0": [
[
0.1059765625,
0.5424016201496125
],
[
0.64892578125,
0.2658117674291134
],
[
0.79361328125,
0.1722280565276742
],
[
0.89083984375,
0.09743562746793032
],
[
0.94720703125,
0.051459523779340086
]
]
},
"ofdma_uncorrected": {
"10.0": [
[
0.50865234375,
0.43710263311862946
],
[
0.76029296875,
0.2157912875711918
],
[
0.8459375,
0.14081338860094547
],
[
0.9133984375,
0.08355670671910048
],
[
0.9558984375,
0.04483862698078155
]
],
"20.0": [
[
0.3259765625,
0.4835157571732998
],
[
0.68376953125,
0.23547276966273784
],
[
0.7949609375,
0.1552288055792451
],
[
0.886640625,
0.09062881361693144
],
[
0.94580078125,
0.04779002937488258
]
]
},
"uwca_corrected": {
"10.0": [
[
0.2655859375,
0.49615009009838107
],
[
0.44373046875,
0.4498268289864063
],
[
0.5089453125,
0.4324074760079384
],
[
0.578828125,
0.4135142582654953
],
[
0.6497265625,
0.38951330006122586
]
],
"20.0": [
[
0.11287109375,
0.5400555384159088
],
[
0.30025390625,
0.4892691922187805
],
[
0.38263671875,
0.46662179097533224
],
[
0.4680078125,
0.4436407870054245
],
[
0.56431640625,
0.41600462675094607
]
]
},
"ofdma_corrected": {
"10.0": [
[
0.50662109375,
0.4369038107991219
],
[
0.53580078125,
0.42834869906306267
],
[
0.55255859375,
0.42323953911662104
],
[
0.58455078125,
0.41399665489792825
],
[
0.638125,
0.3948879507184029
]
],
"20.0": [
[
0.32869140625,
0.48293048948049544
],
[
0.371953125,
0.4720873585343361
],
[
0.403359375,
0.46447199031710623
],
[
0.45724609375,
0.44948955610394475
],
[
0.53859375,
0.42527498200535774
]
]
},
"uwca_corrected_err20": {
"10.0": [
[
0.26931640625,
0.49530661895871164
],
[
0.5301953125,
0.3851976223289967
],
[
0.58978515625,
0.3633556814491749
],
[
0.65712890625,
0.33998452201485635
],
[
0.7178125,
0.3151700422167778
]
],
"20.0": [
[
0.11326171875,
0.5398727428913116
],
[
0.407734375,
0.4189111949503422
],
[
0.48626953125,
0.39070201337337496
],
[
0.56044921875,
0.3684333018958569
],
[
0.64603515625,
0.33623267963528636
]
]
}
}
}
File diff suppressed because it is too large Load Diff
-107
View File
@@ -1,107 +0,0 @@
{
"snr": [
0.0,
2.0,
4.0,
6.0,
8.0,
10.0,
12.0,
14.0,
16.0,
18.0,
20.0
],
"configs": {
"frozen": {
"ser": [
0.7918229166666667,
0.685703125,
0.5696354166666666,
0.45276041666666667,
0.35044270833333335,
0.270703125,
0.2078125,
0.16442708333333333,
0.14369791666666668,
0.11671875,
0.10502604166666667
],
"cos": [
0.33901638666788736,
0.3792428519328435,
0.41583929598331454,
0.44846010764439903,
0.47460420747598014,
0.49550534566243487,
0.5113285048802694,
0.5235649347305298,
0.530758779446284,
0.5387160217761994,
0.5428356532255808
],
"erank": 63.314430236816406,
"rho_off": 0.998196005821228
},
"naive": {
"ser": [
0.00020833333333333335,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0
],
"cos": [
0.9946125821272532,
0.9967783908049266,
0.9977629196643829,
0.9983737409114838,
0.9987331410249074,
0.9989773007233937,
0.9991132164001465,
0.9992019935448965,
0.999260938167572,
0.9992937278747559,
0.9993155153592428
],
"erank": 41.47739028930664,
"rho_off": 0.999997615814209
},
"vicreg": {
"ser": [
0.7002864583333334,
0.5877083333333334,
0.45828125,
0.36255208333333333,
0.28338541666666667,
0.21833333333333332,
0.171875,
0.14651041666666667,
0.12901041666666666,
0.12166666666666667,
0.11083333333333334
],
"cos": [
0.3612262072165807,
0.40026772101720176,
0.4415491064389547,
0.4709076561530431,
0.49452649215857186,
0.5151174678405126,
0.5307369756698609,
0.5408004929622015,
0.5477419094244639,
0.5502727842330932,
0.5561861228942871
],
"erank": 34.763675689697266,
"rho_off": 0.9972559809684753
}
}
}