File size: 7,286 Bytes
575e16b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
001425d
 
575e16b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
001425d
575e16b
 
 
001425d
 
 
575e16b
 
001425d
575e16b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
---

license: cc-by-4.0
library_name: pytorch
pipeline_tag: audio-classification
datasets:
- InsectSet32
metrics:
- accuracy
- f1
tags:
- audio-classification
- insect
- bioacoustics
- experimental
- local-inference
- litert
- tflite
---


# Kernel Insect Sound Classifier (InsectCNN `full_model`, experimental 0.1.0)



A compact CNN (159k parameters) that classifies **32 sound-producing insect species** (9 Orthoptera, 23 Cicadidae) from audio. It was trained on [InsectSet32](https://zenodo.org/records/7072196).



> **This is not a grain-pest detector.** Do not use it to certify grain as clean or safe, to accept or reject lots, or to trigger treatment. It is a research baseline trained on a small dataset.



## Model details



| | |

|---|---|

| Architecture | `InsectCNN`: 3 conv blocks (16/32/64 ch, BatchNorm, ReLU) + dense head (128) with dropout 0.25 (`src/model.py`) |

| Input | Mono audio → resampled to 16 kHz → 2 s windows, peak-normalised → 64-bin log-mel (n_fft 512, hop 160), per-record standardised (`src/audio.py`) |
| Inference | Softmax averaged over 5 evenly spaced 2 s windows (`eval_crops: 5` in `config.json`) |
| Output | 32 species scores, plus a hierarchical species → genus → group answer |
| Base model | None. Trained from scratch (no pretrained weights, not a fine-tune) |
| Framework | PyTorch & Google LiteRT / TFLite |

### Files

- `model.tflite`: Google LiteRT / TensorFlow Lite on-device model for Android / edge mobile deployment.
- `model.pt`: PyTorch state dict weights. Load it with `torch.load(..., weights_only=True)`.
- `model.h5`: PyTorch state dict in a project-specific HDF5 layout (`kernel-pytorch-state-dict-hdf5-v1`). **It is not a Keras model.** `src.inference.load_model` reads it.
- `config.json`, `labels.json`: architecture, preprocessing settings and class-index → species mapping.
- `metrics.json`, `history.json`: test metrics (with per-class report) and the training curve.
- `src/`, `predict.py`, `export_litert.py`, `test_inference.py`: model definition, audio frontend, exporter and testing scripts.
- `train.py`, `evaluate.py`, `data/*.csv`: reproduction scripts and the official split annotations (the audio itself is not included).

## Usage

This is a custom PyTorch model. It does **not** load with `transformers`, and the hosted inference widget and Inference API don't support it. Run it locally:

```bash

pip install huggingface_hub

python -c "from huggingface_hub import snapshot_download; print(snapshot_download('ganesh333/kernel-insect-classifier', local_dir='kernel-insect-classifier'))"

cd kernel-insect-classifier

pip install -r requirements.txt

python predict.py path/to/recording.wav

```

WAV works out of the box. FLAC, OGG and MP3 need `soundfile`, which `requirements.txt` includes. Inference is fully local; no audio is sent anywhere.

Python API:

```python

from src.inference import predict_wav

r = predict_wav("recording.wav", model_dir=".")

print(r["identification"])                     # {'level': 'species'|'genus'|'group'|'unknown', 'name': ..., 'confidence': ...}

print(r["predicted_species"], r["confidence"])  # raw top-1

print(r["top_k"], r["quality_pass"], r["quality_reasons"])

```

**Hierarchical identification.** The model reports the most specific level whose summed probability is at least 0.6: species, then genus, then group (cicadas vs crickets/grasshoppers). Otherwise it reports `unknown`. The threshold was chosen on the validation split.

## Training

Data: InsectSet32. Using the dataset's official `train`/`validation`/`test` partitions, 331 recordings were loaded (206 / 51 / 74).

```bash

# place Cicadidae.csv, Orthoptera.csv, Cicadidae.zip, Orthoptera.zip in data/

python train.py --epochs 60 --random-crop --eval-crops 5 --output .

```

- AdamW (lr 1e-3, weight decay 1e-4), batch size 16, class-weighted cross entropy (weights from train only), seed 42.
- Each epoch trains on a fresh random 2 s window per file.
- The checkpoint is chosen by best validation macro-F1 (0.548). The test split was scored once, after selection.
- About 4 minutes on a CPU.

## Evaluation

Official test split (n = 74 recordings). 95% CIs from a file-level bootstrap:

| Metric | Value |
|---|---|
| Accuracy | 0.486 [0.38, 0.59] |
| Macro-F1 | 0.400 [0.29, 0.47] |
| Weighted-F1 | 0.474 |
| Session-clean accuracy / macro-F1 (n = 48) | 0.458 / 0.343 |

"Session-clean" counts only test files whose source recording session never appears in train or validation. See *Data leakage* below.

Accuracy among test files whose score at that level is at least 0.6:

| Level | Share of test files ≥ 0.6 | Accuracy on those (val / test) |
|---|---|---|
| Species | 43% | 77% / 72% |
| Genus | 77% | 90% / 95% |
| Group | 96% | 98% / 99% |

For comparison, the earlier center-crop baseline of the same architecture scored 0.392 accuracy and 0.329 macro-F1 on the same split. The CIs overlap, so with only 74 test files these differences are not conclusive.

## Limitations

- **Small, imbalanced data.** Species have 4–22 recordings each, and `Roeselianaroeselii` has no test files. All scores are uncertain.
- **Data leakage.** The official split groups by file, not by source recording: 26 of the 74 test files share a source session with train or validation. Official-split scores are therefore optimistic; the session-clean numbers are the more honest estimate.
- **Label noise.** Five `MHV 318 P.capensis` source files are labelled `Platypleuracfcatenata`. They were kept as published.
- **Closed set.** Every input is mapped onto the 32 trained species. Silence, pure tones and white noise can receive high-confidence species predictions. Use `quality_reasons` and treat `genus`/`unknown` answers as exactly that.
- **Noise sensitivity.** Added background noise (SNR 0–20 dB) often changes the prediction.
- **Not calibrated.** The scores are not probabilities of grain infestation. Recording conditions differ from grain sacks and warehouses.
- **Not mobile-ready.** This is not a validated Android LiteRT/TFLite model. See `docs/deployment.md` before any on-device port.
- `model.pt` is a pickle-based file and may be flagged by the Hub's pickle scanner. It contains only tensors. Prefer `model.h5`, or load with `weights_only=True`.

## Dataset attribution and citation

Trained on **InsectSet32** by Marius Faiß, Baudewijn Odé and Ed Baker (CC BY 4.0, [Zenodo 7072196](https://zenodo.org/records/7072196)). Orthoptera recordings: Baudewijn Odé. Cicadidae recordings: the Global Cicada Sound Collection on Bioacoustica ([doi.org/10.1093/database/bav054](https://doi.org/10.1093/database/bav054)). Copyright in individual recordings belongs to the recordists. See `data/README.txt`.

For academic use, please cite the dataset paper: Faiß, M. & Stowell, D. *Adaptive representations of sound for automatic insect recognition*, PLOS Computational Biology (2023), [doi.org/10.1371/journal.pcbi.1011541](https://doi.org/10.1371/journal.pcbi.1011541).

## License

- Model weights and this card: **CC BY 4.0**, matching the training data's license. Keep the attribution above when you redistribute.
- Code (`src/`, `*.py`): **MIT**. See `LICENSE`.