Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

88 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

BirdCLEF 2026

Training, ensembling, and inference code for the BirdCLEF 2026 Kaggle competition. The project centers on a CNN/SED audio classifier and augments it with Perch-based branches, prototype scoring, site/time priors, and OOF-fitted calibration.

Competition: https://www.kaggle.com/competitions/birdclef-2026

Architecture

The repository is split into an importable library under src/ and runnable workflow entrypoints under scripts/.

Kaggle audio/metadata
    -> src.data: labels, folds, waveform loading, mel spectrograms, augmentation
    -> src.model: timm CNN encoder + frequency pooling + attentive SED head
    -> src.training: fold-safe training, metrics, EMA, schedulers, thresholds
    -> outputs/<timestamp>: checkpoints, logs, OOF arrays, ONNX exports
    -> scripts.onnx: checkpoint ranking, ONNX export, model/head merging
    -> src.perch + src.ensemble: Perch heads, native labels, prototypes, priors
    -> scripts.inference: local/Kaggle-style submission generation

Main prediction branches:

  • cnn: log-mel windows passed through exported CNN/SED ONNX models.
  • perch: frozen Perch v2 embeddings passed through trained BirdCLEF heads.
  • perch_native: Perch's native label logits mapped onto the competition taxonomy.
  • perch_proto: nearest-prototype scoring in Perch embedding space.
  • site_prior: a site/date/time prior fitted from labeled soundscape windows.

The ensemble can use fixed blend weights or a per-class logistic stacker fitted from fold-safe soundscape OOF predictions.

Repository Layout

src/
  config.py          Paths and default training/inference settings
  model.py           CNN/SED model, ASL loss, optional Perch distillation
  data/              Audio IO, mel features, augmentations, datasets, labels
  training/          Fold training loop, metrics, schedulers, EMA, thresholds
  perch/             Perch ONNX extractor, embedding data helpers, head model
  ensemble/          OOF generation, calibration, pseudo labels, priors
  inference_utils.py Shared ONNX/session/windowing utilities
scripts/
  training/          Train folds, train Perch heads, grid search
  onnx/              Export, rank, and merge ONNX models
  perch/             Extract embeddings and build prototype banks
  ensemble/          Build OOF arrays, calibrators, pseudo labels
  inference/         Submission and hybrid inference entrypoints
notebooks/           Exploration and Kaggle notebooks
tests/               Local smoke tests

Use python -m ... from the repository root so imports resolve consistently. Most reusable logic belongs in src/; executable workflows belong in scripts/.

Setup

python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Download the Kaggle competition data and unpack it here:

data/birdclef-2026/
  train.csv
  taxonomy.csv
  sample_submission.csv
  train_audio/
  train_soundscapes/
  train_soundscapes_labels.csv
  test_soundscapes/

Perch workflows also need:

data/perch_v2.onnx
data/perch_labels.csv

src/perch/extractor.py can download perch_v2.onnx when used without an explicit model path. The Perch labels file should match the official Perch label asset used by the model.

Common Workflows

Train the CNN/SED folds:

python -m scripts.training.train_all_folds \
  --bs 128 --lr 3e-4 --wd 1e-3 \
  --cpu-friendly \
  --no-pseudo-labels

Export checkpoints and build a weighted CNN ensemble:

RUN=20260525_230046

python -m scripts.onnx.export --run "$RUN"
python -m scripts.onnx.rank_checkpoints \
  --run "$RUN" --one-per-fold --top-k 5 \
  --out-specs "outputs/$RUN/cnn_weighted_fold5.txt"
python -m scripts.onnx.merge_models \
  --run "$RUN" \
  --model-specs "outputs/$RUN/cnn_weighted_fold5.txt"

Train Perch heads and build prototype banks:

python -m scripts.perch.extract_embeddings --perch-path data/perch_v2.onnx

for FOLD in 0 1 2 3 4; do
  python -m scripts.training.train_perch_head --fold "$FOLD" --bs 512 --lr 3e-4 --wd 1e-3
done

python -m scripts.onnx.merge_perch_heads --dir outputs/perch_head
python -m scripts.perch.build_perch_prototypes \
  --out outputs/perch_prototypes/perch_proto_all.npz \
  --fold-prefix outputs/perch_prototypes/perch_proto

Create soundscape OOF arrays and fit a calibrator:

RUN=20260525_230046

python -m scripts.ensemble.soundscape_oof \
  --out-prefix "outputs/$RUN/soundscape_full" \
  --cnn-models-file "outputs/$RUN/cnn_weighted_fold5.txt" \
  --perch-heads outputs/perch_head/perch_head_fold0.onnx outputs/perch_head/perch_head_fold1.onnx outputs/perch_head/perch_head_fold2.onnx outputs/perch_head/perch_head_fold3.onnx outputs/perch_head/perch_head_fold4.onnx \
  --perch-native \
  --perch-prototypes outputs/perch_prototypes/perch_proto_fold0.npz outputs/perch_prototypes/perch_proto_fold1.npz outputs/perch_prototypes/perch_proto_fold2.npz outputs/perch_prototypes/perch_proto_fold3.npz outputs/perch_prototypes/perch_proto_fold4.npz \
  --site-time-prior

python -m scripts.ensemble.fit_ensemble_calibrator \
  --targets "outputs/$RUN/soundscape_full_targets.npy" \
  --branch "cnn:outputs/$RUN/soundscape_full_cnn_probs.npy" \
  --branch "perch:outputs/$RUN/soundscape_full_perch_probs.npy" \
  --input-space prob \
  --fallback-weights cnn:0.55,perch:0.45 \
  --output "outputs/$RUN/hybrid_calibrator.npz"

Run hybrid inference:

RUN=20260525_230046

python -m scripts.inference.hybrid_perch_cnn_inference \
  --cnn-models "outputs/$RUN/merged_model/fused_model.onnx" \
  --perch-heads outputs/perch_head/perch_head_ensemble.onnx \
  --perch-native \
  --perch-prototypes outputs/perch_prototypes/perch_proto_all.npz \
  --site-time-prior \
  --calibrator "outputs/$RUN/hybrid_calibrator.npz" \
  --out submission.csv

Tests

python -m tests.test_perch
python -m tests.test_train_cpu

The CPU training smoke test expects a small usable copy of the competition data under data/birdclef-2026/.

Notes

  • Outputs are timestamped under outputs/; replace RUN=... with your run directory name, or use --run latest where a command supports it.
  • Fold-aware OOF commands expect fold-specific filenames containing fold0 through fold4.
  • Pseudo labels are mined with scripts.ensemble.generate_pseudo_labels and can be passed back into CNN training with --pseudo-labels.
  • Kaggle submission notebooks should stay self-contained; they cannot rely on importing local src/ or scripts/ modules unless those files are packaged as notebook inputs.

About

Fully developed training infrastructure and model architecture for BirdCLEF competition

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages