Audio Classification
PyTorch
LiteRT
LiteRT
kernel-insect-cnn
insect
bioacoustics
experimental
local-inference
Instructions to use ganesh333/kernel-insect-classifier with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LiteRT
How to use ganesh333/kernel-insect-classifier with LiteRT:
# No code snippets available yet for this library. # To use this model, check the repository files and the library's documentation. # Want to help? PRs adding snippets are welcome at: # https://github.com/huggingface/huggingface.js
- Notebooks
- Google Colab
- Kaggle
Upload folder using huggingface_hub
Browse files- LICENSE +11 -0
- README.md +127 -0
- config.json +14 -0
- data/Cicadidae.csv +189 -0
- data/Orthoptera.csv +144 -0
- data/README.txt +114 -0
- docs/deployment.md +16 -0
- evaluate.py +21 -0
- history.json +302 -0
- labels.json +34 -0
- metrics.json +551 -0
- model.h5 +3 -0
- model.pt +3 -0
- predict.py +22 -0
- requirements.txt +7 -0
- src/__init__.py +0 -0
- src/audio.py +104 -0
- src/inference.py +70 -0
- src/model.py +20 -0
- tests/test_model.py +37 -0
- train.py +151 -0
LICENSE
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
This repository code is provided under the MIT License.
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2026 Kernel MVP contributors
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
| 6 |
+
|
| 7 |
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
| 8 |
+
|
| 9 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
| 10 |
+
|
| 11 |
+
Note: dataset audio is separately licensed/attributed as described in data/README.txt and is not relicensed by this code license.
|
README.md
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: cc-by-4.0
|
| 3 |
+
library_name: pytorch
|
| 4 |
+
pipeline_tag: audio-classification
|
| 5 |
+
datasets:
|
| 6 |
+
- InsectSet32
|
| 7 |
+
metrics:
|
| 8 |
+
- accuracy
|
| 9 |
+
- f1
|
| 10 |
+
tags:
|
| 11 |
+
- audio-classification
|
| 12 |
+
- insect
|
| 13 |
+
- bioacoustics
|
| 14 |
+
- experimental
|
| 15 |
+
- local-inference
|
| 16 |
+
---
|
| 17 |
+
|
| 18 |
+
# Kernel Insect Sound Classifier (InsectCNN `full_model`, experimental 0.1.0)
|
| 19 |
+
|
| 20 |
+
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).
|
| 21 |
+
|
| 22 |
+
> **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.
|
| 23 |
+
|
| 24 |
+
## Model details
|
| 25 |
+
|
| 26 |
+
| | |
|
| 27 |
+
|---|---|
|
| 28 |
+
| Architecture | `InsectCNN`: 3 conv blocks (16/32/64 ch, BatchNorm, ReLU) + dense head (128) with dropout 0.25 (`src/model.py`) |
|
| 29 |
+
| 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`) |
|
| 30 |
+
| Inference | Softmax averaged over 5 evenly spaced 2 s windows (`eval_crops: 5` in `config.json`) |
|
| 31 |
+
| Output | 32 species scores, plus a hierarchical species → genus → group answer |
|
| 32 |
+
| Base model | None. Trained from scratch (no pretrained weights, not a fine-tune) |
|
| 33 |
+
| Framework | PyTorch. Weights stored as a state dict |
|
| 34 |
+
|
| 35 |
+
### Files
|
| 36 |
+
|
| 37 |
+
- `model.h5`: the 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.
|
| 38 |
+
- `model.pt`: the same weights as a PyTorch state dict. Load it with `torch.load(..., weights_only=True)`.
|
| 39 |
+
- `config.json`, `labels.json`: architecture, preprocessing settings and class-index → species mapping.
|
| 40 |
+
- `metrics.json`, `history.json`: test metrics (with per-class report) and the training curve.
|
| 41 |
+
- `src/`, `predict.py`: model definition, audio frontend, loader and CLI.
|
| 42 |
+
- `train.py`, `evaluate.py`, `data/*.csv`: reproduction scripts and the official split annotations (the audio itself is not included).
|
| 43 |
+
|
| 44 |
+
## Usage
|
| 45 |
+
|
| 46 |
+
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:
|
| 47 |
+
|
| 48 |
+
```bash
|
| 49 |
+
pip install huggingface_hub
|
| 50 |
+
python -c "from huggingface_hub import snapshot_download; print(snapshot_download('ganesh333/kernel-insect-classifier', local_dir='kernel-insect-classifier'))"
|
| 51 |
+
cd kernel-insect-classifier
|
| 52 |
+
pip install -r requirements.txt
|
| 53 |
+
python predict.py path/to/recording.wav
|
| 54 |
+
```
|
| 55 |
+
|
| 56 |
+
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.
|
| 57 |
+
|
| 58 |
+
Python API:
|
| 59 |
+
|
| 60 |
+
```python
|
| 61 |
+
from src.inference import predict_wav
|
| 62 |
+
r = predict_wav("recording.wav", model_dir=".")
|
| 63 |
+
print(r["identification"]) # {'level': 'species'|'genus'|'group'|'unknown', 'name': ..., 'confidence': ...}
|
| 64 |
+
print(r["predicted_species"], r["confidence"]) # raw top-1
|
| 65 |
+
print(r["top_k"], r["quality_pass"], r["quality_reasons"])
|
| 66 |
+
```
|
| 67 |
+
|
| 68 |
+
**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.
|
| 69 |
+
|
| 70 |
+
## Training
|
| 71 |
+
|
| 72 |
+
Data: InsectSet32. Using the dataset's official `train`/`validation`/`test` partitions, 331 recordings were loaded (206 / 51 / 74).
|
| 73 |
+
|
| 74 |
+
```bash
|
| 75 |
+
# place Cicadidae.csv, Orthoptera.csv, Cicadidae.zip, Orthoptera.zip in data/
|
| 76 |
+
python train.py --epochs 60 --random-crop --eval-crops 5 --output .
|
| 77 |
+
```
|
| 78 |
+
|
| 79 |
+
- AdamW (lr 1e-3, weight decay 1e-4), batch size 16, class-weighted cross entropy (weights from train only), seed 42.
|
| 80 |
+
- Each epoch trains on a fresh random 2 s window per file.
|
| 81 |
+
- The checkpoint is chosen by best validation macro-F1 (0.548). The test split was scored once, after selection.
|
| 82 |
+
- About 4 minutes on a CPU.
|
| 83 |
+
|
| 84 |
+
## Evaluation
|
| 85 |
+
|
| 86 |
+
Official test split (n = 74 recordings). 95% CIs from a file-level bootstrap:
|
| 87 |
+
|
| 88 |
+
| Metric | Value |
|
| 89 |
+
|---|---|
|
| 90 |
+
| Accuracy | 0.486 [0.38, 0.59] |
|
| 91 |
+
| Macro-F1 | 0.400 [0.29, 0.47] |
|
| 92 |
+
| Weighted-F1 | 0.474 |
|
| 93 |
+
| Session-clean accuracy / macro-F1 (n = 48) | 0.458 / 0.343 |
|
| 94 |
+
|
| 95 |
+
"Session-clean" counts only test files whose source recording session never appears in train or validation. See *Data leakage* below.
|
| 96 |
+
|
| 97 |
+
Accuracy among test files whose score at that level is at least 0.6:
|
| 98 |
+
|
| 99 |
+
| Level | Share of test files ≥ 0.6 | Accuracy on those (val / test) |
|
| 100 |
+
|---|---|---|
|
| 101 |
+
| Species | 43% | 77% / 72% |
|
| 102 |
+
| Genus | 77% | 90% / 95% |
|
| 103 |
+
| Group | 96% | 98% / 99% |
|
| 104 |
+
|
| 105 |
+
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.
|
| 106 |
+
|
| 107 |
+
## Limitations
|
| 108 |
+
|
| 109 |
+
- **Small, imbalanced data.** Species have 4–22 recordings each, and `Roeselianaroeselii` has no test files. All scores are uncertain.
|
| 110 |
+
- **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.
|
| 111 |
+
- **Label noise.** Five `MHV 318 P.capensis` source files are labelled `Platypleuracfcatenata`. They were kept as published.
|
| 112 |
+
- **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.
|
| 113 |
+
- **Noise sensitivity.** Added background noise (SNR 0–20 dB) often changes the prediction.
|
| 114 |
+
- **Not calibrated.** The scores are not probabilities of grain infestation. Recording conditions differ from grain sacks and warehouses.
|
| 115 |
+
- **Not mobile-ready.** This is not a validated Android LiteRT/TFLite model. See `docs/deployment.md` before any on-device port.
|
| 116 |
+
- `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`.
|
| 117 |
+
|
| 118 |
+
## Dataset attribution and citation
|
| 119 |
+
|
| 120 |
+
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`.
|
| 121 |
+
|
| 122 |
+
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).
|
| 123 |
+
|
| 124 |
+
## License
|
| 125 |
+
|
| 126 |
+
- Model weights and this card: **CC BY 4.0**, matching the training data's license. Keep the attribution above when you redistribute.
|
| 127 |
+
- Code (`src/`, `*.py`): **MIT**. See `LICENSE`.
|
config.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model_type": "kernel-insect-cnn",
|
| 3 |
+
"architecture": "InsectCNN",
|
| 4 |
+
"num_classes": 32,
|
| 5 |
+
"sample_rate": 16000,
|
| 6 |
+
"clip_seconds": 2.0,
|
| 7 |
+
"feature": "64-bin log-mel spectrogram",
|
| 8 |
+
"eval_crops": 5,
|
| 9 |
+
"model_version": "0.1.0-experimental",
|
| 10 |
+
"framework": "PyTorch",
|
| 11 |
+
"hdf5_format": "kernel-pytorch-state-dict-hdf5-v1",
|
| 12 |
+
"task": "insect species classification",
|
| 13 |
+
"experimental": true
|
| 14 |
+
}
|
data/Cicadidae.csv
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
file_name,species,class_ID,data_set,original_file_name
|
| 2 |
+
Myopsaltamelanobasis_Myopsalta_melanobasis_Brigalow.wav,Myopsaltamelanobasis,9,test,Myopsalta_melanobasis_Brigalow.wav
|
| 3 |
+
Platypleurasp10_MHV%20313%20P.sp10%20Die%20Koo%20%236b.wav,Platypleurasp10,24,train,MHV%20313%20P.sp10%20Die%20Koo%20%236b.wav
|
| 4 |
+
Platypleurasp13_MHV%201016%20P.sp13%20nr%20Hankey.wav,Platypleurasp13,27,validation,MHV%201016%20P.sp13%20nr%20Hankey.wav
|
| 5 |
+
Platypleuraintercapedinis_MHV%20952%20P.cf_.brunea%20Mtunzini%20%235.wav,Platypleuraintercapedinis,21,train,MHV%20952%20P.cf_.brunea%20Mtunzini%20%235.wav
|
| 6 |
+
Myopsaltaxerograsidia_Myopsalta_xerograsidia_Laura_River.wav,Myopsaltaxerograsidia,10,train,Myopsalta_xerograsidia_Laura_River.wav
|
| 7 |
+
Platypleuracfcatenata_MHV%20608%20P.catenata%20Robinson%20Pass.wav,Platypleuracfcatenata,15,test,MHV%20608%20P.catenata%20Robinson%20Pass.wav
|
| 8 |
+
Brevisianabrevis_MHV%20959%20B.brevis%20Morningside%20Ranch%20%232.wav,Brevisianabrevis,1,test,MHV%20959%20B.brevis%20Morningside%20Ranch%20%232.wav
|
| 9 |
+
Myopsaltaxerograsidia_Myopsalta_xerograsidia_Musselbrook.wav,Myopsaltaxerograsidia,10,test,Myopsalta_xerograsidia_Musselbrook.wav
|
| 10 |
+
Brevisianabrevis_MHV%20959%20B.brevis%20Morningside%20Ranch%20%233.wav,Brevisianabrevis,1,train,MHV%20959%20B.brevis%20Morningside%20Ranch%20%233.wav
|
| 11 |
+
Platypleuradeusta_MHV%20993%20P.duesta%20nr%20Piet%20Retief%20%232%20%28maybe%29.wav,Platypleuradeusta,17,train,MHV%20993%20P.duesta%20nr%20Piet%20Retief%20%232%20%28maybe%29.wav
|
| 12 |
+
Platypleurasp10_MHV%20313%20P.sp10%20Die%20Koo%20%236a.wav,Platypleurasp10,24,train,MHV%20313%20P.sp10%20Die%20Koo%20%236a.wav
|
| 13 |
+
Platypleuraplumosa_MHV%201021%20P.plumosa%20nr%20Addo%20N.P..wav,Platypleuraplumosa,22,train,MHV%201021%20P.plumosa%20nr%20Addo%20N.P..wav
|
| 14 |
+
Platypleurasp10_MHV%20866%20P.sp10%20Van%20Ryns%20Pass%20%233.wav,Platypleurasp10,24,train,MHV%20866%20P.sp10%20Van%20Ryns%20Pass%20%233.wav
|
| 15 |
+
Platypleurachalybaea_MHV%20914%20P.chalybaea%20Kenton%20%235.wav,Platypleurachalybaea,16,test,MHV%20914%20P.chalybaea%20Kenton%20%235.wav
|
| 16 |
+
Myopsaltaleona_Myopsalta_leona_Kindon.wav,Myopsaltaleona,6,test,Myopsalta_leona_Kindon.wav
|
| 17 |
+
Brevisianabrevis_MHV%20959%20B.brevis%20Morningside%20Ranch%20%231.wav,Brevisianabrevis,1,validation,MHV%20959%20B.brevis%20Morningside%20Ranch%20%231.wav
|
| 18 |
+
Azanicadazuluensis_MHV%20937%20A.zuluensis%20Trafalgar.wav,Azanicadazuluensis,0,train,MHV%20937%20A.zuluensis%20Trafalgar.wav
|
| 19 |
+
Platypleurasp04_MHV%20597%20P.sp4%20Meiringspoort%20Pass%20%232_0.wav,Platypleurasp04,23,train,MHV%20597%20P.sp4%20Meiringspoort%20Pass%20%232_0.wav
|
| 20 |
+
Platypleurachalybaea_MHV%20914%20P.chalybaea%20Kenton%20%234.wav,Platypleurachalybaea,16,test,MHV%20914%20P.chalybaea%20Kenton%20%234.wav
|
| 21 |
+
Platypleuraintercapedinis_MHV%20945%20P.cf_.brunea%20Ingwe%20Lodge.wav,Platypleuraintercapedinis,21,validation,MHV%20945%20P.cf_.brunea%20Ingwe%20Lodge.wav
|
| 22 |
+
Platypleurasp12cfhirtipennis_MHV%20840%20P.sp12%20nr%20Laingsburg.wav,Platypleurasp12cfhirtipennis,26,train,MHV%20840%20P.sp12%20nr%20Laingsburg.wav
|
| 23 |
+
Platypleurasp10_MHV%20866%20P.sp10%20Van%20Ryns%20Pass%20%232.wav,Platypleurasp10,24,test,MHV%20866%20P.sp10%20Van%20Ryns%20Pass%20%232.wav
|
| 24 |
+
Platypleuracfcatenata_MHV%20286%20P.catenata%20Grabow%20%231.wav,Platypleuracfcatenata,15,train,MHV%20286%20P.catenata%20Grabow%20%231.wav
|
| 25 |
+
Platypleurasp11cfhirtipennis_MHV%20843%20P.sp11%20nr%20Karookloof%20%232.wav,Platypleurasp11cfhirtipennis,25,train,MHV%20843%20P.sp11%20nr%20Karookloof%20%232.wav
|
| 26 |
+
Platypleuraplumosa_MHV%201037%20P.plumosa%20Paniel%20Farm.wav,Platypleuraplumosa,22,train,MHV%201037%20P.plumosa%20Paniel%20Farm.wav
|
| 27 |
+
Platypleurasp10_MHV%20313%20P.sp10%20Die%20Koo%20%231.wav,Platypleurasp10,24,validation,MHV%20313%20P.sp10%20Die%20Koo%20%231.wav
|
| 28 |
+
Brevisianabrevis_MHV%20959%20B.brevis%20Morningside%20Ranch%20%234.wav,Brevisianabrevis,1,train,MHV%20959%20B.brevis%20Morningside%20Ranch%20%234.wav
|
| 29 |
+
Platypleuradeusta_MHV%20993%20P.duesta%20nr%20Piet%20Retief%20%231.wav,Platypleuradeusta,17,train,MHV%20993%20P.duesta%20nr%20Piet%20Retief%20%231.wav
|
| 30 |
+
Platypleurachalybaea_MHV%20914%20P.chalybaea%20Kenton%20%231.wav,Platypleurachalybaea,16,train,MHV%20914%20P.chalybaea%20Kenton%20%231.wav
|
| 31 |
+
Platypleuracfcatenata_MHV%20283%20P.catenata%20Sir%20Lowry%27s%20Pass%20%232.wav,Platypleuracfcatenata,15,train,MHV%20283%20P.catenata%20Sir%20Lowry%27s%20Pass%20%232.wav
|
| 32 |
+
Platypleurasp10_MHV%20313%20P.sp10%20Die%20Koo%20%237a.wav,Platypleurasp10,24,train,MHV%20313%20P.sp10%20Die%20Koo%20%237a.wav
|
| 33 |
+
Platypleurasp12cfhirtipennis_MHV%20842%20P.sp12%20nr%20Maitjiesfontein.wav,Platypleurasp12cfhirtipennis,26,train,MHV%20842%20P.sp12%20nr%20Maitjiesfontein.wav
|
| 34 |
+
Platypleuracfcatenata_MHV%20286%20P.catenata%20Grabow%20%232.wav,Platypleuracfcatenata,15,validation,MHV%20286%20P.catenata%20Grabow%20%232.wav
|
| 35 |
+
Myopsaltamackinlayi_Myopsalta_mackinlayi_Ceratodus.wav,Myopsaltamackinlayi,8,test,Myopsalta_mackinlayi_Ceratodus.wav
|
| 36 |
+
Platypleurasp11cfhirtipennis_MHV%20843%20P.sp11%20nr%20Karookloof%20%231.wav,Platypleurasp11cfhirtipennis,25,validation,MHV%20843%20P.sp11%20nr%20Karookloof%20%231.wav
|
| 37 |
+
Myopsaltamackinlayi_Myopsalta_mackinlayi_6.1km_E_Kaimkillenbun.wav,Myopsaltamackinlayi,8,train,Myopsalta_mackinlayi_6.1km_E_Kaimkillenbun.wav
|
| 38 |
+
Kikihiamuta_08_Kikihia_muta_Rose_Saddle.wav,Kikihiamuta,5,train,08_Kikihia_muta_Rose_Saddle.wav
|
| 39 |
+
Platypleurasp10_MHV%20313%20P.sp10%20Die%20Koo%20%232.wav,Platypleurasp10,24,train,MHV%20313%20P.sp10%20Die%20Koo%20%232.wav
|
| 40 |
+
Myopsaltalongicauda_Myopsalta_longicauda_Myall_Park.wav,Myopsaltalongicauda,7,test,Myopsalta_longicauda_Myall_Park.wav
|
| 41 |
+
Platypleurahaglundi_MHV%20975%20P.haglundi%20Morningside%20Ranch.wav,Platypleurahaglundi,19,test,MHV%20975%20P.haglundi%20Morningside%20Ranch.wav
|
| 42 |
+
Pycnasemiclara_MHV%20919%20P.semiclara%20nr%20Tzaneen.wav,Pycnasemiclara,29,train,MHV%20919%20P.semiclara%20nr%20Tzaneen.wav
|
| 43 |
+
Platypleurachalybaea_MHV%20914%20P.chalybaea%20Kenton%20%233.wav,Platypleurachalybaea,16,train,MHV%20914%20P.chalybaea%20Kenton%20%233.wav
|
| 44 |
+
Platypleurachalybaea_MHV%20914%20P.chalybaea%20Kenton%20%232.wav,Platypleurachalybaea,16,validation,MHV%20914%20P.chalybaea%20Kenton%20%232.wav
|
| 45 |
+
Kikihiamuta_10_Kikihia_muta_Fox_River.wav,Kikihiamuta,5,train,10_Kikihia_muta_Fox_River.wav
|
| 46 |
+
Platypleurasp10_MHV%20313%20P.sp10%20Die%20Koo%20%233.wav,Platypleurasp10,24,train,MHV%20313%20P.sp10%20Die%20Koo%20%233.wav
|
| 47 |
+
Platypleuracfcatenata_MHV%20283%20P.catenata%20Sir%20Lowry%27s%20Pass%20%231.wav,Platypleuracfcatenata,15,train,MHV%20283%20P.catenata%20Sir%20Lowry%27s%20Pass%20%231.wav
|
| 48 |
+
Platypleurasp10_MHV%20866%20P.sp10%20Van%20Ryns%20Pass%20%234.wav,Platypleurasp10,24,train,MHV%20866%20P.sp10%20Van%20Ryns%20Pass%20%234.wav
|
| 49 |
+
Platypleurasp10_MHV%20313%20P.sp10%20Die%20Koo%20%237b.wav,Platypleurasp10,24,train,MHV%20313%20P.sp10%20Die%20Koo%20%237b.wav
|
| 50 |
+
Platypleuracfcatenata_MHV%20286%20P.catenata%20Grabow%20%233.wav,Platypleuracfcatenata,15,validation,MHV%20286%20P.catenata%20Grabow%20%233.wav
|
| 51 |
+
Pycnasemiclara_MHV%20321%20P.plumosa%20Ghwarriepoort%20River%20%231_0.wav,Pycnasemiclara,29,validation,MHV%20321%20P.plumosa%20Ghwarriepoort%20River%20%231_0.wav
|
| 52 |
+
Myopsaltalongicauda_Myopsalta_longicauda_Possum_Park.wav,Myopsaltalongicauda,7,train,Myopsalta_longicauda_Possum_Park.wav
|
| 53 |
+
Platypleuraplumosa_MHV%201488%20P.plumosa%20Nanaga%20Rec%20%233.wav,Platypleuraplumosa,22,train,MHV%201488%20P.plumosa%20Nanaga%20Rec%20%233.wav
|
| 54 |
+
Platypleurasp04_MHV%20596%20P.sp4%2010km%20S%20De%20Rust%20%232.wav,Platypleurasp04,23,train,MHV%20596%20P.sp4%2010km%20S%20De%20Rust%20%232.wav
|
| 55 |
+
Pycnasemiclara_MHV%20930%20P.semiclara%20R614%20nr%20Wartberg.wav,Pycnasemiclara,29,test,MHV%20930%20P.semiclara%20R614%20nr%20Wartberg.wav
|
| 56 |
+
Platypleurasp12cfhirtipennis_MHV%20838%20P.sp12%20Swartberg%20Pass.wav,Platypleurasp12cfhirtipennis,26,validation,MHV%20838%20P.sp12%20Swartberg%20Pass.wav
|
| 57 |
+
Myopsaltaxerograsidia_Myopsalta_xerograsidia_8km_W_Alice_Springs.wav,Myopsaltaxerograsidia,10,train,Myopsalta_xerograsidia_8km_W_Alice_Springs.wav
|
| 58 |
+
Platypleurasp10_MHV%20600%20P.sp10%2045km%20N%20Montague.wav,Platypleurasp10,24,train,MHV%20600%20P.sp10%2045km%20N%20Montague.wav
|
| 59 |
+
Platypleurachalybaea_MHV%201022%20P.chalybaea%20Zuurberg%20Pass%20%232.wav,Platypleurachalybaea,16,train,MHV%201022%20P.chalybaea%20Zuurberg%20Pass%20%232.wav
|
| 60 |
+
Platypleurasp13_MHV%201486%20P.sp%2013%20nr%20Gamtoos%20River%20Bridge%20%231.wav,Platypleurasp13,27,train,MHV%201486%20P.sp%2013%20nr%20Gamtoos%20River%20Bridge%20%231.wav
|
| 61 |
+
Platypleuraplumosa_MHV%201488%20P.plumosa%20Nanaga%20Rec%20%232.wav,Platypleuraplumosa,22,train,MHV%201488%20P.plumosa%20Nanaga%20Rec%20%232.wav
|
| 62 |
+
Pycnasemiclara_MHV%20922%20P.semiclara%20Woodcliffe%20Farm.wav,Pycnasemiclara,29,test,MHV%20922%20P.semiclara%20Woodcliffe%20Farm.wav
|
| 63 |
+
Platypleurasp13_MHV%201486%20P.sp%2013%20nr%20Gamtoos%20River%20Bridge%20%233.wav,Platypleurasp13,27,train,MHV%201486%20P.sp%2013%20nr%20Gamtoos%20River%20Bridge%20%233.wav
|
| 64 |
+
Platypleurasp04_MHV%20596%20P.sp4%2010km%20S%20De%20Rust%20%231.wav,Platypleurasp04,23,validation,MHV%20596%20P.sp4%2010km%20S%20De%20Rust%20%231.wav
|
| 65 |
+
Myopsaltaxerograsidia_Myopsalta_xerograsidia_Herberton.wav,Myopsaltaxerograsidia,10,test,Myopsalta_xerograsidia_Herberton.wav
|
| 66 |
+
Platypleurasp13_MHV%201486%20P.sp%2013%20nr%20Gamtoos%20River%20Bridge%20%232.wav,Platypleurasp13,27,validation,MHV%201486%20P.sp%2013%20nr%20Gamtoos%20River%20Bridge%20%232.wav
|
| 67 |
+
Platypleurachalybaea_MHV%201022%20P.chalybaea%20Zuurberg%20Pass%20%231.wav,Platypleurachalybaea,16,train,MHV%201022%20P.chalybaea%20Zuurberg%20Pass%20%231.wav
|
| 68 |
+
Platypleuraplumosa_MHV%201488%20P.plumosa%20Nanaga%20Rec%20%231.wav,Platypleuraplumosa,22,train,MHV%201488%20P.plumosa%20Nanaga%20Rec%20%231.wav
|
| 69 |
+
Platypleuradivisa_MHV%20989%20P.maytenophila%20nr%20Jozini.wav,Platypleuradivisa,18,train,MHV%20989%20P.maytenophila%20nr%20Jozini.wav
|
| 70 |
+
Kikihiamuta_06_Kikihia_muta_totoptype_Queen_Charlotte_Sound.wav,Kikihiamuta,5,test,06_Kikihia_muta_totoptype_Queen_Charlotte_Sound.wav
|
| 71 |
+
Myopsaltamackinlayi_Myopsalta_mackinlayi_Girraween.wav,Myopsaltamackinlayi,8,train,Myopsalta_mackinlayi_Girraween.wav
|
| 72 |
+
Platypleurahaglundi_MHV%20978%20P.haglundi%20nr%20Qudeni%20Forest.wav,Platypleurahaglundi,19,train,MHV%20978%20P.haglundi%20nr%20Qudeni%20Forest.wav
|
| 73 |
+
Platypleuracfcatenata_MHV%20288%20P.catenata%20Houwhoek%20Pass%20%232.wav,Platypleuracfcatenata,15,train,MHV%20288%20P.catenata%20Houwhoek%20Pass%20%232.wav
|
| 74 |
+
Platypleuracfcatenata_MHV%20288%20P.catenata%20Houwhoek%20Pass%20%233.wav,Platypleuracfcatenata,15,train,MHV%20288%20P.catenata%20Houwhoek%20Pass%20%233.wav
|
| 75 |
+
Platypleuraplumosa_MHV%20609%20P.plumosa%204km%20W%20De%20Rust%20%231.wav,Platypleuraplumosa,22,train,MHV%20609%20P.plumosa%204km%20W%20De%20Rust%20%231.wav
|
| 76 |
+
Myopsaltaleona_Myopsalta_leona_Eidsvold.wav,Myopsaltaleona,6,train,Myopsalta_leona_Eidsvold.wav
|
| 77 |
+
Platypleuraplumosa_MHV%201488%20P.plumosa%20Nanaga%20Rec%20%234.wav,Platypleuraplumosa,22,train,MHV%201488%20P.plumosa%20Nanaga%20Rec%20%234.wav
|
| 78 |
+
Platypleuracfcatenata_MHV%20900%20P.catenata%20Tradouws%20Pass%20%28maybe%20901%29.wav,Platypleuracfcatenata,15,train,MHV%20900%20P.catenata%20Tradouws%20Pass%20%28maybe%20901%29.wav
|
| 79 |
+
Azanicadazuluensis_MHV%20936%20A.zuluensis%20Mission%20Rock%20%232.wav,Azanicadazuluensis,0,train,MHV%20936%20A.zuluensis%20Mission%20Rock%20%232.wav
|
| 80 |
+
Platypleuradivisa_MHV%20954%20P.divisa%20nr%20Harrismith%20%28same%20as%20MHV%20990%29.wav,Platypleuradivisa,18,test,MHV%20954%20P.divisa%20nr%20Harrismith%20%28same%20as%20MHV%20990%29.wav
|
| 81 |
+
Platypleurasp12cfhirtipennis_MHV%20603%20P.sp12%205km%20W%20Prince%20Albert.wav,Platypleurasp12cfhirtipennis,26,test,MHV%20603%20P.sp12%205km%20W%20Prince%20Albert.wav
|
| 82 |
+
Myopsaltaleona_Myopsalta_leona_Cravens_Peak.wav,Myopsaltaleona,6,test,Myopsalta_leona_Cravens_Peak.wav
|
| 83 |
+
Myopsaltamackinlayi_Myopsalta_mackinlayi_Coolbaggie_dusk.wav,Myopsaltamackinlayi,8,train,Myopsalta_mackinlayi_Coolbaggie_dusk.wav
|
| 84 |
+
Kikihiamuta_07_Kikihia_muta_Nelson.wav,Kikihiamuta,5,test,07_Kikihia_muta_Nelson.wav
|
| 85 |
+
Platypleuracfcatenata_MHV%20288%20P.catenata%20Houwhoek%20Pass%20%231.wav,Platypleuracfcatenata,15,validation,MHV%20288%20P.catenata%20Houwhoek%20Pass%20%231.wav
|
| 86 |
+
Platypleuraplumosa_MHV%20609%20P.plumosa%204km%20W%20De%20Rust%20%232.wav,Platypleuraplumosa,22,test,MHV%20609%20P.plumosa%204km%20W%20De%20Rust%20%232.wav
|
| 87 |
+
Platypleurasp13_MHV%201486%20P.sp%2013%20nr%20Gamtoos%20River%20Bridge%20%234.wav,Platypleurasp13,27,test,MHV%201486%20P.sp%2013%20nr%20Gamtoos%20River%20Bridge%20%234.wav
|
| 88 |
+
Kikihiamuta_05_Kikihia_muta_North_Island_form.wav,Kikihiamuta,5,validation,05_Kikihia_muta_North_Island_form.wav
|
| 89 |
+
Myopsaltamackinlayi_Myopsalta_mackinlayi_Clandulla.wav,Myopsaltamackinlayi,8,test,Myopsalta_mackinlayi_Clandulla.wav
|
| 90 |
+
Azanicadazuluensis_MHV%20936%20A.zuluensis%20Mission%20Rock%20%231.wav,Azanicadazuluensis,0,test,MHV%20936%20A.zuluensis%20Mission%20Rock%20%231.wav
|
| 91 |
+
Kikihiamuta_09_Kikihia_muta_Westland_0.wav,Kikihiamuta,5,train,09_Kikihia_muta_Westland_0.wav
|
| 92 |
+
Pycnasemiclara_MHV%20925%20P.semiclara%20nr%20Grasskop%20%231.wav,Pycnasemiclara,29,train,MHV%20925%20P.semiclara%20nr%20Grasskop%20%231.wav
|
| 93 |
+
Platypleuradeusta_MHV%20990%20P.divisa%20nr%20Harrismith%20%28same%20as%20MHV%20990%29.wav,Platypleuradeusta,17,test,MHV%20990%20P.divisa%20nr%20Harrismith%20%28same%20as%20MHV%20990%29.wav
|
| 94 |
+
Myopsaltaxerograsidia_Myopsalta_xerograsidia_Cravens_Peak.wav,Myopsaltaxerograsidia,10,validation,Myopsalta_xerograsidia_Cravens_Peak.wav
|
| 95 |
+
Platypleuradivisa_MHV%20982%20P.divisa%20nr%20Barberton%20%28check%20ID%29.wav,Platypleuradivisa,18,train,MHV%20982%20P.divisa%20nr%20Barberton%20%28check%20ID%29.wav
|
| 96 |
+
Platypleuracapensis_MHV%20274%20P.capensis%20nr%20Arniston%20%232.wav,Platypleuracapensis,14,train,MHV%20274%20P.capensis%20nr%20Arniston%20%232.wav
|
| 97 |
+
Brevisianabrevis_MHV%201408%20Brevisiana%20brevis%20Dedza.wav,Brevisianabrevis,1,train,MHV%201408%20Brevisiana%20brevis%20Dedza.wav
|
| 98 |
+
Pycnasemiclara_MHV%20916%20P.semiclara%20nr%20Amajuba.wav,Pycnasemiclara,29,train,MHV%20916%20P.semiclara%20nr%20Amajuba.wav
|
| 99 |
+
Platypleuraplumosa_MHV%20329%20P.plumosa%20Steydtlerville%20%235a.wav,Platypleuraplumosa,22,train,MHV%20329%20P.plumosa%20Steydtlerville%20%235a.wav
|
| 100 |
+
Platypleurasp10_MHV%20891%20P.sp10%20Piekenierskloop%20Pass.wav,Platypleurasp10,24,train,MHV%20891%20P.sp10%20Piekenierskloop%20Pass.wav
|
| 101 |
+
Pycnasemiclara_MHV%20925%20P.semiclara%20nr%20Grasskop%20%232.wav,Pycnasemiclara,29,train,MHV%20925%20P.semiclara%20nr%20Grasskop%20%232.wav
|
| 102 |
+
Platypleuracfcatenata_MHV%20318%20P.capensis%20Prince%20Alberts%20Pass%20%235.wav,Platypleuracfcatenata,15,train,MHV%20318%20P.capensis%20Prince%20Alberts%20Pass%20%235.wav
|
| 103 |
+
Platypleuraplumosa_MHV%20501%20P.plumosa%20Fort%20Brown.wav,Platypleuraplumosa,22,test,MHV%20501%20P.plumosa%20Fort%20Brown.wav
|
| 104 |
+
Platypleuracapensis_MHV%20274%20P.capensis%20nr%20Arniston%20%231.wav,Platypleuracapensis,14,validation,MHV%20274%20P.capensis%20nr%20Arniston%20%231.wav
|
| 105 |
+
Platypleurasp12cfhirtipennis_MHV%20839%20P.sp12%20Swartberg%20Pass.wav,Platypleurasp12cfhirtipennis,26,test,MHV%20839%20P.sp12%20Swartberg%20Pass.wav
|
| 106 |
+
Myopsaltaleona_Myopsalta_leona_Wyalong.wav,Myopsaltaleona,6,train,Myopsalta_leona_Wyalong.wav
|
| 107 |
+
Platypleurasp04_MHV%20598%20P.sp4%20nr%20Maitjiesfontein.wav,Platypleurasp04,23,train,MHV%20598%20P.sp4%20nr%20Maitjiesfontein.wav
|
| 108 |
+
Platypleuracfcatenata_MHV%20318%20P.capensis%20Prince%20Alberts%20Pass%20%234.wav,Platypleuracfcatenata,15,train,MHV%20318%20P.capensis%20Prince%20Alberts%20Pass%20%234.wav
|
| 109 |
+
Platypleuradivisa_MHV%20983%20P.divisa%20nr%20Piet%20Retief.wav,Platypleuradivisa,18,train,MHV%20983%20P.divisa%20nr%20Piet%20Retief.wav
|
| 110 |
+
Platypleuraplumosa_MHV%20329%20P.plumosa%20Steydtlerville%20%235b.wav,Platypleuraplumosa,22,test,MHV%20329%20P.plumosa%20Steydtlerville%20%235b.wav
|
| 111 |
+
Platypleurahaglundi_MHV%20973%20P.haglundi%20nr%20Barberton%20%231.wav,Platypleurahaglundi,19,test,MHV%20973%20P.haglundi%20nr%20Barberton%20%231.wav
|
| 112 |
+
Azanicadazuluensis_MHV%20935%20A.zuluensis%20Haga%20Haga%20%235.wav,Azanicadazuluensis,0,validation,MHV%20935%20A.zuluensis%20Haga%20Haga%20%235.wav
|
| 113 |
+
Platypleuracfcatenata_MHV%20903%20P.catenata%20nrWitrivier.wav,Platypleuracfcatenata,15,train,MHV%20903%20P.catenata%20nrWitrivier.wav
|
| 114 |
+
Platypleuraplumosa_MHV%20321%20P.plumosa%20Ghwarriepoort%20River%20%231.wav,Platypleuraplumosa,22,validation,MHV%20321%20P.plumosa%20Ghwarriepoort%20River%20%231.wav
|
| 115 |
+
Platypleurasp04_MHV%20597%20P.sp4%20Meiringspoort%20Pass%20%231.wav,Platypleurasp04,23,test,MHV%20597%20P.sp4%20Meiringspoort%20Pass%20%231.wav
|
| 116 |
+
Myopsaltamelanobasis_Myopsalta_melanobasis_Maclagan.wav,Myopsaltamelanobasis,9,train,Myopsalta_melanobasis_Maclagan.wav
|
| 117 |
+
Platypleurahirtipennis_MHV%20486%20P.hirtipennis%20Coombs%20View%20%231.wav,Platypleurahirtipennis,20,validation,MHV%20486%20P.hirtipennis%20Coombs%20View%20%231.wav
|
| 118 |
+
Platypleuracapensis_MHV%201489%20P.capensis%20nr%20R102%20%231.wav,Platypleuracapensis,14,train,MHV%201489%20P.capensis%20nr%20R102%20%231.wav
|
| 119 |
+
Platypleurasp12cfhirtipennis_MHV%20602%20P.sp12%2020km%20SE%20Prince%20Albert.wav,Platypleurasp12cfhirtipennis,26,train,MHV%20602%20P.sp12%2020km%20SE%20Prince%20Albert.wav
|
| 120 |
+
Platypleuracfcatenata_MHV%20318%20P.capensis%20Prince%20Alberts%20Pass%20%231.wav,Platypleuracfcatenata,15,train,MHV%20318%20P.capensis%20Prince%20Alberts%20Pass%20%231.wav
|
| 121 |
+
Platypleurasp12cfhirtipennis_MHV%20898%20P.sp12%20nr%20Ganskop.wav,Platypleurasp12cfhirtipennis,26,train,MHV%20898%20P.sp12%20nr%20Ganskop.wav
|
| 122 |
+
Platypleurahaglundi_MHV%20976%20P.haglundi%20Blyde%20River%20Canyon.wav,Platypleurahaglundi,19,train,MHV%20976%20P.haglundi%20Blyde%20River%20Canyon.wav
|
| 123 |
+
Myopsaltaleona_Myopsalta_leona_Willowvale.wav,Myopsaltaleona,6,train,Myopsalta_leona_Willowvale.wav
|
| 124 |
+
Platypleuradeusta_MHV%20991%20P.duesta%20Woodcliffe%20Farm.wav,Platypleuradeusta,17,train,MHV%20991%20P.duesta%20Woodcliffe%20Farm.wav
|
| 125 |
+
Platypleurahaglundi_MHV%20973%20P.haglundi%20nr%20Barberton%20%232.wav,Platypleurahaglundi,19,validation,MHV%20973%20P.haglundi%20nr%20Barberton%20%232.wav
|
| 126 |
+
Myopsaltamackinlayi_Myopsalta_mackinlayi_Brigalow_Research_Station.wav,Myopsaltamackinlayi,8,train,Myopsalta_mackinlayi_Brigalow_Research_Station.wav
|
| 127 |
+
Platypleuraplumosa_MHV%20321%20P.plumosa%20Ghwarriepoort%20River%20%232.wav,Platypleuraplumosa,22,train,MHV%20321%20P.plumosa%20Ghwarriepoort%20River%20%232.wav
|
| 128 |
+
Platypleuraplumosa_MHV%20540%20P.plumosa%20Fish%20River%20Bridge.wav,Platypleuraplumosa,22,train,MHV%20540%20P.plumosa%20Fish%20River%20Bridge.wav
|
| 129 |
+
Platypleuracfcatenata_MHV%20318%20P.capensis%20Prince%20Alberts%20Pass%20%233.wav,Platypleuracfcatenata,15,train,MHV%20318%20P.capensis%20Prince%20Alberts%20Pass%20%233.wav
|
| 130 |
+
Platypleurahirtipennis_MHV%201028%20P.hirtipennis%20nr%20Patterson.wav,Platypleurahirtipennis,20,train,MHV%201028%20P.hirtipennis%20nr%20Patterson.wav
|
| 131 |
+
Platypleurasp04_MHV%20597%20P.sp4%20Meiringspoort%20Pass%20%232.wav,Platypleurasp04,23,test,MHV%20597%20P.sp4%20Meiringspoort%20Pass%20%232.wav
|
| 132 |
+
Platypleurahirtipennis_MHV%20486%20P.hirtipennis%20Coombs%20View%20%232.wav,Platypleurahirtipennis,20,test,MHV%20486%20P.hirtipennis%20Coombs%20View%20%232.wav
|
| 133 |
+
Platypleuracfcatenata_MHV%20318%20P.capensis%20Prince%20Alberts%20Pass%20%232.wav,Platypleuracfcatenata,15,train,MHV%20318%20P.capensis%20Prince%20Alberts%20Pass%20%232.wav
|
| 134 |
+
Platypleuraplumosa_MHV%20610%20P.plumosa%2040km%20E%20Prince%20Albert.wav,Platypleuraplumosa,22,train,MHV%20610%20P.plumosa%2040km%20E%20Prince%20Albert.wav
|
| 135 |
+
Myopsaltaleona_Myopsalta_leona_9km_NW_Grenfell.wav,Myopsaltaleona,6,train,Myopsalta_leona_9km_NW_Grenfell.wav
|
| 136 |
+
Platypleuraplumosa_MHV%20329%20P.plumosa%20Steydtlerville%20%233.wav,Platypleuraplumosa,22,validation,MHV%20329%20P.plumosa%20Steydtlerville%20%233.wav
|
| 137 |
+
Platypleurasp04_MHV%20595%20P.sp4%20nr%20Van%20Wyk%27s%20Dorp.wav,Platypleurasp04,23,train,MHV%20595%20P.sp4%20nr%20Van%20Wyk%27s%20Dorp.wav
|
| 138 |
+
Platypleuracfcatenata_MHV%20393%20P.catenata%20Jefferies%20Bay%20%233.wav,Platypleuracfcatenata,15,test,MHV%20393%20P.catenata%20Jefferies%20Bay%20%233.wav
|
| 139 |
+
Platypleuradeusta_MHV%20514%20P.duesta%20Nico%20Malan%20Pass%20%231.wav,Platypleuradeusta,17,validation,MHV%20514%20P.duesta%20Nico%20Malan%20Pass%20%231.wav
|
| 140 |
+
Platypleurasp10_MHV%20847%20P.sp10%20nr%20Kagga%20Kama%20%232.wav,Platypleurasp10,24,test,MHV%20847%20P.sp10%20nr%20Kagga%20Kama%20%232.wav
|
| 141 |
+
Platypleurasp13_MHV%201487%20P.sp%2013%20nr%20Thornhill%20%235.wav,Platypleurasp13,27,train,MHV%201487%20P.sp%2013%20nr%20Thornhill%20%235.wav
|
| 142 |
+
Platypleuradivisa_MHV%20515%20P.divisa%20S%20of%20Whittlesey%20%231.wav,Platypleuradivisa,18,validation,MHV%20515%20P.divisa%20S%20of%20Whittlesey%20%231.wav
|
| 143 |
+
Platypleurahirtipennis_MHV%20488%20P.hirtipennis%20Fish%20River%20Mouth%20%233.wav,Platypleurahirtipennis,20,train,MHV%20488%20P.hirtipennis%20Fish%20River%20Mouth%20%233.wav
|
| 144 |
+
Platypleurahirtipennis_MHV%20488%20P.hirtipennis%20Fish%20River%20Mouth%20%232.wav,Platypleurahirtipennis,20,train,MHV%20488%20P.hirtipennis%20Fish%20River%20Mouth%20%232.wav
|
| 145 |
+
Myopsaltaxerograsidia_Myopsalta_xerograsidia_Surat.wav,Myopsaltaxerograsidia,10,train,Myopsalta_xerograsidia_Surat.wav
|
| 146 |
+
Platypleurasp13_MHV%201487%20P.sp%2013%20nr%20Thornhill%20%234.wav,Platypleurasp13,27,test,MHV%201487%20P.sp%2013%20nr%20Thornhill%20%234.wav
|
| 147 |
+
Platypleuracapensis_MHV%20277%20P.capensis%204km%20W%20Die%20Dam%20%231.wav,Platypleuracapensis,14,train,MHV%20277%20P.capensis%204km%20W%20Die%20Dam%20%231.wav
|
| 148 |
+
Platypleuracfcatenata_MHV%20393%20P.catenata%20Jefferies%20Bay%20%232.wav,Platypleuracfcatenata,15,train,MHV%20393%20P.catenata%20Jefferies%20Bay%20%232.wav
|
| 149 |
+
Platypleurasp10_MHV%20313%20P.sp10%20Die%20Koo%20%238a.wav,Platypleurasp10,24,train,MHV%20313%20P.sp10%20Die%20Koo%20%238a.wav
|
| 150 |
+
Platypleuraplumosa_MHV%20329%20P.plumosa%20Steydtlerville%20%232.wav,Platypleuraplumosa,22,train,MHV%20329%20P.plumosa%20Steydtlerville%20%232.wav
|
| 151 |
+
Pycnasemiclara_MHV%20931%20P.semiclara%20Coffee%20Bay%20%232.wav,Pycnasemiclara,29,train,MHV%20931%20P.semiclara%20Coffee%20Bay%20%232.wav
|
| 152 |
+
Platypleuradeusta_MHV%20514%20P.duesta%20Nico%20Malan%20Pass%20%232.wav,Platypleuradeusta,17,test,MHV%20514%20P.duesta%20Nico%20Malan%20Pass%20%232.wav
|
| 153 |
+
Platypleuracapensis_MHV%20277%20P.capensis%204km%20W%20Die%20Dam%20%233.wav,Platypleuracapensis,14,test,MHV%20277%20P.capensis%204km%20W%20Die%20Dam%20%233.wav
|
| 154 |
+
Platypleurasp10_MHV%20847%20P.sp10%20nr%20Kagga%20Kama%20%231.wav,Platypleurasp10,24,test,MHV%20847%20P.sp10%20nr%20Kagga%20Kama%20%231.wav
|
| 155 |
+
Platypleurasp11cfhirtipennis_MHV%20845%20P.sp11%20Leeuwenshof%20%232.wav,Platypleurasp11cfhirtipennis,25,train,MHV%20845%20P.sp11%20Leeuwenshof%20%232.wav
|
| 156 |
+
Myopsaltamackinlayi_Myopsalta_mackinlayi_Boomer_Range.wav,Myopsaltamackinlayi,8,validation,Myopsalta_mackinlayi_Boomer_Range.wav
|
| 157 |
+
Platypleuradivisa_MHV%20515%20P.divisa%20S%20of%20Whittlesey%20%232.wav,Platypleuradivisa,18,test,MHV%20515%20P.divisa%20S%20of%20Whittlesey%20%232.wav
|
| 158 |
+
Platypleuradeusta_MHV%20994%20P.duesta%20Fort%20Nottingham.wav,Platypleuradeusta,17,train,MHV%20994%20P.duesta%20Fort%20Nottingham.wav
|
| 159 |
+
Platypleurahirtipennis_MHV%20488%20P.hirtipennis%20Fish%20River%20Mouth%20%231.wav,Platypleurahirtipennis,20,test,MHV%20488%20P.hirtipennis%20Fish%20River%20Mouth%20%231.wav
|
| 160 |
+
Myopsaltamelanobasis_Myopsalta_melanobasis_Southwood.wav,Myopsaltamelanobasis,9,train,Myopsalta_melanobasis_Southwood.wav
|
| 161 |
+
Platypleurasp04_MHV%20906%20P.sp4%20nr%20Barrydale.wav,Platypleurasp04,23,train,MHV%20906%20P.sp4%20nr%20Barrydale.wav
|
| 162 |
+
Platypleurasp12cfhirtipennis_MHV%20601%20P.sp12%2015km%20S%20Ladismith.wav,Platypleurasp12cfhirtipennis,26,validation,MHV%20601%20P.sp12%2015km%20S%20Ladismith.wav
|
| 163 |
+
Platypleuradeusta_MHV%20514%20P.duesta%20Nico%20Malan%20Pass%20%233.wav,Platypleuradeusta,17,train,MHV%20514%20P.duesta%20Nico%20Malan%20Pass%20%233.wav
|
| 164 |
+
Platypleuracfcatenata_MHV%20393%20P.catenata%20Jefferies%20Bay%20%231.wav,Platypleuracfcatenata,15,train,MHV%20393%20P.catenata%20Jefferies%20Bay%20%231.wav
|
| 165 |
+
Platypleurasp10_MHV%20313%20P.sp10%20Die%20Koo%20%234a.wav,Platypleurasp10,24,validation,MHV%20313%20P.sp10%20Die%20Koo%20%234a.wav
|
| 166 |
+
Platypleuraplumosa_MHV%20329%20P.plumosa%20Steydtlerville%20%231.wav,Platypleuraplumosa,22,test,MHV%20329%20P.plumosa%20Steydtlerville%20%231.wav
|
| 167 |
+
Myopsaltalongicauda_Myopsalta_longicauda_Stockingbingal.wav,Myopsaltalongicauda,7,train,Myopsalta_longicauda_Stockingbingal.wav
|
| 168 |
+
Platypleurasp13_MHV%201487%20P.sp%2013%20nr%20Thornhill%20%233.wav,Platypleurasp13,27,train,MHV%201487%20P.sp%2013%20nr%20Thornhill%20%233.wav
|
| 169 |
+
Platypleurasp13_MHV%201490%20P.sp%2013%20Gamtoos%20Pass%20%232.wav,Platypleurasp13,27,train,MHV%201490%20P.sp%2013%20Gamtoos%20Pass%20%232.wav
|
| 170 |
+
Pycnasemiclara_MHV%20923%20P.semiclara%20nr%20Donnybrook.wav,Pycnasemiclara,29,validation,MHV%20923%20P.semiclara%20nr%20Donnybrook.wav
|
| 171 |
+
Platypleurasp12cfhirtipennis_MHV%20606%20P.sp12%2020km%20S%20Ladismith.wav,Platypleurasp12cfhirtipennis,26,train,MHV%20606%20P.sp12%2020km%20S%20Ladismith.wav
|
| 172 |
+
Platypleuracfcatenata_MHV%20835%20P.catenata%20Swartberg%20Pass.wav,Platypleuracfcatenata,15,test,MHV%20835%20P.catenata%20Swartberg%20Pass.wav
|
| 173 |
+
Platypleuraintercapedinis_MHV%20947%20P.cf_.brunea%20Morningside%20Ranch%20%231.wav,Platypleuraintercapedinis,21,test,MHV%20947%20P.cf_.brunea%20Morningside%20Ranch%20%231.wav
|
| 174 |
+
Myopsaltamelanobasis_Myopsalta_melanobasis_20km_S_Taroom.wav,Myopsaltamelanobasis,9,test,Myopsalta_melanobasis_20km_S_Taroom.wav
|
| 175 |
+
Platypleurasp13_MHV%201487%20P.sp%2013%20nr%20Thornhill%20%232.wav,Platypleurasp13,27,train,MHV%201487%20P.sp%2013%20nr%20Thornhill%20%232.wav
|
| 176 |
+
Myopsaltalongicauda_Myopsalta_longicauda_Geham.wav,Myopsaltalongicauda,7,validation,Myopsalta_longicauda_Geham.wav
|
| 177 |
+
Platypleuraplumosa_MHV%20329%20P.plumosa%20Steydtlerville%20%234.wav,Platypleuraplumosa,22,train,MHV%20329%20P.plumosa%20Steydtlerville%20%234.wav
|
| 178 |
+
Platypleurasp12cfhirtipennis_MHV%20605%20P.sp12%2030km%20SW%20Ladismith.wav,Platypleurasp12cfhirtipennis,26,train,MHV%20605%20P.sp12%2030km%20SW%20Ladismith.wav
|
| 179 |
+
Platypleuradeusta_MHV%20992%20P.duesta%20nr%20Grasskop.wav,Platypleuradeusta,17,train,MHV%20992%20P.duesta%20nr%20Grasskop.wav
|
| 180 |
+
Myopsaltaleona_Myopsalta_leona_4km_W_Binjour.wav,Myopsaltaleona,6,validation,Myopsalta_leona_4km_W_Binjour.wav
|
| 181 |
+
Platypleurasp13_MHV%201490%20P.sp%2013%20Gamtoos%20Pass%20%231.wav,Platypleurasp13,27,train,MHV%201490%20P.sp%2013%20Gamtoos%20Pass%20%231.wav
|
| 182 |
+
Platypleurasp11cfhirtipennis_MHV%20859%20P.sp11%20Trawal%20%232.wav,Platypleurasp11cfhirtipennis,25,test,MHV%20859%20P.sp11%20Trawal%20%232.wav
|
| 183 |
+
Platypleuraintercapedinis_MHV%20947%20P.cf_.brunea%20Morningside%20Ranch%20%232.wav,Platypleuraintercapedinis,21,test,MHV%20947%20P.cf_.brunea%20Morningside%20Ranch%20%232.wav
|
| 184 |
+
Myopsaltamelanobasis_Myopsalta_melanobasis_14.6km_W_Drillham_Ck.wav,Myopsaltamelanobasis,9,validation,Myopsalta_melanobasis_14.6km_W_Drillham_Ck.wav
|
| 185 |
+
Platypleurasp13_MHV%201487%20P.sp%2013%20nr%20Thornhill%20%231.wav,Platypleurasp13,27,test,MHV%201487%20P.sp%2013%20nr%20Thornhill%20%231.wav
|
| 186 |
+
Platypleuracfcatenata_MHV%20607%20P.catenata%2020km%20W%20Swellendam%20R324.wav,Platypleuracfcatenata,15,test,MHV%20607%20P.catenata%2020km%20W%20Swellendam%20R324.wav
|
| 187 |
+
Platypleuracapensis_MHV%20277%20P.capensis%204km%20W%20Die%20Dam%20%234.wav,Platypleuracapensis,14,train,MHV%20277%20P.capensis%204km%20W%20Die%20Dam%20%234.wav
|
| 188 |
+
Platypleuraintercapedinis_MHV%20948%20P.cf_.brunea%20Morning%20Sun%20Ranch.wav,Platypleuraintercapedinis,21,train,MHV%20948%20P.cf_.brunea%20Morning%20Sun%20Ranch.wav
|
| 189 |
+
Platypleuracfcatenata_MHV%201017%20P.catenata%20nr%20Hankey%20%2817th%20Jan%202008%20rec%237%29.wav,Platypleuracfcatenata,15,train,MHV%201017%20P.catenata%20nr%20Hankey%20%2817th%20Jan%202008%20rec%237%29.wav
|
data/Orthoptera.csv
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
file_name,species,class_ID,data_set,original_file_name
|
| 2 |
+
Tettigoniaviridissima_200726_0062.M.wav,Tettigoniaviridissima,31,validation,200726_0062.M.wav
|
| 3 |
+
Grylluscampestris_GRYCAM_20210728_115826.M.wav,Grylluscampestris,4,train,GRYCAM_20210728_115826.M.wav
|
| 4 |
+
Grylluscampestris_dat008-019.M.wav,Grylluscampestris,4,train,dat008-019.M.wav
|
| 5 |
+
Pseudochorthippusparallelus_dat003-016.M.wav,Pseudochorthippusparallelus,28,train,dat003-016.M.wav
|
| 6 |
+
Nemobiussylvestris_dat017-001.wav,Nemobiussylvestris,11,train,dat017-001.wav
|
| 7 |
+
Grylluscampestris_dat003-004.M.wav,Grylluscampestris,4,validation,dat003-004.M.wav
|
| 8 |
+
Nemobiussylvestris_MixPre-304.M.wav,Nemobiussylvestris,11,test,MixPre-304.M.wav
|
| 9 |
+
Pholidopteragriseoaptera_dat006-002.M.wav,Pholidopteragriseoaptera,13,train,dat006-002.M.wav
|
| 10 |
+
Chorthippusbiguttulus_CHOBIG_20190906_163909.M.wav,Chorthippusbiguttulus,2,train,CHOBIG_20190906_163909.M.wav
|
| 11 |
+
Chorthippusbrunneus_dat024-016.wav,Chorthippusbrunneus,3,train,dat024-016.wav
|
| 12 |
+
Pseudochorthippusparallelus_VOC_150705-0325.M.wav,Pseudochorthippusparallelus,28,test,VOC_150705-0325.M.wav
|
| 13 |
+
Chorthippusbiguttulus_Take91.wav,Chorthippusbiguttulus,2,test,Take91.wav
|
| 14 |
+
Grylluscampestris_Take11.M.wav,Grylluscampestris,4,train,Take11.M.wav
|
| 15 |
+
Pseudochorthippusparallelus_Take00.M.wav,Pseudochorthippusparallelus,28,train,Take00.M.wav
|
| 16 |
+
Tettigoniaviridissima_MixPre-198.wav,Tettigoniaviridissima,31,test,MixPre-198.wav
|
| 17 |
+
Nemobiussylvestris_Take23.wav,Nemobiussylvestris,11,train,Take23.wav
|
| 18 |
+
Tettigoniaviridissima_dat118-003.M.wav,Tettigoniaviridissima,31,train,dat118-003.M.wav
|
| 19 |
+
Pholidopteragriseoaptera_dat022-004.wav,Pholidopteragriseoaptera,13,test,dat022-004.wav
|
| 20 |
+
Pholidopteragriseoaptera_dat097-023.wav,Pholidopteragriseoaptera,13,test,dat097-023.wav
|
| 21 |
+
Pholidopteragriseoaptera_dat003-037.M.wav,Pholidopteragriseoaptera,13,validation,dat003-037.M.wav
|
| 22 |
+
Grylluscampestris_dat010-007.M.wav,Grylluscampestris,4,test,dat010-007.M.wav
|
| 23 |
+
Tettigoniaviridissima_Take23.M.wav,Tettigoniaviridissima,31,train,Take23.M.wav
|
| 24 |
+
Chorthippusbiguttulus_Take45.M.wav,Chorthippusbiguttulus,2,train,Take45.M.wav
|
| 25 |
+
Nemobiussylvestris_Take20.wav,Nemobiussylvestris,11,train,Take20.wav
|
| 26 |
+
Nemobiussylvestris_Take21-1.wav,Nemobiussylvestris,11,train,Take21-1.wav
|
| 27 |
+
Grylluscampestris_dat010-005.M.wav,Grylluscampestris,4,train,dat010-005.M.wav
|
| 28 |
+
Oecanthuspellucens_Take05.wav,Oecanthuspellucens,12,train,Take05.wav
|
| 29 |
+
Chorthippusbrunneus_dat005-044.M.wav,Chorthippusbrunneus,3,train,dat005-044.M.wav
|
| 30 |
+
Chorthippusbrunneus_NoID_20200809_160342.M.wav,Chorthippusbrunneus,3,train,NoID_20200809_160342.M.wav
|
| 31 |
+
Tettigoniaviridissima_Take05.M.wav,Tettigoniaviridissima,31,train,Take05.M.wav
|
| 32 |
+
Nemobiussylvestris_Take21.wav,Nemobiussylvestris,11,train,Take21.wav
|
| 33 |
+
Tettigoniaviridissima_dat017-007.M.wav,Tettigoniaviridissima,31,train,dat017-007.M.wav
|
| 34 |
+
Chorthippusbiguttulus_dat028-023.wav,Chorthippusbiguttulus,2,train,dat028-023.wav
|
| 35 |
+
Nemobiussylvestris_20170828_205431.M.wav,Nemobiussylvestris,11,train,20170828_205431.M.wav
|
| 36 |
+
Chorthippusbiguttulus_Take07.M.wav,Chorthippusbiguttulus,2,test,Take07.M.wav
|
| 37 |
+
Tettigoniaviridissima_dat029-004.M.wav,Tettigoniaviridissima,31,train,dat029-004.M.wav
|
| 38 |
+
Roeselianaroeselii_dat025-009.M.wav,Roeselianaroeselii,30,train,dat025-009.M.wav
|
| 39 |
+
Pseudochorthippusparallelus_dat023-006.wav,Pseudochorthippusparallelus,28,train,dat023-006.wav
|
| 40 |
+
Chorthippusbiguttulus_dat179-001.wav,Chorthippusbiguttulus,2,train,dat179-001.wav
|
| 41 |
+
Roeselianaroeselii_dat025-010.M.wav,Roeselianaroeselii,30,train,dat025-010.M.wav
|
| 42 |
+
Pholidopteragriseoaptera_dat003-029.M.wav,Pholidopteragriseoaptera,13,train,dat003-029.M.wav
|
| 43 |
+
Pseudochorthippusparallelus_CHOPAR_20190626_194920.M.wav,Pseudochorthippusparallelus,28,train,CHOPAR_20190626_194920.M.wav
|
| 44 |
+
Pholidopteragriseoaptera_PHOGRI_20190914_155550.M.wav,Pholidopteragriseoaptera,13,train,PHOGRI_20190914_155550.M.wav
|
| 45 |
+
Roeselianaroeselii_Ultramic_20130809 190241.M.wav,Roeselianaroeselii,30,train,Ultramic_20130809 190241.M.wav
|
| 46 |
+
Grylluscampestris_dat008-018.M.wav,Grylluscampestris,4,train,dat008-018.M.wav
|
| 47 |
+
Grylluscampestris_dat008-008.wav,Grylluscampestris,4,train,dat008-008.wav
|
| 48 |
+
Roeselianaroeselii_dat006-019.M.wav,Roeselianaroeselii,30,validation,dat006-019.M.wav
|
| 49 |
+
Pseudochorthippusparallelus_dat023-005.wav,Pseudochorthippusparallelus,28,validation,dat023-005.wav
|
| 50 |
+
Grylluscampestris_dat008-009.wav,Grylluscampestris,4,train,dat008-009.wav
|
| 51 |
+
Chorthippusbiguttulus_dat001-018.M.wav,Chorthippusbiguttulus,2,train,dat001-018.M.wav
|
| 52 |
+
Grylluscampestris_dat003-005.M.wav,Grylluscampestris,4,test,dat003-005.M.wav
|
| 53 |
+
Tettigoniaviridissima_TETVIR_20200808_183034.M.wav,Tettigoniaviridissima,31,train,TETVIR_20200808_183034.M.wav
|
| 54 |
+
Pholidopteragriseoaptera_Ultramic_20130915 203136.M.wav,Pholidopteragriseoaptera,13,train,Ultramic_20130915 203136.M.wav
|
| 55 |
+
Pseudochorthippusparallelus_20170718_205835.M.wav,Pseudochorthippusparallelus,28,validation,20170718_205835.M.wav
|
| 56 |
+
Chorthippusbrunneus_No_ID_20170802_132433.M.wav,Chorthippusbrunneus,3,train,No_ID_20170802_132433.M.wav
|
| 57 |
+
Roeselianaroeselii_dat006-020.M.wav,Roeselianaroeselii,30,train,dat006-020.M.wav
|
| 58 |
+
Pseudochorthippusparallelus_dat001-044.M.wav,Pseudochorthippusparallelus,28,train,dat001-044.M.wav
|
| 59 |
+
Chorthippusbrunneus_dat011-004.wav,Chorthippusbrunneus,3,validation,dat011-004.wav
|
| 60 |
+
Pseudochorthippusparallelus_dat044-019.wav,Pseudochorthippusparallelus,28,train,dat044-019.wav
|
| 61 |
+
Grylluscampestris_Take32.M.wav,Grylluscampestris,4,validation,Take32.M.wav
|
| 62 |
+
Pseudochorthippusparallelus_dat004-016.M.wav,Pseudochorthippusparallelus,28,test,dat004-016.M.wav
|
| 63 |
+
Roeselianaroeselii_dat015-001.M.wav,Roeselianaroeselii,30,train,dat015-001.M.wav
|
| 64 |
+
Oecanthuspellucens_dat168-015.wav,Oecanthuspellucens,12,test,dat168-015.wav
|
| 65 |
+
Chorthippusbiguttulus_file0224.M.wav,Chorthippusbiguttulus,2,train,file0224.M.wav
|
| 66 |
+
Chorthippusbrunneus_dat003-020.M.wav,Chorthippusbrunneus,3,train,dat003-020.M.wav
|
| 67 |
+
Chorthippusbrunneus_dat022-008.wav,Chorthippusbrunneus,3,train,dat022-008.wav
|
| 68 |
+
Chorthippusbiguttulus_dat185-002.wav,Chorthippusbiguttulus,2,train,dat185-002.wav
|
| 69 |
+
Chorthippusbiguttulus_dat005-056.M.wav,Chorthippusbiguttulus,2,train,dat005-056.M.wav
|
| 70 |
+
Roeselianaroeselii_dat006-006.M.wav,Roeselianaroeselii,30,train,dat006-006.M.wav
|
| 71 |
+
Oecanthuspellucens_Take73.M.wav,Oecanthuspellucens,12,validation,Take73.M.wav
|
| 72 |
+
Tettigoniaviridissima_dat003-039.M.wav,Tettigoniaviridissima,31,train,dat003-039.M.wav
|
| 73 |
+
Chorthippusbiguttulus_NoID_20210729_115824.M.wav,Chorthippusbiguttulus,2,train,NoID_20210729_115824.M.wav
|
| 74 |
+
Pseudochorthippusparallelus_dat026-038.M.wav,Pseudochorthippusparallelus,28,test,dat026-038.M.wav
|
| 75 |
+
Grylluscampestris_dat010-006.M.wav,Grylluscampestris,4,train,dat010-006.M.wav
|
| 76 |
+
Chorthippusbiguttulus_Take22.wav,Chorthippusbiguttulus,2,validation,Take22.wav
|
| 77 |
+
Grylluscampestris_dat010-004.wav,Grylluscampestris,4,train,dat010-004.wav
|
| 78 |
+
Chorthippusbiguttulus_dat001-020.M.wav.M.wav,Chorthippusbiguttulus,2,validation,dat001-020.M.wav.M.wav
|
| 79 |
+
Tettigoniaviridissima_dat110-002.M.wav,Tettigoniaviridissima,31,train,dat110-002.M.wav
|
| 80 |
+
Pholidopteragriseoaptera_20200705_063934.M.wav,Pholidopteragriseoaptera,13,validation,20200705_063934.M.wav
|
| 81 |
+
Pseudochorthippusparallelus_PSEPAR_20210729_164449.M.wav,Pseudochorthippusparallelus,28,train,PSEPAR_20210729_164449.M.wav
|
| 82 |
+
Nemobiussylvestris_dat044-015.wav,Nemobiussylvestris,11,validation,dat044-015.wav
|
| 83 |
+
Grylluscampestris_dat008-012.M.wav,Grylluscampestris,4,train,dat008-012.M.wav
|
| 84 |
+
Chorthippusbrunneus_dat124-003.M.wav,Chorthippusbrunneus,3,validation,dat124-003.M.wav
|
| 85 |
+
Tettigoniaviridissima_Take70.M.wav,Tettigoniaviridissima,31,test,Take70.M.wav
|
| 86 |
+
Roeselianaroeselii_Metrioptera roeselii Echt.M.wav,Roeselianaroeselii,30,train,Metrioptera roeselii Echt.M.wav
|
| 87 |
+
Oecanthuspellucens_Take40.M.wav,Oecanthuspellucens,12,train,Take40.M.wav
|
| 88 |
+
Oecanthuspellucens_Take38.M.wav,Oecanthuspellucens,12,train,Take38.M.wav
|
| 89 |
+
Nemobiussylvestris_NoID_20210724_144844.M.wav,Nemobiussylvestris,11,train,NoID_20210724_144844.M.wav
|
| 90 |
+
Oecanthuspellucens_dat213-002.wav,Oecanthuspellucens,12,validation,dat213-002.wav
|
| 91 |
+
Chorthippusbrunneus_dat001-040.M.wav,Chorthippusbrunneus,3,train,dat001-040.M.wav
|
| 92 |
+
Oecanthuspellucens_dat116-008.M.wav,Oecanthuspellucens,12,test,dat116-008.M.wav
|
| 93 |
+
Roeselianaroeselii_dat006-015.M.wav,Roeselianaroeselii,30,train,dat006-015.M.wav
|
| 94 |
+
Nemobiussylvestris_No_ID_20170828_205643.M.wav,Nemobiussylvestris,11,train,No_ID_20170828_205643.M.wav
|
| 95 |
+
Grylluscampestris_dat008-010.wav,Grylluscampestris,4,train,dat008-010.wav
|
| 96 |
+
Grylluscampestris_dat008-014.M.wav,Grylluscampestris,4,train,dat008-014.M.wav
|
| 97 |
+
Chorthippusbiguttulus_CHOBIG_20190906_164243.M.wav,Chorthippusbiguttulus,2,test,CHOBIG_20190906_164243.M.wav
|
| 98 |
+
Tettigoniaviridissima_Ultramic_20130809 212842.M.wav,Tettigoniaviridissima,31,test,Ultramic_20130809 212842.M.wav
|
| 99 |
+
Chorthippusbrunneus_dat001-021.M.wav,Chorthippusbrunneus,3,test,dat001-021.M.wav
|
| 100 |
+
Grylluscampestris_dat010-003.wav,Grylluscampestris,4,train,dat010-003.wav
|
| 101 |
+
Oecanthuspellucens_dat213-001.wav,Oecanthuspellucens,12,test,dat213-001.wav
|
| 102 |
+
Oecanthuspellucens_dat174-004.wav,Oecanthuspellucens,12,train,dat174-004.wav
|
| 103 |
+
Pholidopteragriseoaptera_dat001-054.M.wav,Pholidopteragriseoaptera,13,train,dat001-054.M.wav
|
| 104 |
+
Grylluscampestris_dat008-016.M.wav,Grylluscampestris,4,train,dat008-016.M.wav
|
| 105 |
+
Oecanthuspellucens_Take03.M.wav,Oecanthuspellucens,12,validation,Take03.M.wav
|
| 106 |
+
Roeselianaroeselii_Metrioptera roeselii Vjjl.M.wav,Roeselianaroeselii,30,train,Metrioptera roeselii Vjjl.M.wav
|
| 107 |
+
Pseudochorthippusparallelus_dat097-022.M.wav,Pseudochorthippusparallelus,28,train,dat097-022.M.wav
|
| 108 |
+
Chorthippusbiguttulus_dat001-053.M.wav,Chorthippusbiguttulus,2,train,dat001-053.M.wav
|
| 109 |
+
Pholidopteragriseoaptera_dat148-009.wav,Pholidopteragriseoaptera,13,train,dat148-009.wav
|
| 110 |
+
Pholidopteragriseoaptera_dat169-001.M.wav,Pholidopteragriseoaptera,13,train,dat169-001.M.wav
|
| 111 |
+
Oecanthuspellucens_dat174-005.wav,Oecanthuspellucens,12,train,dat174-005.wav
|
| 112 |
+
Oecanthuspellucens_Take39.M.wav,Oecanthuspellucens,12,train,Take39.M.wav
|
| 113 |
+
Grylluscampestris_dat008-011.M.wav,Grylluscampestris,4,test,dat008-011.M.wav
|
| 114 |
+
Grylluscampestris_Take02.M.wav,Grylluscampestris,4,test,Take02.M.wav
|
| 115 |
+
Pseudochorthippusparallelus_dat005-060.M.wav,Pseudochorthippusparallelus,28,train,dat005-060.M.wav
|
| 116 |
+
Chorthippusbiguttulus_dat030-001.wav,Chorthippusbiguttulus,2,validation,dat030-001.wav
|
| 117 |
+
Grylluscampestris_file0045.M.wav,Grylluscampestris,4,train,file0045.M.wav
|
| 118 |
+
Tettigoniaviridissima_Take14.wav,Tettigoniaviridissima,31,test,Take14.wav
|
| 119 |
+
Nemobiussylvestris_dat004-037.M.wav,Nemobiussylvestris,11,train,dat004-037.M.wav
|
| 120 |
+
Pseudochorthippusparallelus_dat027-012.M.wav,Pseudochorthippusparallelus,28,test,dat027-012.M.wav
|
| 121 |
+
Pholidopteragriseoaptera_NoID_20190907_210359.M.wav,Pholidopteragriseoaptera,13,train,NoID_20190907_210359.M.wav
|
| 122 |
+
Nemobiussylvestris_No_ID_20170828_205759.M.wav,Nemobiussylvestris,11,train,No_ID_20170828_205759.M.wav
|
| 123 |
+
Chorthippusbrunneus_dat003-009.M.wav,Chorthippusbrunneus,3,validation,dat003-009.M.wav
|
| 124 |
+
Pholidopteragriseoaptera_NoID_20200810_181548.M.wav,Pholidopteragriseoaptera,13,train,NoID_20200810_181548.M.wav
|
| 125 |
+
Pseudochorthippusparallelus_VOC_190626-1033.wav,Pseudochorthippusparallelus,28,validation,VOC_190626-1033.wav
|
| 126 |
+
Chorthippusbiguttulus_dat031-007.wav,Chorthippusbiguttulus,2,train,dat031-007.wav
|
| 127 |
+
Chorthippusbrunneus_Take92.wav,Chorthippusbrunneus,3,train,Take92.wav
|
| 128 |
+
Nemobiussylvestris_Take16.wav,Nemobiussylvestris,11,test,Take16.wav
|
| 129 |
+
Grylluscampestris_dat008-017.M.wav,Grylluscampestris,4,train,dat008-017.M.wav
|
| 130 |
+
Chorthippusbiguttulus_dat003-040.M.wav,Chorthippusbiguttulus,2,test,dat003-040.M.wav
|
| 131 |
+
Oecanthuspellucens_Take47.M.wav,Oecanthuspellucens,12,train,Take47.M.wav
|
| 132 |
+
Chorthippusbrunneus_CHOBRU_20180914_141921.M.wav,Chorthippusbrunneus,3,train,CHOBRU_20180914_141921.M.wav
|
| 133 |
+
Tettigoniaviridissima_dat001-006.M.wav,Tettigoniaviridissima,31,test,dat001-006.M.wav
|
| 134 |
+
Pholidopteragriseoaptera_dat005-041.M.wav,Pholidopteragriseoaptera,13,validation,dat005-041.M.wav
|
| 135 |
+
Tettigoniaviridissima_20170629_201050.M.wav,Tettigoniaviridissima,31,validation,20170629_201050.M.wav
|
| 136 |
+
Chorthippusbiguttulus_dat149-002.wav,Chorthippusbiguttulus,2,test,dat149-002.wav
|
| 137 |
+
Nemobiussylvestris_Take17.wav,Nemobiussylvestris,11,test,Take17.wav
|
| 138 |
+
Pholidopteragriseoaptera___20150723_231036.M.wav,Pholidopteragriseoaptera,13,train,__20150723_231036.M.wav
|
| 139 |
+
Oecanthuspellucens_dat026-008.M.wav,Oecanthuspellucens,12,train,dat026-008.M.wav
|
| 140 |
+
Nemobiussylvestris_dat004-031.M.wav,Nemobiussylvestris,11,train,dat004-031.M.wav
|
| 141 |
+
Roeselianaroeselii_ROEROE_20200811_113904.M.wav,Roeselianaroeselii,30,train,ROEROE_20200811_113904.M.wav
|
| 142 |
+
Tettigoniaviridissima_dat020-004.M.wav,Tettigoniaviridissima,31,train,dat020-004.M.wav
|
| 143 |
+
Nemobiussylvestris_dat016-020.wav,Nemobiussylvestris,11,train,dat016-020.wav
|
| 144 |
+
Nemobiussylvestris_dat145-001.wav,Nemobiussylvestris,11,train,dat145-001.wav
|
data/README.txt
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#############################################
|
| 2 |
+
|
| 3 |
+
Description:
|
| 4 |
+
|
| 5 |
+
This dataset contains recordings of 32 sound producing insect species with a total 335 files and a length of 57 minutes. The dataset was compiled for training neural networks to automatically identify insect species while comparing adaptive, waveform-based frontends to conventional mel-spectrogram methods for audio feature extraction. This work will be submitted for publication in the future and the dataset can be used to replicate the results or for similar research. The scripts for audio processing and the machine learning implementations that were used will be published on Github (github.com/mariusfaiss/Adaptive-Representations-of-Sound-for-Automatic-Insect-Recognition).
|
| 6 |
+
|
| 7 |
+
Roughly half of the recordings (147) are of nine species belonging to the order Orthoptera. These recordings stem from a dataset that was originally compiled by Baudewijn Odé (unpublished). The remaining recordings (188) are of 23 species in the family Cicadidae. These recordings were selected from the Global Cicada Sound Collection hosted on Bioacoustica (doi.org/10.1093/database/bav054), including recordings published in doi.org/10.3897/BDJ.3.e5792 & doi.org/10.11646/zootaxa.4340.1. Many recordings from this collection included speech annotations in the beginning of the recordings, therefore the last ten seconds of audio were extracted and used in this dataset.
|
| 8 |
+
|
| 9 |
+
All files were manually inspected and files with strong noise interference or with sounds of multiple species were removed. Between species, the number of files ranges from four to 22 files and the length from 40 seconds to almost nine minutes of audio material for a single species. The files range in length from less than one second to several minutes. All original files were available with sample rates of at least 44.1 kHz or higher but were resampled to 44.1 kHz mono WAV files for consistency.
|
| 10 |
+
|
| 11 |
+
#############################################
|
| 12 |
+
|
| 13 |
+
CSV:
|
| 14 |
+
|
| 15 |
+
The annotation files for both parts of the dataset include information for all recordings:
|
| 16 |
+
|
| 17 |
+
file_name: The file name used in this dataset, with the species name attached
|
| 18 |
+
species: The name of the species in the recording (see species list below)
|
| 19 |
+
class_ID: A numeric class identifier relating to each species (0-31, see below)
|
| 20 |
+
data_set: The data-subset the file was included in for training, testing or validating a neural network
|
| 21 |
+
original_file_name: The original file name from the source dataset, without the species name
|
| 22 |
+
|
| 23 |
+
#############################################
|
| 24 |
+
|
| 25 |
+
Baudewijn Odé - Orthoptera:
|
| 26 |
+
|
| 27 |
+
Species n min
|
| 28 |
+
Chorthippus biguttulus 20 3:43
|
| 29 |
+
Chorthippus brunneus 13 2:15
|
| 30 |
+
Gryllus campestris 22 3:38
|
| 31 |
+
Nemobius sylvestris 18 8:54
|
| 32 |
+
Oecanthus pellucens 14 4:27
|
| 33 |
+
Pholidoptera griseoaptera 15 1:54
|
| 34 |
+
Pseudochorthippus parallelus 17 2:01
|
| 35 |
+
Roeseliana roeselii 12 1:03
|
| 36 |
+
Tettigonia viridissima 16 1:34
|
| 37 |
+
|
| 38 |
+
#############################################
|
| 39 |
+
|
| 40 |
+
Ed Baker - Cicadidae:
|
| 41 |
+
|
| 42 |
+
Species n min
|
| 43 |
+
Azanicada zuluensis 4 0:40
|
| 44 |
+
Brevisiana brevis 5 0:50
|
| 45 |
+
Kikihia muta 6 1:00
|
| 46 |
+
Myopsalta leona 7 1:10
|
| 47 |
+
Myopsalta longicauda 4 0:40
|
| 48 |
+
Myopsalta mackinlayi 7 1:08
|
| 49 |
+
Myopsalta melanobasis 5 0:43
|
| 50 |
+
Myopsalta xerograsidia 6 1:00
|
| 51 |
+
Platypleura capensis 6 1:00
|
| 52 |
+
Platypleura cfcatenata 22 3:34
|
| 53 |
+
Platypleura chalybaea 7 1:10
|
| 54 |
+
Platypleura deusta 9 1:23
|
| 55 |
+
Platypleura divisa 6 1:00
|
| 56 |
+
Platypleura haglundi 5 0:50
|
| 57 |
+
Platypleura hirtipennis 6 0:54
|
| 58 |
+
Platypleura intercapedinis 5 0:50
|
| 59 |
+
Platypleura plumosa 19 3:09
|
| 60 |
+
Platypleura sp04 8 1:20
|
| 61 |
+
Platypleura sp10 16 2:24
|
| 62 |
+
Platypleura sp11 cfhirtipennis 4 0:40
|
| 63 |
+
Platypleura sp12 cfhirtipennis 10 1:40
|
| 64 |
+
Platypleura sp13 12 2:00
|
| 65 |
+
Pycna semiclara 9 1:30
|
| 66 |
+
|
| 67 |
+
#############################################
|
| 68 |
+
|
| 69 |
+
class_ID list:
|
| 70 |
+
|
| 71 |
+
Azanicadazuluensis 0
|
| 72 |
+
Brevisianabrevis 1
|
| 73 |
+
Chorthippusbiguttulus 2
|
| 74 |
+
Chorthippusbrunneus 3
|
| 75 |
+
Grylluscampestris 4
|
| 76 |
+
Kikihiamuta 5
|
| 77 |
+
Myopsaltaleona 6
|
| 78 |
+
Myopsaltalongicauda 7
|
| 79 |
+
Myopsaltamackinlayi 8
|
| 80 |
+
Myopsaltamelanobasis 9
|
| 81 |
+
Myopsaltaxerograsidia 10
|
| 82 |
+
Nemobiussylvestris 11
|
| 83 |
+
Oecanthuspellucens 12
|
| 84 |
+
Pholidopteragriseoaptera 13
|
| 85 |
+
Platypleuracapensis 14
|
| 86 |
+
Platypleuracfcatenata 15
|
| 87 |
+
Platypleurachalybaea 16
|
| 88 |
+
Platypleuradeusta 17
|
| 89 |
+
Platypleuradivisa 18
|
| 90 |
+
Platypleurahaglundi 19
|
| 91 |
+
Platypleurahirtipennis 20
|
| 92 |
+
Platypleuraintercapedinis 21
|
| 93 |
+
Platypleuraplumosa 22
|
| 94 |
+
Platypleurasp04 23
|
| 95 |
+
Platypleurasp10 24
|
| 96 |
+
Platypleurasp11cfhirtipennis 25
|
| 97 |
+
Platypleurasp12cfhirtipennis 26
|
| 98 |
+
Platypleurasp13 27
|
| 99 |
+
Pseudochorthippusparallelus 28
|
| 100 |
+
Pycnasemiclara 29
|
| 101 |
+
Roeselianaroeselii 30
|
| 102 |
+
Tettigoniaviridissima 31
|
| 103 |
+
|
| 104 |
+
#############################################
|
| 105 |
+
|
| 106 |
+
Copyright (c) is held by the individual recordists.
|
| 107 |
+
|
| 108 |
+
These data are published under the Creative Commons Attribution licence (CC BY):
|
| 109 |
+
https://creativecommons.org/licenses/by/4.0/
|
| 110 |
+
This licence allows to to re-use the data for almost any purpose (follow the link for more information), as long as you give credit to the original source.
|
| 111 |
+
|
| 112 |
+
For academic reuse, we ask that you do this as a citation to the research paper, given above.
|
| 113 |
+
|
| 114 |
+
|
docs/deployment.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Local deployment
|
| 2 |
+
|
| 3 |
+
## Desktop / local service integration
|
| 4 |
+
The supported entry point is `src.inference.predict_wav`. Install requirements and keep `model.h5`, `config.json`, `labels.json`, and `src/` together. There is no network dependency in the inference code.
|
| 5 |
+
|
| 6 |
+
## Android / Kernel integration notes
|
| 7 |
+
Kernel's supplied architecture requires all live inference to remain on-device. This package is a Python/PyTorch training artifact, not yet a drop-in Android artifact. Before shipping:
|
| 8 |
+
1. Freeze the audio frontend and compare it against the training implementation using a golden WAV fixture.
|
| 9 |
+
2. Convert the model to an Android-supported runtime (e.g. LiteRT/TFLite) and test numerical parity; do not rename `.pt`/`.h5` to `.tflite`.
|
| 10 |
+
3. Benchmark on the actual iQOO 15: latency, thermal/battery, noise, sample-rate path and memory.
|
| 11 |
+
4. Validate with field-collected grain-pest recordings and verified physical inspections.
|
| 12 |
+
5. Keep outputs experimental until false-positive, false-negative, uncertainty and cross-device performance are evaluated.
|
| 13 |
+
6. Store model version, audio quality and human-verified outcome separately. Never treat a Clean prediction as proof of pest-free grain.
|
| 14 |
+
|
| 15 |
+
## Suggested production architecture
|
| 16 |
+
Microphone -> signal-quality gate -> exactly matched local preprocessing -> local model -> experimental result UI -> local SQLite record. GCP services, if enabled, should sync only authorized metadata and must not receive raw audio or perform inference.
|
evaluate.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Re-score an existing CNN model dir on the official test split (and its session-clean subset)."""
|
| 2 |
+
import argparse, json
|
| 3 |
+
from pathlib import Path
|
| 4 |
+
from src.inference import load_model
|
| 5 |
+
from train import load_rows, evaluate_test, ROOT
|
| 6 |
+
|
| 7 |
+
p=argparse.ArgumentParser()
|
| 8 |
+
p.add_argument('--model-dir',default=str(ROOT)); p.add_argument('--data-dir',default=str(ROOT/'data'))
|
| 9 |
+
p.add_argument('--eval-crops',type=int,default=None,help='defaults to eval_crops in the model config (1 if absent)')
|
| 10 |
+
p.add_argument('--name',default=None,help='label for compare_models.py; result saved to eval/<name>.json')
|
| 11 |
+
a=p.parse_args()
|
| 12 |
+
mdir=Path(a.model_dir) if Path(a.model_dir).exists() else ROOT/a.model_dir
|
| 13 |
+
model,labels,cfg=load_model(mdir)
|
| 14 |
+
k=a.eval_crops if a.eval_crops is not None else int(cfg.get('eval_crops',1))
|
| 15 |
+
ev=evaluate_test(model,load_rows(a.data_dir),k,labels)
|
| 16 |
+
res={'model_dir':str(mdir),'eval_crops':k,**ev}
|
| 17 |
+
name=a.name or f"{mdir.resolve().name}_k{k}"
|
| 18 |
+
out=Path(__file__).resolve().parent/'eval'; out.mkdir(exist_ok=True)
|
| 19 |
+
(out/f'{name}.json').write_text(json.dumps(res,indent=2))
|
| 20 |
+
summary={s:{m:v for m,v in (ev[s] or {}).items() if m!='report'} for s in ev}
|
| 21 |
+
print(json.dumps({'name':name,'eval_crops':k,**summary},indent=2))
|
history.json
ADDED
|
@@ -0,0 +1,302 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
{
|
| 3 |
+
"epoch": 1,
|
| 4 |
+
"train_loss": 3.549590092438918,
|
| 5 |
+
"validation_macro_f1": 0.0729895104895105
|
| 6 |
+
},
|
| 7 |
+
{
|
| 8 |
+
"epoch": 2,
|
| 9 |
+
"train_loss": 3.2208462678469143,
|
| 10 |
+
"validation_macro_f1": 0.07673611111111112
|
| 11 |
+
},
|
| 12 |
+
{
|
| 13 |
+
"epoch": 3,
|
| 14 |
+
"train_loss": 2.91882507617657,
|
| 15 |
+
"validation_macro_f1": 0.07138480392156864
|
| 16 |
+
},
|
| 17 |
+
{
|
| 18 |
+
"epoch": 4,
|
| 19 |
+
"train_loss": 2.692603404705341,
|
| 20 |
+
"validation_macro_f1": 0.08596299533799534
|
| 21 |
+
},
|
| 22 |
+
{
|
| 23 |
+
"epoch": 5,
|
| 24 |
+
"train_loss": 2.4573555176074686,
|
| 25 |
+
"validation_macro_f1": 0.2512648809523809
|
| 26 |
+
},
|
| 27 |
+
{
|
| 28 |
+
"epoch": 6,
|
| 29 |
+
"train_loss": 2.263241639504066,
|
| 30 |
+
"validation_macro_f1": 0.1829410173160173
|
| 31 |
+
},
|
| 32 |
+
{
|
| 33 |
+
"epoch": 7,
|
| 34 |
+
"train_loss": 2.1775223842033973,
|
| 35 |
+
"validation_macro_f1": 0.26106150793650795
|
| 36 |
+
},
|
| 37 |
+
{
|
| 38 |
+
"epoch": 8,
|
| 39 |
+
"train_loss": 2.0498767632704515,
|
| 40 |
+
"validation_macro_f1": 0.2673363095238095
|
| 41 |
+
},
|
| 42 |
+
{
|
| 43 |
+
"epoch": 9,
|
| 44 |
+
"train_loss": 1.9059001757548406,
|
| 45 |
+
"validation_macro_f1": 0.2243371212121212
|
| 46 |
+
},
|
| 47 |
+
{
|
| 48 |
+
"epoch": 10,
|
| 49 |
+
"train_loss": 1.7863830052889311,
|
| 50 |
+
"validation_macro_f1": 0.3174107142857143
|
| 51 |
+
},
|
| 52 |
+
{
|
| 53 |
+
"epoch": 11,
|
| 54 |
+
"train_loss": 1.6624305523358858,
|
| 55 |
+
"validation_macro_f1": 0.271875
|
| 56 |
+
},
|
| 57 |
+
{
|
| 58 |
+
"epoch": 12,
|
| 59 |
+
"train_loss": 1.6673363172090971,
|
| 60 |
+
"validation_macro_f1": 0.210123556998557
|
| 61 |
+
},
|
| 62 |
+
{
|
| 63 |
+
"epoch": 13,
|
| 64 |
+
"train_loss": 1.578295845251817,
|
| 65 |
+
"validation_macro_f1": 0.304265873015873
|
| 66 |
+
},
|
| 67 |
+
{
|
| 68 |
+
"epoch": 14,
|
| 69 |
+
"train_loss": 1.431467129633977,
|
| 70 |
+
"validation_macro_f1": 0.3928571428571429
|
| 71 |
+
},
|
| 72 |
+
{
|
| 73 |
+
"epoch": 15,
|
| 74 |
+
"train_loss": 1.4111314874428968,
|
| 75 |
+
"validation_macro_f1": 0.4458333333333333
|
| 76 |
+
},
|
| 77 |
+
{
|
| 78 |
+
"epoch": 16,
|
| 79 |
+
"train_loss": 1.416034460067749,
|
| 80 |
+
"validation_macro_f1": 0.4265625
|
| 81 |
+
},
|
| 82 |
+
{
|
| 83 |
+
"epoch": 17,
|
| 84 |
+
"train_loss": 1.321886534874256,
|
| 85 |
+
"validation_macro_f1": 0.3136160714285714
|
| 86 |
+
},
|
| 87 |
+
{
|
| 88 |
+
"epoch": 18,
|
| 89 |
+
"train_loss": 1.3062187295693617,
|
| 90 |
+
"validation_macro_f1": 0.4526785714285714
|
| 91 |
+
},
|
| 92 |
+
{
|
| 93 |
+
"epoch": 19,
|
| 94 |
+
"train_loss": 1.2392334662950957,
|
| 95 |
+
"validation_macro_f1": 0.3239583333333333
|
| 96 |
+
},
|
| 97 |
+
{
|
| 98 |
+
"epoch": 20,
|
| 99 |
+
"train_loss": 1.1840643057456384,
|
| 100 |
+
"validation_macro_f1": 0.33348214285714284
|
| 101 |
+
},
|
| 102 |
+
{
|
| 103 |
+
"epoch": 21,
|
| 104 |
+
"train_loss": 1.0871062324597285,
|
| 105 |
+
"validation_macro_f1": 0.41403769841269844
|
| 106 |
+
},
|
| 107 |
+
{
|
| 108 |
+
"epoch": 22,
|
| 109 |
+
"train_loss": 1.034065645474654,
|
| 110 |
+
"validation_macro_f1": 0.41443452380952384
|
| 111 |
+
},
|
| 112 |
+
{
|
| 113 |
+
"epoch": 23,
|
| 114 |
+
"train_loss": 1.09239622262808,
|
| 115 |
+
"validation_macro_f1": 0.28385416666666663
|
| 116 |
+
},
|
| 117 |
+
{
|
| 118 |
+
"epoch": 24,
|
| 119 |
+
"train_loss": 1.0812750504567072,
|
| 120 |
+
"validation_macro_f1": 0.40788690476190476
|
| 121 |
+
},
|
| 122 |
+
{
|
| 123 |
+
"epoch": 25,
|
| 124 |
+
"train_loss": 0.9923067643092229,
|
| 125 |
+
"validation_macro_f1": 0.4029017857142857
|
| 126 |
+
},
|
| 127 |
+
{
|
| 128 |
+
"epoch": 26,
|
| 129 |
+
"train_loss": 0.949020443054346,
|
| 130 |
+
"validation_macro_f1": 0.37656249999999997
|
| 131 |
+
},
|
| 132 |
+
{
|
| 133 |
+
"epoch": 27,
|
| 134 |
+
"train_loss": 0.9958093166351318,
|
| 135 |
+
"validation_macro_f1": 0.4095238095238095
|
| 136 |
+
},
|
| 137 |
+
{
|
| 138 |
+
"epoch": 28,
|
| 139 |
+
"train_loss": 0.984066536793342,
|
| 140 |
+
"validation_macro_f1": 0.3671875
|
| 141 |
+
},
|
| 142 |
+
{
|
| 143 |
+
"epoch": 29,
|
| 144 |
+
"train_loss": 0.9425493799723111,
|
| 145 |
+
"validation_macro_f1": 0.3669642857142857
|
| 146 |
+
},
|
| 147 |
+
{
|
| 148 |
+
"epoch": 30,
|
| 149 |
+
"train_loss": 0.888027026103093,
|
| 150 |
+
"validation_macro_f1": 0.4125
|
| 151 |
+
},
|
| 152 |
+
{
|
| 153 |
+
"epoch": 31,
|
| 154 |
+
"train_loss": 0.8223837109712454,
|
| 155 |
+
"validation_macro_f1": 0.41770833333333335
|
| 156 |
+
},
|
| 157 |
+
{
|
| 158 |
+
"epoch": 32,
|
| 159 |
+
"train_loss": 0.8049154189916757,
|
| 160 |
+
"validation_macro_f1": 0.41488095238095235
|
| 161 |
+
},
|
| 162 |
+
{
|
| 163 |
+
"epoch": 33,
|
| 164 |
+
"train_loss": 0.7919926161949451,
|
| 165 |
+
"validation_macro_f1": 0.3965029761904762
|
| 166 |
+
},
|
| 167 |
+
{
|
| 168 |
+
"epoch": 34,
|
| 169 |
+
"train_loss": 0.8035265940886277,
|
| 170 |
+
"validation_macro_f1": 0.3972470238095238
|
| 171 |
+
},
|
| 172 |
+
{
|
| 173 |
+
"epoch": 35,
|
| 174 |
+
"train_loss": 0.6834720992124997,
|
| 175 |
+
"validation_macro_f1": 0.390625
|
| 176 |
+
},
|
| 177 |
+
{
|
| 178 |
+
"epoch": 36,
|
| 179 |
+
"train_loss": 0.8087582496496347,
|
| 180 |
+
"validation_macro_f1": 0.3942708333333333
|
| 181 |
+
},
|
| 182 |
+
{
|
| 183 |
+
"epoch": 37,
|
| 184 |
+
"train_loss": 0.8021313754411844,
|
| 185 |
+
"validation_macro_f1": 0.5049107142857143
|
| 186 |
+
},
|
| 187 |
+
{
|
| 188 |
+
"epoch": 38,
|
| 189 |
+
"train_loss": 0.7348064826085017,
|
| 190 |
+
"validation_macro_f1": 0.44494047619047616
|
| 191 |
+
},
|
| 192 |
+
{
|
| 193 |
+
"epoch": 39,
|
| 194 |
+
"train_loss": 0.8007802000412574,
|
| 195 |
+
"validation_macro_f1": 0.4438988095238095
|
| 196 |
+
},
|
| 197 |
+
{
|
| 198 |
+
"epoch": 40,
|
| 199 |
+
"train_loss": 0.6960412997465867,
|
| 200 |
+
"validation_macro_f1": 0.41562499999999997
|
| 201 |
+
},
|
| 202 |
+
{
|
| 203 |
+
"epoch": 41,
|
| 204 |
+
"train_loss": 0.6792902808922988,
|
| 205 |
+
"validation_macro_f1": 0.4413690476190476
|
| 206 |
+
},
|
| 207 |
+
{
|
| 208 |
+
"epoch": 42,
|
| 209 |
+
"train_loss": 0.7683078875908484,
|
| 210 |
+
"validation_macro_f1": 0.44999999999999996
|
| 211 |
+
},
|
| 212 |
+
{
|
| 213 |
+
"epoch": 43,
|
| 214 |
+
"train_loss": 0.6988282685096447,
|
| 215 |
+
"validation_macro_f1": 0.4438988095238095
|
| 216 |
+
},
|
| 217 |
+
{
|
| 218 |
+
"epoch": 44,
|
| 219 |
+
"train_loss": 0.6402304653938,
|
| 220 |
+
"validation_macro_f1": 0.44218749999999996
|
| 221 |
+
},
|
| 222 |
+
{
|
| 223 |
+
"epoch": 45,
|
| 224 |
+
"train_loss": 0.611903557410607,
|
| 225 |
+
"validation_macro_f1": 0.44955357142857144
|
| 226 |
+
},
|
| 227 |
+
{
|
| 228 |
+
"epoch": 46,
|
| 229 |
+
"train_loss": 0.5640731900930405,
|
| 230 |
+
"validation_macro_f1": 0.48177083333333337
|
| 231 |
+
},
|
| 232 |
+
{
|
| 233 |
+
"epoch": 47,
|
| 234 |
+
"train_loss": 0.5864904935543354,
|
| 235 |
+
"validation_macro_f1": 0.5484374999999999
|
| 236 |
+
},
|
| 237 |
+
{
|
| 238 |
+
"epoch": 48,
|
| 239 |
+
"train_loss": 0.6681630175847274,
|
| 240 |
+
"validation_macro_f1": 0.3572916666666667
|
| 241 |
+
},
|
| 242 |
+
{
|
| 243 |
+
"epoch": 49,
|
| 244 |
+
"train_loss": 0.6659798106321921,
|
| 245 |
+
"validation_macro_f1": 0.45362103174603174
|
| 246 |
+
},
|
| 247 |
+
{
|
| 248 |
+
"epoch": 50,
|
| 249 |
+
"train_loss": 0.5747443850223835,
|
| 250 |
+
"validation_macro_f1": 0.54375
|
| 251 |
+
},
|
| 252 |
+
{
|
| 253 |
+
"epoch": 51,
|
| 254 |
+
"train_loss": 0.48586812156897324,
|
| 255 |
+
"validation_macro_f1": 0.4979166666666666
|
| 256 |
+
},
|
| 257 |
+
{
|
| 258 |
+
"epoch": 52,
|
| 259 |
+
"train_loss": 0.5781429868478042,
|
| 260 |
+
"validation_macro_f1": 0.4869047619047619
|
| 261 |
+
},
|
| 262 |
+
{
|
| 263 |
+
"epoch": 53,
|
| 264 |
+
"train_loss": 0.6054044022009923,
|
| 265 |
+
"validation_macro_f1": 0.4695684523809524
|
| 266 |
+
},
|
| 267 |
+
{
|
| 268 |
+
"epoch": 54,
|
| 269 |
+
"train_loss": 0.5589048977081592,
|
| 270 |
+
"validation_macro_f1": 0.5058779761904761
|
| 271 |
+
},
|
| 272 |
+
{
|
| 273 |
+
"epoch": 55,
|
| 274 |
+
"train_loss": 0.6121608293973483,
|
| 275 |
+
"validation_macro_f1": 0.49069940476190477
|
| 276 |
+
},
|
| 277 |
+
{
|
| 278 |
+
"epoch": 56,
|
| 279 |
+
"train_loss": 0.556478527876047,
|
| 280 |
+
"validation_macro_f1": 0.4575892857142857
|
| 281 |
+
},
|
| 282 |
+
{
|
| 283 |
+
"epoch": 57,
|
| 284 |
+
"train_loss": 0.567545989385018,
|
| 285 |
+
"validation_macro_f1": 0.45401785714285714
|
| 286 |
+
},
|
| 287 |
+
{
|
| 288 |
+
"epoch": 58,
|
| 289 |
+
"train_loss": 0.5471948671799439,
|
| 290 |
+
"validation_macro_f1": 0.5364583333333334
|
| 291 |
+
},
|
| 292 |
+
{
|
| 293 |
+
"epoch": 59,
|
| 294 |
+
"train_loss": 0.47601646872667164,
|
| 295 |
+
"validation_macro_f1": 0.38139880952380956
|
| 296 |
+
},
|
| 297 |
+
{
|
| 298 |
+
"epoch": 60,
|
| 299 |
+
"train_loss": 0.4983831655520659,
|
| 300 |
+
"validation_macro_f1": 0.49114583333333334
|
| 301 |
+
}
|
| 302 |
+
]
|
labels.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"0": "Azanicadazuluensis",
|
| 3 |
+
"1": "Brevisianabrevis",
|
| 4 |
+
"2": "Chorthippusbiguttulus",
|
| 5 |
+
"3": "Chorthippusbrunneus",
|
| 6 |
+
"4": "Grylluscampestris",
|
| 7 |
+
"5": "Kikihiamuta",
|
| 8 |
+
"6": "Myopsaltaleona",
|
| 9 |
+
"7": "Myopsaltalongicauda",
|
| 10 |
+
"8": "Myopsaltamackinlayi",
|
| 11 |
+
"9": "Myopsaltamelanobasis",
|
| 12 |
+
"10": "Myopsaltaxerograsidia",
|
| 13 |
+
"11": "Nemobiussylvestris",
|
| 14 |
+
"12": "Oecanthuspellucens",
|
| 15 |
+
"13": "Pholidopteragriseoaptera",
|
| 16 |
+
"14": "Platypleuracapensis",
|
| 17 |
+
"15": "Platypleuracfcatenata",
|
| 18 |
+
"16": "Platypleurachalybaea",
|
| 19 |
+
"17": "Platypleuradeusta",
|
| 20 |
+
"18": "Platypleuradivisa",
|
| 21 |
+
"19": "Platypleurahaglundi",
|
| 22 |
+
"20": "Platypleurahirtipennis",
|
| 23 |
+
"21": "Platypleuraintercapedinis",
|
| 24 |
+
"22": "Platypleuraplumosa",
|
| 25 |
+
"23": "Platypleurasp04",
|
| 26 |
+
"24": "Platypleurasp10",
|
| 27 |
+
"25": "Platypleurasp11cfhirtipennis",
|
| 28 |
+
"26": "Platypleurasp12cfhirtipennis",
|
| 29 |
+
"27": "Platypleurasp13",
|
| 30 |
+
"28": "Pseudochorthippusparallelus",
|
| 31 |
+
"29": "Pycnasemiclara",
|
| 32 |
+
"30": "Roeselianaroeselii",
|
| 33 |
+
"31": "Tettigoniaviridissima"
|
| 34 |
+
}
|
metrics.json
ADDED
|
@@ -0,0 +1,551 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"dataset_files_loaded": 331,
|
| 3 |
+
"split_counts": {
|
| 4 |
+
"train": 206,
|
| 5 |
+
"validation": 51,
|
| 6 |
+
"test": 74
|
| 7 |
+
},
|
| 8 |
+
"num_classes": 32,
|
| 9 |
+
"test_accuracy": 0.4864864864864865,
|
| 10 |
+
"test_macro_f1": 0.40037202380952375,
|
| 11 |
+
"test_weighted_f1": 0.47425997425997424,
|
| 12 |
+
"test_accuracy_ci95": [
|
| 13 |
+
0.3780405405405406,
|
| 14 |
+
0.5945945945945946
|
| 15 |
+
],
|
| 16 |
+
"test_macro_f1_ci95": [
|
| 17 |
+
0.2855325728085446,
|
| 18 |
+
0.46932641432641425
|
| 19 |
+
],
|
| 20 |
+
"test_report": {
|
| 21 |
+
"Azanicadazuluensis": {
|
| 22 |
+
"precision": 1.0,
|
| 23 |
+
"recall": 1.0,
|
| 24 |
+
"f1-score": 1.0,
|
| 25 |
+
"support": 1.0
|
| 26 |
+
},
|
| 27 |
+
"Brevisianabrevis": {
|
| 28 |
+
"precision": 0.0,
|
| 29 |
+
"recall": 0.0,
|
| 30 |
+
"f1-score": 0.0,
|
| 31 |
+
"support": 1.0
|
| 32 |
+
},
|
| 33 |
+
"Chorthippusbiguttulus": {
|
| 34 |
+
"precision": 0.75,
|
| 35 |
+
"recall": 0.6,
|
| 36 |
+
"f1-score": 0.6666666666666666,
|
| 37 |
+
"support": 5.0
|
| 38 |
+
},
|
| 39 |
+
"Chorthippusbrunneus": {
|
| 40 |
+
"precision": 0.5,
|
| 41 |
+
"recall": 1.0,
|
| 42 |
+
"f1-score": 0.6666666666666666,
|
| 43 |
+
"support": 1.0
|
| 44 |
+
},
|
| 45 |
+
"Grylluscampestris": {
|
| 46 |
+
"precision": 1.0,
|
| 47 |
+
"recall": 1.0,
|
| 48 |
+
"f1-score": 1.0,
|
| 49 |
+
"support": 4.0
|
| 50 |
+
},
|
| 51 |
+
"Kikihiamuta": {
|
| 52 |
+
"precision": 1.0,
|
| 53 |
+
"recall": 0.5,
|
| 54 |
+
"f1-score": 0.6666666666666666,
|
| 55 |
+
"support": 2.0
|
| 56 |
+
},
|
| 57 |
+
"Myopsaltaleona": {
|
| 58 |
+
"precision": 0.0,
|
| 59 |
+
"recall": 0.0,
|
| 60 |
+
"f1-score": 0.0,
|
| 61 |
+
"support": 2.0
|
| 62 |
+
},
|
| 63 |
+
"Myopsaltalongicauda": {
|
| 64 |
+
"precision": 0.0,
|
| 65 |
+
"recall": 0.0,
|
| 66 |
+
"f1-score": 0.0,
|
| 67 |
+
"support": 1.0
|
| 68 |
+
},
|
| 69 |
+
"Myopsaltamackinlayi": {
|
| 70 |
+
"precision": 0.0,
|
| 71 |
+
"recall": 0.0,
|
| 72 |
+
"f1-score": 0.0,
|
| 73 |
+
"support": 2.0
|
| 74 |
+
},
|
| 75 |
+
"Myopsaltamelanobasis": {
|
| 76 |
+
"precision": 0.0,
|
| 77 |
+
"recall": 0.0,
|
| 78 |
+
"f1-score": 0.0,
|
| 79 |
+
"support": 2.0
|
| 80 |
+
},
|
| 81 |
+
"Myopsaltaxerograsidia": {
|
| 82 |
+
"precision": 1.0,
|
| 83 |
+
"recall": 0.5,
|
| 84 |
+
"f1-score": 0.6666666666666666,
|
| 85 |
+
"support": 2.0
|
| 86 |
+
},
|
| 87 |
+
"Nemobiussylvestris": {
|
| 88 |
+
"precision": 1.0,
|
| 89 |
+
"recall": 0.6666666666666666,
|
| 90 |
+
"f1-score": 0.8,
|
| 91 |
+
"support": 3.0
|
| 92 |
+
},
|
| 93 |
+
"Oecanthuspellucens": {
|
| 94 |
+
"precision": 1.0,
|
| 95 |
+
"recall": 1.0,
|
| 96 |
+
"f1-score": 1.0,
|
| 97 |
+
"support": 3.0
|
| 98 |
+
},
|
| 99 |
+
"Pholidopteragriseoaptera": {
|
| 100 |
+
"precision": 1.0,
|
| 101 |
+
"recall": 0.5,
|
| 102 |
+
"f1-score": 0.6666666666666666,
|
| 103 |
+
"support": 2.0
|
| 104 |
+
},
|
| 105 |
+
"Platypleuracapensis": {
|
| 106 |
+
"precision": 0.25,
|
| 107 |
+
"recall": 1.0,
|
| 108 |
+
"f1-score": 0.4,
|
| 109 |
+
"support": 1.0
|
| 110 |
+
},
|
| 111 |
+
"Platypleuracfcatenata": {
|
| 112 |
+
"precision": 0.3333333333333333,
|
| 113 |
+
"recall": 0.25,
|
| 114 |
+
"f1-score": 0.2857142857142857,
|
| 115 |
+
"support": 4.0
|
| 116 |
+
},
|
| 117 |
+
"Platypleurachalybaea": {
|
| 118 |
+
"precision": 0.0,
|
| 119 |
+
"recall": 0.0,
|
| 120 |
+
"f1-score": 0.0,
|
| 121 |
+
"support": 2.0
|
| 122 |
+
},
|
| 123 |
+
"Platypleuradeusta": {
|
| 124 |
+
"precision": 0.0,
|
| 125 |
+
"recall": 0.0,
|
| 126 |
+
"f1-score": 0.0,
|
| 127 |
+
"support": 2.0
|
| 128 |
+
},
|
| 129 |
+
"Platypleuradivisa": {
|
| 130 |
+
"precision": 0.3333333333333333,
|
| 131 |
+
"recall": 0.5,
|
| 132 |
+
"f1-score": 0.4,
|
| 133 |
+
"support": 2.0
|
| 134 |
+
},
|
| 135 |
+
"Platypleurahaglundi": {
|
| 136 |
+
"precision": 0.4,
|
| 137 |
+
"recall": 1.0,
|
| 138 |
+
"f1-score": 0.5714285714285714,
|
| 139 |
+
"support": 2.0
|
| 140 |
+
},
|
| 141 |
+
"Platypleurahirtipennis": {
|
| 142 |
+
"precision": 0.0,
|
| 143 |
+
"recall": 0.0,
|
| 144 |
+
"f1-score": 0.0,
|
| 145 |
+
"support": 2.0
|
| 146 |
+
},
|
| 147 |
+
"Platypleuraintercapedinis": {
|
| 148 |
+
"precision": 0.0,
|
| 149 |
+
"recall": 0.0,
|
| 150 |
+
"f1-score": 0.0,
|
| 151 |
+
"support": 2.0
|
| 152 |
+
},
|
| 153 |
+
"Platypleuraplumosa": {
|
| 154 |
+
"precision": 0.25,
|
| 155 |
+
"recall": 0.25,
|
| 156 |
+
"f1-score": 0.25,
|
| 157 |
+
"support": 4.0
|
| 158 |
+
},
|
| 159 |
+
"Platypleurasp04": {
|
| 160 |
+
"precision": 0.4,
|
| 161 |
+
"recall": 1.0,
|
| 162 |
+
"f1-score": 0.5714285714285714,
|
| 163 |
+
"support": 2.0
|
| 164 |
+
},
|
| 165 |
+
"Platypleurasp10": {
|
| 166 |
+
"precision": 0.6666666666666666,
|
| 167 |
+
"recall": 0.6666666666666666,
|
| 168 |
+
"f1-score": 0.6666666666666666,
|
| 169 |
+
"support": 3.0
|
| 170 |
+
},
|
| 171 |
+
"Platypleurasp11cfhirtipennis": {
|
| 172 |
+
"precision": 0.0,
|
| 173 |
+
"recall": 0.0,
|
| 174 |
+
"f1-score": 0.0,
|
| 175 |
+
"support": 1.0
|
| 176 |
+
},
|
| 177 |
+
"Platypleurasp12cfhirtipennis": {
|
| 178 |
+
"precision": 0.0,
|
| 179 |
+
"recall": 0.0,
|
| 180 |
+
"f1-score": 0.0,
|
| 181 |
+
"support": 2.0
|
| 182 |
+
},
|
| 183 |
+
"Platypleurasp13": {
|
| 184 |
+
"precision": 0.5,
|
| 185 |
+
"recall": 0.3333333333333333,
|
| 186 |
+
"f1-score": 0.4,
|
| 187 |
+
"support": 3.0
|
| 188 |
+
},
|
| 189 |
+
"Pseudochorthippusparallelus": {
|
| 190 |
+
"precision": 0.6666666666666666,
|
| 191 |
+
"recall": 1.0,
|
| 192 |
+
"f1-score": 0.8,
|
| 193 |
+
"support": 4.0
|
| 194 |
+
},
|
| 195 |
+
"Pycnasemiclara": {
|
| 196 |
+
"precision": 1.0,
|
| 197 |
+
"recall": 0.5,
|
| 198 |
+
"f1-score": 0.6666666666666666,
|
| 199 |
+
"support": 2.0
|
| 200 |
+
},
|
| 201 |
+
"Roeselianaroeselii": {
|
| 202 |
+
"precision": 0.0,
|
| 203 |
+
"recall": 0.0,
|
| 204 |
+
"f1-score": 0.0,
|
| 205 |
+
"support": 0.0
|
| 206 |
+
},
|
| 207 |
+
"Tettigoniaviridissima": {
|
| 208 |
+
"precision": 0.75,
|
| 209 |
+
"recall": 0.6,
|
| 210 |
+
"f1-score": 0.6666666666666666,
|
| 211 |
+
"support": 5.0
|
| 212 |
+
},
|
| 213 |
+
"accuracy": 0.4864864864864865,
|
| 214 |
+
"macro avg": {
|
| 215 |
+
"precision": 0.43125,
|
| 216 |
+
"recall": 0.4333333333333333,
|
| 217 |
+
"f1-score": 0.40037202380952375,
|
| 218 |
+
"support": 74.0
|
| 219 |
+
},
|
| 220 |
+
"weighted avg": {
|
| 221 |
+
"precision": 0.5137387387387388,
|
| 222 |
+
"recall": 0.4864864864864865,
|
| 223 |
+
"f1-score": 0.47425997425997424,
|
| 224 |
+
"support": 74.0
|
| 225 |
+
}
|
| 226 |
+
},
|
| 227 |
+
"test_session_clean": {
|
| 228 |
+
"count": 48,
|
| 229 |
+
"accuracy": 0.4583333333333333,
|
| 230 |
+
"macro_f1": 0.34285714285714286,
|
| 231 |
+
"weighted_f1": 0.48298611111111106,
|
| 232 |
+
"accuracy_ci95": [
|
| 233 |
+
0.3125,
|
| 234 |
+
0.6041666666666666
|
| 235 |
+
],
|
| 236 |
+
"macro_f1_ci95": [
|
| 237 |
+
0.21914404761904757,
|
| 238 |
+
0.4203331677380589
|
| 239 |
+
]
|
| 240 |
+
},
|
| 241 |
+
"best_validation_macro_f1": 0.5484374999999999,
|
| 242 |
+
"eval_crops": 5,
|
| 243 |
+
"random_crop": true,
|
| 244 |
+
"init_from": null,
|
| 245 |
+
"lr": 0.001,
|
| 246 |
+
"epochs": 60,
|
| 247 |
+
"history": [
|
| 248 |
+
{
|
| 249 |
+
"epoch": 1,
|
| 250 |
+
"train_loss": 3.549590092438918,
|
| 251 |
+
"validation_macro_f1": 0.0729895104895105
|
| 252 |
+
},
|
| 253 |
+
{
|
| 254 |
+
"epoch": 2,
|
| 255 |
+
"train_loss": 3.2208462678469143,
|
| 256 |
+
"validation_macro_f1": 0.07673611111111112
|
| 257 |
+
},
|
| 258 |
+
{
|
| 259 |
+
"epoch": 3,
|
| 260 |
+
"train_loss": 2.91882507617657,
|
| 261 |
+
"validation_macro_f1": 0.07138480392156864
|
| 262 |
+
},
|
| 263 |
+
{
|
| 264 |
+
"epoch": 4,
|
| 265 |
+
"train_loss": 2.692603404705341,
|
| 266 |
+
"validation_macro_f1": 0.08596299533799534
|
| 267 |
+
},
|
| 268 |
+
{
|
| 269 |
+
"epoch": 5,
|
| 270 |
+
"train_loss": 2.4573555176074686,
|
| 271 |
+
"validation_macro_f1": 0.2512648809523809
|
| 272 |
+
},
|
| 273 |
+
{
|
| 274 |
+
"epoch": 6,
|
| 275 |
+
"train_loss": 2.263241639504066,
|
| 276 |
+
"validation_macro_f1": 0.1829410173160173
|
| 277 |
+
},
|
| 278 |
+
{
|
| 279 |
+
"epoch": 7,
|
| 280 |
+
"train_loss": 2.1775223842033973,
|
| 281 |
+
"validation_macro_f1": 0.26106150793650795
|
| 282 |
+
},
|
| 283 |
+
{
|
| 284 |
+
"epoch": 8,
|
| 285 |
+
"train_loss": 2.0498767632704515,
|
| 286 |
+
"validation_macro_f1": 0.2673363095238095
|
| 287 |
+
},
|
| 288 |
+
{
|
| 289 |
+
"epoch": 9,
|
| 290 |
+
"train_loss": 1.9059001757548406,
|
| 291 |
+
"validation_macro_f1": 0.2243371212121212
|
| 292 |
+
},
|
| 293 |
+
{
|
| 294 |
+
"epoch": 10,
|
| 295 |
+
"train_loss": 1.7863830052889311,
|
| 296 |
+
"validation_macro_f1": 0.3174107142857143
|
| 297 |
+
},
|
| 298 |
+
{
|
| 299 |
+
"epoch": 11,
|
| 300 |
+
"train_loss": 1.6624305523358858,
|
| 301 |
+
"validation_macro_f1": 0.271875
|
| 302 |
+
},
|
| 303 |
+
{
|
| 304 |
+
"epoch": 12,
|
| 305 |
+
"train_loss": 1.6673363172090971,
|
| 306 |
+
"validation_macro_f1": 0.210123556998557
|
| 307 |
+
},
|
| 308 |
+
{
|
| 309 |
+
"epoch": 13,
|
| 310 |
+
"train_loss": 1.578295845251817,
|
| 311 |
+
"validation_macro_f1": 0.304265873015873
|
| 312 |
+
},
|
| 313 |
+
{
|
| 314 |
+
"epoch": 14,
|
| 315 |
+
"train_loss": 1.431467129633977,
|
| 316 |
+
"validation_macro_f1": 0.3928571428571429
|
| 317 |
+
},
|
| 318 |
+
{
|
| 319 |
+
"epoch": 15,
|
| 320 |
+
"train_loss": 1.4111314874428968,
|
| 321 |
+
"validation_macro_f1": 0.4458333333333333
|
| 322 |
+
},
|
| 323 |
+
{
|
| 324 |
+
"epoch": 16,
|
| 325 |
+
"train_loss": 1.416034460067749,
|
| 326 |
+
"validation_macro_f1": 0.4265625
|
| 327 |
+
},
|
| 328 |
+
{
|
| 329 |
+
"epoch": 17,
|
| 330 |
+
"train_loss": 1.321886534874256,
|
| 331 |
+
"validation_macro_f1": 0.3136160714285714
|
| 332 |
+
},
|
| 333 |
+
{
|
| 334 |
+
"epoch": 18,
|
| 335 |
+
"train_loss": 1.3062187295693617,
|
| 336 |
+
"validation_macro_f1": 0.4526785714285714
|
| 337 |
+
},
|
| 338 |
+
{
|
| 339 |
+
"epoch": 19,
|
| 340 |
+
"train_loss": 1.2392334662950957,
|
| 341 |
+
"validation_macro_f1": 0.3239583333333333
|
| 342 |
+
},
|
| 343 |
+
{
|
| 344 |
+
"epoch": 20,
|
| 345 |
+
"train_loss": 1.1840643057456384,
|
| 346 |
+
"validation_macro_f1": 0.33348214285714284
|
| 347 |
+
},
|
| 348 |
+
{
|
| 349 |
+
"epoch": 21,
|
| 350 |
+
"train_loss": 1.0871062324597285,
|
| 351 |
+
"validation_macro_f1": 0.41403769841269844
|
| 352 |
+
},
|
| 353 |
+
{
|
| 354 |
+
"epoch": 22,
|
| 355 |
+
"train_loss": 1.034065645474654,
|
| 356 |
+
"validation_macro_f1": 0.41443452380952384
|
| 357 |
+
},
|
| 358 |
+
{
|
| 359 |
+
"epoch": 23,
|
| 360 |
+
"train_loss": 1.09239622262808,
|
| 361 |
+
"validation_macro_f1": 0.28385416666666663
|
| 362 |
+
},
|
| 363 |
+
{
|
| 364 |
+
"epoch": 24,
|
| 365 |
+
"train_loss": 1.0812750504567072,
|
| 366 |
+
"validation_macro_f1": 0.40788690476190476
|
| 367 |
+
},
|
| 368 |
+
{
|
| 369 |
+
"epoch": 25,
|
| 370 |
+
"train_loss": 0.9923067643092229,
|
| 371 |
+
"validation_macro_f1": 0.4029017857142857
|
| 372 |
+
},
|
| 373 |
+
{
|
| 374 |
+
"epoch": 26,
|
| 375 |
+
"train_loss": 0.949020443054346,
|
| 376 |
+
"validation_macro_f1": 0.37656249999999997
|
| 377 |
+
},
|
| 378 |
+
{
|
| 379 |
+
"epoch": 27,
|
| 380 |
+
"train_loss": 0.9958093166351318,
|
| 381 |
+
"validation_macro_f1": 0.4095238095238095
|
| 382 |
+
},
|
| 383 |
+
{
|
| 384 |
+
"epoch": 28,
|
| 385 |
+
"train_loss": 0.984066536793342,
|
| 386 |
+
"validation_macro_f1": 0.3671875
|
| 387 |
+
},
|
| 388 |
+
{
|
| 389 |
+
"epoch": 29,
|
| 390 |
+
"train_loss": 0.9425493799723111,
|
| 391 |
+
"validation_macro_f1": 0.3669642857142857
|
| 392 |
+
},
|
| 393 |
+
{
|
| 394 |
+
"epoch": 30,
|
| 395 |
+
"train_loss": 0.888027026103093,
|
| 396 |
+
"validation_macro_f1": 0.4125
|
| 397 |
+
},
|
| 398 |
+
{
|
| 399 |
+
"epoch": 31,
|
| 400 |
+
"train_loss": 0.8223837109712454,
|
| 401 |
+
"validation_macro_f1": 0.41770833333333335
|
| 402 |
+
},
|
| 403 |
+
{
|
| 404 |
+
"epoch": 32,
|
| 405 |
+
"train_loss": 0.8049154189916757,
|
| 406 |
+
"validation_macro_f1": 0.41488095238095235
|
| 407 |
+
},
|
| 408 |
+
{
|
| 409 |
+
"epoch": 33,
|
| 410 |
+
"train_loss": 0.7919926161949451,
|
| 411 |
+
"validation_macro_f1": 0.3965029761904762
|
| 412 |
+
},
|
| 413 |
+
{
|
| 414 |
+
"epoch": 34,
|
| 415 |
+
"train_loss": 0.8035265940886277,
|
| 416 |
+
"validation_macro_f1": 0.3972470238095238
|
| 417 |
+
},
|
| 418 |
+
{
|
| 419 |
+
"epoch": 35,
|
| 420 |
+
"train_loss": 0.6834720992124997,
|
| 421 |
+
"validation_macro_f1": 0.390625
|
| 422 |
+
},
|
| 423 |
+
{
|
| 424 |
+
"epoch": 36,
|
| 425 |
+
"train_loss": 0.8087582496496347,
|
| 426 |
+
"validation_macro_f1": 0.3942708333333333
|
| 427 |
+
},
|
| 428 |
+
{
|
| 429 |
+
"epoch": 37,
|
| 430 |
+
"train_loss": 0.8021313754411844,
|
| 431 |
+
"validation_macro_f1": 0.5049107142857143
|
| 432 |
+
},
|
| 433 |
+
{
|
| 434 |
+
"epoch": 38,
|
| 435 |
+
"train_loss": 0.7348064826085017,
|
| 436 |
+
"validation_macro_f1": 0.44494047619047616
|
| 437 |
+
},
|
| 438 |
+
{
|
| 439 |
+
"epoch": 39,
|
| 440 |
+
"train_loss": 0.8007802000412574,
|
| 441 |
+
"validation_macro_f1": 0.4438988095238095
|
| 442 |
+
},
|
| 443 |
+
{
|
| 444 |
+
"epoch": 40,
|
| 445 |
+
"train_loss": 0.6960412997465867,
|
| 446 |
+
"validation_macro_f1": 0.41562499999999997
|
| 447 |
+
},
|
| 448 |
+
{
|
| 449 |
+
"epoch": 41,
|
| 450 |
+
"train_loss": 0.6792902808922988,
|
| 451 |
+
"validation_macro_f1": 0.4413690476190476
|
| 452 |
+
},
|
| 453 |
+
{
|
| 454 |
+
"epoch": 42,
|
| 455 |
+
"train_loss": 0.7683078875908484,
|
| 456 |
+
"validation_macro_f1": 0.44999999999999996
|
| 457 |
+
},
|
| 458 |
+
{
|
| 459 |
+
"epoch": 43,
|
| 460 |
+
"train_loss": 0.6988282685096447,
|
| 461 |
+
"validation_macro_f1": 0.4438988095238095
|
| 462 |
+
},
|
| 463 |
+
{
|
| 464 |
+
"epoch": 44,
|
| 465 |
+
"train_loss": 0.6402304653938,
|
| 466 |
+
"validation_macro_f1": 0.44218749999999996
|
| 467 |
+
},
|
| 468 |
+
{
|
| 469 |
+
"epoch": 45,
|
| 470 |
+
"train_loss": 0.611903557410607,
|
| 471 |
+
"validation_macro_f1": 0.44955357142857144
|
| 472 |
+
},
|
| 473 |
+
{
|
| 474 |
+
"epoch": 46,
|
| 475 |
+
"train_loss": 0.5640731900930405,
|
| 476 |
+
"validation_macro_f1": 0.48177083333333337
|
| 477 |
+
},
|
| 478 |
+
{
|
| 479 |
+
"epoch": 47,
|
| 480 |
+
"train_loss": 0.5864904935543354,
|
| 481 |
+
"validation_macro_f1": 0.5484374999999999
|
| 482 |
+
},
|
| 483 |
+
{
|
| 484 |
+
"epoch": 48,
|
| 485 |
+
"train_loss": 0.6681630175847274,
|
| 486 |
+
"validation_macro_f1": 0.3572916666666667
|
| 487 |
+
},
|
| 488 |
+
{
|
| 489 |
+
"epoch": 49,
|
| 490 |
+
"train_loss": 0.6659798106321921,
|
| 491 |
+
"validation_macro_f1": 0.45362103174603174
|
| 492 |
+
},
|
| 493 |
+
{
|
| 494 |
+
"epoch": 50,
|
| 495 |
+
"train_loss": 0.5747443850223835,
|
| 496 |
+
"validation_macro_f1": 0.54375
|
| 497 |
+
},
|
| 498 |
+
{
|
| 499 |
+
"epoch": 51,
|
| 500 |
+
"train_loss": 0.48586812156897324,
|
| 501 |
+
"validation_macro_f1": 0.4979166666666666
|
| 502 |
+
},
|
| 503 |
+
{
|
| 504 |
+
"epoch": 52,
|
| 505 |
+
"train_loss": 0.5781429868478042,
|
| 506 |
+
"validation_macro_f1": 0.4869047619047619
|
| 507 |
+
},
|
| 508 |
+
{
|
| 509 |
+
"epoch": 53,
|
| 510 |
+
"train_loss": 0.6054044022009923,
|
| 511 |
+
"validation_macro_f1": 0.4695684523809524
|
| 512 |
+
},
|
| 513 |
+
{
|
| 514 |
+
"epoch": 54,
|
| 515 |
+
"train_loss": 0.5589048977081592,
|
| 516 |
+
"validation_macro_f1": 0.5058779761904761
|
| 517 |
+
},
|
| 518 |
+
{
|
| 519 |
+
"epoch": 55,
|
| 520 |
+
"train_loss": 0.6121608293973483,
|
| 521 |
+
"validation_macro_f1": 0.49069940476190477
|
| 522 |
+
},
|
| 523 |
+
{
|
| 524 |
+
"epoch": 56,
|
| 525 |
+
"train_loss": 0.556478527876047,
|
| 526 |
+
"validation_macro_f1": 0.4575892857142857
|
| 527 |
+
},
|
| 528 |
+
{
|
| 529 |
+
"epoch": 57,
|
| 530 |
+
"train_loss": 0.567545989385018,
|
| 531 |
+
"validation_macro_f1": 0.45401785714285714
|
| 532 |
+
},
|
| 533 |
+
{
|
| 534 |
+
"epoch": 58,
|
| 535 |
+
"train_loss": 0.5471948671799439,
|
| 536 |
+
"validation_macro_f1": 0.5364583333333334
|
| 537 |
+
},
|
| 538 |
+
{
|
| 539 |
+
"epoch": 59,
|
| 540 |
+
"train_loss": 0.47601646872667164,
|
| 541 |
+
"validation_macro_f1": 0.38139880952380956
|
| 542 |
+
},
|
| 543 |
+
{
|
| 544 |
+
"epoch": 60,
|
| 545 |
+
"train_loss": 0.4983831655520659,
|
| 546 |
+
"validation_macro_f1": 0.49114583333333334
|
| 547 |
+
}
|
| 548 |
+
],
|
| 549 |
+
"seed": 42,
|
| 550 |
+
"limitations": "Small imbalanced research dataset; results are not evidence of grain-pest detection."
|
| 551 |
+
}
|
model.h5
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6a31529c5c7e27767246b99617c8f54ca36165fcb172814a9e50a8e168fc0ca7
|
| 3 |
+
size 653312
|
model.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:768f84773266fd847e97dd5b0546a250b1bf507046df851f93c9002ae92a55fb
|
| 3 |
+
size 643418
|
predict.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import argparse, json, sys
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
from src.inference import predict_wav
|
| 4 |
+
|
| 5 |
+
ROOT=Path(__file__).resolve().parent
|
| 6 |
+
def resolve(p):
|
| 7 |
+
"""Use the path as given if it exists, else relative to this project folder (so the script works from any cwd)."""
|
| 8 |
+
p=Path(p)
|
| 9 |
+
return p if p.exists() or p.is_absolute() else ROOT/p
|
| 10 |
+
|
| 11 |
+
p=argparse.ArgumentParser(description='Run the local experimental Kernel insect classifier')
|
| 12 |
+
p.add_argument('wav'); p.add_argument('--model-dir',default='.')
|
| 13 |
+
p.add_argument('--device',default='cpu')
|
| 14 |
+
a=p.parse_args()
|
| 15 |
+
wav=Path(a.wav); model_dir=resolve(a.model_dir)
|
| 16 |
+
if not wav.is_file(): sys.exit(f"Audio file not found: {wav.resolve()}\nPass the path to a real recording (.wav, or .flac/.ogg/.mp3 with soundfile installed), e.g. python predict.py C:/path/to/clip.wav --model-dir full_model")
|
| 17 |
+
if not (model_dir/'model.h5').is_file(): sys.exit(f"No model.h5 in {model_dir}. Use --model-dir . (baseline), full_model or finetuned_cnn.")
|
| 18 |
+
try:
|
| 19 |
+
print(json.dumps(predict_wav(wav,model_dir,a.device),indent=2))
|
| 20 |
+
except (ValueError,RuntimeError) as e:
|
| 21 |
+
# soundfile raises LibsndfileError (a RuntimeError) for unreadable files.
|
| 22 |
+
sys.exit(f"Could not read {wav} as audio ({e}). Convert it first, e.g. ffmpeg -i input.mp3 -ac 1 output.wav")
|
requirements.txt
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
numpy>=1.24
|
| 2 |
+
scipy>=1.10
|
| 3 |
+
pandas>=2.0
|
| 4 |
+
scikit-learn>=1.3
|
| 5 |
+
torch>=2.1
|
| 6 |
+
h5py>=3.9
|
| 7 |
+
soundfile>=0.12 # FLAC/OGG/MP3 input; WAV works without it
|
src/__init__.py
ADDED
|
File without changes
|
src/audio.py
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Deterministic 16 kHz waveform -> log-mel features; standard-library/scipy implementation."""
|
| 2 |
+
import numpy as np
|
| 3 |
+
from scipy.io import wavfile
|
| 4 |
+
from scipy.signal import resample_poly, stft
|
| 5 |
+
from scipy.fft import dct
|
| 6 |
+
|
| 7 |
+
def to_float(y):
|
| 8 |
+
"""Scale PCM samples to float32 in [-1,1]; must run before mixing to mono, which drops the integer dtype."""
|
| 9 |
+
y=np.asarray(y)
|
| 10 |
+
if y.dtype==np.uint8: return (y.astype(np.float32)-128.)/128.
|
| 11 |
+
if np.issubdtype(y.dtype,np.integer):
|
| 12 |
+
return y.astype(np.float32)/max(abs(np.iinfo(y.dtype).min),np.iinfo(y.dtype).max)
|
| 13 |
+
return y.astype(np.float32)
|
| 14 |
+
|
| 15 |
+
def read_audio(path):
|
| 16 |
+
"""(sample_rate, mono float32 waveform) from WAV via scipy, or FLAC/OGG/MP3/... via the optional soundfile package."""
|
| 17 |
+
path=str(path)
|
| 18 |
+
if path.lower().endswith(('.wav','.wave')):
|
| 19 |
+
try:
|
| 20 |
+
sr,y=wavfile.read(path); y=to_float(y)
|
| 21 |
+
except ValueError:
|
| 22 |
+
# Compressed or unusual WAV encodings scipy cannot parse; libsndfile often can.
|
| 23 |
+
sr,y=_read_soundfile(path)
|
| 24 |
+
else: sr,y=_read_soundfile(path)
|
| 25 |
+
if y.ndim==2: y=y.mean(axis=1)
|
| 26 |
+
return int(sr),y.astype(np.float32)
|
| 27 |
+
|
| 28 |
+
def _read_soundfile(path):
|
| 29 |
+
try: import soundfile as sf
|
| 30 |
+
except ImportError:
|
| 31 |
+
raise RuntimeError(f"Reading {path} needs the soundfile package (pip install soundfile), "
|
| 32 |
+
"or convert it first: ffmpeg -i input.mp3 -ac 1 output.wav") from None
|
| 33 |
+
y,sr=sf.read(path,dtype='float32',always_2d=False)
|
| 34 |
+
return sr,y
|
| 35 |
+
|
| 36 |
+
SR=16000
|
| 37 |
+
DURATION=2.0
|
| 38 |
+
N_MELS=64
|
| 39 |
+
N_FFT=512
|
| 40 |
+
HOP=160
|
| 41 |
+
|
| 42 |
+
def _hz_to_mel(hz): return 2595.0*np.log10(1.0+np.asarray(hz)/700.0)
|
| 43 |
+
def _mel_to_hz(mel): return 700.0*(10.0**(np.asarray(mel)/2595.0)-1.0)
|
| 44 |
+
def mel_filterbank(sr=SR, n_fft=N_FFT, n_mels=N_MELS):
|
| 45 |
+
points=_mel_to_hz(np.linspace(_hz_to_mel(0),_hz_to_mel(sr/2),n_mels+2))
|
| 46 |
+
bins=np.floor((n_fft+1)*points/sr).astype(int)
|
| 47 |
+
fb=np.zeros((n_mels,n_fft//2+1),dtype=np.float32)
|
| 48 |
+
for m in range(1,n_mels+1):
|
| 49 |
+
left,center,right=bins[m-1:m+2]
|
| 50 |
+
if center>left:
|
| 51 |
+
fb[m-1,left:center]=np.arange(left,center)-left
|
| 52 |
+
fb[m-1,left:center]/=(center-left)
|
| 53 |
+
if right>center:
|
| 54 |
+
fb[m-1,center:right]=(right-np.arange(center,right))/(right-center)
|
| 55 |
+
return fb
|
| 56 |
+
|
| 57 |
+
_FB=mel_filterbank()
|
| 58 |
+
def resample(y, sr):
|
| 59 |
+
y=np.asarray(y,dtype=np.float32).reshape(-1)
|
| 60 |
+
if sr != SR:
|
| 61 |
+
import math
|
| 62 |
+
g=math.gcd(int(sr),SR)
|
| 63 |
+
y=resample_poly(y,SR//g,int(sr)//g).astype(np.float32)
|
| 64 |
+
return y
|
| 65 |
+
|
| 66 |
+
def crop_offsets(n_samples, k):
|
| 67 |
+
"""k evenly spaced 2 s crop starts covering a 16 kHz waveform; k=1 gives the center crop."""
|
| 68 |
+
n=int(SR*DURATION)
|
| 69 |
+
if n_samples<=n or k<=1: return [None]
|
| 70 |
+
return [int(round(o)) for o in np.linspace(0,n_samples-n,k)]
|
| 71 |
+
|
| 72 |
+
def prepare_waveform(y, sr, offset=None):
|
| 73 |
+
y=resample(y,sr)
|
| 74 |
+
n=int(SR*DURATION)
|
| 75 |
+
if len(y)>n:
|
| 76 |
+
# Center crop by default: deterministic inference and evaluation.
|
| 77 |
+
start=(len(y)-n)//2 if offset is None else min(max(0,int(offset)),len(y)-n)
|
| 78 |
+
y=y[start:start+n]
|
| 79 |
+
elif len(y)<n:
|
| 80 |
+
y=np.pad(y,(0,n-len(y)))
|
| 81 |
+
peak=float(np.max(np.abs(y))) if len(y) else 0.
|
| 82 |
+
if peak>1e-8: y=y/peak
|
| 83 |
+
return y
|
| 84 |
+
|
| 85 |
+
def logmel(y, sr=SR, offset=None):
|
| 86 |
+
y=prepare_waveform(y,sr,offset)
|
| 87 |
+
_,_,z=stft(y,fs=SR,nperseg=N_FFT,noverlap=N_FFT-HOP,
|
| 88 |
+
nfft=N_FFT,boundary='zeros',padded=True)
|
| 89 |
+
power=(np.abs(z)**2).astype(np.float32)
|
| 90 |
+
mel=_FB @ power
|
| 91 |
+
feat=np.log(np.maximum(mel,1e-8))
|
| 92 |
+
# Per-record normalization stabilizes recorder gain; retain a consistent transformation.
|
| 93 |
+
feat=(feat-feat.mean())/(feat.std()+1e-5)
|
| 94 |
+
return feat.astype(np.float32)[None,:,:]
|
| 95 |
+
|
| 96 |
+
def audio_quality(y):
|
| 97 |
+
y=np.asarray(y,dtype=np.float32)
|
| 98 |
+
if y.size==0: return False, ['empty_audio']
|
| 99 |
+
rms=float(np.sqrt(np.mean(y*y)))
|
| 100 |
+
peak=float(np.max(np.abs(y)))
|
| 101 |
+
reasons=[]
|
| 102 |
+
if rms<0.002: reasons.append('low_level_or_silence')
|
| 103 |
+
if peak>0.999: reasons.append('possible_clipping')
|
| 104 |
+
return len(reasons)==0, reasons
|
src/inference.py
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Load and run the packaged model locally. No network calls are made."""
|
| 2 |
+
import json, h5py, numpy as np, torch
|
| 3 |
+
from pathlib import Path
|
| 4 |
+
from .model import InsectCNN
|
| 5 |
+
from .audio import logmel, audio_quality, resample, crop_offsets, read_audio, SR
|
| 6 |
+
|
| 7 |
+
# Labels are 'GenusSpecies' with no separator; longest prefix first so Pseudochorthippus != Chorthippus.
|
| 8 |
+
ORTHOPTERA=['Pseudochorthippus','Chorthippus','Gryllus','Nemobius','Oecanthus','Pholidoptera','Roeseliana','Tettigonia']
|
| 9 |
+
CICADIDAE=['Azanicada','Brevisiana','Kikihia','Myopsalta','Platypleura','Pycna']
|
| 10 |
+
# Chosen on the validation split for full_model (species ~77%, genus ~90%, group ~98% correct above it).
|
| 11 |
+
DEFAULT_THRESHOLD=0.6
|
| 12 |
+
|
| 13 |
+
def genus_of(species):
|
| 14 |
+
return next((g for g in ORTHOPTERA+CICADIDAE if species.startswith(g)),species)
|
| 15 |
+
|
| 16 |
+
def group_of(species):
|
| 17 |
+
return 'Orthoptera (crickets/grasshoppers)' if genus_of(species) in ORTHOPTERA else 'Cicadidae (cicadas)'
|
| 18 |
+
|
| 19 |
+
def _summed(probs, labels, keyf):
|
| 20 |
+
out={}
|
| 21 |
+
for i,p in enumerate(probs): k=keyf(labels[str(i)]); out[k]=out.get(k,0.)+float(p)
|
| 22 |
+
return sorted(out.items(),key=lambda kv:-kv[1])
|
| 23 |
+
|
| 24 |
+
def identify(probs, labels, threshold=DEFAULT_THRESHOLD):
|
| 25 |
+
"""Most specific taxonomic level whose summed probability reaches the threshold, else 'unknown'."""
|
| 26 |
+
top=int(np.argmax(probs))
|
| 27 |
+
levels=[('species',[(labels[str(top)],float(probs[top]))]),
|
| 28 |
+
('genus',_summed(probs,labels,genus_of)),('group',_summed(probs,labels,group_of))]
|
| 29 |
+
for level,ranked in levels:
|
| 30 |
+
if ranked[0][1]>=threshold: return {'level':level,'name':ranked[0][0],'confidence':ranked[0][1]}
|
| 31 |
+
return {'level':'unknown','name':'Uncertain - possibly a species outside the 32 trained classes','confidence':levels[-1][1][0][1]}
|
| 32 |
+
|
| 33 |
+
def load_model(model_dir, device='cpu'):
|
| 34 |
+
model_dir=Path(model_dir)
|
| 35 |
+
cfg=json.loads((model_dir/'config.json').read_text())
|
| 36 |
+
labels=json.loads((model_dir/'labels.json').read_text())
|
| 37 |
+
net=InsectCNN(cfg['num_classes'])
|
| 38 |
+
h5_path=model_dir/'model.h5'
|
| 39 |
+
with h5py.File(h5_path,'r') as h:
|
| 40 |
+
state={}
|
| 41 |
+
for key in h['state_dict']:
|
| 42 |
+
arr=np.asarray(h['state_dict'][key])
|
| 43 |
+
state[key]=torch.from_numpy(arr.copy())
|
| 44 |
+
net.load_state_dict(state)
|
| 45 |
+
net.to(device).eval()
|
| 46 |
+
return net, labels, cfg
|
| 47 |
+
|
| 48 |
+
def predict_wav(path, model_dir, device='cpu'):
|
| 49 |
+
net,labels,cfg=load_model(model_dir,device)
|
| 50 |
+
# Integer PCM is scaled to [-1,1] before mixing to mono so the quality check sees true levels.
|
| 51 |
+
sr,y=read_audio(path)
|
| 52 |
+
ok,reasons=audio_quality(y)
|
| 53 |
+
# eval_crops>1 averages over evenly spaced 2 s windows; older bundles use the center crop.
|
| 54 |
+
y16=resample(y,sr)
|
| 55 |
+
offs=crop_offsets(len(y16),int(cfg.get('eval_crops',1)))
|
| 56 |
+
x=torch.from_numpy(np.stack([logmel(y16,SR,o) for o in offs])).to(device)
|
| 57 |
+
with torch.no_grad():
|
| 58 |
+
probs=torch.softmax(net(x),dim=1).mean(dim=0).cpu().numpy()
|
| 59 |
+
order=np.argsort(probs)[::-1][:5]
|
| 60 |
+
thr=float(cfg.get('confidence_threshold',DEFAULT_THRESHOLD))
|
| 61 |
+
return {'identification':identify(probs,labels,thr),
|
| 62 |
+
'genus_scores':[{'genus':g,'score':v} for g,v in _summed(probs,labels,genus_of)[:3]],
|
| 63 |
+
'group_scores':[{'group':g,'score':v} for g,v in _summed(probs,labels,group_of)],
|
| 64 |
+
'predicted_species':labels[str(int(order[0]))],
|
| 65 |
+
'confidence':float(probs[order[0]]),
|
| 66 |
+
'top_k':[{'species':labels[str(int(i))],'score':float(probs[i])} for i in order],
|
| 67 |
+
'quality_pass':bool(ok),'quality_reasons':reasons,
|
| 68 |
+
'model_version':cfg['model_version'],
|
| 69 |
+
'experimental':True,
|
| 70 |
+
'warning':'Research insect-species classifier only. Not trained for grain-pest detection or grain safety.'}
|
src/model.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Small CNN for 32-way insect acoustic species classification."""
|
| 2 |
+
import torch
|
| 3 |
+
from torch import nn
|
| 4 |
+
|
| 5 |
+
class InsectCNN(nn.Module):
|
| 6 |
+
def __init__(self, num_classes=32):
|
| 7 |
+
super().__init__()
|
| 8 |
+
self.features = nn.Sequential(
|
| 9 |
+
nn.Conv2d(1, 16, 3, padding=1), nn.BatchNorm2d(16), nn.ReLU(),
|
| 10 |
+
nn.MaxPool2d(2),
|
| 11 |
+
nn.Conv2d(16, 32, 3, padding=1), nn.BatchNorm2d(32), nn.ReLU(),
|
| 12 |
+
nn.MaxPool2d(2),
|
| 13 |
+
nn.Conv2d(32, 64, 3, padding=1), nn.BatchNorm2d(64), nn.ReLU(),
|
| 14 |
+
nn.AdaptiveAvgPool2d((4, 4)),
|
| 15 |
+
)
|
| 16 |
+
self.classifier = nn.Sequential(nn.Flatten(), nn.Dropout(0.25),
|
| 17 |
+
nn.Linear(64*4*4, 128), nn.ReLU(),
|
| 18 |
+
nn.Dropout(0.25), nn.Linear(128, num_classes))
|
| 19 |
+
def forward(self, x):
|
| 20 |
+
return self.classifier(self.features(x))
|
tests/test_model.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import unittest, json
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
import numpy as np, torch
|
| 4 |
+
from src.model import InsectCNN
|
| 5 |
+
from src.inference import load_model
|
| 6 |
+
from src.inference import identify, genus_of
|
| 7 |
+
from src.audio import logmel, crop_offsets, resample, SR
|
| 8 |
+
ROOT=Path(__file__).resolve().parents[1]
|
| 9 |
+
class ModelPackageTests(unittest.TestCase):
|
| 10 |
+
def test_forward_shape(self):
|
| 11 |
+
m=InsectCNN(32).eval()
|
| 12 |
+
with torch.no_grad(): out=m(torch.zeros(2,1,64,201))
|
| 13 |
+
self.assertEqual(tuple(out.shape),(2,32))
|
| 14 |
+
def test_hdf5_load(self):
|
| 15 |
+
m,labels,cfg=load_model(ROOT)
|
| 16 |
+
self.assertEqual(len(labels),32)
|
| 17 |
+
self.assertEqual(cfg['num_classes'],32)
|
| 18 |
+
def test_center_crop_default_unchanged(self):
|
| 19 |
+
y=np.random.default_rng(0).standard_normal(44100*5).astype(np.float32)
|
| 20 |
+
y16=resample(y,44100)
|
| 21 |
+
np.testing.assert_allclose(logmel(y,44100),logmel(y16,SR,(len(y16)-2*SR)//2),atol=1e-5)
|
| 22 |
+
self.assertEqual(crop_offsets(len(y16),1),[None])
|
| 23 |
+
offs=crop_offsets(len(y16),5)
|
| 24 |
+
self.assertEqual((offs[0],offs[-1]),(0,len(y16)-2*SR))
|
| 25 |
+
def test_finetuned_bundle_loads(self):
|
| 26 |
+
d=ROOT/'finetuned_cnn'
|
| 27 |
+
if not (d/'model.h5').exists(): self.skipTest('finetuned_cnn not trained')
|
| 28 |
+
m,labels,cfg=load_model(d)
|
| 29 |
+
self.assertEqual(len(labels),32)
|
| 30 |
+
def test_identify_levels(self):
|
| 31 |
+
labels={str(i):n for i,n in enumerate(['Myopsaltaleona','Myopsaltamackinlayi','Chorthippusbrunneus','Pseudochorthippusparallelus'])}
|
| 32 |
+
self.assertEqual(genus_of('Pseudochorthippusparallelus'),'Pseudochorthippus')
|
| 33 |
+
self.assertEqual(identify(np.array([.7,.1,.1,.1]),labels)['level'],'species')
|
| 34 |
+
r=identify(np.array([.4,.35,.15,.1]),labels); self.assertEqual((r['level'],r['name']),('genus','Myopsalta'))
|
| 35 |
+
self.assertEqual(identify(np.array([.15,.15,.35,.35]),labels,0.6)['name'],'Orthoptera (crickets/grasshoppers)')
|
| 36 |
+
self.assertEqual(identify(np.array([.3,.2,.3,.2]),labels,0.6)['level'],'unknown')
|
| 37 |
+
if __name__=='__main__': unittest.main()
|
train.py
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os, io, re, json, zipfile, argparse, random
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
from urllib.parse import unquote
|
| 4 |
+
import numpy as np, pandas as pd, torch, h5py
|
| 5 |
+
from scipy.io import wavfile
|
| 6 |
+
from sklearn.metrics import accuracy_score, classification_report, f1_score
|
| 7 |
+
from src.audio import logmel, resample, crop_offsets, SR, DURATION
|
| 8 |
+
from src.model import InsectCNN
|
| 9 |
+
|
| 10 |
+
ROOT=Path(__file__).resolve().parent
|
| 11 |
+
|
| 12 |
+
def load_rows(data_dir=ROOT/'data'):
|
| 13 |
+
"""Return dicts with the 16 kHz waveform, label, split and source session of every CSV row found in the zips."""
|
| 14 |
+
rows=[]
|
| 15 |
+
for csv,zipname in [('Cicadidae.csv','Cicadidae.zip'),('Orthoptera.csv','Orthoptera.zip')]:
|
| 16 |
+
df=pd.read_csv(Path(data_dir)/csv)
|
| 17 |
+
with zipfile.ZipFile(Path(data_dir)/zipname) as z:
|
| 18 |
+
wavs=[n for n in z.namelist() if n.lower().endswith('.wav') and '/._' not in n]
|
| 19 |
+
lookup={}
|
| 20 |
+
for n in wavs: lookup.setdefault(n.split('/')[-1],n)
|
| 21 |
+
for _,r in df.iterrows():
|
| 22 |
+
fn=str(r['file_name'])
|
| 23 |
+
member=lookup.get(fn)
|
| 24 |
+
if not member:
|
| 25 |
+
matches=[n for n in wavs if n.endswith('/'+fn)]
|
| 26 |
+
if matches: member=matches[0]
|
| 27 |
+
if not member:
|
| 28 |
+
print('MISSING',fn); continue
|
| 29 |
+
sr,y=wavfile.read(io.BytesIO(z.read(member)))
|
| 30 |
+
if y.ndim==2: y=y.astype(np.float32).mean(axis=1)
|
| 31 |
+
if np.issubdtype(y.dtype,np.integer):
|
| 32 |
+
y=y.astype(np.float32)/max(abs(np.iinfo(y.dtype).min),np.iinfo(y.dtype).max)
|
| 33 |
+
else: y=y.astype(np.float32)
|
| 34 |
+
rows.append({'wave':resample(y,sr),'label':int(r['class_ID']),'species':str(r['species']),
|
| 35 |
+
'split':str(r['data_set']).lower(),'file_name':fn,
|
| 36 |
+
'session':session_key(str(r['species']),str(r['original_file_name']))})
|
| 37 |
+
return rows
|
| 38 |
+
|
| 39 |
+
def session_key(species, original_file_name):
|
| 40 |
+
"""Group files cut from the same source recording/tape (e.g. 'MHV 313 ... #6a/#6b', 'dat008-019')."""
|
| 41 |
+
s=unquote(original_file_name)
|
| 42 |
+
for p in [r'(MHV\s*\d+)',r'(dat\d+)',r'([A-Z]+_\d{8})',r'(\d{6})_']:
|
| 43 |
+
m=re.match(p,s)
|
| 44 |
+
if m: return species+'|'+m.group(1)
|
| 45 |
+
return species+'|'+s.rsplit('.',1)[0]
|
| 46 |
+
|
| 47 |
+
def features(waves, offsets):
|
| 48 |
+
return torch.from_numpy(np.stack([logmel(w,SR,o) for w,o in zip(waves,offsets)]))
|
| 49 |
+
|
| 50 |
+
def predict_probs(model, rows, idx, eval_crops=1):
|
| 51 |
+
"""Per-file class probabilities, averaged over eval_crops evenly spaced 2 s windows."""
|
| 52 |
+
model.eval(); out=[]
|
| 53 |
+
with torch.no_grad():
|
| 54 |
+
for i in idx:
|
| 55 |
+
offs=crop_offsets(len(rows[i]['wave']),eval_crops)
|
| 56 |
+
out.append(torch.softmax(model(features([rows[i]['wave']]*len(offs),offs)),dim=1).mean(dim=0).numpy())
|
| 57 |
+
return np.stack(out) if out else np.empty((0,32))
|
| 58 |
+
|
| 59 |
+
def evaluate_split(model, rows, idx, eval_crops=1, names=None, n_boot=1000, seed=42):
|
| 60 |
+
y=np.array([rows[i]['label'] for i in idx]); pred=np.argmax(predict_probs(model,rows,idx,eval_crops),axis=1)
|
| 61 |
+
res={'count':int(len(idx)),'accuracy':float(accuracy_score(y,pred)),
|
| 62 |
+
'macro_f1':float(f1_score(y,pred,average='macro',zero_division=0)),
|
| 63 |
+
'weighted_f1':float(f1_score(y,pred,average='weighted',zero_division=0))}
|
| 64 |
+
# Bootstrap over files: with ~74 test files the point estimates are very uncertain.
|
| 65 |
+
rng=np.random.default_rng(seed); acc=[]; mf1=[]
|
| 66 |
+
for _ in range(n_boot):
|
| 67 |
+
b=rng.integers(0,len(y),len(y))
|
| 68 |
+
acc.append(accuracy_score(y[b],pred[b])); mf1.append(f1_score(y[b],pred[b],average='macro',zero_division=0))
|
| 69 |
+
res['accuracy_ci95']=[float(np.percentile(acc,2.5)),float(np.percentile(acc,97.5))]
|
| 70 |
+
res['macro_f1_ci95']=[float(np.percentile(mf1,2.5)),float(np.percentile(mf1,97.5))]
|
| 71 |
+
if names:
|
| 72 |
+
res['report']=classification_report(y,pred,labels=list(range(32)),target_names=[names[str(i)] for i in range(32)],output_dict=True,zero_division=0)
|
| 73 |
+
return res
|
| 74 |
+
|
| 75 |
+
def evaluate_test(model, rows, eval_crops=1, names=None):
|
| 76 |
+
"""Official test split, plus the subset whose source session never occurs in train/validation."""
|
| 77 |
+
split=np.array([r['split'] for r in rows]); test=np.where(split=='test')[0]
|
| 78 |
+
seen={r['session'] for r in rows if r['split']!='test'}
|
| 79 |
+
clean=np.array([i for i in test if rows[i]['session'] not in seen])
|
| 80 |
+
return {'test':evaluate_split(model,rows,test,eval_crops,names),
|
| 81 |
+
'test_session_clean':evaluate_split(model,rows,clean,eval_crops) if len(clean) else None}
|
| 82 |
+
|
| 83 |
+
def main():
|
| 84 |
+
ap=argparse.ArgumentParser()
|
| 85 |
+
ap.add_argument('--epochs',type=int,default=16); ap.add_argument('--seed',type=int,default=42)
|
| 86 |
+
ap.add_argument('--output',default='.'); ap.add_argument('--data-dir',default=str(ROOT/'data'))
|
| 87 |
+
ap.add_argument('--init-from',default=None,help='model dir to warm-start from (fine-tuning)')
|
| 88 |
+
ap.add_argument('--lr',type=float,default=1e-3)
|
| 89 |
+
ap.add_argument('--random-crop',action='store_true',help='train on a fresh random 2 s window per file each epoch')
|
| 90 |
+
ap.add_argument('--eval-crops',type=int,default=1,help='average over K evenly spaced windows for validation/test')
|
| 91 |
+
args=ap.parse_args()
|
| 92 |
+
random.seed(args.seed); np.random.seed(args.seed); torch.manual_seed(args.seed)
|
| 93 |
+
torch.set_num_threads(max(1,min(4,os.cpu_count() or 1)))
|
| 94 |
+
rows=load_rows(args.data_dir)
|
| 95 |
+
if not rows: raise RuntimeError('No audio rows loaded. Check data/ zip and CSV files.')
|
| 96 |
+
y=np.array([r['label'] for r in rows]); split=np.array([r['split'] for r in rows])
|
| 97 |
+
train=np.where(split=='train')[0]; val=np.where(split=='validation')[0]; test=np.where(split=='test')[0]
|
| 98 |
+
# Dataset-provided partitions are preserved; no random file-level split. Test is only scored once, after selection.
|
| 99 |
+
waves=[r['wave'] for r in rows]; yt=torch.tensor(y,dtype=torch.long)
|
| 100 |
+
if args.init_from:
|
| 101 |
+
from src.inference import load_model
|
| 102 |
+
model,_,_=load_model(args.init_from)
|
| 103 |
+
else:
|
| 104 |
+
model=InsectCNN(32)
|
| 105 |
+
n=int(SR*DURATION)
|
| 106 |
+
xcenter=features(waves,[None]*len(waves)) if not args.random_crop else None
|
| 107 |
+
counts=np.bincount(y[train],minlength=32)
|
| 108 |
+
weights=np.array([len(train)/(32*max(1,c)) for c in counts],dtype=np.float32)
|
| 109 |
+
criterion=torch.nn.CrossEntropyLoss(weight=torch.tensor(weights))
|
| 110 |
+
opt=torch.optim.AdamW(model.parameters(),lr=args.lr,weight_decay=1e-4)
|
| 111 |
+
best=-1; best_state=None; history=[]
|
| 112 |
+
for epoch in range(args.epochs):
|
| 113 |
+
model.train(); perm=np.random.permutation(train); losses=[]
|
| 114 |
+
for start in range(0,len(perm),16):
|
| 115 |
+
idx=perm[start:start+16]
|
| 116 |
+
if args.random_crop:
|
| 117 |
+
offs=[np.random.randint(0,len(waves[i])-n+1) if len(waves[i])>n else None for i in idx]
|
| 118 |
+
xb=features([waves[i] for i in idx],offs)
|
| 119 |
+
else: xb=xcenter[idx]
|
| 120 |
+
opt.zero_grad(); logits=model(xb); loss=criterion(logits,yt[idx]); loss.backward(); opt.step(); losses.append(float(loss.item()))
|
| 121 |
+
pv=np.argmax(predict_probs(model,rows,val,args.eval_crops),axis=1) if len(val) else np.array([])
|
| 122 |
+
score=f1_score(y[val],pv,average='macro',zero_division=0) if len(val) else -np.mean(losses)
|
| 123 |
+
history.append({'epoch':epoch+1,'train_loss':float(np.mean(losses)),'validation_macro_f1':float(score)})
|
| 124 |
+
print(f"epoch {epoch+1}/{args.epochs}: loss={np.mean(losses):.4f} val_macro_f1={score:.4f}",flush=True)
|
| 125 |
+
if score>best:
|
| 126 |
+
best=score; best_state={k:v.detach().cpu().clone() for k,v in model.state_dict().items()}
|
| 127 |
+
model.load_state_dict(best_state); model.eval()
|
| 128 |
+
ids=sorted(set(int(i) for i in y))
|
| 129 |
+
names={str(i):next((r['species'] for r in rows if r['label']==i),f'class_{i}') for i in ids}
|
| 130 |
+
ev=evaluate_test(model,rows,args.eval_crops,names); t=ev['test']
|
| 131 |
+
metrics={'dataset_files_loaded':len(rows),'split_counts':{s:int((split==s).sum()) for s in ['train','validation','test']},
|
| 132 |
+
'num_classes':32,'test_accuracy':t['accuracy'],'test_macro_f1':t['macro_f1'],'test_weighted_f1':t['weighted_f1'],
|
| 133 |
+
'test_accuracy_ci95':t['accuracy_ci95'],'test_macro_f1_ci95':t['macro_f1_ci95'],
|
| 134 |
+
'test_report':t['report'],'test_session_clean':ev['test_session_clean'],
|
| 135 |
+
'best_validation_macro_f1':float(best),'eval_crops':args.eval_crops,'random_crop':args.random_crop,
|
| 136 |
+
'init_from':args.init_from,'lr':args.lr,'epochs':args.epochs,
|
| 137 |
+
'history':history,'seed':args.seed,'limitations':'Small imbalanced research dataset; results are not evidence of grain-pest detection.'}
|
| 138 |
+
out=Path(args.output); out.mkdir(parents=True,exist_ok=True)
|
| 139 |
+
torch.save(model.state_dict(),out/'model.pt')
|
| 140 |
+
with h5py.File(out/'model.h5','w') as h:
|
| 141 |
+
h.attrs['format']='kernel-pytorch-state-dict-hdf5-v1'
|
| 142 |
+
h.attrs['model_architecture']='InsectCNN'
|
| 143 |
+
h.attrs['model_version']='0.1.0-experimental'
|
| 144 |
+
sd=h.create_group('state_dict')
|
| 145 |
+
for k,v in model.state_dict().items(): sd.create_dataset(k,data=v.detach().cpu().numpy())
|
| 146 |
+
(out/'labels.json').write_text(json.dumps(names,indent=2))
|
| 147 |
+
(out/'config.json').write_text(json.dumps({'model_type':'kernel-insect-cnn','architecture':'InsectCNN','num_classes':32,'sample_rate':16000,'clip_seconds':2.0,'feature':'64-bin log-mel spectrogram','eval_crops':args.eval_crops,'model_version':'0.1.0-experimental','framework':'PyTorch','hdf5_format':'kernel-pytorch-state-dict-hdf5-v1','task':'insect species classification','experimental':True},indent=2))
|
| 148 |
+
(out/'metrics.json').write_text(json.dumps(metrics,indent=2))
|
| 149 |
+
(out/'history.json').write_text(json.dumps(history,indent=2))
|
| 150 |
+
print(json.dumps({k:v for k,v in metrics.items() if k not in ('test_report','history')},indent=2))
|
| 151 |
+
if __name__=='__main__': main()
|