Keras
English
audio
anomaly-detection
industrial
predictive-maintenance
acoustic-monitoring
dcase2020
arcface
transformer
tensorflow
Instructions to use Jvachier/dcase2020-task2-anomaly-detection with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Keras
How to use Jvachier/dcase2020-task2-anomaly-detection with Keras:
# Available backend options are: "jax", "torch", "tensorflow". import os os.environ["KERAS_BACKEND"] = "jax" import keras model = keras.saving.load_model("hf://Jvachier/dcase2020-task2-anomaly-detection") - Notebooks
- Google Colab
- Kaggle
File size: 8,907 Bytes
dcfe291 3e77b67 dcfe291 3e77b67 f8794ab 3e77b67 | 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 216 217 218 219 220 221 222 | ---
license: apache-2.0
language: en
library_name: keras
tags:
- audio
- anomaly-detection
- industrial
- predictive-maintenance
- acoustic-monitoring
- dcase2020
- arcface
- transformer
- keras
- tensorflow
metrics:
- roc_auc
---
# DCASE 2020 Task 2 — Valve Anomaly Detection (ArcFace Embedding + Mahalanobis)
Unsupervised acoustic anomaly detection for industrial valves. Trained on **normal
operating sounds only** (no anomalous examples seen during training); anomalies are
detected as embeddings that fall far from the learned distribution of normal acoustic
signatures.
- **Task**: unsupervised anomaly detection (DCASE 2020 Challenge Task 2 formulation)
- **Equipment type**: valve
- **Metric**: pooled Mahalanobis distance AUC-ROC = **0.947 ± 0.006** (mean ± std over 3 seeds)
- **Deployment**: no machine ID required at inference (pooled scoring)
- **Code**: [github.com/jvachier/industrial-audio-anomaly-detection](https://github.com/jvachier/industrial-audio-anomaly-detection)
- **Demo**: Gradio App
---
## Model description
The model is a multiscale Transformer encoder trained on a **pretext task**: given a
log-mel spectrogram patch, predict which physical valve unit (machine ID) it came from.
This forces the encoder to learn fine-grained acoustic signatures characteristic of each
unit's normal operation. An **ArcFace additive angular margin loss** (`s=32`, `m=0.10`)
tightens the per-ID clusters on the embedding hypersphere during training.
After training, the classification head is discarded. What remains is a 128-dimensional
embedding function. At inference, the anomaly score is the **Mahalanobis distance** from
a clip's embedding to a single LedoitWolf-estimated Gaussian fitted over *all* training
embeddings pooled across machine IDs — this is what makes the deployed model usable
without knowing which physical unit produced a given recording.
**Architecture**:
```
Input: log-mel spectrogram (64 frames x 128 mel bins)
-> multiscale patch tokenisation: patch sizes [8, 4] frames, each scale gets its own
linear projection to 128-d + sinusoidal positional encoding, then concatenated
-> 2 x Transformer encoder block (4 heads, d_model=128)
-> mean pooling -> 128-d embedding
-> (training only) ArcFace head, s=32, m=0.10, over 4 machine-ID classes
```
Trained independently for 3 random seeds (0, 1, 2); the reference implementation
z-score-ensembles all three at inference for a more robust score (see Usage below).
---
## Intended use
- **Primary use case**: screening industrial valve acoustic recordings for anomalous
operating conditions (e.g. predictive maintenance), as a proof-of-concept / benchmark
model on the DCASE 2020 Task 2 dataset.
- **Not validated for**: real-world deployment audio outside the DCASE 2020 / MIMII
valve distribution (different valve types, microphone placement, background noise
profiles, or SNR than the benchmark's synthetic 0 dB mixing). Treat scores from
out-of-distribution audio as unreliable without re-calibration.
- **Not included in this repo**: fan and pump models. This repository currently ships
the valve model only.
---
## How to use
This model uses custom Keras layers (`ArcFaceLayer`, multiscale patch tokenizer) that
are registered via `@keras.saving.register_keras_serializable` in the companion
`iaad` Python package — loading the `.keras` file with bare `keras.models.load_model()`
without that package installed will fail to resolve the custom layers. Install the
package from GitHub (not yet published to PyPI):
```bash
pip install git+https://github.com/jvachier/industrial-audio-anomaly-detection.git
```
**Single seed:**
```python
from iaad.inference import AnomalyDetector
det = AnomalyDetector.from_hub(machine_type="valve", seed=0)
result = det.score_file("path/to/valve_clip.wav", score="mahalanobis")
print(result.is_anomalous, result.percentile)
```
**Ensemble of all 3 seeds (recommended — more robust score):**
```python
from iaad.inference import EnsembleDetector
ens = EnsembleDetector.from_hub(machine_type="valve")
result = ens.score_file("path/to/valve_clip.wav", score="mahalanobis")
print(result["is_anomalous"], result["percentile"])
```
Input audio should be a 16 kHz mono WAV clip (10 s recommended, matching training
clip length); other sample rates are auto-resampled with a warning.
---
## Training data
[DCASE 2020 Challenge Task 2](https://dcase.community/challenge2020/task2-unsupervised-detection-of-anomalous-sounds)
(MIMII-based), valve subset, mirrored on
[Kaggle: daisukelab/dc2020task2](https://www.kaggle.com/datasets/daisukelab/dc2020task2).
- 4 machine IDs: `id_00`, `id_02`, `id_04`, `id_06`
- Condition: 0 dB SNR (target machine signal + factory background noise at equal power)
- ~1000 ten-second normal-only training clips per machine ID; a labelled normal +
anomaly test split is used only for evaluation, never for training
- 85/15 train/validation split (validation is normal-only, used for early stopping)
**Preprocessing** (`src/iaad/features.py`, no external audio library):
log-mel spectrogram, 128 mel bins, 50–8000 Hz, 512-sample FFT window / 256-sample hop,
64-frame (~1.02 s) non-overlapping patches, per-clip CMVN (mean-normalised per mel bin).
SpecAugment is disabled for valve specifically (empirically best AUC without it; fan/pump
use frequency + time masking).
---
## Training procedure
| Hyperparameter | Value |
|---|---|
| Optimizer | Adam, lr=1e-3 |
| Batch size | 64 |
| Epochs | up to 120, early stopping (patience=10, restore best weights) |
| Loss | ArcFace-modified softmax cross-entropy over 4 machine-ID classes |
| ArcFace scale / margin | s=32, m=0.10 |
| Seeds | 0, 1, 2 (independent runs, deterministic — `tf.config.experimental.enable_op_determinism()`) |
| Hardware | single GPU (Kaggle P100/T4), no mixed precision |
After training, a calibration pass fits a LedoitWolf covariance estimator over all
training-set embeddings (pooled across machine IDs) and records percentile thresholds
of the resulting Mahalanobis distances — this is what ships in `valve_calib_s{seed}.npz`
and lets inference flag a clip as anomalous (e.g. above the 95th percentile of normal)
without any refitting.
---
## Evaluation results
Per-machine-ID mean AUC-ROC, averaged over 3 random seeds (chance = 0.500):
| Machine | EMB pooled Mahalanobis |
|---------|:----------------------:|
| **valve** | **0.947 ± 0.006** |
Pooled scoring is the deployment-safe metric (no machine ID needed at inference). See
the [GitHub repo's evaluation docs](https://github.com/jvachier/industrial-audio-anomaly-detection/blob/main/docs/evaluation.md)
for the full comparison against earlier detector families (dense autoencoder,
Transformer-VAE) and the oracle (per-ID, ID-known) scoring variant.
---
## Files in this repository
| File | Description |
|---|---|
| `version.json` | `{"emb_version": "v5", "run_tag": "v5.4"}` — model family marker read by `AnomalyDetector._load()` |
| `valve_emb_s{0,1,2}.keras` | Trained `EMBClassifier` weights, one per seed |
| `valve_norm_s{0,1,2}.npz` | Per-mel-bin normalisation stats (mean, std) fit on that seed's training split |
| `valve_calib_s{0,1,2}.npz` | Calibration: pooled LedoitWolf location/precision + percentile thresholds |
---
## Limitations and biases
- Trained and evaluated exclusively on the DCASE 2020 Task 2 synthetic 0 dB SNR mixing;
performance on cleaner or noisier real-world recordings is unverified.
- Unsupervised training means the model has never seen a true anomaly label; its notion
of "anomalous" is entirely defined by the DCASE benchmark's specific injected fault
types, which may not cover all real failure modes.
- Anomaly threshold (95th percentile by default) is a design choice trading recall for
precision — recalibrate on your own normal-operation data before deploying to a
different valve installation.
---
## License
Apache 2.0 — see the [GitHub repository's LICENSE](https://github.com/jvachier/industrial-audio-anomaly-detection/blob/main/LICENSE).
## Citation
```bibtex
@misc{vachier2025iaad,
author = {Vachier, Jeremy},
title = {Industrial Audio Anomaly Detection -- DCASE 2020 Task 2 Baseline},
year = {2026},
url = {https://github.com/jvachier/industrial-audio-anomaly-detection},
}
@inproceedings{koizumi2020dcase,
author = {Koizumi, Yuma and Saito, Shoichiro and Uematsu, Hisashi and Harada, Noboru and Imoto, Keisuke},
title = {ToyADMOS: A Dataset of Miniature-Machine Operating Sounds for Anomalous Sound Detection},
booktitle = {Proceedings of the Detection and Classification of Acoustic Scenes and Events 2020 Workshop (DCASE2020)},
year = {2020},
}
@misc{huggingface_hub,
author = {Hugging Face},
title = {Hugging Face Hub},
year = {2026},
url = {https://github.com/huggingface/huggingface_hub},
}
``` |