File size: 7,224 Bytes
2bc4b7d d8c192f 2bc4b7d d8c192f fd45d19 d8c192f 2bc4b7d d8c192f 2bc4b7d d8c192f 2bc4b7d d8c192f 2bc4b7d f2f6f18 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 | ---
license: apache-2.0
tags:
- audio
- speaker-verification
- asv
- speaker-recognition
- speaker-identification
- pytorch
- redimnet2
- voice-biometrics
language:
- en
pipeline_tag: audio-classification
---
# ReDimNet2+: Speaker Verification Model
ReDimNet2+ is a robustness-oriented adaptation of the compact ReDimNet2-B6 backbone for Automatic Speaker Verification (ASV), trained for robustness to channel and codec mismatch (compression, telephony codecs, noise, reverberation). The model uses a ReDimNet2 backbone with a Mel-spectrogram frontend and produces 192-dimensional speaker embeddings.
- **Code (training, eval, Docker submission pipeline):** [github.com/lab260ru/redimnet2-plus](https://github.com/lab260ru/redimnet2-plus)
- **Paper:** *ReDimNet2+ for Robust Speaker Verification under Channel and Codec Shift* (manuscript submitted to ICASSP 2027)
## Results
Evaluated with random 4-second windows and cosine similarity on L2-normalized embeddings (VoxCeleb1, EER %; EER<sub>p</sub> pools O/E/H; EER<sub>ph</sub> is a 26-condition codec/waveform stress test). See the paper for the full protocol and ablations.
| System | EER<sub>o</sub> | EER<sub>e</sub> | EER<sub>h</sub> | EER<sub>p</sub> | EER<sub>ph</sub> |
|---|---:|---:|---:|---:|---:|
| ReDimNet2 baseline (public ckpt.) | 1.601 | 1.725 | 3.039 | 2.420 | 7.214 |
| WeSpeaker CAM++ (best evaluated WeSpeaker ckpt.) | 0.787 | 0.928 | 1.824 | — | — |
| **ReDimNet2+ LMFT (this checkpoint)** | **0.351** | **0.523** | **1.055** | **0.824** | **1.991** |
## Model Architecture
- **Backbone**: ReDimNet2-B6
- **Embedding Dimension**: 192
- **Input**: Mel-spectrograms (64 mel bins, 10ms hop)
- **Sample Rate**: 16 kHz
- **Frontend**: Log-Mel spectrogram with 64 mel bands
- **Pooling**: ASTP (Attentive Statistics Aware Pooling)
- **Normalization**: L2 normalization on embeddings
## Usage
### Installation
```bash
pip install torch torchaudio soundfile omegaconf
```
### Loading the Model
```python
import torch
from huggingface_hub import hf_hub_download
from omegaconf import OmegaConf
# Download model weights
model_path = hf_hub_download("lab260/redimnet2-plus", "pytorch_model_fsdp.bin")
# Load checkpoint
state_dict = torch.load(model_path, map_location="cpu")
# Strip FSDP wrapper prefixes
state_dict = {
k.replace("_orig_mod.", "").replace("module.", ""): v
for k, v in state_dict.items()
}
# Model configuration
model_config = {
"encoder": {
"_target_": "asv.models.redimnet2.ReDimNet2Encoder",
"model_name": "b6",
"pretrained": False,
"train_type": "lm",
"dataset": "vox2",
"strict_load": True,
"model_overrides": {
"out_channels": 224,
"return_2d_output": False
}
},
"bridge": {
"_target_": "asv.models.bridge.IdentityBridge"
},
"classifier": {
"_target_": "asv.models.classifier.IdentityClassifier"
}
}
```
### Extracting Embeddings
```python
import torchaudio.transforms as T
def load_audio(path, sr=16000):
"""Load audio file."""
audio, sr = torchaudio.load(path)
if audio.shape[0] > 1:
audio = audio.mean(dim=0) # Convert to mono
return audio, sr
def compute_mel_spec(audio, sr=16000):
"""Compute mel-spectrogram."""
mel_transform = T.MelSpectrogram(
sample_rate=sr,
n_fft=512,
hop_length=160,
n_mels=64,
normalized=False
)
mel = mel_transform(audio.unsqueeze(0))
mel = torch.log(mel + 1e-6)
return mel
def extract_embedding(model, audio_path, device="cpu"):
"""Extract speaker embedding from audio."""
# Load and preprocess
audio, sr = load_audio(audio_path)
mel = compute_mel_spec(audio, sr)
# Add channel dim
if mel.ndim == 3:
mel = mel.unsqueeze(1)
mel = mel.to(device)
model = model.to(device)
model.eval()
with torch.no_grad():
embedding = model(mel)
embedding = torch.nn.functional.normalize(embedding, dim=1)
return embedding.cpu().squeeze(0)
# Example usage
embedding = extract_embedding(model, "audio.wav")
print(f"Embedding shape: {embedding.shape}") # [192]
```
### Speaker Verification
```python
def cosine_similarity(e1, e2):
"""Calculate cosine similarity between embeddings."""
return torch.dot(e1, e2).item()
def verify_speaker(model, audio1_path, audio2_path, threshold=0.79):
"""Verify if two audio samples are from the same speaker."""
emb1 = extract_embedding(model, audio1_path)
emb2 = extract_embedding(model, audio2_path)
similarity = cosine_similarity(emb1, emb2)
is_same = similarity >= threshold
return {
"similarity": similarity,
"is_same_speaker": is_same,
"confidence": abs(similarity - threshold)
}
```
## Model Details
- **File Format**: PyTorch state_dict (binary)
- **File Size**: ~100 MB
- **Framework**: PyTorch 2.11+
- **Key Prefix**: `_orig_mod.` (should be stripped during loading)
## Training
Full recipe and code: [github.com/lab260ru/redimnet2-plus](https://github.com/lab260ru/redimnet2-plus). Summary:
- **Initialization**: public ReDimNet2-B6 checkpoint, backbone architecture unchanged.
- **Data**: 7 corpora, ~63.9k speakers, ~4.6M utterances, ~8,675 h — VoxBlink2, VoxCeleb2, 3D-Speaker, CN-Celeb/CN-Celeb2, TidyVoice, KeSpeech.
- **Augmentation**: filters, additive noise (colored, MUSAN, RawBoost-style), simulated RIRs, speed perturbation, and codec simulation (MP3, Opus, AAC, FLAC, Vorbis, G.723.1, IMA ADPCM, G.722, A-law, μ-law, Speex, AMR-NB at 8/16 kHz), plus SpecAugment/CutMix.
- **Loss Function**: SphereFace2 (one-vs-all)
- **Optimizer**: AdamW, BFloat16, Accelerate + FSDP on 6 GPUs, gradient clipping at 20
- **Recipe**: staged multi-corpus adaptation followed by large-margin fine-tuning (LMFT) on 6-second windows (margin 0.3)
This checkpoint (`pytorch_model_fsdp.bin`) is the final **ReDimNet2+ LMFT** model from the paper.
## Retrieval reranking
The GitHub repo also ships a training-free, graph-based reranking stage (mean-chain + k-NN graph reranking with hubness correction) for open-set retrieval on top of these embeddings — see [`submission/reranking/`](https://github.com/lab260ru/redimnet2-plus/tree/main/submission/reranking). It raises VoxBlink2-subset Pr@k from 0.7413 to 0.7687 without retraining.
## Limitations
- Model expects 16 kHz audio input
- Maximum audio duration: 60 seconds
- EER roughly doubles from VoxCeleb1-E to -H (hard impostors), and the 26-condition codec/waveform stress test (EER<sub>ph</sub>) stays above the clean metrics even after LMFT — see the paper's limitations section
- External comparisons in the paper are shared-protocol, not equal-data comparisons
## Citation
```bibtex
@unpublished{borodin2027redimnet2plus,
title = {{ReDimNet2+} for Robust Speaker Verification under Channel and Codec Shift},
author = {Borodin, Kirill and Kudryavtsev, Vasiliy and Mkrchian, Grach},
year = {2026},
note = {Manuscript submitted to ICASSP 2027}
}
```
## License
This model is released under the Apache 2.0 license.
## Contact
- Email: kborodin.research@gmail.com
- Telegram: [@korallll_ai](https://t.me/korallll_ai)
|