SSL-Mamba / implementation-notes.md
korallll's picture
Wrapper code (speech-spoof-bench)
ae9d1a9 verified
|
Raw History Blame Contribute Delete
4.49 kB
# SSL-Mamba — implementation notes (2026-11-01)
Tran, Lolive, Guennec, Sini, Delhay, Marteau, "Leveraging SSL Speech Features and Mamba for Enhanced
DeepFake Detection", Interspeech 2025, pp. 5323-5327, doi 10.21437/Interspeech.2025-1703 (DOI goes in
`paper.arxiv_id`, our convention for DOI-only papers). Not XLSR-Mamba (Xiao & Das) — a different model.
## Source
- Code: github.com/hoanmyTran/spoofing_ssl_mamba @ 9afc33de7f74a9b9b3423a9028c10e1d18c1c6b8 (MIT -> `LICENSE.source`).
- Weights: HF hoanmyTran/ssl_spoofing_mamba @ 4e72dfcef4f03460e08f68a4a5fbcf3705a3414e `interspeech2025.pt`
(Apache-2.0, 1.27 GB, sha256 f468bddca22696f4e5e83fddb34669c0b400ae90f1ed34d5ef594ab5cac70534), downloaded to
`benchmarks/_ckpt_dl/hoanmyTran__ssl_spoofing_mamba/`. Pickle globals checked first (only OrderedDict,
FloatStorage, _rebuild_tensor_v2) then loaded with `weights_only=True`: flat state_dict, 580 keys.
`loss_fn.weight` ([0.1, 0.9], CrossEntropyLoss buffer) dropped -> 579 tensors -> `model.safetensors`.
- Hyper-parameters from model.py / config.yaml (confirmed by checkpoint shapes): 12 Mamba blocks d_model 128,
d_state 16, d_conv 4, expand 2 (d_inner 256, dt_rank 8); cgMLP kernels 7/15/23/31, merge 31; MHAP 4 heads,
mean+std -> 256; max_len 64600.
- Parameters: 317,521,282 (no buffers; includes XLS-R `masked_spec_embed`). `params_millions: 317.5213`.
## Edits (all inference-only; listed in `_net.py` header)
1. Lightning/torchmetrics scaffolding removed; plain nn.Module with identical submodule names -> strict load.
2. XLS-R built from `xlsr_300m_config.json` (facebook/wav2vec2-xls-r-300m config, saved locally) — no
Hub weights; front-end is fully fine-tuned and in the checkpoint. pos_conv uses the new parametrized
weight-norm keys (`parametrizations.weight.original0/1`) -> needs recent transformers (5.3.0 here).
3. `mamba_ssm.Mamba` -> `_mamba_v1.Mamba` (copied byte-identical from XLSR-Mamba-LA/: pure-PyTorch,
chunked closed-form selective scan, == `selective_scan_ref` within 1e-4 on the full net — test).
Only the plain `Mamba` mixer is used here (no Block/RMSNorm): block = Sequential(Mamba, LayerNorm),
x = x + LN(Mamba(x)), unidirectional.
4. `multiconv_cgmlp.py`, `_espnet_shim.py`, `pooling.py` copied from SSL-Feature-Gating/ (same authors;
cgMLP identical to this repo's except espnet imports -> shim). pooling.py is not in this repo.
5. inplace SiLU/SELU -> non-inplace (same values).
## Inference conventions
- Window (maintainer decision 2026-11-01): FIXED first 64,600 samples, repeat-tiled (source dataset.pad).
Deviation: the authors' eval (batch 1, no transform) scores the full variable-length utterance.
No resampling, no normalisation. FP32. `.to(device)` then `.eval()`.
- Score = log_softmax[:,1] - log_softmax[:,0] (source `_produce_evaluation_file` llr; class 1 = bona fide).
## Paper sanity targets (12 blocks, EER %)
19LA 0.11; 21LA fix 2.77 / var 1.78; 21DF fix 1.97 / var 1.51; ITW 5.12 (var).
## Results
(2026-11-01; GPUs shared with other agents' jobs, throughputs are lower bounds)
- Tests (`test_ssl_mamba.py`): 7/7 pass on both cards (pad, strict load + eval + param count, batched == single
1e-4, chunked == reference scan, determinism, sign/finite).
- PyTorch sweep (`sweep.py`): RTX 4070 Ti SUPER ~57 utt/s (plateau bs 4-32) -> `batch_size = 16`;
RTX 5060 Ti ~28.6 utt/s at bs 2-4 -> 4 (set in load()).
- TensorRT (`trt_ssl_mamba.py`, sidecar `trt_ssl-mamba.json`, class `trt_ssl_mamba:SSLMambaTRT`): FP16 failed the
build ranking check (Spearman 0.9995 / 0.9998 < 0.9999) -> **FP32** on both cards (fp16 plans deleted).
best_batch 32; 70.3 utt/s (4070 Ti S), 59.4 utt/s (5060 Ti). Build parity (64 ITW clips) Spearman 1.0000.
TRT warning "Slice ... last_affine/Pad ... incorrect fill value type" = a skipped tactic, harmless.
One ONNX kept (`ssl-mamba_RTX_4070_Ti_SUPER.onnx`; graph is card-independent).
- Full J-SPAW_LA (2,397 trials): PyTorch EER 5.875% (`results_pt/`); TRT 4070 Ti S 5.875 (Spearman 0.999999,
max |d| 0.022) (`results_trt2/`); TRT 5060 Ti 5.875 (Spearman 0.999999, max |d| 0.028) (`results_trt3/`)
-> both engines accepted.
- Full InTheWild (31,779 clips, TRT 4070 Ti S): EER 5.83% (paper 5.12% with full-utterance eval; the 4 s
window costs ~0.7 pt). No per-utterance author score files are published -> no per-clip parity check.
- `setup_lane.sh <2|3>` drove tests / PT J-SPAW / TRT export / TRT J-SPAW; `compare_scores.py` = score parity.