Audio-based classification of machine health states across three machine types - a lightweight CNN that hears whether a machine is healthy or faulty.
▶ Try the live demo on Hugging Face Spaces · 📄 Read the full report (PDF)
Domain. Acoustic machine condition monitoring for predictive maintenance - given a short clip recorded near a running machine, decide whether it is operating normally or exhibiting a fault. Acoustic monitoring is attractive because a single non-contact microphone captures the full vibrational signature of the equipment, making it cheap to deploy at scale on factory floors.
Task. A supervised 6-way classification over {machine type} × {health state}: three industrial machines (M1, M2, M3), each with a Normal and Abnormal class. This is a closed-set re-framing of the broader Anomalous Sound Detection problem - the same setup popularised by the DCASE Challenge Task 2 series (DCASE 2020 / 2022 / 2023) and the MIMII / MIMII-DG datasets, but here the labels are known at training time.
| Property | Value |
|---|---|
| Files | 56,236 WAV clips (~54 GB) |
| Format | PCM 16-bit mono, 48 kHz |
| Duration | 11.0 s (M1, M2), 10.0 s (M3) |
| Class balance | ≈ 5 : 1 Normal : Abnormal |
| Hidden structure | Multiple recording sections per machine (different mics / units / operating conditions) |
Why it's hard. The fault signature lives in fine spectro-temporal detail (transient timing for M2, harmonic smearing for M3, broadband shifts of 1–3 dB for M1), so global summary statistics don't separate Normal from Abnormal. Worse, each machine was recorded across multiple sections that look acoustically distinct (cosine similarity as low as 0.27 between M2 sections). A naive random split lets the model memorise section fingerprints - an early version reached F1 ≈ 0.999 purely from leakage. Honest, section-disjoint splits are what made the 91.9% / 82.0% headline numbers meaningful.
Reference. Koizumi et al., “Description and Discussion on DCASE2020 Challenge Task 2: Unsupervised Detection of Anomalous Sounds for Machine Condition Monitoring,” DCASE 2020 - the foundational paper for this problem framing (cited in the project report).
- 0.24M parameters - a 4-block CNN small enough for edge deployment, trained from scratch.
- PCEN features - Per-Channel Energy Normalisation in front of a log-mel pipeline, robust to gain drift.
- Frequency-MixStyle - cross-section domain generalisation; mixes per-(channel,freq) statistics across batch partners drawn from the same class but a different recording section.
- Hybrid factored head - a plain 6-way FC head for inference, plus auxiliary factored heads (machine + per-machine health) used only at training time as a regulariser.
- Reproducible pipeline - feature cache → cluster-aware split → train → infer, all scripted; Docker image included.
| Label | Machine | Health |
|---|---|---|
| 0 | M1 | Normal |
| 1 | M1 | Abnormal |
| 2 | M2 | Normal |
| 3 | M2 | Abnormal |
| 4 | M3 | Normal |
| 5 | M3 | Abnormal |
| Metric | Value |
|---|---|
| Test Accuracy | 91.9% |
| Balanced Accuracy | 82.0% |
| Parameters | 0.24M |
| Inference (CPU) | ~tens of ms / clip |
See docs/Report.pdf for ablations (PCEN vs log-mel, FreqMixStyle on/off, plain vs factored head) and full per-class breakdowns.
SmallCNNFactored - defined in src/models.py. Inference uses only the plain 6-way FC head; the factored heads are dropped after training.
Model architecture (SmallCNNFactored).
Each machine is recorded across multiple sections (operating conditions / locations / mics). A naive split leaks section identity and overstates accuracy. We cluster log-mel spectra to discover sections, then build a section-disjoint hybrid split: train on some sections, evaluate on held-out ones. This is what the model actually generalises to.
PCA per machine/health - silhouette-validated clusters reveal latent recording sections.
Held-out sections (red) live in different regions of feature space than train sections (blue) - the gap the model must close.
Final per-machine split sizes (Normal stacked, Abnormal on top).
1. precompute.py - Cache PCEN + log-mel features from WAV files
2. splits.py - Discover sections (clustering), assign train/val/test
3. audit_splits.py - Sanity-check the split (leakage, class balance)
4. train_cnn.py - Train SmallCNNFactored
5. infer.py - Run inference on new WAV files
Processing pipeline: feature cache → split → train → infer.
./run.sh <wav_folder> <results_folder>The helper builds the image on first run, then mounts your folders. Outputs:
results.txt— one predicted class index (0–5) per file, in filename-numeric ordertime.txt— per-file inference time in seconds
pip install -r requirements.txt
python infer.py --data <wav_folder> --out results/Defaults to models/final.pt. Override with --model <path>.
# 1. Precompute features
python precompute.py
# 2. Generate cluster-aware splits
python splits.py --mode hybrid
# 3. Train
python train_cnn.py --model small_cnn_factored --epochs 25 --variant B \
--class-weight-cap 1.0 --select-metric val_bal_acc \
--fms-prob 0.5 --fms-alpha 0.1 \
--ckpt-path "models/final.pt"