A tiny, purely supervised model trained to name 14,795 species beats every self-supervised foundation model at understanding animal sound — and transfers to whales it never heard.
You drop an autonomous microphone in a rainforest. It records for six months. You come back with 4,000 hours of audio. Somewhere in that ocean of sound is the booming call of an endangered bittern, the dialect of a single warbler population, the click train of an orca pod. Where?
This is bioacoustics: using sound to monitor biodiversity. It matters because a hidden microphone is cheap, never sleeps, and doesn't scare the animals. But a human can't listen to 4,000 hours. We need a model that turns raw audio into something searchable — a model that, given a 5-second clip, can say "that's a Cerulean Warbler" or at least "that sounds like this other clip you already labelled."
That last clause is the twist. The field has very little labelled marine data, very little insect data, very little amphibian data. It has a mountain of labelled birdsong, because birders have been uploading recordings to citizen-science archives like Xeno-Canto for twenty years. The dream is a model trained mostly on birds that nonetheless transfers to whales, frogs, bats, and mosquitoes.
Everywhere else in ML, the recipe of the last five years has been self-supervised foundation models: train a giant model on a sea of unlabelled data (mask out patches, predict the next token), then fine-tune. DINOv2 saw 142 million images with no labels. wav2vec masked speech. The labels were the bottleneck, so we threw them away.
Bioacoustics tried to copy this. Bird-MAE (masked autoencoder), BirdAVES, SimCLR-style contrastive models — all self-supervised. The authors of Perch tried it too: MAEs, HuBERT, SimCLR.
Most ML papers optimize one number on one test set. Perch 2.0 optimizes for a deployment shape:
| Requirement | Why it matters for ecology |
|---|---|
| Small model (EfficientNet-B3, 12M params) | Runs on a laptop; can embed 4,000 hours overnight |
| Frozen embeddings (no fine-tuning) | Ecologists lack GPUs & ML skill; embed once, reuse forever |
| Linearly separable embeddings | A linear probe / nearest-neighbour search is all they get |
| Cross-taxa transfer | Train on birds, deploy on whales |
Hold this list in your head. Every design decision in the paper — the mixup, the three heads, the self-distillation — exists to push the frozen embedding toward being small, linearly separable, and transferable. That is the through-line.
Rich Sutton's famous essay The Bitter Lesson (2019) argues that general, compute-hungry methods (search, learning) always win over hand-crafted human knowledge. Perch 2.0's title is a pun: the bittern lesson (a bittern is a shy, booming heron). And the lesson is almost the opposite flavour: here, a simple, well-tuned supervised model is the thing that's "difficult to beat."
Imagine two training regimes for the same network:
Section C.1 of the paper makes this concrete: if you deliberately coarsen the labels (merge species into genera, genera into families), transfer performance gets worse. The harder the original problem, the better the leftover features. This echoes Hong et al. (2024), "Why fine-grained labels in pretraining benefit generalization."
Watch the embedding cloud: with 2 coarse labels the points blur into two soft blobs; with 14,795 fine labels the model carves clean, separable clusters. A linear probe on the right-hand picture is trivial; on the left it's hopeless.
Two facts make avian audio a freakishly good pre-training source:
Before any learning happens, raw sound must become a tensor a CNN can chew on. Let's trace one 5-second clip through the front of the model, shape by shape.
The model ingests monaural audio at 32 kHz. A 5-second clip is therefore:
A raw waveform is a terrible input — it's a 1-D wiggle where the same bird call shifted by one millisecond looks completely different numerically. So we convert to a spectrogram: chop the signal into short overlapping frames, take the Fourier transform of each, and stack the frequency content over time. The result is a picture: time across, frequency up, brightness = energy.
The exact recipe the paper uses:
| Parameter | Value | Why |
|---|---|---|
| Window length | 20 ms | Long enough to resolve frequency, short enough to localise in time |
| Hop length | 10 ms | 50% overlap → smooth time axis |
| Frames out | 500 | 5 s ÷ 10 ms = 500 time steps |
| Mel bins | 128 | Perceptual frequency axis (60 Hz – 16 kHz) |
Two design choices worth understanding. The mel scale spaces frequency bins the way the ear does — fine resolution low down (where most animal calls live), coarse up high. The log (of energy) compresses dynamic range, so a loud call and a faint call have comparable contrast — exactly like how we perceive loudness. The bins span 60 Hz–16 kHz, which is also why the authors throw out all bat recordings: bats vocalize above 16 kHz and simply don't exist in this representation.
That [500, 128] picture goes into an EfficientNet-B3 — a convolutional residual network with depthwise convolutions, 12M parameters. (Perch 1.0 used the smaller B1, 7.8M; the extra data justified scaling up.) The CNN downsamples spatially and grows the channel axis, producing a spatial embedding:
Then we average over the two spatial axes (the 5×3 grid) to get a single vector — the mean embedding:
This 1536-dim vector is the product. Everything the ecologist uses — nearest-neighbour search, clustering, the linear probe — operates on EA. The whole rest of the paper is machinery to make EA as good as possible, then thrown away at deployment. The heads exist only during training.
[160000] waveform → [500,128] log-mel → EfficientNet-B3 → ES [5,3,1536] spatial → mean-pool → EA [1536] mean embedding. ES feeds the prototype head (it needs spatial detail); EA feeds the linear and source-prediction heads.Here's a problem buried in the data. Recordings range from under a second to over an hour, and the labels are weak: a 2-minute file tagged "Cerulean Warbler" doesn't tell you which 5 seconds actually contain the bird. The bird might be silent for most of it. So when we crop a random 5-second window, we might get pure wind.
Perch 1.0 fixed this with energy-peak selection — a wavelet detector that finds the loudest moment and crops there, assuming the labelled species is the loudest thing. Perch 2.0 keeps this option but also asks a sharper question: how do we make the classification problem harder, on purpose, to force better features? (Remember Chapter 1: harder task → better embedding.)
Standard mixup (Zhang et al., 2018) blends two training examples into one and asks the model to predict both. Perch 2.0 generalizes it to more than two sources. The procedure, step by step:
Say N=3 with weights w = (0.6, 0.3, 0.1) for a robin, a thrush, and a faint warbler. The normalizer is
So xmix = (0.6·robin + 0.3·thrush + 0.1·warbler) / 0.678. The robin enters at 0.6/0.678 ≈ 0.88× its original amplitude. And the target? [robin=1, thrush=1, warbler=1] — the warbler at 0.1 weight is demanded just as confidently as the robin at 0.6.
Drag any bar to change its weight. Watch two things: the gain normalizer keeps the composite loudness flat as you add sources, and the target row stays all-1 no matter how quiet a source gets. That's the multi-hot rule made visible.
Now the heart of the architecture. From the shared embedding, training drives three output heads, each with its own loss. None of them survive to deployment — they're scaffolding that shapes EA. Let's meet them, then watch gradients flow.
| Head | Input | Forces the embedding to… |
|---|---|---|
| Linear | EA [1536] | be a place where a straight line separates species → great for linear probes |
| Prototype | ES [5,3,1536] | contain localized, part-based evidence ("this trill looks like that stored prototype") |
| Source | EA [1536] | encode fine recording-level identity → maximal feature granularity |
Step through it. On the forward pass the embedding lights up all three heads. On the backward pass, notice the red ✕ on the prototype→embedding edge — that's the stop-gradient. The teacher's gradients are not allowed to update the shared embedding. Why that matters is the whole next chapter.
We have two species classifiers reading the same embedding: a plain linear head and a fancier prototype head. The paper makes the prototype head teach the linear head. This is self-distillation: a model improving by learning from a slightly-better version of itself.
ProtoPNet (Chen et al., 2019) reasons by analogy: it stores a handful of learned prototypes per class — little reference patterns — and classifies a new clip by "this region looks like that stored prototype." Perch learns 4 prototypes per class and the prediction uses the maximum activation across them. An orthogonality loss pushes the 4 prototypes apart so they capture different aspects of a call (the intro buzz vs. the terminal trill) rather than collapsing to one.
Because it consumes the spatial ES and matches local patterns, the prototype head tends to make sharper, better-calibrated predictions than the global linear head. It's the better classifier — so it's the teacher.
Instead of training the linear head against the hard multi-hot label, in Phase II we train it against the prototype head's soft probability distribution:
Two pieces decode this. pproto is the teacher's softmax — a soft target like "92% Cerulean, 5% Black-throated Blue, 3% other," which carries dark knowledge: the relative similarity between classes that a hard one-hot label throws away. And stopgrad[·] means: treat the teacher's output as a fixed constant when computing gradients.
| Phase I (≤300K steps) | Phase II (≤400K steps) | |
|---|---|---|
| Linear head | trained on multi-hot labels | trained on prototype soft targets (distill) |
| Prototype head | trained, but not used as teacher yet | now the teacher |
| Source head | trained | trained (lower weight) |
| Vizier-preferred mixup | heavy (N=2–5) | little/none (mostly N=1) |
| Distill loss weight | 0 | high (1.5–4.5) |
You can't distill from a teacher that doesn't exist yet. Phase I builds a competent prototype teacher. Phase II then uses it. By Phase II the embedding is already good, so the model wants gentler treatment: small learning rate, almost no mixup, less dropout.
The third head is the strangest and most clever. It asks the model to predict: which of the 1.5 million source recordings did this 5-second window come from? Each recording is literally its own class. This is the DIET objective (Balestriero, 2023): "Datum IndEx as Target."
A one-hour recording can be sliced into dozens of completely non-overlapping 5-second windows. They share no audio samples — a window from minute 3 and a window from minute 47 are acoustically unrelated. Yet they have the same source label. So to predict the source from a single window, the model must learn the stable, recording-level fingerprint — the individual bird's voice, the habitat's ambient signature, the microphone's character — that persists across the whole file.
A normal linear head from a 1536-dim embedding to 1.5M classes would be a weight matrix of
— larger than the entire rest of the model by 100×. Absurd. So the source head is low-rank, rank 512:
This factorization says "there are really only ~512 latent dimensions that distinguish recordings" — and it shrinks the head's parameters dramatically while keeping the gradient signal. One footnote-level gotcha: with 1.5M classes the cross-entropy loss is numerically large, so its loss weight is tuned carefully (Vizier picked 0.1–0.9 in Phase I, dropping toward 0 in Phase II) to avoid drowning out the species loss.
All minimized with Adam. The λ weights were swept with Vizier (Google's black-box hyperparameter optimizer): 100 models per stage, two stages per phase. Each model took 20–30 hours on a TPUv3-8.
The model is trained. Now the embedding model is frozen — no more gradients ever touch it. How do we use it, and how do we know it's good? Both the deployment workflow and the model-selection procedure are built around three frozen-embedding tasks.
| Mode | Labels needed | How it works |
|---|---|---|
| Pre-trained classifier (Pre) | none | Use the built-in head's scores directly (only for known species) |
| Retrieval (1-shot) | 1 example | Embed a query, rank everything by cosine distance to it |
| Linear probe (LP) | ~16/class | Train a tiny scikit-learn linear classifier on frozen embeddings |
| Prototype probe (PP) | ~16/class | Same, but with the prototype head — better on detection tasks |
The reason this list exists: practitioners have little labelled data and no GPUs. Embedding the dataset once and running a linear probe is cheap, requires no ML expertise, and reuses the same embeddings for clustering and search. This is the "agile modeling" workflow (Dumoulin et al., 2025).
You can't pick the best model on a single held-out accuracy — you'd pick one that's good at that domain and brittle elsewhere. So Perch validates on 19 datasets across three task types (pre-trained classification, retrieval, linear transfer) covering bird soundscapes, call-types, dialects, and non-avian taxa.
The aggregation choice is deliberate: a geometric mean of per-task scores, not an arithmetic mean.
Two benchmarks. BirdSet: six fully-annotated bird soundscapes (US, Hawai‘i, Peru, Colombia). BEANS: twelve cross-taxa tasks — birds, land & marine mammals, anurans, insects. Crucially, Perch 2.0 uses no fine-tuning: on BirdSet it applies its prototype head directly; on BEANS it trains only a linear/prototype probe on frozen embeddings.
On the AUROC metric the authors trust most (the most stable, per van Merriënboer et al.), Perch 2.0 reaches 0.908 on BirdSet, beating AudioProtoPNet-5 (0.896), Bird-MAE-L (0.886), and its own predecessor Perch 1.0 (0.839) — all without touching the embedding weights.
| Model | BirdSet AUROC | BirdSet cmAP | BEANS Acc |
|---|---|---|---|
| Perch 1.0 | 0.839 | 0.356 | — |
| Bird-MAE-L (self-sup.) | 0.886 | 0.440 | — |
| AudioProtoPNet-5 | 0.896 | 0.423 | — |
| BioLingual (zero-shot) | — | — | 0.479 (mAP) |
| Perch 2.0 (Random) | 0.908 | 0.431 | 0.665 |
Perch 2.0 sits at a crossroads of audio ML, transfer learning, and interpretable deep learning. Here's how it links to ideas you may already know — and a one-page summary of every symbol.
The whole training objective — three heads, the stop-gradient, the multi-hot mixup target — fits in one readable forward pass:
The single most important line is p_proto.softmax(-1).detach() — .detach() is the stop-gradient. Remove it and the teacher would warp the embedding to flatter itself. Everything else is bookkeeping.
| Symbol | Meaning | Shape / value |
|---|---|---|
| xmix | multi-source mixup waveform | [160000] |
| N ∼ BetaBin(n,α,β)+1 | number of blended sources | {1..6}, best 2–5 |
| w ∼ SymDir(N,ω) | blend weights (sum to 1) | ω ≈ 10–30 |
| ES | spatial embedding → prototype head | [5, 3, 1536] |
| EA | mean embedding (the deployed product) | [1536] |
| Lspecies | linear-head softmax CE on species | 14,795 classes |
| Lproto | prototype-head CE + orthogonality | 4 protos/class |
| Ldistill | student ← stopgrad(teacher soft targets) | λ ≈ 1.5–4.5 |
| Lsource | DIET: predict source recording (low-rank) | rank 512, 1.5M cls |
If your domain has hundreds of thousands of fine-grained labels, don't reach for self-supervision — train a small supervised model on the hardest classification task you can construct, freeze it, and let its embeddings be the foundation. The bittern is shy, but the lesson is loud.