Work

A Federated Multimodal Attention Framework for Privacy-Aware Intracranial Haemorrhage Detection and Subtype Classification under Non-IID Data

Year: 2026
Type: software
Abstract: # FedMAF: reference implementation Executable PyTorch implementation of the paper *FedMAF: A Federated MultimodalAttention Framework for Privacy-Aware Intracranial Haemorrhage Detection andSubtype Classification under Non-IID Data*. Every table in the Results section(Tables 3, 4 and 6 to 17) is regenerated from training runs, not typed in. ## What is implemented | Paper element | Where ||---|---|| PhysioNet CT-ICH v1.3.1 indexing, 2,500 paired slices, age/sex/slice position (Table 2) | `fedmaf/data.py` || Patient-level 56/13/13 stratified split; dominant subtype with ties going to the rarer one (Sec. 3.3) | `split_patients` || Per-stratum Dirichlet client partition with rejection (Eq. 1, Table 4) | `dirichlet_partition` || x/255 input, brain+bone stacked, flip/±10° rotation/0.9–1.1 intensity augmentation (Eq. 2, Table 5) | `fedmaf/torch_data.py` || EfficientNet-B0 (ImageNet) → 64 tokens → 4 pre-LN Transformer layers, d=256, 8 heads (Eqs. 3–4) | `fedmaf/model.py` || Metadata MLP + learned null embedding (Eq. 5) | `MetaEncoder` || Pass 1 metadata→CT attention, Pass 2 conditioning gated by mᵢ, W_fuse (Eqs. 8–10) | `CrossModalFusion` || Two-stage heads (Eq. 11), U-Net decoder with skip connections (Eq. 12) | `FedMAF`, `SegDecoder` || Focal, Dice+BCE, alignment and composite losses (Eqs. 18–22) | `focal_loss`, `dice_bce`, `total_loss` || FedAvg, FedProx (μ=0.01), SCAFFOLD (option II) (Eqs. 13–14) | `fedmaf/federated.py` || Attention-aware aggregation: KL divergence, exp(−βD) weights, ρ=0.5 floor, round 1 = FedAvg (Eqs. 15–16) | `attention_weights` || Branch-wise aggregation and the missing-metadata simulation (Eq. 17, Sec. 3.6) | `aggregate` || Extra Table 7 baselines: parameter-divergence variant of Eq. 16, FedAtt, FoolsGold | `run_federated` || DP-SGD (Poisson q, per-slice clipping C, noise σC, τ=10 steps per round) | `dp_local_train` || Rényi DP accountant (Mironov 2019) with Balle et al. (2020) conversion | `fedmaf/privacy.py` || Youden/max-F1 thresholds, Stage-1/Stage-2/six-category/patient-level metrics, patient-clustered bootstrap, paired test with Holm correction (Sec. 3.9, 4.10) | `fedmaf/metrics.py` || Communication accounting (Eq. 29) | `run_federated` | ## Install ```bashpip install -r requirements.txt # a CUDA build of torch is strongly recommended``` ## Data Download **PhysioNet CT-ICH v1.3.1** (https://doi.org/10.13026/4nae-zg36) and passthe folder that contains `hemorrhage_diagnosis.csv`, `Patient_demographics.csv`and `Patients_CT/`. The first run caches the resized images in `cache/`. ## Run ```bash# 0. Check that everything works (synthetic data, CPU, a few minutes)bash smoke_test.sh # 1. Privacy accountant: reproduces the paper's ε = 1.45 and the σ column of Table 14 (no GPU, no data)python -m fedmaf.main privacy # 2. Tables 3 and 4 (no training); also writes split.json with the patient IDspython -m fedmaf.main partitions --data-root /path/to/ct-ich # 3. Training runs (results cached per run and seed in results/runs/)python -m fedmaf.main run --data-root /path/to/ct-ich --table core # FedAvg, FedProx, SCAFFOLD, FedMAF, centralizedpython -m fedmaf.main run --data-root /path/to/ct-ich --table table10 # any single tablepython -m fedmaf.main all --data-root /path/to/ct-ich # every run for every table # 4. Rebuild results/tables.md from whatever runs have finishedpython -m fedmaf.main tables --data-root /path/to/ct-ich``` Useful flags: `--seeds 0 1 2 3 4`, `--rounds 100`, `--patience 15`,`--split-file split.json` (to fix exact patient IDs), `--label-source csv`(Stage-1 label from `No_Hemorrhage` instead of mask presence),`--no-pretrained`, `--device cuda:0`, `--force`. Run `python -m fedmaf.main list`to see every named run and its configuration. **Compute budget.** One run is up to 100 rounds × 4 clients × ~1,700 slices,plus validation every round. That is roughly 30–90 minutes on a single modernGPU. The full grid is 37 configurations × 5 seeds, so start with `--table core`.DP runs are fast because each round is only 10 noisy steps per client. ## Verified without training `python -m fedmaf.main privacy` reproduces Section 3.8 exactly: for q = 0.01,σ = 1.2, 1,000 steps and δ = 10⁻⁵, it gives ε = 1.45 at order 10.9 (ε = 1.77with the classical conversion). The σ values for ε = 1, 2, 4 and 8 come out as1.513, 1.022, 0.778 and 0.616. ## Implementation choices where the paper is ambiguous - **Eq. 17 vs. Section 3.6.** Eq. 17 aggregates the image branch with plain n_k weights; only the shared/fusion parameters get attention weights w_k. The code follows Eq. 17. Use `attn_weight_img=True` in `Config` to apply w_k to the image branch as well.- **Pass 2 (Eq. 9)** is implemented with a residual, Z_CT + mᵢ·1_N(z_meta W^V W^O), so that CT information is kept in the fused tokens.- **Metadata MLP.** Table 5 says "256→128→256", but Eq. 5 has two layers on 3 inputs. The code uses 3→128→256 (GELU, dropout).- **Subtype loss.** Section 3.7 lists two options. The default is the "conditional" one the text calls more principled (`subtype_loss="all"` gives the other). Indicator-gated terms are averaged over the slices they apply to. The alignment loss uses a per-dimension mean.- **Attention summaries A_k** are accumulated during each client's local epoch, over its training slices (no validation data).- **DP.** BatchNorm statistics are frozen during DP-SGD so they cannot leak. The accountant reports ε both for T_DP = 1,000 and for the steps actually run before early stopping.- **Client accuracy (Table 12)** = the global model's Stage-1 accuracy on each client's own slices.- **ImageNet normalisation** is applied inside the encoder after Eq. 2, because the pretrained stem expects it.- **Split.** Deterministic stratified draws are repeated until all five subtypes appear in the test set, as Section 3.9 states. `--split-file` overrides this with your exact IDs.- **FedAMP and FedFomo** are personalised methods without a single global model, so they are not included in Table 7. ## Notes on the manuscript (found while implementing) These are worth checking before submission; the code will give the real values. 1. Abstract and Table 7 give 98.87% as **Stage-1** slice accuracy, but in Table 8 the Stage-1 slice accuracy is 93.8% and 98.87% is listed as Stage-2.2. With 404 test slices and 5 seeds, a mean accuracy must be a multiple of 1/2020. That makes **98.87%, 99.19% and 98.05% impossible** (the nearest attainable values are 98.86%, 99.21% and 98.07%). 97.62% and 98.31% are attainable.3. In **Table 9, four F1 values don't match their own precision and recall**: EDH 98.90 (should be 98.59), SDH 98.20 (97.89), SAH 97.60 (97.33) and IVH 98.40 (98.05).4. Section 4.9 evaluates segmentation on "n = 340 haemorrhage-positive slices from 13 patients". Table 3 has 64 ICH-positive test slices from 6 patients; 340 is the no-haemorrhage count.5. Table 16's Dice 95% CI (98.12–99.42%) is identical to the accuracy CI in the abstract, and Dice is given as a range rather than mean ± SD.6. Table 17: the last row copies the CI and p-value of the row above it. Its effect is +0.32 although centralized (99.19%) is better than federated (98.87%), so it should be −0.32.7. Table 11 lists naïve zero-filling at 97.20% and branch-wise at 96.30%, which contradicts the text ("96.30 vs 96.20" and "preserves accuracy relative to naïve zero-filling").8. Table 13: β = 0.5 and β = 1.0 have identical mean weights. The β = 0 row's macro-F1 (95.80%) differs from FedAvg in Table 7 (96.91%), although the text says β = 0 is FedAvg.9. Section 3.2.1 reports "319 slice discrepancies" between mask absence and `No_Hemorrhage`. That contradicts the preceding statement that the two correspond. `build_index` prints the actual count.10. Slice counts: Section 3.2.1 says "2,501 paired slices", but excluding 084/36 leaves 2,500 (Table 3 uses 2,500). Table 2 lists 2,500 bone images, while the text says 2,501.11. Table 7 has empty rows (FedAtt, FedAMP, FedFomo, FoolsGold). Section 4.3 says "FedAMP's weighting" where FedMAF's is meant.12. Table 8 repeats the same macro-F1 (98.42) and ROC-AUC (99.36) across all five endpoints.
Language: English
Open Access status: green
OpenAlex ID: W7225137405
Cites:
Cited by:
Related to: 10