nii-yamagishilab commited on
Commit
af5ed45
Β·
verified Β·
1 Parent(s): 8e9edbf

Update README.md

Browse files
Files changed (1) hide show
  1. README.md +197 -6
README.md CHANGED
@@ -1,9 +1,200 @@
1
  ---
2
- tags:
3
- - model_hub_mixin
4
- - pytorch_model_hub_mixin
 
 
 
 
 
 
5
  ---
6
 
7
- This model has been pushed to the Hub using the [PytorchModelHubMixin](https://huggingface.co/docs/huggingface_hub/package_reference/mixins#huggingface_hub.PyTorchModelHubMixin) integration:
8
- - Library: [More Information Needed]
9
- - Docs: [More Information Needed]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ license: cc-by-nc-sa-4.0
3
+ metrics:
4
+ - accuracy
5
+ - precision
6
+ - recall
7
+ - f1
8
+ - roc_auc
9
+ base_model:
10
+ - facebook/wav2vec2-large-960h-lv60-self
11
  ---
12
 
13
+ # πŸ” **SSL-AntiDeepfake**
14
+
15
+ The **SSL-AntiDeepfake** models are a series of self-supervised learning (SSL) models fine-tuned on multiple datasets of real and deepfake speech.
16
+ They are trained to classify speech as either "Real" 🟒 or "Fake" πŸ”΄.
17
+ | Repository | Link |
18
+ |------------|------|
19
+ | SSL-AntiDeepfake | [GitHub Repository](https://github.com/nii-yamagishilab/Ultra-SSL-AntiDeepfake) |
20
+
21
+
22
+ # πŸš€ **Model: Wav2Vec2-Large-AntiDeepfake**
23
+
24
+ # 🌟 **Key Features**
25
+ - **Architecture**: Wav2Vec 2.0 - [`facebook/wav2vec2-large-960h-lv60-self `](https://huggingface.co/facebook/wav2vec2-large-960h-lv60-self/tree/main) πŸ”—.
26
+ - **Input**: 16kHz sampled speech with arbitrary length πŸŽ™οΈ.
27
+ - **Output**: Binary classification score (<Fake score 🟒 , Real scoreπŸ”΄>).
28
+ - **Training Dataset**: Totally 18k hours of fake speech and 56k hours of real speech.
29
+
30
+ # πŸ—οΈ **Architecture**
31
+ - **Front-end Feature Extractor**: Wav2Vec2-Large.
32
+ - **Back-end Classifier**: A fully connected layer.
33
+
34
+ # βš™οΈ **Training Details**
35
+ - **Optimizer**: AdamW with a learning rate of `1e-7`.
36
+ - **Batch Size**: Dynamic Batching, maximum length per batch is set to 100 seconds.
37
+ - **Data Augmentation**: RawBoost series: (1)+(2)
38
+ - **Loss Function**: Cross-Entropy Loss.
39
+ - **Evaluation Metrics**: Equal Error Rate (EER), ROC AUC, Accuracy, Precision, Recall, F1 Score.
40
+
41
+ # πŸš€ **Inference with PyTorch**
42
+ πŸ“¦ Dependencies:
43
+ ```
44
+ pip install pip==23.1.1
45
+ pip install huggingface-hub fairseq safetensors soundfile
46
+ (pip install huggingface-hub==0.31.1 fairseq==0.12.2 safetensors==0.5.3 soundfile==0.13.1)
47
+ ```
48
+
49
+ πŸš€ Inference:
50
+ ```python
51
+ import os
52
+ import urllib.request
53
+ import torch
54
+ import torchaudio
55
+ import fairseq
56
+ from huggingface_hub import PyTorchModelHubMixin
57
+
58
+
59
+ # === Download Fairseq checkpoint if not present ===
60
+ # The downloaded checkpoint is used for building front-end architecture,
61
+ # its weights will be replaced by the model.safetensors file in this repo.
62
+ ssl_path = "w2v_large_lv_fsh_swbd_cv.pt"
63
+ ssl_url = "https://dl.fbaipublicfiles.com/fairseq/wav2vec/w2v_large_lv_fsh_swbd_cv.pt"
64
+
65
+ if not os.path.exists(ssl_path):
66
+ print(f"Downloading checkpoint to {ssl_path}...")
67
+ urllib.request.urlretrieve(ssl_url, ssl_path)
68
+ print("Download complete.")
69
+ else:
70
+ print(f"{ssl_path} already exists. Skipping download.")
71
+
72
+ # === Wrapper for the SSL model ===
73
+ class SSLModel(torch.nn.Module):
74
+ def __init__(self):
75
+ super().__init__()
76
+ # The downloaded .pt file is used here
77
+ model, _, _ = fairseq.checkpoint_utils.load_model_ensemble_and_task([ssl_path])
78
+ self.model = model[0]
79
+
80
+ def extract_feat(self, input_data):
81
+ # If input has shape (B, T, 1), squeeze the last dim
82
+ if input_data.ndim == 3:
83
+ input_data = input_data[:, :, 0]
84
+
85
+ # Extract features
86
+ with torch.no_grad():
87
+ features = self.model(input_data, mask=False, features_only=True)['x']
88
+ return features
89
+
90
+ # === Function for reading and pre-processing waveforms ===
91
+ def load_wav_and_preprocess(wav_path, target_sr=16000):
92
+ # Load audio file
93
+ wav, sr = torchaudio.load(wav_path)
94
+ # Convert to mono if stereo
95
+ wav = wav.mean(dim=0)
96
+ # Resample to target sampling rate
97
+ wav = torchaudio.functional.resample(wav, sr, new_freq=target_sr)
98
+ # Normalize waveform
99
+ with torch.no_grad():
100
+ wav = torch.nn.functional.layer_norm(wav, wav.shape)
101
+ # Add batch dimension and return
102
+ return wav.unsqueeze(0)
103
+
104
+ # === The actual deepfake detection model using SSL frontend + FC backend ===
105
+ class DeepfakeDetector(torch.nn.Module, PyTorchModelHubMixin):
106
+ def __init__(self):
107
+ super().__init__()
108
+ self.ssl_orig_output_dim = 1024
109
+ self.num_classes = 2
110
+
111
+ # Frontend: SSL model
112
+ self.m_ssl = SSLModel()
113
+
114
+ # Backend: Pooling + Classification
115
+ self.adap_pool1d = torch.nn.AdaptiveAvgPool1d(output_size=1)
116
+ self.proj_fc = torch.nn.Linear(
117
+ in_features=self.ssl_orig_output_dim,
118
+ out_features=self.num_classes,
119
+ )
120
+
121
+ def forward(self, wav):
122
+ emb = self.m_ssl.extract_feat(wav) # [B, T, D]
123
+ emb = emb.transpose(1, 2) # [B, D, T]
124
+ pooled_emb = self.adap_pool1d(emb) # [B, D, 1]
125
+ pooled_emb = pooled_emb.squeeze(-1) # [B, D]
126
+ logits = self.proj_fc(pooled_emb) # [B, 2]
127
+ return logits
128
+
129
+ # === Load AntiDeepfake model from Hugging Face===
130
+ model = DeepfakeDetector.from_pretrained("nii-yamagishilab/wav2vec-large-anti-deepfake")
131
+ model.eval()
132
+
133
+ # === Inference on a folder of audio files ===
134
+ folder_path = "path/to/folder/contains/wavs/"
135
+ supported_formats = (".mp3", ".wav", ".flac", ".m4a")
136
+
137
+ results = []
138
+ for root, _, files in os.walk(folder_path):
139
+ for file in files:
140
+ if file.lower().endswith(supported_formats):
141
+ input_path = os.path.join(root, file)
142
+ with torch.no_grad():
143
+ wav = load_wav_and_preprocess(input_path)
144
+ logits = model(wav)
145
+ probs = torch.nn.functional.softmax(logits, dim=1)
146
+ results.append((file, probs.cpu().numpy()[0]))
147
+
148
+ # Sort results alphabetically by filename
149
+ results.sort(key=lambda x: x[0])
150
+
151
+ # Print formatted results
152
+ print("\n=== Deepfake Detection Results ===")
153
+ for file_name, prob in results:
154
+ print(f"{file_name}: real prob = {prob[1]:.3f}, fake prob = {prob[0]:.3f}")
155
+ ```
156
+ # πŸ“Š **Performance Metrics**
157
+ | Test Database | ROC AUC | Accuracy | Precision | Recall | F1-score | FPR | FNR | EER (%) @ Threshold |
158
+ |----------------------|---------|----------|-----------|--------|----------|-------|-------|----------------------|
159
+ | ADD2023 | 0.950 | 0.912 | 0.939 | 0.942 | 0.940 | 0.175 | 0.058 | 13.25 @ 0.8520 |
160
+ | DeepVoice | 0.991 | 0.762 | 0.340 | 0.994 | 0.507 | 0.270 | 0.006 | 4.53 @ 0.9974 |
161
+ | FakeOrReal | 1.000 | 0.992 | 0.994 | 0.989 | 0.991 | 0.005 | 0.011 | 0.63 @ 0.3727 |
162
+ | FakeOrReal-norm | 0.999 | 0.986 | 0.975 | 0.997 | 0.986 | 0.025 | 0.003 | 0.97 @ 0.7975 |
163
+ | In-the-Wild | 0.997 | 0.976 | 0.991 | 0.970 | 0.980 | 0.015 | 0.030 | 1.91 @ 0.3240 |
164
+ | WildSVDD-TEST_A | 0.739 | 0.663 | 0.616 | 0.895 | 0.729 | 0.577 | 0.105 | 34.85 @ 0.9942 |
165
+ | WildSVDD-TEST_B | 0.654 | 0.696 | 0.740 | 0.836 | 0.785 | 0.583 | 0.164 | 41.67 @ 0.9842 |
166
+
167
+
168
+ # **Training Set**
169
+ | πŸ“š Database | 🌍 Language | βœ… Genuine (hrs) | ❌ Fake (hrs) |
170
+ |----------------------|------------------|----------------|-------------|
171
+ | AISHELL3 | zh | 85.62 | 0 |
172
+ | ASVspoof2019-LA | en | 11.85 | 97.80 |
173
+ | ASVspoof2021-LA | en | 16.40 | 116.10 |
174
+ | ASVspoof2021-DF | en | 20.73 | 487.00 |
175
+ | ASVspoof5 | en | 413.49 | 1808.48 |
176
+ | CFAD | zh | 171.25 | 224.55 |
177
+ | CNCeleb2 | zh | 1084.34 | 0 |
178
+ | Codecfake | en, zh | 129.66 | 808.32 |
179
+ | CodecFake | en | 0 | 660.92 |
180
+ | CVoiceFake | en, fr, de, it, zh| 315.14 | 1561.16 |
181
+ | DECRO | en, zh | 35.18 | 102.44 |
182
+ | DFADD | en | 41.62 | 66.01 |
183
+ | Diffuse or Confuse | en | 0 | 231.66 |
184
+ | DiffSSD | en | 0 | 139.73 |
185
+ | DSD | en, ja, ko | 100.98 | 60.23 |
186
+ | FLEURS | 102 languages | 1388.97 | 0 |
187
+ | FLEURS-R | 102 languages | 0 | 1238.83 |
188
+ | HABLA | es | 35.56 | 87.83 |
189
+ | LibriTTS | en | 585.83 | 0 |
190
+ | LibriTTS-R | en | 0 | 583.15 |
191
+ | LibriTTS-Vocoded | en | 0 | 2345.14 |
192
+ | LJSpeech | en | 23.92 | 0 |
193
+ | MLADD | 38 languages | 0 | 377.96 |
194
+ | MLS | 8 languages | 50558.11 | 0 |
195
+ | SpoofCeleb | Multilingual | 173.00 | 1916.20 |
196
+ | VoiceMOS | en | 0 | 448.44 |
197
+ | VoxCeleb2 | Multilingual | 1179.62 | 0 |
198
+ | VoxCeleb2-Vocoded | Multilingual | 0 | 4721.46 |
199
+ | WaveFake | en, ja | 0 | 198.65 |
200
+ | Train Set | Over 100 languages| 56370.00 | 18280.00 |