Benjamin Elizalde, Soham Deshmukh, Mahmoud Al Ismail, Huaming Wang (Microsoft) — arXiv:2206.04769, June 2022

CLAP: Audio Concepts from Natural Language

Stop teaching machines a fixed menu of sounds. Teach them the relationship between what a recording sounds like and what a human would say about it — and the menu disappears.

Prerequisites: what a dot product is + what softmax does. Spectrograms, contrastive loss, and zero-shot inference are built from zero.
10
Chapters
12
Interactive Sims
128k
Training Pairs
82.6%
ESC50 Zero-Shot

Chapter 0: The Locked Menu

You have shipped a sound classifier. It is a good one: a convolutional network trained on fifty environmental sound classes, 82% accurate on the held-out fold, running in 40 ms on a phone. Dog barking, rain, chainsaw, crying baby, church bells — fifty categories, learned from thousands of labelled clips.

Then a product manager walks over and says: "Can it flag smoke alarms?"

Smoke alarm is not one of your fifty. And here is the part that should bother you: your model cannot even tell you that it does not know. Ask it about a smoke alarm recording and it will return a probability distribution over fifty categories that sum to one. It will pick something. It will pick it confidently.

Let us make that concrete before we make it abstract. Suppose the final layer produces three raw scores — call them logits, the unnormalised numbers that come out just before the softmax — on a smoke alarm clip:

z = [ dog barking: 1.2 , rain: 0.4 , church bell: 0.9 ]

Softmax exponentiates each and divides by the total: e1.2 = 3.320, e0.4 = 1.492, e0.9 = 2.460. The sum is 7.272. Divide:

p = [ 0.457 , 0.205 , 0.338 ]  →  "dog barking, 45.7% confident"

The clip contains no dog. The model was never able to say otherwise. The softmax denominator is the sum over the classes the model knows, so the probabilities are conditional on an assumption that is false: that one of my classes is the answer. There is no slot for "none of the above", because a slot is exactly what the architecture cannot grow.

The bug is not accuracy. The bug is the interface. A classifier's final layer is a matrix W with one row per class. The row for "smoke alarm" does not exist, and you cannot conjure it: a new row is a new set of parameters, which needs labelled smoke-alarm audio, which needs an annotation budget, which needs a retraining run, which needs a redeploy. The paper's opening sentence names this exactly — mainstream audio models learn under "one class label to many recordings, focusing on one task" — and calls it restricted supervision that "limits the flexibility of models."

Why the output layer is a prison

Walk the tensor shapes and the prison becomes visible. A typical audio classifier takes a spectrogram, runs it through an encoder to get a single vector h of size D (say 2048), and then does exactly one more thing:

z = W h + b,   W ∈ RC×D,  b ∈ RC,  then p = softmax(z)

Everything interesting lives in h. The encoder has learned something rich — texture, onset sharpness, harmonicity, room reverberation. But the only way to ask a question of that richness is through W, and W has exactly C rows, fixed at training time, one per category someone decided on months ago.

C is not a hyperparameter you can nudge at inference. It is the shape of a weight tensor. Change C and you change the model's identity: new parameters, new optimiser state, new data requirement, new evaluation. The vocabulary of the model is welded shut.

Question you want to askFixed-head classifierWhat it costs
"Is there a dog barking?"Yes — class 3 existsFree
"Is there a smoke alarm?"Impossible — no rowAnnotate + retrain + redeploy
"Is there a small dog barking, indoors?"Impossible — the label space has no compositional structureDefine a new taxonomy from scratch
"Rank these 50 clips by 'sounds like an emergency'"Impossible — that is not a classA whole new project
"None of the above?"Cannot be expressed — softmax sums to 1 over known classesThreshold hacks that do not transfer

Look at row three. The label space is not just small, it is flat. "Small dog barking indoors" is not a point some distance from "dog barking" — it is nowhere at all, because the one-hot label space has no geometry. Every class is equidistant from every other. A dog bark and a wolf howl are exactly as unrelated, to the loss function, as a dog bark and a trombone.

One-hot labels destroy information on purpose. The annotator who wrote "dog barking" for that clip knew far more: that a dog was barking repeatedly, that a person spoke nearby, that it happened outdoors. The labelling protocol threw all of it away and kept a single integer. Every one of the 128,010 pairs CLAP trains on is that thrown-away information, recovered.

What about self-supervised learning?

The obvious escape is to stop needing labels at all. Self-supervised learning (SSL) — pretraining on unlabelled audio with a pretext task like masked prediction or contrastive augmentation — does exactly that, and the paper credits it fairly: SSL "pretrains models with unlabeled audio, avoiding the limited supervision of learning from class labels."

But read the next sentence carefully, because it is the hinge of this whole paper: "However, SSL excludes semantic knowledge from natural language." An SSL model learns what audio looks like from the inside. It learns nothing about what any of it means to a person. And when you deploy it, you still bolt a fixed classification head on top and train it with class labels. Same prison, one floor up.

Supervised
Labelled audio → encoder → fixed head over C classes. Needs labels. Menu locked.
↓ remove the label requirement from pretraining…
Self-supervised
Unlabelled audio → encoder → then still a fixed head over C classes, trained with labels. No language. Menu still locked.
↓ …and give the model language instead
Natural-language supervision (CLAP)
Audio + free-text captions → two encoders → a shared space. The classifier head is replaced by text you type at inference time. No menu.

The paper calls this third option "a middle path between both approaches" and notes, in 2022, that it is "underexplored" for audio. Computer vision had already walked it: CLIP, Florence, ALIGN. In audio, the closest prior work — Wav2CLIP and AudioCLIP — distilled from CLIP and trained "with audio and class labels from AudioSet instead of audio and natural language." Close, but still label-shaped. Chapter 1 is about why that difference matters more than it looks.

See the prison, then see the door

Before any machinery, play with the failure. The simulation below runs the same three-second clip through two models. On the left is a fixed-head classifier with a menu of ten classes. On the right is an open-vocabulary model that scores whatever text you give it. Add a class the fixed head has never seen and watch what each one does.

Locked menu vs open vocabulary

Pick the sound that is actually playing, then add or remove candidate labels. The fixed head can only redistribute mass over its ten frozen rows — it has no way to represent an absent class, and no way to abstain. The open-vocabulary model scores every label you type, including ones nobody trained on.

True sound:

Three things to notice while you play. First, the fixed head's bars always sum to 100% — that is not confidence, it is arithmetic. Second, adding a class to the open-vocabulary model costs one forward pass of a text encoder and nothing else: no gradient step, no data, no redeploy. Third, the open model happily scores a phrase — "a small dog barking indoors" — which the fixed head could never have as a row.

The claim CLAP will make, stated now so you can hold it to account. If you train a model to place audio and its written description at the same point in a shared space, then classification becomes retrieval: embed the audio once, embed each candidate description once, and rank by similarity. The set of candidate descriptions is chosen at inference. It can be fifty classes or five, in a taxonomy nobody has ever written down. On ESC50 — fifty environmental sounds, none of which CLAP was trained to classify — this reaches 82.6% accuracy. Reported human performance on that dataset is 81%.

Three escapes people try first, and why each fails

Before accepting a new paradigm, it is worth being sure the old one is genuinely stuck. Here are the three fixes an engineer reaches for, in order, and where each one breaks.

Escape 1: just train on more classes. Go from 50 to 527 (AudioSet) or 200 (FSD50K). This helps and it does not solve anything, because the problem is not the size of the menu, it is that there is a menu. Someone still has to enumerate the categories in advance, and the annotation cost is now 500 times larger. The 528th sound still cannot be asked about.

Escape 2: use a hierarchy. AudioSet ships an ontology — "Animal → Domestic animals → Dog → Bark". Now "smoke alarm" can inherit from "Alarm". This buys real generalisation, and it buys it at a brutal price: the hierarchy is hand-built, it is finite, and it encodes exactly one way of carving up sound. "A small dog barking indoors" is not a node in anyone's ontology, and it never will be, because the space of useful descriptions is compositional and unbounded.

Escape 3: threshold for open-set rejection. If the maximum probability is below some θ, say "unknown". This is the most sophisticated of the three and it fails in an instructive way. Return to the smoke alarm example: the softmax gave (0.457, 0.205, 0.338). Set θ = 0.5 and the model correctly abstains. Now feed it a genuine dog bark whose logits are (2.4, 0.4, 0.9):

e2.4 = 11.023, e0.4 = 1.492, e0.9 = 2.460  →   sum 14.975
p = (0.736, 0.100, 0.164)  →  accepted at θ = 0.5

Fine so far. But now feed it a wolf howl — also absent from the taxonomy, and genuinely similar to a dog. Its logits might be (2.1, 0.3, 1.0), giving a maximum probability of 0.681 — comfortably above threshold, and confidently wrong. The threshold cannot distinguish "unknown but far from everything" from "unknown but close to something." The failure mode is worst exactly where it matters most: on near-neighbours of known classes.

Inline concept check — answer before reading on. Suppose you set θ = 0.8 to catch the wolf. What breaks?   …  Every genuine 50-way classification whose top probability is a healthy 0.7 now gets rejected too. On a 50-class task the model's correct answers routinely sit between 0.4 and 0.8, so a threshold tight enough to reject near-neighbours rejects most of your true positives. There is no setting of one scalar that separates "confident and right" from "confident and out of vocabulary", because both live at the same place in the output geometry.

All three escapes share a root cause: they try to fix the model's uncertainty when the actual deficiency is its vocabulary. CLAP does not improve the calibration of a fixed head. It removes the head.

What "zero-shot" actually means here

The phrase gets abused, so pin it down. Zero-shot in this paper means: the model performs a classification task with no training stage for that task at all. No fine-tuning, no linear probe, not even one labelled example. You supply the class names as text at inference time and read off similarities.

The paper is explicit: "Zero-shot requires no training stage so there are no predefined categories." That is a stronger claim than "generalises well." It means the deployment story changes shape — a new category is a string, not a project.

SetupLabelled examples of the target taskGradient steps at deploymentCan add a class at 3am?
SupervisedThousandsFull training runNo
Linear probe on SSL featuresHundreds to thousandsHead onlyNo
Few-shot1–16 per classSomeSort of
Zero-shot (CLAP)ZeroNoneYes — type the string

Hold on to the honesty, though, because this lesson will not oversell. CLAP's zero-shot numbers are spectacular on sound events and close to random on keyword spotting. Chapter 6 shows every number, including the embarrassing ones, and Chapter 8 explains why they are exactly the numbers you should have predicted from the training data.

How audio classification got here

The locked menu is not a mistake anyone made. It is the accumulated shape of two decades of sensible decisions, and knowing the sequence makes the break feel earned rather than arbitrary.

EraWhat supervision looked likeWhat it unlockedWhat stayed locked
Feature engineering (1990s–2000s)Hand-designed features (MFCCs, spectral centroid) plus a GMM or SVM per classSpeech recognition, speaker ID, first environmental sound systemsFeatures were fixed by a human; each task needed its own pipeline
Benchmark challenges (DCASE, from 2013)Curated, labelled datasets with a fixed taxonomy per challengeComparable results, real progress, a research communityThe taxonomy became the definition of the problem
Deep supervised (2015–2020)Spectrograms as images, CNNs, softmax over C classes. AudioSet's 2M clips and 527 classesLarge-scale transfer: PANNs, YAMNet — encoders you could reuseThe reusable part was the encoder. The head was still per-task and still fixed
Self-supervised (2020–2022)No labels during pretraining; masked or contrastive pretext tasksFreedom from annotation at pretraining timeStill a fixed head at fine-tuning time. And no language at all
Natural-language supervision (2022–)Audio paired with a human sentenceThe head disappears; the taxonomy is chosen at inferenceOnly what people write about — which Chapter 6 will measure precisely

Read down the last column. Each era freed one thing and left the interface alone. AudioSet's 527 classes made the menu bigger; self-supervision made the menu cheaper to build; neither removed it. That is the specific act CLAP performs.

The paper's three contributions, numbered

The introduction states them explicitly, and it is worth holding all three separately because they are usually collapsed into one.

1. The model
CLAP itself, trained on 128k audio-text pairs with two encoders and contrastive learning — a demonstration that the CLIP recipe transfers to audio at a fraction of the data.
2. The capability
Zero-shot prediction: "removes the need of training and forcing a predefined set of categories and enables flexible class prediction at inference time."
3. The evidence
Generalisation to 16 downstream tasks across 8 domains, establishing zero-shot state of the art — plus supervised state of the art on five of them.

Contribution 2 is the one that changes how systems are built; contribution 3 is what makes 2 believable. Contribution 1 is, honestly, the least novel part — the architecture is CLIP's, and the paper says so. Novelty and importance are not the same axis, and this paper is a clean example of the gap.

Inline concept check. If CLAP's architecture is essentially CLIP's, what is the actual scientific claim being tested?  …  That audio concepts are learnable from natural language at a data scale three orders of magnitude below CLIP's. That was not obvious in advance: audio captions are scarcer, noisier, and less standardised than image alt-text, and no one knew whether 128k pairs was above or below the threshold where the paradigm starts working. The result is a measurement, not an invention.

Where we are going

Chapters 1–3 — build the machine
Why captions are richer supervision than labels → how a pressure wave becomes a 64×690 tensor → two encoders and two projections, with every shape named
Chapters 4–5 — the two showcases
Derive the similarity matrix and its symmetric cross-entropy loss by hand on a 3×3 batch → then watch classification collapse into retrieval
Chapters 6–9 — interrogate it
All 16 tasks with the lows included → which tower actually matters → what the paper only whispers → the lineage it started
A fixed-head classifier trained on 50 classes is given a smoke alarm recording. Why can it not report "none of the above"?

Chapter 1: Captions Are Supervision

Chapter 0 ended with a promise: replace the label with a sentence. That sounds like a small edit — a richer annotation format. It is not. It changes what the loss function can possibly teach, and it changes what the model can possibly be asked at inference. This chapter is about why.

Here are four real captions from CLAP's training data, sampled in the paper's own appendix table:

"A bow playing a stringed instrument in a one note tone repeatedly before violins join to create the melody" — ClothoV2

"Several sirens are wailing and a horn is honked twice" — AudioCaps

"Canada geese flying down and landing near a lakeshore. Recorded with an Olympus LS-14." — FSD50K

"Two people having a conversation nearby while a lot of adults and a child talk far away" — MACS

Now compress each into one integer from a taxonomy. "Music." "Siren." "Bird." "Speech." Look at what evaporates.

Information in the captionSurvives the label?What it would have taught
Multiple sources present at onceNo (single label)Scene composition, source separation priors
Temporal order ("before violins join")NoThat sound has structure in time, not just identity
Counting ("honked twice", "a child")NoRepetition, cardinality
Distance / perspective ("nearby", "far away")NoLoudness and reverberation carry spatial meaning
Manner ("wailing", "repeatedly", "flying down and landing")NoFine-grained acoustic dynamics
The recording gear ("Olympus LS-14")NoNothing useful — genuine caption noise, and CLAP eats it anyway
Category identityYesExactly the one bit of the taxonomy
The measurable version of "richer". A one-hot label over 50 classes carries at most log2(50) ≈ 5.6 bits about the clip. A 15-word English caption drawn from a realistic vocabulary carries hundreds of bits, and — more importantly — those bits are structured: "wailing" and "honked" are close in a language model's space in a way that class 7 and class 12 never are. Natural language is a supervision signal that arrives with its own geometry pre-installed.

The geometry point, made precisely

This is worth slowing down for, because it is the load-bearing idea of the whole paradigm. Take the one-hot targets for three classes:

dog = (1,0,0),   wolf = (0,1,0),   trombone = (0,0,1)

Compute the distance between any two: the squared Euclidean distance is 2 for every pair. Dog-to-wolf: 2. Dog-to-trombone: 2. The loss function is structurally incapable of knowing that a dog and a wolf are related. If the model confuses a wolf howl for a dog bark, it is penalised exactly as hard as if it had said trombone.

Now take the caption route. "A dog barking in a yard" and "a wolf howling in the distance" are two token sequences that a language encoder maps to two vectors that are genuinely close, because they share a, in, the animal-vocalisation frame, and the outdoor-scene frame. The target for the audio is no longer an arbitrary corner of a simplex; it is a point in a space where semantic neighbours are geometric neighbours.

That is the entire trick. The text encoder donates its geometry to the audio encoder. Everything else — the contrastive loss, the projections, the temperature — is plumbing to make the donation happen.

What a caption buys you that a label cannot

The same clip, supervised two ways. Click any word in the caption to see which acoustic evidence it commits the model to explain. Toggle to label mode and watch the evidence collapse to a single point — and watch the target geometry collapse with it.

Where 128,010 pairs came from

The paper did not commission a new dataset. It assembled one out of four public corpora, and the assembly is itself instructive:

DatasetPairsUnique audiosUnique captionsHow the text was obtained
FSD50K36,79636,79636,796Title + description from Freesound metadata, concatenated. The class label was deliberately ignored.
ClothoV229,6465,92929,6465 human captions per clip → 5 pairs per clip
AudioCaps44,29244,29244,2921 crowdsourced caption per 10-second AudioSet clip
MACS17,2763,93017,276Multiple annotators per clip → multiple pairs per clip
Total128,01090,947128,010Four datasets, one shared idea

Two details in that table are easy to skim past and both are load-bearing.

Pairs exceed unique audios by 41%. 128,010 pairs over 90,947 clips. ClothoV2 contributes five captions for each of 5,929 clips; MACS multiplies similarly. So the same audio appears repeatedly with different descriptions. That is free regularisation: the model is being told, five ways, that one waveform has many valid verbalisations. It cannot latch onto one phrasing. It is nudged toward the meaning that all five share.

FSD50K's class label was thrown away on purpose. FSD50K ships with clean sound-event labels — the paper's own Table 1 evaluates on them. And the authors chose the messy human-written title and description instead. That is a bet: that noisy natural language beats clean categories as a training signal. Chapter 8 will show you the one place that bet failed spectacularly.

Scale check, and it is humbling. CLIP — the vision model CLAP is explicitly modelled on — reports 400 million image-text pairs. CLAP has 128,010. That is roughly one three-thousandth (0.032%) of the data. The paper's conclusion phrases this awkwardly ("at least 0.001% smaller"), but the point stands and is the most surprising thing about the result: the paradigm's returns did not require CLIP's scale to show up. A hundred thousand honest captions were enough to beat human accuracy on ESC50.

Counting the bits, properly

"Captions are richer" deserves an actual number rather than a gesture. Information theory gives one.

A label drawn uniformly from C categories carries log2(C) bits. For ESC50's fifty classes that is 5.64 bits. For FSD50K's 200 classes, 7.64 bits — and even that is optimistic, because real label distributions are skewed, which lowers the entropy further.

A caption is a sequence of words. If you model English at roughly 8–10 bits per word for content-bearing text (Shannon's classic estimate for English is about 1 bit per character after redundancy, so a 5-letter word plus a space runs about 6 bits, and audio captions are less predictable than newspaper prose), then a 15-word caption carries on the order of a hundred bits. Two orders of magnitude more than the label.

SupervisionRough information contentStructured?
One-hot over 50 classes≈ 5.6 bitsNo — all pairs equidistant
One-hot over 527 classes (AudioSet)≈ 9.0 bitsOntology helps, but is hand-built and finite
Multi-label over 200 classesup to 200 bits, in practice a handfulSlightly — co-occurrence carries some structure
A 15-word captionon the order of 100 bitsYes — a pretrained language geometry comes free with it

But the bit count is the less important half. The label's 5.6 bits are unstructured: they identify a corner of a simplex and say nothing about which corners are near which. The caption's hundred bits arrive already embedded in a space where synonyms are close, negations are far, and compositional phrases land between their parts. That structure is what CLAP is really harvesting.

Inline concept check. Why does the same clip appearing five times with five different captions help, rather than confuse?  …  Because the audio embedding is being pulled toward five different points, so the only stable solution is the region they share. Idiosyncratic wording — one annotator's "buzzing", another's "droning" — cancels. What survives is the intersection: the meaning. Five noisy targets around a truth beat one clean target that is the wrong kind of thing.

How the pairs are actually assembled

python — constructing CLAP's 128,010 pairspairs = []

# FSD50K: 36,796 clips. The class label is available and DELIBERATELY IGNORED.
for clip in fsd50k_train_and_val:
    caption = clip.title + ". " + clip.description      # raw Freesound metadata
    pairs.append((clip.audio, caption))                   # 1 pair per clip

# ClothoV2: 5,929 clips, each with 5 human captions -> 5 pairs each.
for clip in clotho_v2:
    for caption in clip.captions:                         # len == 5
        pairs.append((clip.audio, caption))               # 29,646 total

# AudioCaps: 44,292 ten-second AudioSet clips, 1 crowdsourced caption each.
# MACS: 3,930 clips captioned by multiple annotators -> 17,276 pairs.

len(pairs)                       # 128,010
len({p[0] for p in pairs})       # 90,947 unique clips  <- 41% more pairs than audio
len({p[1] for p in pairs})       # 128,010 unique captions <- every caption is distinct

Look at the last two lines together. Every caption is unique; the clips are not. That asymmetry is a design decision with a consequence we will meet again in Chapter 8: at large batch sizes, two entries in the same batch can be the same audio with different captions, and the contrastive loss will insist they are negatives of each other.

The FSD50K decision, read as an experiment. FSD50K ships with clean, curated, multi-label sound-event annotations — and the authors used the Freesound uploader's free-text title and description instead. Uploaders write things like "Canada geese flying down and landing near a lakeshore. Recorded with an Olympus LS-14." That last sentence is pure noise: no acoustic content, just gear. The authors kept it. That is a deliberate bet that the noise-to-signal ratio of human prose still beats the information ceiling of a taxonomy. Chapter 6 shows the bet paying off — and Chapter 8 shows precisely where it stops paying.

CLIP, Wav2CLIP, AudioCLIP — and the difference that matters

Two audio models had already borrowed CLIP's machinery by 2022, and understanding why CLAP is not just a third one clarifies the contribution.

ModelText signal it learns fromRelationship to CLIPConsequence
Wav2CLIPAudioSet class labels, routed through CLIP's frozen text encoderDistils from CLIP; audio is aligned to CLIP's existing image-text spaceInherits CLIP's vocabulary but is trained on label-shaped text
AudioCLIPAudioSet class labels, in a tri-modal image/text/audio setupExtends CLIP with a third towerSame: the supervision is a taxonomy wearing a sentence's clothes
CLAPFree-form human captions describing what the clip sounds likeSame recipe as CLIP, trained from scratch on audio-textLearns the full distribution of ways people describe sound

The paper is measured about the prior work — "the performance was promising" — but names the gap precisely: those models are "trained with audio and class labels from AudioSet instead of audio and natural language," so "it is yet to be explored how natural language can benefit flexibility and generalization to new classes and tasks."

Why does training on label-text hurt? Because of a distribution mismatch that will come back in Chapter 5. If every training text is a bare category name, the text encoder's useful region is a small island of noun phrases. Ask it about "a small dog barking indoors" and you are off the island. If instead the training text is real sentences, the model has seen the whole continent, and the class names at inference are the odd case — which, delightfully, is exactly the problem the prompt templates of Chapter 5 exist to fix.

The results back the argument. On ESC50 zero-shot, AudioCLIP reaches 69.40% and CLAP reaches 82.6% — an absolute 12-point gap. On UrbanSound8K, AudioCLIP 65.31% versus CLAP 73.24%. On the multi-label FSD50K, Wav2CLIP reaches 3.02% mAP and CLAP reaches 30.24% — a 27-point absolute jump. Same architecture family, same contrastive idea, different text. The text is the contribution.

What "natural language supervision" is not

The phrase is loose enough to cover several different things, and CLAP means exactly one of them. Pin the boundaries.

Not thisWhy it is different
Text as an auxiliary task — predict a caption from audio with a decoderThat is audio captioning: a generative objective producing one output. CLAP's objective is discriminative and produces a space. Captioning models cannot rank arbitrary candidate strings cheaply
Labels written as words — "dog_barking" turned into "dog barking"The vocabulary is still a closed taxonomy. This is Wav2CLIP and AudioCLIP, and Chapter 6 shows the 12-point gap it leaves on the table
Text-conditioned generation — produce audio from a promptThe opposite direction. It consumes a joint space rather than building one — and, as Chapter 9 notes, several such systems consume CLAP's
Instruction tuning on audio — answer questions about a clipRequires a language model, not a language encoder. That arrives two years later and is built on top of this
This: pair a clip with a free-form description and learn a shared space contrastivelyDiscriminative, dual-encoder, and the description is whatever a human happened to write

The narrowness is the point. CLAP does one thing: it makes audio and its description land in the same place. Everything in the rest of this lesson is a consequence of that single commitment.

Reading four captions like an engineer

Take the paper's own samples and ask, of each, what the model is being asked to solve.

CaptionThe task it silently sets
"An insect buzzing in the foreground as birds chirp in the background"Figure-ground separation. The model must represent two simultaneous sources and their relative prominence — from a single pooled vector
"Church bells chime loudly and repeatedly"Intensity and periodicity. "Loudly" is an absolute-level claim the log compression partly erases; "repeatedly" is a temporal-structure claim clip-level pooling erases entirely
"Water dripping in a cave or underground temple"Reverberation as a scene cue. The source is a drip; the room is inferred from the tail. This is the acoustic-scene skill that gives TUT2017 its 25% headroom in Chapter 6
"Beating drum getting faster than children voices and clapping then adult male voice"Three sources, a tempo change, and an ordering. Roughly half of this is unlearnable for a bag-of-events model — and it is still better supervision than the label "drum"

Two of the four demand things the architecture provably cannot represent. That is not a flaw in the data; it is how the ceiling gets set. The model extracts what it can and treats the rest as noise, which is exactly why the resulting embedding is a good event detector and a poor sequence model.

The honest version of "richer supervision". A caption is not a better label. It is a partially unlearnable target that contains the label plus a great deal more. The model captures the learnable fraction, and even that fraction beats a taxonomy. Contrast this with the usual framing — "more information is better" — which would predict that the most detailed captions help most. Chapter 8 shows the opposite failure: captions that are detailed about the wrong thing (a YouTube title describing a whole video) are actively harmful. The relevant axis is not detail. It is acoustic relevance.

The one-sentence method

Before the plumbing chapters, here is the whole model in a sentence you should be able to reconstruct by Chapter 4: encode the audio, encode the caption, project both into one shared space, and train so that each clip's own caption is the nearest text in the batch and every other caption is far.

Input: a pair
One audio clip and one human sentence describing it. That is the entire annotation.
↓ two independent encoders (Chapter 3)
Two vectors, two different sizes
2048-dim from audio, 768-dim from text. Not yet comparable — different spaces, different units.
↓ two learnable linear projections
One shared space, d = 1024
Now a dot product between them means something. This is the joint multimodal space.
↓ contrastive loss over the batch (Chapter 4)
Pull the N matched pairs together, push the N2−N mismatched pairs apart
No class labels appear anywhere in this objective. That is the point.
Wav2CLIP and AudioCLIP also connect audio to text. What is the substantive difference in CLAP's supervision, and why does the paper argue it matters?

Chapter 2: From Pressure Wave to Tensor

Chapter 1 gave us pairs: a clip and a sentence. The sentence is easy — text encoders eat text. The clip is not. A microphone hands you a list of numbers describing air pressure over time, and a convolutional network wants a two-dimensional array with meaningful local structure. Getting from one to the other is a sequence of deliberate, lossy decisions, and the paper specifies every one of them in three lines of Section 3.2. This chapter unpacks those three lines completely, because if you cannot state the shape of the tensor entering the audio encoder, you do not understand the model.

Here is the paper's own specification, verbatim in substance: log Mel spectrogram, sampling rate 44.1 kHz, hop size 320, window size 1024, 64 Mel bins in the range 50–8000 Hz, each clip randomly truncated to a continuous 5-second segment or padded if shorter.

A typo worth naming, because it will confuse you otherwise. The paper writes "hop size of 320 secs, window size 1024 secs." Those units are impossible — a 1024-second window on a 5-second clip. These are samples. At 44.1 kHz, 1024 samples is 23.22 ms and 320 samples is 7.26 ms, which are entirely standard values. Read every number in a paper by asking whether the units make physical sense; here they do not, and the fix is obvious.

Step 1 — the raw signal, and why it is not enough

At 44.1 kHz, five seconds of audio is 5 × 44,100 = 220,500 floating-point numbers. That is a one-dimensional array. You could hand it straight to a network — some models do — but for a convolutional encoder it is a bad substrate for three reasons.

The features are non-local in time. A 440 Hz tone is a pattern that repeats every 100 samples. To notice it, a filter needs a receptive field spanning hundreds of samples. To notice a 50 Hz rumble it needs 880. Pitch information lives at scales that a small convolution kernel cannot see.

Phase is mostly nuisance. Shift the whole waveform by one sample and every number changes, while the sound is perceptually identical. You would be asking the network to learn shift-invariance from scratch, using capacity you would rather spend elsewhere.

It is enormous. 220,500 numbers per clip, times a batch, times 40 epochs.

So we transform: chop time into overlapping frames, take the frequency content of each frame, and stack the results into an image-like array where one axis is time and the other is frequency. Convolutions are good at images. That array is the spectrogram.

Step 2 — framing: window 1024, hop 320

The window length is how many consecutive samples go into one frequency analysis; the hop is how far you slide before the next one. CLAP uses 1024 and 320.

QuantityIn samplesIn time at 44.1 kHzWhy this value
Window102423.22 msLong enough that a periodic sound completes several cycles (a 100 Hz tone fits 2.3 cycles); short enough that the sound does not change much within it — the "locally stationary" assumption
Hop3207.26 msFine enough to place a transient (a click, a consonant, a drum hit) to within about 7 ms; coarse enough to keep the tensor small
Overlap70415.96 ms68.75% overlap. Neighbouring frames share most of their samples, so an event straddling a boundary is never lost
Frames in 5 s1 + ⌊220,500 / 320⌋ = 690This is T, the time axis of the tensor

Notice the tension the two numbers resolve. Make the window longer and you get sharper frequency resolution but you smear transients — a sudden bark becomes a blur. Make it shorter and onsets get crisp but pitch turns to mush. This is the time-frequency uncertainty tradeoff, and 23 ms is the conventional compromise for general audio.

Then hop is chosen separately and smaller, which is the part beginners often miss. Overlap does not improve the frequency resolution of any single frame — that is set by the window. What it buys is temporal sampling density: the analysis is re-run every 7.26 ms so that whatever the window sees, it sees at many alignments.

Step 3 — the FFT, and 513 bins nobody wants

Each 1024-sample frame goes through a discrete Fourier transform, yielding 1024 complex coefficients. Real signals have conjugate-symmetric spectra, so only 1024/2 + 1 = 513 of them are independent. Take their magnitudes and discard phase.

Each of those 513 bins covers 44,100 / 1024 = 43.07 Hz, uniformly. That uniformity is the problem. Uniform spacing means bin 1 (43 Hz) to bin 2 (86 Hz) is one octave — a gigantic perceptual leap — while bin 400 (17,226 Hz) to bin 401 (17,269 Hz) is a difference no human can hear. The representation spends most of its dimensions on distinctions nobody perceives.

Step 4 — Mel: 513 bins to 64, warped to hearing

The Mel scale is an empirical mapping from frequency in hertz to perceived pitch, built so that equal steps on the Mel axis sound like equal pitch steps. The standard form:

m(f) = 2595 · log10(1 + f / 700)

Let us actually run CLAP's numbers rather than admire the formula. The band is 50 to 8000 Hz with 64 filters.

StepComputationResult
Low edge in Mel2595 · log10(1 + 50/700) = 2595 · log10(1.0714)77.75 mel
High edge in Mel2595 · log10(1 + 8000/700) = 2595 · log10(12.4286)2840.02 mel
Span2840.02 − 77.752762.27 mel
Spacing (64 filters need 66 edge points, so 65 gaps)2762.27 / 6542.50 mel per step
First filter, in hertzedges at 50.0 and 108.7 Hz58.7 Hz wide
Last filter, in hertzedges at 7368.0 and 8000.0 Hz632.0 Hz wide

The last filter is 10.8 times wider than the first. That single ratio is the entire content of the Mel warp: fine resolution where hearing is fine, coarse where it is coarse. Each of the 64 outputs is a weighted sum of the 513 FFT magnitudes, with triangular weights over that filter's band. 513 numbers become 64, and the ones we kept are aligned with perception.

The decision nobody flags: the ceiling is 8000 Hz, but Nyquist is 22,050 Hz. Sampling at 44.1 kHz means frequencies up to 22.05 kHz are representable — and CLAP's front end throws away everything above 8 kHz, roughly 64% of the available band. For environmental sound events this is defensible: barks, engines, rain, and sirens carry their identity far below 8 kHz. But sibilance in speech ("s", "sh", "f") lives from 4 to 10 kHz, cymbals and brushes carry brilliance above 8 kHz, and the fine spectral detail that separates one speaker's voice from another is partly up there too. Keep this in your pocket: in Chapter 6 CLAP is near chance on keyword spotting and emotion recognition, and this front end is one of several converging reasons.

Step 5 — the logarithm

Mel energies span an enormous dynamic range: a loud transient can be a million times the energy of a quiet background. Feed that to a network and the loud bins dominate every gradient. So take the logarithm.

Two things happen, and both are useful. First, dynamic range compression: six orders of magnitude become a span of about 14 in natural log, comfortable for a network. Second, and more elegant, gain becomes an offset. Record the same sound twice as loud and every energy is multiplied by 4; in the log domain every value gains a constant log 4. A network with any translation tolerance — or a batch-norm layer — can shrug that off. Volume stops being a confound.

This also mirrors hearing: perceived loudness is roughly logarithmic in intensity, which is exactly why we measure it in decibels.

The tensor, finally

Xa ∈ RF×T = R64 × 690

This is the paper's own notation from Section 2.1: "Let the processed audio be Xa such that Xa ∈ RF×T where F are the number of spectral components (e.g. Mel bins) and T are the number of time bins." Now you can fill in both letters: F = 64, T = 690.

That is 44,160 floats, down from 220,500 raw samples — a 5.0× compression, and every surviving number is perceptually meaningful. In a batch of N pairs the audio tensor is (N, 64, 690), or (N, 1, 64, 690) once you add the channel axis a 2-D convolution expects.

Waveform to spectrogram explorer

Top: the pressure wave. Bottom: the log-Mel spectrogram CLAP's encoder actually sees. Change the window, hop, and Mel-bin count and watch the tensor shape recompute live. The paper's settings are marked. Push the window down to 256 and watch pitch structure dissolve into vertical smears; push it to 4096 and watch a transient spread across time.

Window 1024
Hop 320
Mel bins 64

The uncertainty tradeoff, with actual numbers

"Longer window, sharper frequency, blurrier time" is easy to say and worth quantifying, because the numbers explain why 1024 and not 256 or 4096.

Window (samples)DurationFFT bin widthFrames in 5 s at hop 320What it does well / badly
2565.8 ms172.3 Hz690Onsets are razor sharp. Pitch is unusable — a 172 Hz bin cannot separate a bass note from the one above it
51211.6 ms86.1 Hz690Common for speech, where phonemes are short
102423.2 ms43.07 Hz690CLAP's choice. Resolves musical pitch above ~90 Hz while keeping events crisp
204846.4 ms21.5 Hz690Beautiful harmonics; a handclap smears across two frames
409692.9 ms10.8 Hz690Music-analysis territory. Environmental transients are destroyed

Two things to notice in that table. First, the frame count does not change with the window — it is set entirely by the hop. Window and hop are genuinely independent knobs, controlling resolution and sampling density respectively. Second, the product of duration and bin width is constant at about 1.0: 5.8 ms × 172.3 Hz ≈ 1, 92.9 ms × 10.8 Hz ≈ 1. That is the time-frequency uncertainty principle, and no amount of engineering escapes it. You can only choose where to spend it.

Inline concept check. A 100 Hz tone (a low hum) needs how many samples for one full cycle at 44.1 kHz, and does CLAP's window contain it?  …  44,100 / 100 = 441 samples per cycle. A 1024-sample window holds 2.3 cycles — just enough for the FFT to register a peak, and exactly why the Mel filterbank's lowest edge sits at 50 Hz rather than 20: below about 90 Hz there is barely more than one cycle in the window, so the estimate is unreliable.

One Mel filter, weight by weight

The filterbank is often treated as a black box. It is not; it is 64 triangles. Build filter 0 by hand.

Its three edge frequencies, from the Mel spacing computed above, are 50.0, 78.8, and 108.7 Hz. Convert each to an FFT bin index by dividing by the 43.07 Hz bin width:

bin(50.0) = 50.0 / 43.07 = 1.16 → 1  ·  bin(78.8) = 1.83 → 1  ·  bin(108.7) = 2.52 → 2

The triangle rises from bin 1 to its peak near bin 1.83 and falls to bin 2.52. With only two or three FFT bins underneath it, the weights come out roughly 0.63 on bin 1 and 0.37 on bin 2. Compare filter 63, spanning 7368 to 8000 Hz: bins 171 through 186, sixteen bins wide, with a smooth triangular ramp over all of them.

That contrast is the Mel warp made concrete. Low filters are starved — barely more than one FFT bin each — while high filters average sixteen. If you wanted better low-frequency resolution you would need a longer window, and you would pay for it in time smearing. The filterbank does not create resolution; it allocates the resolution the FFT gave you.

Why not just feed the raw waveform?

Learned front ends exist and work — SincNet, LEAF, and the convolutional stems of wav2vec-style models all take samples directly. So the log-Mel choice is a decision, not a law. Weigh it honestly:

Fixed log-Mel (CLAP)Learned front end
ParametersZero — the filterbank is a constant matrixThousands to millions, trained
Data neededNone — it encodes psychoacoustics for freeSubstantial; the front end must be learned from scratch
Inductive biasStrong and usually correct: log frequency, log amplitude, phase discardedWeak — can discover better filters, or waste capacity rediscovering the Mel scale
TransferabilityTotal — every audio model speaks log-MelTied to the model it was trained with
CeilingCapped by what the filterbank preserves — and it discards phase and everything above 8 kHzHigher, given enough data

With 128,010 pairs, the strong prior wins. CLAP has nowhere near enough data to learn a front end; it barely has enough to learn an alignment. The log-Mel front end is 44,160 free, perceptually-organised numbers, and that is exactly the deal a small-data project should take.

The same pipeline, three ways

First by hand, on one frame, so nothing is magic:

the arithmetic for ONE frame# frame 0 = samples 0..1023 of a 220,500-sample clip
x = signal[0:1024]                  # 1024 floats
x = x * hann_window                  # taper the edges so the FFT sees no cliff
X = fft(x)                           # 1024 complex numbers
mag = abs(X[0:513])                 # keep the non-redundant half, drop phase
power = mag ** 2                     # 513 energies, one per 43.07 Hz bin

# mel filter 0 covers 50.0 -> 108.7 Hz, i.e. FFT bins 1..2 (43.07 Hz each)
# with triangular weights peaking at 78.8 Hz:
mel[0] = 0.63*power[1] + 0.37*power[2]
# mel filter 63 covers 7368 -> 8000 Hz, i.e. FFT bins 171..186 -- 16 bins wide
mel[63] = sum(w[i] * power[i] for i in range(171, 187))
logmel = np.log(mel + 1e-10)          # epsilon so log(0) is finite
# repeat for frames 1..689, hopping 320 samples each time -> (64, 690)

Then the honest loop, which is what the hand version generalises to:

python — numpy, from scratchimport numpy as np

SR, WIN, HOP, N_MEL, FMIN, FMAX = 44100, 1024, 320, 64, 50, 8000

def hz_to_mel(f): return 2595 * np.log10(1 + f / 700)
def mel_to_hz(m): return 700 * (10 ** (m / 2595) - 1)

def mel_filterbank():
    edges = np.linspace(hz_to_mel(FMIN), hz_to_mel(FMAX), N_MEL + 2)   # 66 points
    hz    = mel_to_hz(edges)                                       # 50.0 ... 8000.0
    bins  = np.floor((WIN + 1) * hz / SR).astype(int)
    fb    = np.zeros((N_MEL, WIN // 2 + 1))                        # (64, 513)
    for m in range(N_MEL):
        l, c, r = bins[m], bins[m + 1], bins[m + 2]
        fb[m, l:c] = np.linspace(0, 1, c - l)                       # triangle up
        fb[m, c:r] = np.linspace(1, 0, r - c)                       # triangle down
    return fb

def log_mel(sig):                       # sig: (220500,) float32
    win  = np.hanning(WIN)
    n    = 1 + (len(sig) - WIN) // HOP
    S    = np.stack([np.abs(np.fft.rfft(sig[i*HOP : i*HOP+WIN] * win)) ** 2
                      for i in range(n)], axis=1)          # (513, T)
    return np.log(mel_filterbank() @ S + 1e-10)          # (64, T)

And the one-liner you would actually ship:

python — torchaudio, the one-linerimport torchaudio.transforms as T

front_end = torch.nn.Sequential(
    T.MelSpectrogram(sample_rate=44100, n_fft=1024, win_length=1024,
                     hop_length=320, f_min=50, f_max=8000, n_mels=64),
    T.AmplitudeToDB())
X_a = front_end(waveform)      # (B, 64, 690)  <- the paper's X_a, exactly

The 5-second crop, and a cost the paper does not price

"During training, each audio clip is randomly truncated to a continuous segment of 5 secs, or padded if shorter." Two clauses, two consequences.

Random truncation is augmentation and it is also label noise. ClothoV2 clips run 15 to 30 seconds and their captions describe the whole clip. Take a random 5-second window of "a bow playing a stringed instrument in a one note tone repeatedly before violins join to create the melody" and there is a good chance your window contains only the bow, or only the violins. The caption is then partly wrong for the crop you are training on. Over 40 epochs the crop re-randomises, so on average the model sees every part of the clip paired with the full caption — the noise averages toward a weak-labelling signal rather than a systematic bias. But the per-step gradient is noisier than the pairing suggests, and this is one reason a large batch matters (Chapter 8).

Padding is worse than it looks, on exactly the tasks that failed. The paper never mentions this, but run the arithmetic on the downstream datasets and a pattern jumps out:

Task datasetClip durationFraction of the 5 s input that is real audioCLAP zero-shot
ESC505 s100%0.826
UrbanSound8Kup to 4 s80% or less0.7324
Vocal Sound5 s100%0.4945
Mridangam Stroke / Tonic0.81 s16%0.3447 / 0.1965
Speech Commands V21 s20%0.1063 (random is 0.083)

This is a correlation on a handful of points, not a proof, and Chapter 8 will give a much stronger explanation for the speech failures — the training captions simply do not describe speech content. But note the mechanism, because it is real: a CNN14 that global-pools over the time axis is averaging over 690 frames of which 552 are silence for a Speech Commands clip. Whatever evidence exists is diluted five-fold before the classifier ever sees it.

Front ends are not neutral. Every choice in this chapter — 8 kHz ceiling, 64 bins, 23 ms windows, 5-second crops, zero padding — is a statement about which distinctions matter. The front end was tuned for sound events, and the model that grows on top of it will be excellent at sound events and mediocre elsewhere. When you read Chapter 6's table, read it as the front end's report card too.
CLAP samples at 44.1 kHz but its Mel filterbank tops out at 8000 Hz. What is the direct consequence?

Chapter 3: Two Towers, One Space

We have Xa ∈ R64×690 and a caption string. Section 2.1 of the paper compresses the next stage into two equations. This chapter expands them into every tensor shape, every parameter count, and every design decision behind them — because "two encoders and two projections" is a diagram, and a diagram is not understanding.

a = fa(Xa) ;   X̂t = ft(Xt)    (1)

Where, in the paper's words, X̂a ∈ RN×V are the audio representations of dimensionality V, and X̂t ∈ RN×U the text representations of dimensionality U. N is the batch size. From Section 3.2 we can name V and U: V = 2048 and U = 768.

Tower A: CNN14, the borrowed ear

The audio encoder fa is CNN14, taken from PANNs (reference [23] in the paper). The paper gives its vital statistics: 80.8 million parameters, embedding size 2048, and — the important part — "pretrained with 2M audio clips from AudioSet."

Read that last clause slowly. CLAP does not learn to hear from 128k captioned clips. It starts from an encoder that already learned to hear from two million labelled AudioSet clips, and then re-purposes that ear to speak to language. The 128k pairs are not building an audio front end; they are building a bridge. This is why 128k pairs is enough where CLIP needed 400M — CLIP's vision tower was trained from scratch.

The paper also states its own reason for the choice: CNN14 was picked "to provide a fair comparison to previous SoTA models." PANNs, Wav2CLIP, and AudioCLIP all use it, so any difference in the results is attributable to the training signal, not to a fancier encoder. That is good experimental hygiene and worth copying.

CNN14's internals come from the PANNs paper rather than this one, but they matter for tracing shapes. It is six convolutional blocks; each block is two 3×3 convolutions with batch norm and ReLU, followed by 2×2 average pooling. Channels double each block. Then a global pooling over what remains, and a fully-connected layer to the 2048-dim embedding:

StageTensor shape (one clip)What just happened
Input log-Mel(1, 64, 690)Chapter 2's tensor, with a channel axis
Block 1 (64 ch)(64, 32, 345)Local time-frequency edges; both axes halved
Block 2 (128 ch)(128, 16, 172)Onsets, harmonic stacks
Block 3 (256 ch)(256, 8, 86)Textures spanning ~60 ms
Block 4 (512 ch)(512, 4, 43)Event-scale patterns
Block 5 (1024 ch)(1024, 2, 21)Frequency axis nearly collapsed
Block 6 (2048 ch)(2048, 1, 10)Ten coarse time steps, 2048 feature maps
Global pooling + FC(2048,)One vector for the whole clip. This is X̂a

Sit with the last row. Every temporal detail — "the horn honked twice", "the violins joined after the bow" — is pooled into a single 2048-vector. A clip-level embedding cannot, in principle, distinguish "dog then siren" from "siren then dog". CLAP is a bag-of-events model. That limitation is invisible in the ESC50 number and very visible if you ever try to use CLAP for temporal localisation, and it is precisely what later work (Chapter 9) attacks.

Tower B: BERT, the donated geometry

The text encoder ft is BERT base uncased via HuggingFace: 110 million parameters. Two implementation details from Section 3.2 deserve attention.

"We limited the max text sequence length to 100 chars for computational efficiency." Not 100 tokens — 100 characters. Roughly 20 English words. Check that against the paper's own sample captions in Table 7 and you find genuine casualties: "A bow playing a stringed instrument in a one note tone repeatedly before violins join to create the melody" is 106 characters, so BERT never sees "the melody". "Leaves falling in a forest near a pond. Recorded in October 2017 in a German forest using a Zoom H2n." is 101 characters. Two of the twelve sampled captions get clipped — about 17%. In those cases the tail of the sentence, which is often where the second sound source appears, is discarded.

"The [CLS] token from the final layer of BERT is used as the text embedding with a size of 768." BERT prepends a special [CLS] token to every input; its final-layer vector is conventionally used as a whole-sequence summary, because self-attention lets it read every other token. So a 20-word caption collapses to one 768-dim vector, by exactly the same logic that collapsed 690 frames to one audio vector. Both towers are summarisers.

Both towers pool to a single vector, and that symmetry is not an accident. The loss in Chapter 4 compares one audio vector against one text vector. Any temporal or token-level structure has to be squeezed out before that comparison. This is the deep architectural commitment of the CLIP/CLAP family: a dual-encoder, not a cross-attention model. The payoff is enormous — you can pre-compute every embedding once and then compare with a dot product, which is what makes zero-shot retrieval free. The price is that no token ever attends to any audio frame.

Dual encoder versus cross-attention — the decision that defines the family

There is another way to compare audio and text: let them attend to each other. Feed the 690 audio frames and the 20 text tokens into a joint transformer and let every token look at every frame. That is a cross-attention or fusion model, and it is strictly more expressive. CLAP does not do it. Understanding why is understanding the family.

Dual encoder (CLAP, CLIP)Cross-attention fusion
Comparing one clip to C classes1 audio pass + C text passes (cached) + C dot productsC full joint forward passes — nothing can be cached
ESC50 zero-shot on 2,000 clips, 50 classes2,000 audio passes + 50 text passes, once100,000 joint passes
Can precompute a searchable index?Yes — embeddings are independent of the queryNo — the score exists only for a specific pair
ExpressivenessLimited to what one vector per modality can carryCan model fine-grained token-to-frame correspondence
Training signal per batchN2 comparisons from 2N forward passesN comparisons from N forward passes — no free negatives

The last row is decisive and often overlooked. The contrastive trick of Chapter 4 — getting N2−N negatives for free — only works because the two towers are independent. If scoring a pair required a joint forward pass, computing the full similarity matrix would cost N2 passes instead of 2N, and a batch of 768 would need 589,824 of them. Contrastive pretraining at scale is not merely compatible with the dual-encoder design; it is enabled by it.

Inline concept check. What does CLAP give up by never letting a text token attend to an audio frame?  …  Grounding. It can tell you a clip matches "a dog barks then a siren wails" better than it matches "a violin" — but it cannot tell you which part of the clip is the dog, or check that the dog really did come first. Every judgement is made between two summary vectors. Chapter 9's limitations table is, almost entirely, consequences of this one row of this one table.

The projections: 2.88 million parameters that do the actual joining

Ea = La(X̂a) ;   Et = Lt(X̂t),   Ea ∈ RN×d, Et ∈ RN×d    (2)

Equation (2) is the entire "joint multimodal space." Two learnable linear maps, both landing in d = 1024:

MapShapeWeight parametersRole
La2048 → 10242,097,152Compress the audio embedding into the shared space
Lt768 → 1024786,432Expand the text embedding into the shared space
Projection total2,883,584 (2.88M)1.49% of the model's ~193.7M parameters
Encoders190.8M (80.8 + 110)The other 98.5%

Two questions worth asking here, both of which the paper leaves implicit.

Why linear and not an MLP? A linear map can rotate, scale, shear, and project — it can re-express the encoder's geometry in new coordinates, but it cannot fold or tear it. Neighbours stay neighbours. That is exactly what you want when your goal is to align two existing geometries rather than invent a new one. An MLP could align the training pairs more tightly while distorting the space in ways that do not generalise to unseen class names — and unseen class names are the entire product.

Why does text go up (768 → 1024) while audio comes down (2048 → 1024)? Because d is a choice about the shared space, not about either tower. Meeting in the middle keeps both projections cheap. Note the asymmetry it creates: La must discard information (2048 dims into 1024), while Lt cannot possibly add any (a 768-dim input can only ever span a 768-dim subspace of the 1024-dim output). The text embeddings live on a lower-dimensional sheet inside the shared space, and the audio embeddings must learn to land on that sheet.

Evidence that the projections alone do real work. Table 2 of the paper reports an ablation where both encoders are frozen — only La and Lt are trained. Those 2.88M parameters, on top of encoders that have never seen a caption, reach 55.55% zero-shot accuracy on ESC50. Random is 2%. So more than half of the headline result is achievable by learning nothing but a rotation between two pretrained geometries. Chapter 7 unpacks the rest of that table.

Trace the whole flow

Two towers, every shape, every hop

Click any stage to see what enters, what leaves, and what it costs in parameters. The freeze toggles show which parts receive gradient in each of the paper's four training regimes — blue means gradient flows, grey means the weights are locked. Watch the parameter counter at the bottom.

The model in 30 lines of PyTorch

python — the whole architectureimport torch, torch.nn as nn
from transformers import AutoModel, AutoTokenizer

class CLAP(nn.Module):
    def __init__(self, d=1024):
        super().__init__()
        self.audio_enc = cnn14_pretrained_on_audioset()   # 80.8M, out 2048
        self.text_enc  = AutoModel.from_pretrained("bert-base-uncased")  # 110M, out 768
        self.tok       = AutoTokenizer.from_pretrained("bert-base-uncased")
        self.La = nn.Linear(2048, d)                   # 2,097,152 weights
        self.Lt = nn.Linear(768,  d)                   #    786,432 weights
        # temperature: stored in log space so it stays positive under SGD
        self.logit_scale = nn.Parameter(torch.tensor(np.log(1 / 0.007)))

    def encode_audio(self, x):          # x: (N, 64, 690) log-mel
        h = self.audio_enc(x)             # (N, 2048)   <- X_hat_a
        e = self.La(h)                   # (N, 1024)   <- E_a
        return e / e.norm(dim=-1, keepdim=True)   # unit sphere

    def encode_text(self, captions):    # list[str], truncated to 100 chars
        b = self.tok([c[:100] for c in captions], padding=True, return_tensors="pt")
        h = self.text_enc(**b).last_hidden_state[:, 0]   # [CLS] -> (N, 768)
        e = self.Lt(h)                   # (N, 1024)   <- E_t
        return e / e.norm(dim=-1, keepdim=True)

Note the norm calls. The paper's Equation (3) writes a bare dot product, but a dot product between unnormalised vectors mixes "do these mean the same thing" with "how long are these vectors" — and vector length has no semantics here. Normalising to the unit sphere makes every entry of the similarity matrix a cosine in [−1, 1], which is what makes a single global temperature meaningful. Chapter 4 shows exactly why that matters.

Why L2-normalise, derived rather than asserted

Equation (3) writes a bare dot product. Every implementation normalises first. Here is the argument, in three steps.

Write the dot product in polar form: Et · Ea = ‖Et‖ · ‖Ea‖ · cosθ. Only the angle carries semantics — two embeddings mean the same thing when they point the same way, regardless of length. The two magnitudes are free parameters the model can inflate at will.

Now watch what the loss does with that freedom. The loss wants the diagonal large relative to its row. Doubling ‖Ea,i‖ doubles every entry in column i — useless for a column softmax, but it inflates the diagonal in row i relative to that row's other entries, which are unchanged. So the cheapest way to lower the loss is not to learn better semantics; it is to make the vectors of easy examples longer. The model discovers a shortcut, and length starts encoding confidence instead of meaning.

Normalising kills the shortcut. Every embedding sits on the unit sphere, every entry of C is exactly a cosine in [−1, 1], and the only way to raise the diagonal is to rotate. Two further benefits fall out: the temperature is now comparable across the whole matrix (a single τ is meaningful only if the raw scale is fixed), and cosine similarity at inference is just a dot product, so zero-shot needs no per-query normalisation.

before: Cij = ‖Et,i‖ · ‖Ea,j‖ · cosθij  — unbounded, two nuisance factors
after:  Cij = cosθij ∈ [−1, 1]  — one number, all of it semantic

What happens when an input degrades

A model is defined as much by its behaviour on bad inputs as on good ones. Trace each degradation through the shapes.

Degraded inputWhat the towers produceWhat zero-shot then does
Silence (a 5-second zero vector)The log-Mel is a constant floor (log of the epsilon). CNN14 still emits a well-defined 2048-vector; La still emits a unit vectorRanks all classes by their similarity to the "silence direction". Confident nonsense — there is no null output
A 0.8-second clip (Mridangam)Padded to 5 s; 84% of the 690 frames are silence. Global pooling averages the real evidence with the paddingEvidence diluted roughly 6×. Compare Mridangam Tonic's 0.1965 against a 0.1667 chance level
A 30-second clip (ClothoV2)A random 5-second crop. The caption may describe events outside the cropAt training time this is label noise; at inference it means the prediction depends on which window you took
An empty captionBERT sees just [CLS] and [SEP]; the [CLS] vector is the model's prior over "no content"A single fixed direction that every clip is compared against — effectively a constant added to one column
A caption longer than 100 charactersTruncated. The tail — often the second sound source — is goneSystematically biases the text embedding toward whatever is described first
Audio sampled at 16 kHzResampled to 44.1 kHz; the 8–22 kHz band is empty, but the Mel filterbank already stops at 8 kHzAlmost no effect — an accidental robustness of the low ceiling
Notice the pattern. Every degradation produces a perfectly well-formed unit vector, and therefore a perfectly well-formed ranking. Nothing in the architecture can signal "I have nothing to say about this." The abstention problem from Chapter 0 was not solved by CLAP; it was inherited. What CLAP fixed was the vocabulary, not the calibration.

What it costs to run

QuantityValueWhere it comes from
Parameters, total~193.7M80.8M + 110M + 2.88M
Parameters actually joining the modalities2.88M (1.49%)The two projections
Audio tensor per clip64 × 690 = 44,160 floatsChapter 2
Embedding stored per clip1024 floats = 4 KB (fp32)Ea
Similarity matrix per training stepN × N — 589,824 entries at N = 768Equation (3)
Zero-shot classifier for 50 classes50 × 1024 floats = 200 KB, computed onceChapter 5

How it was trained

SettingValueComment
RegimeBoth encoders unfrozenThe best of the four options in Table 2
Epochs40Over 128,010 pairs
OptimiserAdamReference [26]
Learning rate10−3, reduced on plateau by 10−1, patience 10A high LR for a 190M-parameter model — the projections need to move fast
HardwarePyTorch DDP, 16GB V100, scaling from 8 to 24 GPUsThe GPU count is set by the batch size (Chapter 8)
Temperature τLearnable, initialised to 0.007Scaled logits clipped to a maximum of 100

Compare the two supervised evaluation setups the paper also runs, because they clarify what "the encoder learned" means. Supervised Feature Extraction freezes CLAP and trains 1 or 3 fully-connected layers on top (LR 10−3, 30 epochs) — that measures representation quality. Supervised Finetune unfreezes the audio encoder along with the attached layers (LR 10−4, 30 epochs) — that measures ceiling performance. The paper notes it did no hyperparameter grid search "due to computation constraints," which makes the numbers in Chapter 6 conservative rather than cherry-picked.

CLAP's audio encoder pools 690 time frames into a single 2048-dim vector before any comparison with text. What does this architectural choice make impossible?

Chapter 4: The Similarity Matrix

We have two vectors per pair: Ea from the clip, Et from its caption, both 1024-dimensional, both on the unit sphere. Nothing yet forces them to be near each other. This chapter builds the objective that does — and it builds it by hand, on a batch of three, with every intermediate number written down.

This is the load-bearing chapter of the paper. If you can reconstruct the 3×3 example below on a whiteboard, you can implement CLAP.

First, the objective that does not work

The naive move: maximise the similarity between each clip and its own caption.

maximise  ∑i Et,i · Ea,i

Run gradient descent on that for five minutes and you get a model with a perfect score and zero value. It maps every clip and every caption to the same point on the sphere. Similarity 1.0 for all pairs, matched or not. This failure has a name — representational collapse — and it happens because the objective only ever says "closer", never "not that one."

The fix has to introduce a comparison. A pairing is only meaningful if it beats alternatives. So the objective must be: this caption should match this clip more than the other captions do.

Where do the alternatives come from? The batch itself — for free. Load N pairs. Pair i's caption is the correct match for clip i, and it is also, with near-certainty, a wrong match for clips j ≠ i. So a batch of N pairs silently provides N correct pairs and N2−N incorrect ones. Nobody annotated a single negative. This is the trick that makes contrastive pretraining scale, and it is why batch size is a modelling hyperparameter here, not just a memory setting.

The paper says exactly this, in the sentence right after Equation (3): "The similarity matrix C ∈ RN×N has N correct pairs in the diagonal and N2−N incorrect pairs in the off-diagonal."

Equation (3): building C

C = τ · (Et · EaT)    (3)

Shapes first, always. Et is (N, d) and Ea is (N, d), so EaT is (d, N) and the product is (N, N). Entry C[i][j] is a scaled inner product between text i and audio j.

ObjectShapeMeaning of one element
Et(N, 1024)Row i = the unit-length embedding of caption i
EaT(1024, N)Column j = the unit-length embedding of clip j
Et · EaT(N, N)Cosine similarity between caption i and clip j, in [−1, 1]
C(N, N)The same, scaled by τ — these are the logits
diagonal of C(N,)The N true pairings — what we want to be largest

Since both E's are L2-normalised, each raw entry is a cosine: 1 means "same direction", 0 means "unrelated", −1 means "opposite". That bounded range is exactly what makes a single global temperature sensible.

The temperature puzzle — read this before you implement

Section 3.2 says: "The temperature parameter τ is learnable and initialised to 0.007. To prevent training instability, the logits scaled by τ are clipped to a maximum value of 100."

Take Equation (3) literally with τ = 0.007 and multiply your cosines by 0.007. Every logit now lies in [−0.007, 0.007]. Softmax over a batch of 768 such logits is indistinguishable from uniform: every probability is about 1/768, the loss sits at ln(768) = 6.644 forever, and the gradients are microscopic. The model cannot learn. Also, no product of a number in [−1,1] with 0.007 will ever approach 100, so the stated clipping would never fire.

Both problems vanish under the convention CLIP established and CLAP inherits: 0.007 is the temperature, and the multiplier applied to the cosines is its reciprocal, 1/0.007 = 142.86. Now the numbers all make sense at once:

Reading of Equation (3)Logit range for cosines in [−1, 1]Does clipping at 100 ever fire?Can the model learn?
multiply by 0.007[−0.007, 0.007]NeverNo — softmax is flat, loss pinned at ln N
multiply by 1/0.007 = 142.86[−142.86, 142.86]Yes — exactly what it is protecting againstYes

This is reasoning about the paper, not a quotation from it — but the arithmetic only closes one way, and the reference implementations of both CLIP and CLAP store a learnable logit_scale initialised to log(1/0.007) and exponentiate it.

Why 1/0.007 specifically? Ask the dimension. At initialisation the two towers are unaligned, so Et,i and Ea,j are effectively random unit vectors in d = 1024 dimensions. The cosine between two random unit vectors in d dimensions has standard deviation 1/√d = 1/32 = 0.03125. Multiply by 142.86 and the logits at initialisation have a spread of about 4.5 — big enough that softmax is not flat, small enough that it is not saturated. The temperature is calibrated to the dimensionality of the space. Change d and you should change τ.

And the clip? Once the model is right — diagonal larger than every off-diagonal entry in its row — the loss decreases monotonically as the scale grows. Gradient descent notices. Left alone, the learnable scale runs away, logits explode, exp() overflows in mixed precision, and training dies. Clipping the scaled logits at 100 is a hard ceiling on that runaway. It is a numerical guardrail, not a modelling choice.

Equation (4): the symmetric cross-entropy

L = 0.5 · ( ℓtext(C) + ℓaudio(C) )    (4)

with, in the paper's notation, ℓk = (1/N) ∑i log diag(softmax(C)) taken "along text and audio axes respectively."

Unpack that in three moves.

Move 1 — softmax along an axis turns a similarity row into a choice. Take row i of C: the similarities between caption i and all N clips. Softmax it and you have a probability distribution over "which clip does this caption describe?" The right answer is clip i, the diagonal entry.

Move 2 — the diagonal is the label, so no labels are needed. Cross-entropy with a one-hot target reduces to −log(probability of the correct class). The correct class for row i is index i. The "labels" are literally [0, 1, 2, …, N−1]. That is the whole reason this is called self-supervised.

Move 3 — do it both ways. Softmax along rows answers "given this caption, which clip?" (text-to-audio retrieval). Softmax along columns answers "given this clip, which caption?" (audio-to-text retrieval). These are different questions with different answers, and optimising only one leaves the other free to be bad. Averaging the two gives the symmetric loss.

A sign to fix in your head. Equation (4) as printed sums positive logs, which would be a quantity to maximise. Every implementation minimises the negative log-likelihood. Read ℓk = −(1/N)∑i log(softmax(C)ii). The paper's Table 1 numbers are unaffected; only the reader's sanity is at stake.
The sanity baseline you should always compute first. If the model is guessing, every row of the softmax is uniform at 1/N, so the loss is −log(1/N) = ln N. For N = 3 that is 1.0986. For N = 768, the paper's largest batch, it is 6.644. A contrastive loss that is not visibly below ln N is not learning — and note that raising N raises the bar. Bigger batches are harder tasks and richer signals at once.

The 3×3 batch, worked by hand

Everything above becomes concrete now. To make the arithmetic doable on paper we shrink the shared space from d = 1024 to d = 2 and the batch from N = 768 to N = 3. Nothing else changes — the equations are identical.

Our toy space has two axes: horizontal is impulsive / percussive energy, vertical is sustained / tonal energy. Three pairs:

iAudio clipIts caption
1a dog barking"a dog barks"
2knocking on a wooden door"knocking on a wooden door"
3a violin holding one note"a violin plays a long note"

Step 0 — normalise. The projections La and Lt output arbitrary-length vectors; we put them on the unit circle. Do one by hand so the step is not a black box. Suppose Lt emits (3.984, 0.348) for caption 1:

‖(3.984, 0.348)‖ = √(3.9842 + 0.3482) = √(15.872 + 0.121) = √15.993 = 3.999
Et,1 = (3.984 / 3.999 , 0.348 / 3.999) = (0.996 , 0.087)

Doing that for all six gives our batch:

VectorComponentsReading
Ea,1 (dog audio)(0.966, 0.259)Strongly impulsive
Ea,2 (knock audio)(0.766, 0.643)Impulsive, some resonance from the wood
Ea,3 (violin audio)(−0.174, 0.985)Almost purely tonal
Et,1 ("a dog barks")(0.996, 0.087)Impulsive
Et,2 ("knocking on a wooden door")(0.574, 0.819)Between the two axes
Et,3 ("a violin plays a long note")(−0.342, 0.940)Tonal

Step 1 — the raw similarity matrix. Nine dot products. Here are three of them written out in full; the rest follow identically.

11 = (0.996)(0.966) + (0.087)(0.259) = 0.9621 + 0.0225 = 0.985
12 = (0.996)(0.766) + (0.087)(0.643) = 0.7629 + 0.0559 = 0.819
13 = (0.996)(−0.174) + (0.087)(0.985) = −0.1733 + 0.0857 = −0.088

All nine, with rows indexed by text and columns by audio:

Ĉ = EtEaTaudio 1 (dog)audio 2 (knock)audio 3 (violin)
text 1 "a dog barks"0.9850.819−0.088
text 2 "knocking on a wooden door"0.7670.9660.707
text 3 "a violin plays a long note"−0.0870.3420.985

Before scaling, read the structure. The diagonal is the largest entry in every row and every column — this batch is already mostly right. But look at cell (1,2): 0.819. Caption "a dog barks" is nearly as close to the knock audio as to the dog audio. Both are impulsive. That is our hard negative, and it will dominate the loss.

Step 2 — scale to logits. The real model multiplies by about 143, which would saturate this well-behaved toy instantly. For hand arithmetic take a teaching scale of s = 4, and we will study the real value in a moment. C = 4 · Ĉ:

C = 4 Ĉaudio 1audio 2audio 3
text 13.9403.276−0.352
text 23.0683.8642.828
text 3−0.3481.3683.940

Step 3 — softmax along the text axis (rows). Exponentiate each entry, then divide by the row sum.

Rowexp of each entryRow sumProbabilities−log of the diagonal
text 1e3.940=51.42, e3.276=26.47, e−0.352=0.70378.59(0.654, 0.337, 0.009)−ln 0.654 = 0.424
text 2e3.068=21.50, e3.864=47.66, e2.828=16.9186.07(0.250, 0.554, 0.196)−ln 0.554 = 0.591
text 3e−0.348=0.706, e1.368=3.928, e3.940=51.4256.05(0.013, 0.070, 0.917)−ln 0.917 = 0.086
text = (0.424 + 0.591 + 0.086) / 3 = 1.101 / 3 = 0.367

Step 4 — softmax along the audio axis (columns). Same matrix, same numbers, different normalisation direction. Column 1 asks: given the dog audio, which of the three captions describes it?

Columnexp of each entry (going down)Column sumProbabilities−log of the diagonal
audio 1 (dog)51.42, 21.50, 0.70673.63(0.698, 0.292, 0.010)−ln 0.698 = 0.359
audio 2 (knock)26.47, 47.66, 3.92878.06(0.339, 0.611, 0.050)−ln 0.611 = 0.493
audio 3 (violin)0.703, 16.91, 51.4269.03(0.010, 0.245, 0.745)−ln 0.745 = 0.295
audio = (0.359 + 0.493 + 0.295) / 3 = 1.147 / 3 = 0.382

Step 5 — the symmetric loss.

L = 0.5 · (0.367 + 0.382) = 0.5 · 0.749 = 0.375

Compare to the guessing baseline ln 3 = 1.099. The batch is learning.

Four things the hand computation just taught, which the formula alone would not.

1. The same numbers, normalised two ways, give different answers. Row 2 gave 0.554 for the true pair; column 2 gave 0.611. Same cell. Same logit. Different denominators. That is why the loss is symmetric — neither direction is the "real" one.

2. ℓaudio (0.382) > ℓtext (0.367) here. Retrieving a caption from audio was slightly harder than the reverse, for this batch. In real training these two terms are rarely equal, and their gap is a diagnostic worth logging.

3. One cell dominates. Cell (1,2) = 0.819 hurts twice: it steals mass from row 1's diagonal and from column 2's diagonal. The gradient will push Et,1 away from Ea,2 harder than it pushes anything else. Contrastive learning spends almost all of its effort on hard negatives.

4. The easy pair contributes almost nothing. The violin row's loss is 0.086 — already nearly solved, so almost no gradient. As training proceeds, more and more of the batch goes quiet, which is exactly why you need more negatives (bigger N) to keep finding hard ones.

Now turn the temperature knob

Take the same Ĉ and vary the scale s. Nothing about the model changes — only how sharply we read its similarities.

Scale sRow 1 probabilitiesLRegime
1(0.457, 0.387, 0.156)0.790Mush. The correct answer barely beats the wrong ones. Gradients are weak and undiscriminating — the model is told everything is roughly fine
4(0.654, 0.337, 0.009)0.375Learnable. Clear preference, meaningful residual pressure on the hard negative
20(0.964, 0.036, 0.000)0.041Sharp. Only the hardest negative still matters
142.86 (the paper's)(1.000, 0.000, 0.000)≈ 0Saturatedfor this toy. Real 1024-dim embeddings at initialisation have cosine gaps near 0.03, not 0.17, so s = 143 lands them squarely in the learnable regime. The scale must be read together with the dimension

That last row is the single most common confusion about CLIP-family temperatures, so state it plainly: a temperature is not "sharp" or "soft" in the abstract. It is sharp or soft relative to the typical spread of your similarities, and that spread shrinks as 1/√d.

SHOWCASE — the contrastive engine

The full similarity matrix, live. Change the batch size to add negatives; change the scale to sharpen the softmax; switch the normalisation axis to see the two retrieval directions disagree. Then press Train and watch gradient descent rotate the toy embeddings until the diagonal wins — the diagonal brightening is CLAP learning. The N = 3 setting reproduces the hand-worked numbers above exactly.

Batch size N 3
Logit scale s 4.0

Press Show collapse to see the failure from the top of this chapter play out: with only the diagonal in the objective, every embedding migrates to one point, the whole matrix turns bright, and the model has learned nothing. The off-diagonal is not a nuisance term. It is the entire supervision.

Loss versus scale — the three regimes

The loss of the fixed 3×3 batch as a function of the logit scale, with the guessing baseline ln 3 marked. Drag through the mush, the learnable band, and the saturated tail. Notice the curve is monotonically decreasing once the diagonal wins — which is why a learnable scale runs away and why the paper clips it.

Scale s 4.0

The same loss, three ways to write it

Hand arithmetic first — the exact steps you just did, transcribed:

the arithmetic, for row 1 of the 3x3 batchlogits  = [ 4*0.985 , 4*0.819 , 4*(-0.088) ]  = [ 3.940 , 3.276 , -0.352 ]
exps    = [ 51.42   , 26.47   , 0.703 ]
sum     = 78.59
probs   = [ 51.42/78.59 , 26.47/78.59 , 0.703/78.59 ] = [ 0.654 , 0.337 , 0.009 ]
loss_1  = -ln(0.654) = 0.424            # the diagonal entry is index 0 for row 0
# repeat for rows 2,3 -> 0.591, 0.086 ; average -> l_text = 0.367
# repeat down the COLUMNS         -> 0.359, 0.493, 0.295 ; l_audio = 0.382
# L = 0.5 * (0.367 + 0.382) = 0.375

Then step-by-step numpy, which is the same thing with loops:

python — numpy, every intermediate exposedimport numpy as np

Ea = np.array([[ 0.966, 0.259], [ 0.766, 0.643], [-0.174, 0.985]])   # (3, 2)
Et = np.array([[ 0.996, 0.087], [ 0.574, 0.819], [-0.342, 0.940]])   # (3, 2)
Ea = Ea / np.linalg.norm(Ea, axis=1, keepdims=True)      # unit sphere
Et = Et / np.linalg.norm(Et, axis=1, keepdims=True)

s  = 4.0                          # the real model uses 1/0.007 = 142.86
C  = s * Et @ Ea.T             # (3, 3)  <- Equation (3)
C  = np.minimum(C, 100.0)         # the paper's stability clip

def softmax(x, axis):
    x = x - x.max(axis=axis, keepdims=True)   # subtract max: exp never overflows
    e = np.exp(x)
    return e / e.sum(axis=axis, keepdims=True)

P_text  = softmax(C, axis=1)      # each ROW sums to 1: caption -> which clip?
P_audio = softmax(C, axis=0)      # each COL sums to 1: clip -> which caption?

l_text  = -np.log(np.diag(P_text )).mean()      # 0.367
l_audio = -np.log(np.diag(P_audio)).mean()      # 0.382
L = 0.5 * (l_text + l_audio)                    # 0.375   <- Equation (4)
print(L, "vs guessing baseline", np.log(len(Ea)))   # 0.375 vs 1.0986

And the one-liner you would actually train with. The insight that makes it a one-liner: cross-entropy against the identity is cross-entropy against the index vector [0, 1, …, N−1].

python — PyTorch, production formimport torch.nn.functional as F

logits  = model.logit_scale.exp().clamp(max=100) * E_t @ E_a.T   # (N, N)
targets = torch.arange(len(logits), device=logits.device)          # [0,1,...,N-1]
loss    = 0.5 * (F.cross_entropy(logits,   targets) +      # rows: text -> audio
                 F.cross_entropy(logits.T, targets))        # cols: audio -> text

Three lines. logits.T is the entire content of "symmetric". torch.arange is the entire content of "no labels needed".

What the gradient actually does to the geometry

Differentiate the row term for pair i and the structure is beautifully simple. Writing pij for the softmax probability that caption i matches clip j:

∂ℓtext / ∂Et,i  ∝  −s · ( Ea,i − ∑j pij Ea,j )

Read that as a tug-of-war. The first term pulls caption i toward its own clip. The second pushes it away from a probability-weighted average of all clips in the batch — so the clips the model currently finds confusable pull hardest. In our batch, p12 = 0.337, so the knock audio exerts a third of the repulsion budget, while the violin at p13 = 0.009 exerts almost none.

Two consequences follow immediately, and both reappear in Chapter 8. Larger batches mean more candidates in that weighted average, so a harder and more informative push. And the temperature multiplies the whole gradient by s, which is a second, sneakier reason the learnable scale wants to grow.

Three things that break this loss, and how to spot them

FailureWhat you see in the logsCause and fix
Loss pinned at ln NFlat at 6.644 for batch 768, from step one, foreverThe temperature is being multiplied rather than inverted — logits are in [−0.007, 0.007] and softmax is uniform. Use 1/τ
Loss collapses to zero in the first epochL → 0.001, but zero-shot accuracy stays at chanceA shortcut: the batch is sorted, or all clips in a batch come from one dataset with a distinguishing artefact. Shuffle across sources
NaN after a few hundred stepsLoss becomes NaN; the learnable scale has grown without boundExactly what the clip at 100 exists to prevent. Clamp the scaled logits, and clamp logit_scale itself
text and ℓaudio diverge badlyOne term keeps dropping, the other stallsUsually duplicate items on one side — the same caption or the same audio appearing twice in a batch, making one direction unsatisfiable. Deduplicate when sampling (Chapter 8)
Inline concept check. The similarity matrix is not symmetric — C[i][j] is caption i against clip j, and C[j][i] is caption j against clip i, which are different quantities. So why does the loss get called "symmetric"?  …  The symmetry is in the objective, not the matrix. It uses the same matrix twice, normalising once along each axis, so neither retrieval direction is privileged. A symmetric loss on an asymmetric matrix.
In the hand-worked 3×3 batch, cell (text 1, audio 2) had raw similarity 0.819 — nearly as high as the true pair's 0.985. Why does this single cell dominate the gradient?

Chapter 5: Zero-Shot Is Retrieval in Disguise

Training is over. You have two encoders and two projections. You have no classifier. Someone hands you 2,000 five-second clips and asks you to sort them into fifty environmental categories — categories that appear nowhere in your training objective.

Section 2.2 of the paper answers in three sentences, and this chapter is the unpacking of those three sentences into something you could implement in an afternoon.

The paper's procedure, verbatim in structure. Given a target dataset with C class labels and N test audios: First, compute audio embeddings and text embeddings for the N audios and C classes using the pretrained encoders and their projection layers. Second, because both embeddings are in a common space, compute the cosine similarity between each testing audio and all the class labels — each audio will have as many logits as class labels. Third, logits are turned into a probability distribution by applying softmax for binary or multiclass, and sigmoid for multilabel classification.

The reframe that makes it obvious

Return to Chapter 0's prison. A classifier's last layer is z = W h with W ∈ RC×D, one learned row per class. Now write CLAP's zero-shot computation the same way:

z = Etext · Ea,   where Etext ∈ RC×d is the stack of the C class-name embeddings

These are the same equation. In both cases a matrix of shape (C, d) multiplies a vector of shape (d,) to give C logits. The only difference — and it is the whole paper — is where the matrix comes from.

Fixed-head classifierCLAP zero-shot
The classifier matrixW: learned parametersEtext: the output of a function applied to strings
To add a classAdd a row, get labelled data, retrainRun one string through BERT and the text projection
Cost of a new classDays to weeksMilliseconds
Class geometryArbitrary; learned independentlyInherited from language — "wolf howling" lands near "dog barking"
Who chooses the taxonomyWhoever labelled the training setWhoever types the strings, at inference
Say it out loud: the text encoder is a classifier-weight generator. It maps a string to a row of a classification matrix. That is why the menu disappeared. The rows of W stopped being parameters and became a function of language — and functions are defined everywhere, including on strings nobody trained on.

Worked, with numbers

Same 2-D toy space as Chapter 4 (horizontal = impulsive, vertical = tonal). One test clip — a dog barking, embedded at Ea = (0.966, 0.259). Four candidate classes, each turned into a prompted caption and embedded:

ClassPrompted textEtext rowcosine with Ea
dog"this is a sound of a dog barking"(0.985, 0.174)(0.985)(0.966)+(0.174)(0.259) = 0.996
rooster"this is a sound of a rooster crowing"(0.707, 0.707)(0.707)(0.966)+(0.707)(0.259) = 0.866
rain"this is a sound of rain falling"(0.174, 0.985)(0.174)(0.966)+(0.985)(0.259) = 0.423
violin"this is a sound of a violin playing"(−0.342, 0.940)(−0.342)(0.966)+(0.940)(0.259) = −0.087

Multiply by the logit scale (s = 4 again, for readable arithmetic) and softmax:

Classlogit = 4 × cosineexp(logit)probability
dog3.98553.770.585
rooster3.46431.950.348
rain1.6905.420.059
violin−0.3490.710.008
sum of exps91.851.000

Prediction: dog, 58.5% confident. And look at the runner-up: rooster, at 34.8%. Nothing told the model that dogs and roosters are both impulsive animal vocalisations — the language geometry did. A one-hot classifier's second-place guess carries no such information.

The multilabel case is different and the paper is careful about it. FSD50K and AudioSet clips can contain several events at once, so "which one class" is the wrong question. There you apply a sigmoid to each logit independently:

pc = σ(zc) = 1 / (1 + e−zc)

On the same logits that gives 0.982, 0.970, 0.844, 0.414 — no longer summing to one, because "dog" being present says nothing about whether "rain" is also present. Which is exactly why FSD50K and AudioSet are scored with mAP rather than accuracy in Table 1: they are ranking problems, not choice problems.

What it costs

OperationHow oftenCost
Embed the C class promptsOnce, ever — cache the resultC forward passes of a 110M BERT. For ESC50, 50 of them
Store EtextOnce50 × 1024 floats = 200 KB for all of ESC50
Embed a test clipPer clipOne CNN14 forward pass
ClassifyPer clipOne (50, 1024) × (1024,) matrix-vector product — 51,200 multiply-adds, microseconds
Add a 51st class at runtimeWhenever you likeOne BERT forward pass. No gradients, no data, no redeploy
SHOWCASE — the zero-shot playground

Pick the clip that is playing, then switch candidate labels on and off — including labels no classifier was ever trained on. The bars show cosine similarity; the ring shows the softmax over whichever labels are active. Change the prompt template and watch every text embedding move. Turn off the true class to see what the model does when the answer is not on the menu.

Clip playing:
Prompt template this is a sound of
Logit scale s 4

Two experiments worth running in that widget before moving on. First, turn off the correct label and watch the probabilities redistribute over the survivors — the model is still forced to sum to one, so zero-shot inherits Chapter 0's abstention problem unless you threshold the raw cosine. Second, add the deliberately unusual candidate and see it rank sensibly anyway. That is generalisation to a class that exists only as a string.

The prompt problem, and the paper's honest table

There is a distribution mismatch hiding in the procedure, and Section 4.4 names it: "The training data of CLAP consists of natural language captions containing one or more sentences. However, the vast majority of datasets have class labels defined by a few words — 'dog barking' and 'sneezing'. Using single words instead of language description affects how Zero-Shot learning transfers."

The text encoder spent 40 epochs reading full sentences. At inference you hand it the fragment "dog". That fragment lands in a region of the text space the model rarely visited. The fix is a prompt template: wrap the class name in a sentence shaped like the training data. The paper's default is "This is a sound of [class label]".

Here is Table 3, complete, and it does not say what you expect:

PromptESC50 zero-shot accuracyRelative to the bare label
"i can hear [class label]"0.7860−2.6 points — worse than no template at all
"this is an audio of [class label]"0.8005−1.15 points — also worse
"[class label]" (no template)0.8120baseline
"this is [class label]"0.8135+0.15
"this is a sound of [class label]"0.8260+1.4
Read that table against the story it is supposed to support. The naive version — "class names are out of distribution, so wrap them in a sentence" — predicts that any reasonable sentence beats the bare label. Two of the four templates are worse than the bare label, and "i can hear" is worse by 2.6 points. So the real effect is not "sentences good, fragments bad." It is that the prompt has to place the class in the region of text space where audio captions live. "This is a sound of X" is a caption-shaped assertion about a recording. "I can hear X" is a first-person perceptual report — a genre that barely appears in ClothoV2 or AudioCaps. The prompt is a query into the caption distribution, and the good ones are the ones written in its dialect.

One more honest note. The paper writes that prompting "leads to a 5% acc increase." The table's own span is 0.826 − 0.786 = 4.0 points, and against the more natural baseline of the bare class label it is 1.4 points. The effect is real and free, but it is a percentage point or two, not a transformation. Do not let a rounded claim in prose overwrite a table you can read.

The five prompts, ranked

Table 3, drawn to scale from the bare-label baseline so the two negative templates are visible as negative. The dashed line is the no-template accuracy; the band at the top is reported human performance on ESC50 (81%). Hover targets are the bars — tap one to see the prompt in full.

The three domains that needed a different prompt

Section 3.3 records a detail most readers skim: "The prompt was kept the same for all the domains except three."

DomainPrompt usedWhy the default fails
Emotion Recognition (CREMA-D, RAVDESS)"this person is feeling [class label]""A sound of angry" is not English. Emotion is a property of a speaker, not a category of sound event — the prompt must supply the missing subject
Keyword Spotting (Speech Commands)the keyword aloneThe target is a literal utterance, not a description of one. "This is a sound of yes" describes a recording; the class is the word "yes" itself
Speaker Counting (LibriCount)"[number between 0 - 10] persons speaking"The class is a count. It only becomes a description when attached to a noun phrase

These three exceptions are not tuning noise; they are a map of where the caption distribution runs out. Captions describe what happened acoustically. They rarely annotate a speaker's emotional state, almost never transcribe words, and essentially never count talkers. In Chapter 6 those same three domains produce CLAP's three worst zero-shot numbers. The prompts were the first warning.

Run the same machine backwards: retrieval

Nothing in Chapter 5 says the class list must be short and the audio list long. Swap which axis you loop over and the same model does something else entirely.

TaskFixed sideRanked sideWhat you get
Zero-shot classificationOne clipC class prompts"This clip is a dog barking"
Text-to-audio retrievalOne sentenceN clips in an archive"Here are the 20 clips most like 'glass breaking on tile'"
Audio-to-text retrievalOne clipA caption poolThe nearest human description — a crude captioner
Audio-to-audio searchOne clipN clips"More like this" — the text tower is not even used
Dataset curationA description of what you wantMillions of clipsFilter a corpus by a sentence instead of a label

All five are the same two lines of code with the loops exchanged. That is what "joint embedding space" actually buys, and it is why CLAP's descendants show up inside data pipelines as often as inside classifiers.

The multilabel case, worked

Softmax forces a choice. FSD50K clips genuinely contain several events, so the paper switches to sigmoid there — and the switch has consequences worth walking.

With the same four logits (3.985, 3.464, 1.690, −0.349), sigmoid gives:

σ(3.985) = 1/(1 + e−3.985) = 1/(1 + 0.0186) = 0.982  ·  σ(3.464) = 0.970
σ(1.690) = 0.844  ·  σ(−0.349) = 0.414

Every score is high, including "rain" at 0.844 and "violin" at 0.414 — and their sum is 3.21, not 1. That is not a bug; independence is the point. But it exposes a real difficulty: to turn these into predictions you need a threshold, and cosine similarities between unit vectors are bunched. Because raw cosines rarely go below zero for related concepts, σ(s·cos) sits above 0.5 for almost everything, and the useful threshold depends on both s and the dataset.

This is exactly why FSD50K and AudioSet are scored with mAP — mean average precision — rather than accuracy. mAP evaluates the ranking and never asks you to pick a threshold. When you see a mAP number, read it as "how well does the model order the classes", not "how often is it right".

Inline concept check. CLAP scores 0.3024 mAP on FSD50K zero-shot against Wav2CLIP's 0.0302. Why is a 27-point mAP gain arguably more impressive than the 12-point ESC50 accuracy gain?  …  Because FSD50K is 200 classes, multi-label, with clips from 0.3 to 30 seconds, and mAP averages precision across every class including the rare ones. Chance is under 0.005. A tenfold improvement over the prior zero-shot method on a ranking metric over 200 labels is a much harder thing to move than a 50-way forced choice.

Zero-shot in three forms

the arithmetic, one clip against four classescos     = [ 0.996 , 0.866 , 0.423 , -0.087 ]     # dot products, both sides unit-norm
logits  = 4 * cos = [ 3.985 , 3.464 , 1.690 , -0.349 ]
exps    = [ 53.77 , 31.95 , 5.42 , 0.71 ]
sum     = 91.85
probs   = [ 0.585 , 0.348 , 0.059 , 0.008 ]     # multiclass: softmax
sigmoid = [ 0.982 , 0.970 , 0.844 , 0.414 ]     # multilabel: independent
prediction = argmax = class 0 = "dog"
python — the whole zero-shot classifierimport numpy as np, torch

# ---- ONCE, at "deployment". No gradients anywhere in this file. ----
classes  = ["dog", "rooster", "rain", "violin", "chainsaw"]      # type anything
prompts  = [f"this is a sound of {c}" for c in classes]
with torch.no_grad():
    E_text = model.encode_text(prompts)      # (C, 1024), unit-norm, CACHE THIS

# ---- PER CLIP ----
with torch.no_grad():
    E_a  = model.encode_audio(log_mel(clip))     # (1, 1024), unit-norm
cos      = E_text @ E_a.T                       # (C, 1)  <- cosine similarities
logits   = model.logit_scale.exp() * cos
probs    = logits.softmax(dim=0)                 # multiclass / binary
scores   = torch.sigmoid(logits)                 # multilabel (FSD50K, AudioSet)
print(classes[probs.argmax()])

# adding a 6th class at 3am:
E_text = torch.cat([E_text, model.encode_text(["this is a sound of a smoke alarm"])])
# done. that is the entire deployment story.
python — the one-liner, for the whole test set at oncepreds = (model.encode_audio(X) @ model.encode_text(prompts).T).argmax(-1)
# (N,1024) @ (1024,C) -> (N,C) -> (N,)   ... the temperature cancels under argmax

That last comment is worth a beat. Under argmax the temperature is irrelevant — scaling every logit by the same positive constant cannot change which is largest. Temperature matters for the loss during training and for calibrated probabilities at inference. It does not matter for accuracy. Many people tune it hoping otherwise.

In CLAP's zero-shot classification, what plays the role that the learned weight matrix W plays in an ordinary classifier?

Chapter 6: 16 Tasks, 8 Domains

Every claim so far has been mechanical: this is the tensor, this is the loss, this is the inference procedure. Now the empirical question. A model trained on 128,010 captioned clips, with no classifier and no task-specific training, is pointed at sixteen benchmarks it has never seen. What happens?

The answer is not uniform, and the non-uniformity is the most instructive part. This chapter shows every number, including the ones that make CLAP look bad, because the shape of the failures is what tells you what the model actually learned.

How to read Table 1

Five rows, and confusing them is the fastest way to misread the paper:

RowWhat it isTrained on the target task?
RandomChance level, essentially 1/C for a C-way task
Benchmark (ZS)Best zero-shot result in the prior literature (Wav2CLIP, AudioCLIP)No
CLAP (ZS)CLAP, zero-shot, prompted class namesNo
Benchmark (Best)Best supervised result in the literatureYes, fully
CLAP (Best)Best of CLAP's supervised setups (feature extraction or finetune)Yes

Rows 3 and 4 are not comparable in fairness — one had labelled data for the task and one did not. That asymmetry is exactly what makes some of the numbers below remarkable.

Metrics differ by task, and the caption of Table 1 is precise about it: DCASE17 employs F1, FSD50K and AudioSet employ mAP, everything else uses accuracy. Higher is better everywhere. Random also differs by task, because it is set by the number of classes: 1/50 = 0.02 for ESC50, 1/2 = 0.5 for GTZAN music-versus-speech, and under 0.0018 for AudioSet's 527 multi-label classes.

The three metrics, so the table is readable

Comparing 0.826 on ESC50 with 0.3024 on FSD50K is meaningless unless you know they measure different things.

MetricDefinitionUsed forWhy it was chosen there
AccuracyFraction of clips whose argmax class is correctTwelve of the sixteen tasksSingle-label, forced choice — every clip has exactly one right answer
mAPFor each class, compute average precision over the ranked clip list; average across classesFSD50K (200 classes), AudioSet (527)Multi-label: several classes can be true at once, so "the argmax" is not the question. mAP scores the ranking and needs no threshold
F1Harmonic mean of precision and recall at a chosen operating pointDCASE17 Task 4Detection with sparse positives — accuracy would be dominated by the many true negatives

Three practical consequences. mAP numbers look low compared to accuracy numbers and are not worse for it — 0.30 mAP over 200 classes is a strong result. F1 depends on a threshold, so the number carries an unstated operating-point choice. And chance level differs wildly: 0.02 for ESC50, under 0.0018 for AudioSet, 0.5 for a binary task. Always locate the chance level before reacting to a score.

All sixteen, in full

Domain / datasetClassesRandomBench (ZS)CLAP (ZS)Bench (Best)CLAP (Best)
SEC — ESC50500.020.69400.8260.97150.9670
SEC — FSD50K (mAP)200<0.0050.03020.30240.6410.5859
SEC — UrbanSound8K100.05*0.65310.73240.9070.8796
SEC — DCASE17 Task4 (F1)170.1*0.300.6460.5938
SEC — AudioSet (mAP)527<0.00180.0580.471
Music — GTZAN Music vs Speech20.51.0000.9921.000
Music — GTZAN Genres100.10.2520.8830.9130
Music — Mridangam Stroke100.10.34470.9750.9794
Music — Mridangam Tonic60.16670.19650.9420.9534
Instrument — Beijing Opera40.250.47460.9750.9026
Scene — TUT2017150.060.29630.8430.7463
Emotion — CREMA-D60.16670.17840.7520.6834
Emotion — RAVDESS80.1250.15990.81820.6436
Keyword — Speech Commands120.0830.10630.9870.9683
Vocal Sound60.16670.49450.9050.9795
Speaker Counting — LibriCount110.0900.17880.7850.7783

Bold = CLAP is state of the art in its row's setting. Italic = CLAP is barely above chance. * The paper's random row lists 0.05 and 0.1 for the DCASE17/US8K pair; the values matching class counts are 1/17 ≈ 0.059 and 1/10 = 0.1. Dashes mean the paper reports no number in that cell.

The highs, and why they are genuinely surprising

ESC50: 82.6% zero-shot. Fifty environmental sound classes, five-second clips. The prior zero-shot best was AudioCLIP at 69.40%, so this is an absolute 12-point jump on a benchmark that had been competitively worked. And the paper flags the comparison that gets quoted everywhere: reported human accuracy on ESC50 is 81%. A model with no classifier, told the class names in English at inference time, beats the humans who defined the categories.

GTZAN Music vs Speech: 100% zero-shot. Perfect. And the supervised literature benchmark is 99.2%. Zero-shot beat fully supervised. This is a two-class task on 30-second clips, so it is the easiest cell in the table — but it also demonstrates that when the distinction is one the caption corpus talks about constantly ("a man speaks" versus "music plays"), the language prior is simply sufficient.

FSD50K: 30.24 mAP zero-shot, against Wav2CLIP's 3.02. An absolute 27-point mAP gain, the largest relative jump in the table. FSD50K is multi-label over 200 classes, and the paper notes CLAP's training data includes FSD50K clips — but paired with their free-text titles and descriptions, with the class labels deliberately ignored. So the model saw the audio and a human sentence about it, and then reconstructed a 200-way taxonomy it was never shown.

UrbanSound8K: 73.24% vs AudioCLIP's 65.31%. An 8-point absolute gain on ten urban sound classes.

The lows, stated plainly

The paper is honest here and so is this lesson: "CLAP (ZS) performed better than random on all downstream tasks and achieved good to slightly better than random on some music and speech-related tasks."

TaskRandomCLAP (ZS)Absolute liftVerdict
CREMA-D (emotion)0.16670.1784+1.2 pointsStatistically alive, practically useless
Mridangam Tonic0.16670.1965+3.0 pointsNearly chance
RAVDESS (emotion)0.1250.1599+3.5 pointsNearly chance
Speech Commands (keywords)0.0830.1063+2.3 pointsNearly chance
AudioSet (mAP)<0.00180.058+5.6 points mAP32× random, but 8× below the supervised benchmark of 0.471
A fairer way to score all sixteen: how much of the available headroom did zero-shot capture? Raw accuracy is not comparable across tasks with different class counts — 0.25 is chance on a 4-way task and eleven times chance on a 50-way one. Compute instead (CLAPZS − random) / (1 − random), the fraction of the gap from chance to perfect that was closed:

GTZAN music/speech 100% · ESC50 82.2% · UrbanSound8K 70.3% · Vocal Sound 39.3% · FSD50K 29.9% · Beijing Opera 29.9% · Mridangam Stroke 27.2% · DCASE17 26.3% · TUT2017 25.1% · GTZAN genres 16.9% · LibriCount 9.8% · AudioSet 5.6% · RAVDESS 4.0% · Mridangam Tonic 3.6% · Speech Commands 2.5% · CREMA-D 1.4%

That ordering is not random. The top is sound events and scenes; the bottom is emotion, keywords, and pitch. Chapter 8 explains why in one sentence.
Results explorer — all 16 tasks

Every task, every row of Table 1. Switch between absolute scores and headroom-captured to see the ordering change. Filter by domain to watch the pattern separate: sound events at the top, speech at the bottom. The dashed line on each bar group is chance for that task.

The supervised story: SoTA on five

Zero-shot is the headline, but the paper also asks a quieter question: is CLAP's audio representation good, independent of the zero-shot trick? Two setups answer it. Feature extraction freezes CLAP and trains 1 or 3 fully-connected layers on top. Finetune unfreezes the audio encoder along with those layers. CLAP (Best) is whichever won.

Result: state of the art on five datasets — GTZAN Music vs Speech (100%), GTZAN Genres (91.30%), Mridangam Stroke (97.94%), Mridangam Tonic (95.34%), and Vocal Sound (97.95%). Elsewhere it trails the literature by at most seven points, with the worst case being RAVDESS emotion at 64.36% against a 81.82% benchmark.

Table 6 puts CLAP head to head with the standard audio representation models. A few comparisons worth carrying:

TaskYAMNetOpenL3Wav2CLIPPANNsWav2Vec2CLAP (S)CLAP (F)
ESC500.83750.78230.90850.93100.83890.9670
Speech Commands0.41040.76340.34660.61820.87850.37080.9683
CREMA-D0.4530.5500.5120.5550.65620.28300.6834
Mridangam Tonic0.93690.82890.82440.82830.63910.9534
Vocal Sound0.84110.9795

Look at the Speech Commands row carefully, because it settles an important question. Frozen CLAP features score 0.3708 — worse than OpenL3 and far worse than Wav2Vec2's 0.8785. But finetuned CLAP reaches 0.9683, the best in the row. So the audio encoder is perfectly capable of keyword spotting once gradients are allowed to reshape it. What CLAP's frozen space lacks is not capacity; it is that the contrastive objective never had a reason to encode which word was spoken. Nothing in 128k sound captions ever said "the person said 'left'."

The single sentence that predicts the whole table. The paper writes it in Section 4.2: CLAP's training data "consist of audio captioning datasets, which mainly include the description of sound events, acoustic scenes, actions, and objects. On the other hand, the training data is scarce on human speech and the captions do not describe aspects of its content or context." A model can only learn to recognise what its supervision talks about. Captions talk about events. Therefore CLAP is an event model. Every number above is downstream of that sentence.

Domain by domain, with the mechanism

The headroom ordering is not a mystery once you ask, for each domain, would a person writing a caption about this clip mention the thing being classified?

DomainWould a caption mention it?Headroom captured
Sound events (ESC50, US8K, FSD50K)Yes — this is literally what audio captions are about30–82%
Music vs speechYes — "a man speaks", "music plays" are among the commonest caption phrases100%
Acoustic scene (TUT2017)Often — "in a park", "on a busy street" appear in captions25%
Vocal sounds (cough, sneeze, laughter)Yes — these are events, and captions name them39%
Instrument identity (Beijing Opera)Sometimes — "a drum", "a stringed instrument" appear; specific percussion names rarely30%
Music genreRarely — captions say "music plays", not "this is bebop"17%
Speaker countingOccasionally — "two people talking" exists, but 0-to-10 precision does not10%
Percussion stroke / tonicAlmost never — requires trained musical vocabulary27% / 4%
EmotionEssentially never — captions describe what happened, not how the speaker felt1–4%
Keyword spottingNever — captions do not transcribe2.5%

Read the two columns together and the model stops looking mysterious. CLAP's zero-shot ability on a task is roughly the frequency with which that task's distinction appears in written descriptions of sound. It is not a general audio understanding system; it is a system that understands audio through the vocabulary humans use to write about it.

Notice the Mridangam pair, which is a clean natural experiment. Stroke classification captures 27% of the headroom; tonic classification captures 3.6%. Both are 5-fold tasks on the same 0.81-second clips from the same instrument. The difference is that a stroke is a percussive event with a distinct timbre — the kind of thing captions describe — while a tonic is a pitch, which requires naming a note. Same audio, same encoder, same prompt template; the gap is entirely in whether language talks about it.

What the ESC50 number does and does not mean

82.6% zero-shot on ESC50, above 81% human accuracy, is the line that got CLAP quoted. Two caveats keep it honest.

It is a comparison between different things. The human number comes from crowdworkers listening once and choosing among fifty categories, with human failure modes: attention, memory for the category list, unfamiliarity with some sounds. The model is not "better at hearing"; it is better at this particular forced-choice protocol.

The supervised ceiling is still higher. CLAP's own supervised finetune reaches 96.70% on ESC50, and the literature benchmark is 97.15%. Zero-shot bought you 82.6% for zero labelled examples. That is an extraordinary price-performance point, not an accuracy record.

Reading a benchmark table adversarially — five habits

Table 1 is well constructed, which makes it a good place to practise the habits that catch badly constructed ones.

  1. Find the chance level before the score. 0.4746 on Beijing Opera sounds mediocre until you notice it is a 4-class task with chance at 0.25 — and then 0.4746 sounds much better. 0.4945 on Vocal Sound is a 6-class task with chance at 0.1667, which is better still. The raw numbers are nearly identical; the achievements are not.
  2. Check that the comparison rows are comparable. "Benchmark (Best)" had labelled training data; "CLAP (ZS)" had none. Any row-to-row comparison across that line is measuring two different things, and the paper is careful to separate them — many papers are not.
  3. Look for the missing cells. AudioSet has no CLAP (Best) entry. There is no zero-shot benchmark for eleven of the sixteen tasks. Absence is usually "nobody has done it", occasionally "we did and it looked bad" — and you cannot tell which from the table alone.
  4. Recompute anything the prose claims. "A 5% acc increase" from prompts is 4.0 points in Table 3. "CLAP beat Wav2CLIP by an absolute 27% mAP" checks out exactly: 0.3024 − 0.0302 = 0.2722. One claim survives, one does not.
  5. Ask what the average is averaging. Table 2's "Avg. ZS score" mixes accuracy, mAP, and F1 across chance levels from 0.0018 to 0.5. The comparison between its rows is valid; the absolute value is not interpretable. Chapter 7 returns to this.
Inline concept check. CLAP (Best) beats Benchmark (Best) on Mridangam Tonic, 0.9534 against 0.942 — a 1.1-point win called state of the art. What should you want to know before believing it?  …  The variance. It is a 5-fold cross-validation on 1,000 clips of 0.81 seconds; fold-to-fold spread on such a small set can easily exceed a point. The paper reports no error bars anywhere, so a 1.1-point margin is suggestive rather than settled. The 27-point FSD50K gap needs no such caution.
CLAP's frozen features score 0.3708 on Speech Commands, but the same model finetuned scores 0.9683 — the best number in its row. What does that pair of results establish?

Chapter 7: Which Tower Matters?

CLAP has two pretrained encoders and a training budget. You can update both, one, or neither. That is four experiments, and the paper ran all four. The result is the most quietly consequential finding in the paper, because it tells you what to build next.

Before you read the table, commit to a prediction. Which encoder do you expect to matter more? Most people say audio — the audio side is the one being taught something new, the text side already speaks English. Write your guess down.

Table 2, in full

Audio encoderText encoderAvg. zero-shot across all 16 tasksESC50 accuracy
frozenfrozen0.28090.5555
trainablefrozen0.28180.6415
frozentrainable0.31090.7631
trainabletrainable0.32650.826

Two of those rows are unsurprising. Both frozen is worst; both trainable is best; the paper calls this "expected because unfreezing both encoders allows them to learn the multimodal information from the pairs."

The middle two rows are the finding. Isolate the gains:

What you unfreeze (starting from both frozen)Gain in avg. ZSGain on ESC50
Only the audio encoder (80.8M parameters)+0.0009+8.6 points
Only the text encoder (110M parameters)+0.0300+20.8 points
Ratio, text gain over audio gain33×2.4×
Both (for reference)+0.0456+27.1 points

Unfreezing the text encoder is worth thirty-three times as much as unfreezing the audio encoder, averaged across the sixteen tasks. The paper's own reaction is candid: "Surprisingly, unfreezing the text encoder performed better than unfreezing the audio encoder. Our intuition was that unfreezing the audio encoder would enable learning beyond the SEC coming from the pretrained AudioSet information."

Read the averages against the ESC50 column and a second story appears. On ESC50 alone the ratio is a modest 2.4×. Averaged over all sixteen tasks it explodes to 33×. Why? Because ESC50 is precisely the task the frozen AudioSet-pretrained CNN14 is already built for — sound events are its native problem, so a little audio adaptation goes a long way there. On the other fifteen tasks — music, emotion, counting, scenes — adapting the audio encoder buys almost nothing, while adapting the text encoder helps everywhere. The audio tower generalises across tasks by staying still; the text tower has to move.

Why would the text side matter more? Three mechanisms

The paper does not explain the asymmetry beyond noting the parallel to CLIP. Here are three mechanisms that fit the evidence, flagged as analysis rather than as claims from the paper.

1. Asymmetric domain shift. CNN14 was pretrained on 2M AudioSet clips — the same kind of audio, labelled with the same kind of sound-event concepts. Its features arrive nearly on-task. BERT was pretrained on Wikipedia and BookCorpus, where nobody writes "an insect buzzing in the foreground as birds chirp in the background." Audio captioning is a distinctive, narrow, oddly-structured genre. The text encoder has much further to travel, so it gains more from being allowed to travel.

2. The alignment burden falls where the geometry is coarser. Both towers must be brought into one space, and something has to bend. If the audio geometry is already a good match for sound-event structure, the cheaper solution is to bend the text geometry toward it. Gradient descent will find whichever adaptation lowers the loss for less movement.

3. Forgetting risk is asymmetric. 128,010 pairs is a small dataset for a 80.8M-parameter encoder that learned from 2M clips. Unfreezing the audio tower risks overwriting the AudioSet knowledge with something narrower — and the frozen-audio rows suggest that knowledge is worth a great deal. The text tower has less to lose: BERT's general language ability is not what CLAP needs, only its ability to place caption-like sentences sensibly.

The freezing 2×2

Click any cell of the grid to select a training regime. Blue means gradients flow, grey means locked. The bars show both metrics from Table 2, with the both-frozen row as the reference line so the gains are legible. Watch the average-ZS bar barely move when only the audio tower is unfrozen.

What "frozen" means mechanically

Freezing is not the same as removing. A frozen encoder still runs forward, still produces its 2048- or 768-dimensional vector, and still contributes to the loss. What changes is that requires_grad is off for its parameters, so the optimiser never updates them. Concretely:

python — the four regimes of Table 2def set_regime(model, train_audio, train_text):
    for p in model.audio_enc.parameters(): p.requires_grad = train_audio
    for p in model.text_enc.parameters():  p.requires_grad = train_text
    # the two projections and the temperature ALWAYS train — in all four rows.
    for p in [*model.La.parameters(), *model.Lt.parameters()]: p.requires_grad = True
    model.logit_scale.requires_grad = True

# row 1 of Table 2: 2.88M trainable of 193.68M  -> ESC50 55.55%
# row 2:          83.68M trainable              -> ESC50 64.15%
# row 3:         112.88M trainable              -> ESC50 76.31%
# row 4:         193.68M trainable              -> ESC50 82.60%

That comment block is the whole ablation, and it exposes something the prose glides over: the projections train in every row. So "both frozen" is not "no learning" — it is "learning restricted to a linear map between two fixed geometries." 55.55% on a 50-way task is what a rotation is worth.

Now the gradient story, which explains the asymmetry mechanically. The loss reaches the audio encoder only through La, and reaches the text encoder only through Lt. Both paths are equally short. What differs is what the gradient asks for at each end:

Gradient arriving at the audio tower
"Move the representation of this dog bark so it lands nearer the sentence about dogs." But CNN14, trained on 2M AudioSet clips, already separates dog barks from rain. The requested change is small.
↓ versus
Gradient arriving at the text tower
"Move the representation of 'a dog barks in a yard' so it lands near an acoustic region." BERT organised that sentence by syntax and general semantics, never by how it sounds. The requested change is large.

The LiT echo

The paper connects its finding to reference [27] — Zhai et al., LiT: Zero-Shot Transfer with Locked-image Text Tuning — noting "a similar insight was found for CLIP models in Computer Vision." LiT's headline is that locking the image tower and tuning only the text tower gives better zero-shot transfer than tuning both, precisely because a strong pretrained vision encoder should not be disturbed by a noisy image-text corpus.

Note the difference in conclusion, though, because it is easy to over-read. LiT found locked-image tuning best. CLAP found both-unfrozen best, with text-unfrozen the strongest single choice. Same direction, different endpoint — most plausibly because CLAP's 128k pairs are clean human captions rather than web alt-text, so overwriting the audio tower is less dangerous than overwriting a vision tower with internet noise.

The implication the authors draw, and why it is the most useful sentence in the paper

The paper's own words: "This valuable finding suggests that, under the CLAP learning paradigm, it is possible to use an audio encoder of choice and turn it into a Zero-Shot classifier."

Unpack the engineering consequence. If the audio tower does not need to change much, then the audio tower is a swappable component. Take any strong pretrained audio encoder — PANNs, an Audio Spectrogram Transformer, HTSAT, a self-supervised speech model — bolt on a linear projection, train against captions with a language tower that is allowed to move, and you have converted a fixed-taxonomy classifier into an open-vocabulary one.

That is exactly what the field then did. Every CLAP successor in Chapter 9 is, structurally, this recipe with a different audio tower.

And do not miss the first row. Both encoders frozen — only the 2.88M projection parameters trained — still gives 55.55% on ESC50 against a random baseline of 2%. Over two-thirds of the final zero-shot accuracy is reachable by learning nothing but a linear map between two pretrained geometries. The audio encoder already "knew" about dogs and rain; BERT already "knew" what the words mean; all that was missing was a rotation. That is the cheapest possible statement of what CLAP does.

A caution about the average

One number in Table 2 deserves suspicion, and reading it carefully is good practice. "Avg. ZS score" is the mean of CLAP's zero-shot performance across all sixteen downstream tasks. But those tasks use different metrics (accuracy, mAP, F1) with different chance levels (0.0018 to 0.5). Averaging them is averaging apples, oranges, and a percentage of a percentage.

Concretely: GTZAN Music vs Speech contributes 1.000 to that mean while its chance level is 0.5, and AudioSet contributes 0.058 while its chance level is under 0.002. A tenth of the average is being supplied by a two-class task that any model solves. So the absolute values 0.2809 and 0.3265 do not mean "28% accurate" in any interpretable sense.

What survives the objection is the comparison. All four rows aggregate the same sixteen tasks the same way, so the ordering and the relative gaps are meaningful even though the level is not. The 33× asymmetry is a ratio of two differences computed under an identical aggregation, and it is robust to the aggregation being crude. The ESC50 column, which is a single clean accuracy on a single task, tells the same story at 2.4×.

Inline concept check. Both-frozen gives 0.2809 average and 55.55% on ESC50. Both-trainable gives 0.3265 and 82.6%. ESC50 improved by 49% relative; the average improved by 16% relative. What does that gap tell you?  …  That most of the training benefit concentrates on sound-event tasks — the ones the training captions actually describe. On the other fifteen tasks, unfreezing helps far less, because no amount of gradient can teach a model about emotions from captions that never mention them. Chapter 8 makes this the headline.

What you would do with this in practice

Your situationWhat Table 2 recommends
Strong domain audio encoder, small caption setFreeze audio, train text and both projections. Cheapest, and Table 2's second-best row
Plenty of clean pairs, plenty of computeUnfreeze both — the paper's configuration
Very small or noisy caption setFreeze both, train only the projections. Still worth 55.55% on ESC50 for 2.88M parameters
You want to swap in a new audio encoder next quarterKeep audio frozen so the projection absorbs the interface, and your text tower stays reusable

The fifth row nobody ran

Table 2 has four rows because there are two binary switches. But the interesting design space has more dimensions, and naming the missing experiments sharpens what the four rows actually established.

Experiment not runWhat it would have settled
Freeze the audio tower but train its last block onlyWhether the 8.6-point ESC50 gain from unfreezing audio comes from deep re-representation or a shallow recalibration. If a last-block-only run recovered most of it, the audio tower is even more swappable than claimed
A nonlinear projection with both encoders frozenWhether the 55.55% frozen-frozen result is limited by the linearity of the map or by the encoders' geometry. This is the single cheapest missing experiment in the paper
A randomly initialised audio tower, trainedHow much of CLAP is AudioSet pretraining versus captions. Given 128k pairs, almost certainly a lot — but "almost certainly" is not a measurement
A randomly initialised text tower, trainedWhether BERT's language prior matters, or whether any encoder that maps strings consistently would do. The zero-shot transfer to unseen class names says the prior matters; nothing quantifies it
Freezing schedules — freeze audio for 20 epochs, then releaseWhether the forgetting hypothesis (mechanism 3) is right. If staged unfreezing beat both-from-scratch, that would be strong evidence

Two of these five would have been nearly free — the nonlinear-projection run and the staged unfreeze reuse the same code and the same data. Their absence is a reminder that a four-page paper reports the experiments that fit, not the experiments that exist.

The practical recipe, in code

python — the "audio encoder of choice" recipe# Table 2 row 3: freeze audio, train text + both projections.
# Second-best zero-shot, ~42% of the trainable parameters, and your
# audio tower stays swappable next quarter.

audio_enc = load_any_pretrained_audio_encoder()      # PANNs, AST, BEATs, HTSAT...
for p in audio_enc.parameters(): p.requires_grad = False
audio_enc.eval()                                    # also freezes BatchNorm statistics —
                                                  # forgetting this silently trains the encoder

text_enc  = AutoModel.from_pretrained("bert-base-uncased")   # trainable
La, Lt    = nn.Linear(audio_dim, 1024), nn.Linear(768, 1024)

opt = torch.optim.Adam([
    {"params": text_enc.parameters(), "lr": 1e-5},   # gentle on the pretrained tower
    {"params": [*La.parameters(), *Lt.parameters(), logit_scale], "lr": 1e-3},
])
# with the audio tower frozen you can also PRECOMPUTE every E_a once and
# train on cached vectors — an order-of-magnitude cheaper per epoch.

That last comment is the underrated payoff. A frozen audio tower means the expensive forward pass happens once, offline, for the whole corpus. Training then reads 1024-float vectors off disk. On a single GPU that turns a multi-day run into an afternoon — and Table 2 says you give up 0.0156 of average zero-shot to get it.

Unfreezing only the text encoder gave 33× the average zero-shot gain of unfreezing only the audio encoder. Which reading is best supported?

Chapter 8: What the Paper Whispers

The main text of a four-page conference paper is a highlight reel. The interesting failures live in the appendix, in a footnote, or in a number that does not quite match its prose. CLAP has three appendix findings that matter more than most of Section 4, and a handful of smaller discrepancies worth cataloguing. This chapter reads the quiet parts out loud.

Whisper 1 — 1.7 million more pairs made the model worse

Appendix C.2, in full, is the most useful paragraph in the paper. AudioSet has 2M clips. The authors tried to turn them into pairs by "constructing the text description with the title and the class label(s)." Adding about 1.7M such pairs to the existing 128k produced this:

Task128,010 curated pairs+1.7M AudioSet pairs (1.83M total)Change
ESC500.82600.6715−15.45 points
UrbanSound8K0.73240.7093−2.31 points
Speech Commands V20.100.15+5 points

Fourteen times more data, and the flagship number dropped by fifteen points. In an era whose default assumption is that more pairs are always better, this is a result worth memorising.

The authors diagnose it precisely: "In AudioSet, often the YouTube titles and descriptions do not describe the acoustic content of the video segment under consideration but instead describe the video as a whole."

Picture the failure. A ten-second AudioSet segment contains a dog barking. Its parent video is titled "Ep. 42 — Our Trip to Portugal (Vlog)". The constructed caption describes a travel vlog. The clip contains a bark.

Why noisy pairs are uniquely toxic to contrastive learning — the mechanism, not just the vibe. In supervised learning a wrong label corrupts one example. In contrastive learning the diagonal is the label, so a wrong pair corrupts the entire row and the entire column it sits in. Concretely, that bad pair does three things at once: it pulls the bark audio toward "Trip to Portugal"; it pushes "Trip to Portugal" away from every other clip in the batch, including any clip it might genuinely describe; and it pushes the bark audio away from every other caption in the batch, including "a dog barking," if that caption happens to be present. One bad pair damages 2N−1 relationships. And because cross-entropy's gradient is largest when the model is confidently wrong, a well-trained model fights hardest against its own correct intuition on exactly these examples.

Now do the arithmetic on the mixture. After the addition, 1.7M of 1.828M pairs — 93% — come from the noisy source. The curated captions are outnumbered thirteen to one. The model is not learning "sound events plus some noise"; it is primarily learning "YouTube video titles, with an occasional real caption."

And the one improvement is just as diagnostic. Speech Commands went from 10% to 15%. The authors' guess: "Perhaps due to the large amount of audio containing speech in AudioSet." Even bad captions attached to speech-heavy audio taught the model something about speech — because the base corpus taught it essentially nothing. A signal from noise is still a signal when your baseline is zero.

The tension the paper leaves unresolved, and it is the whole future of the field. The same appendix says: "finding helpful training data for CLAP based on public datasets is difficult, thus relying on large-scale noisy pairs is the only scalable approach." Read that next to the 15-point drop. The authors are saying, in effect: noise is the only way to scale, and noise made things worse. The escape they gesture at — "more intelligent ways of generating descriptions can benefit CLAP training" — is exactly what the next generation did: LAION-CLAP's keyword-to-caption augmentation, and later, captions generated by language models. The bottleneck moved from collecting audio to writing about audio.
Data quality versus data quantity

Two whispers, one canvas. Dilution mode sweeps the fraction of noisy AudioSet-style pairs in the mixture, anchored at the paper's two measured endpoints (0% and 93%) — the curve between them is an interpolation, not a measurement, and is drawn dashed to say so. Batch mode plots the appendix's batch-size story alongside two quantities the paper does not plot: total optimiser steps, and the expected number of same-audio collisions per batch.

Noisy-pair share 0%

Whisper 2 — the speech gap has five converging causes

Chapter 6 established the pattern: sound events near the human ceiling, speech near chance. The paper offers one cause. There are at least five, and they all point the same way.

#CauseSourceEffect on speech tasks
1Captions describe acoustic events, not linguistic content. No training caption ever transcribes a word or names an emotionThe paper, Section 4.2Decisive — the concept is simply absent from the supervision
2The Mel filterbank stops at 8 kHz, discarding the sibilance bandSection 3.2 + Chapter 2 hereRemoves cues that separate "s" from "sh" and one voice from another
31-second Speech Commands clips are padded to 5 seconds — 80% silenceSection 3.2 + our arithmeticDilutes the evidence fivefold before clip-level pooling
4CNN14 pools 690 frames into one vector, destroying phonetic orderChapter 3 here"cat" and "tack" have similar bags of phonemes
5Three of the four speech-adjacent domains needed a custom prompt because the default was ungrammaticalSection 3.3A symptom, not a cause — but a loud one

Cause 1 dominates, and we know it dominates because of the Table 6 control from Chapter 6: finetuned CLAP reaches 96.83% on Speech Commands, the best number in that row. Causes 2 through 4 would still apply after finetuning. So they cannot be what is limiting the frozen model. The bottleneck really is that the contrastive objective was never given a reason to encode which word was spoken.

The paper's own forecast is reasonable and, in hindsight, correct: "We posit that as we increase training data and increase human speech-based captioning, CLAP's performance on speech datasets will increase." That is precisely the arc from CLAP to speech-aware audio-language models (Chapter 9).

Whisper 3 — the batch-768 "anomaly" probably is not one

Appendix C.1 reports a batch-size study: 4 to 24 GPUs, batch sizes 32 to 768, measuring average zero-shot performance across the downstream tasks. Larger batches helped — until 768, where performance dropped. The authors write: "This might be an anamoly in an increasing zero-shot performance trend. We leave the larger batch size investigation to future work."

Fair enough for a four-page paper. But two mechanisms predict exactly that drop, and both are computable from numbers the paper already gives.

Mechanism A: the learning rate was not rescaled, so the big-batch run got 4% of the updates. Section 3.2 fixes the learning rate at 10−3 and the schedule at 40 epochs. Epochs are fixed, so the number of optimiser steps falls linearly with batch size:

Batch sizeSteps per epoch (128,010 pairs)Total steps over 40 epochsRelative to batch 32
324,000160,013100%
1281,00040,00325%
51225010,0016.3%
7681676,6674.2%

With a fixed learning rate, the batch-768 model took one twenty-fourth as many gradient steps as the batch-32 model. Standard practice would scale the learning rate with batch size (linearly, or by the square root) to compensate. Nothing in the paper says that was done. The "anomaly" may be a model that simply had not finished training.

Mechanism B: false negatives grow with N2, and this corpus has duplicate audio by design. Recall Chapter 1: 128,010 pairs cover only 90,947 unique clips, because ClothoV2 supplies five captions per clip and MACS supplies several. So two entries in a batch can be the same audio with different captions — and the loss will insist that caption i matches clip i and not clip j, when clips i and j are byte-identical. That is an unsatisfiable constraint, and it actively penalises correct behaviour.

How often? Count the colliding pairs in the corpus — 5,929 ClothoV2 clips contribute C(5,2) = 10 collisions each, MACS contributes roughly 7.5 per clip over 3,930 clips — giving about 88,800 colliding pairs out of the C(128010, 2) ≈ 8.19 billion possible. The probability that a random pair of batch entries collides is about 1.08 × 10−5, and a batch of N contains C(N,2) pairs, so:

Batch size NPairs in the batchExpected same-audio collisions per batch
324960.005
1288,1280.09
512130,8161.4
768294,5283.2

At batch 32 a collision essentially never happens. At batch 768 there are about three per batch, every batch, for all 40 epochs. Each one is a contradiction the optimiser cannot resolve, and it is aimed at exactly the captions the corpus most wants the model to treat as equivalent.

Flagged as analysis, not as the paper's claim. Neither mechanism above appears in the paper; both are derived from numbers it reports. Mechanism A is the more likely culprit — a 24× reduction in optimiser steps is enormous, while three contradictory pairs in 768 is a 0.4% label-noise rate. But B has the right functional form (quadratic in N) to explain a trend that reverses only at the largest batch, and it is trivially fixable: deduplicate by audio when sampling a batch. Later contrastive audio work does exactly that.

Whisper 4 — the overlap question, asked and answered

Any zero-shot claim invites the same challenge: how much of the evaluation did the model already see? Trace the corpora and the answer is more interesting than a simple yes or no.

Downstream taskRelationship to CLAP's training dataDoes it undermine the claim?
FSD50KDirect — 36,796 FSD50K train/val clips are in the training set, paired with their titles and descriptions. The paper says so plainly, and evaluates on the FSD50K test splitNo test-clip leakage, but the domain and recording style are seen. The 30.24 mAP should be read as "in-domain zero-shot"
AudioSetIndirect — AudioCaps is built from AudioSet clips, so 44,292 AudioSet segments are in training, captionedNotably, CLAP scores its worst headroom here (5.6%). If seeing the audio were sufficient, this cell would be strong. It is not — which is itself evidence that captions, not audio exposure, drive the zero-shot ability
ESC50, US8K, TUT2017, GTZAN, Mridangam, CREMA-D, RAVDESS, Speech Commands, Vocal Sound, LibriCount, DCASE17, Beijing OperaNo stated overlapThese are the clean cases — and ESC50, the headline, is one of them
The AudioSet row is the most reassuring number in the paper, and nobody quotes it. If zero-shot performance came from having memorised the evaluation audio, AudioSet — whose clips CLAP saw 44,292 of, with captions — would be CLAP's strongest task. It is its weakest, at 0.058 mAP against a supervised benchmark of 0.471. Exposure to audio without the right kind of language buys almost nothing. That is the paper's central thesis, accidentally confirmed by its worst result.

Whisper 5 — what a four-page paper cannot tell you

Some gaps are not errors, just consequences of the format. Naming them is part of reading a paper honestly, and each one is a question you would have to answer yourself to reproduce the work.

MissingWhy it matters
Error bars, seeds, or repeated runsIs the 82.6% ±0.3 or ±3? Several of the near-chance numbers (CREMA-D at +1.2 points over random) could plausibly be run-to-run noise
Whether embeddings are L2-normalisedEquation (3) implies not; the temperature's behaviour implies yes. This changes the implementation materially (Chapter 3)
Which of the two supervised setups won each taskTable 1's "CLAP (Best)" is a max over feature-extraction and finetune. Table 6 disambiguates for some tasks, not all
The batch size of the main modelAppendix C.1 studies 32 to 768, but the headline model's batch size is never stated — and the appendix says 768 was worse
Actual values in the batch-size figureFigure 2 shows a trend; no numbers are given in the text, so the drop at 768 cannot be quantified
Whether prompts were tuned on test dataTable 3's five prompts are evaluated on ESC50 and the best is selected. If that selection used the same folds reported in Table 1, the 82.6% carries a small optimistic bias

None of these invalidate the paper. All of them are the difference between "I read the result" and "I could rebuild it." The last one is the only one with teeth, and even there the effect is bounded by Table 3's own spread — at most 1.4 points against the bare-label baseline.

Smaller whispers, collected

WhereWhat is writtenWhat is actually the caseConsequence
Section 3.2"hop size of 320 secs, window size 1024 secs"Those are samples: 7.26 ms and 23.22 ms at 44.1 kHzHarmless typo, total confusion for a careful reader
Equation (3) + Section 3.2C = τ(EtEaT) with τ = 0.007, logits clipped at 100The multiplier is 1/τ ≈ 142.86; 0.007 is the temperature. Only then can the clip ever fireImplement it literally and the model cannot learn (Chapter 4)
Equation (4)k = (1/N)∑ log diag(softmax(C))Implementations minimise the negative log-likelihoodSign error if transcribed directly
Section 3.2"max text sequence length to 100 chars"Characters, not tokens — about 20 words. Two of the twelve captions the paper itself samples exceed it~17% of captions lose their tail, often the second sound source
Section 4.4Prompts give "a 5% acc increase"Table 3 spans 4.0 points worst-to-best, and 1.4 points versus the bare class labelThe effect is real and free, but small
ConclusionTraining data "is at least 0.001% smaller" than comparable vision models128,010 versus CLIP's 400M is 0.032%, i.e. about 1/3125The garbled figure undersells a genuinely striking fact
Table 1 vs Table 5DCASE17 random listed as 0.05; US8K as 0.1DCASE17 has 17 classes (1/17 ≈ 0.059); US8K has 10 (1/10 = 0.1)Column alignment in the typeset table repays care
Why cataloguing these is not pedantry. Every one of them is a place where implementing the paper as written produces a model that does not work, or a claim that does not survive its own table. Reading a paper adversarially — checking units, recomputing percentages, comparing prose to tables — is the difference between reproducing a result and reproducing a rumour. CLAP is a good paper; it is a good paper with seven such places in four pages, which is roughly the field average.

The counterfactual that would settle whisper 1

The AudioSet result is reported as a single before-and-after. What would turn it from an anecdote into a law? Four experiments, none of which needs new data.

ExperimentWhat it distinguishes
Add only 128k AudioSet pairs (a 50/50 mixture) rather than 1.7MWhether noise is harmful per pair or only when it dominates the mixture. If a 50/50 mix is fine, the problem is dilution, not toxicity, and upsampling the clean set fixes it
Add 1.7M AudioSet pairs but weight their loss at 0.1The same question from the optimisation side. Cheap, and standard practice for noisy web data
Filter AudioSet pairs by a CLAP-score threshold from the 128k-trained modelWhether a model trained on clean pairs can identify which noisy pairs are worth keeping — a bootstrapping loop that later work does use
Replace AudioSet titles with class-label templates ("this is a sound of dog, bark")Whether the harm comes from wrong text or merely label-shaped text. Chapter 1 predicts the latter would be mediocre but not destructive

The paper runs none of these, and one sentence explains why: the four-page format. But notice how much the single reported number still constrains the space. Whatever the mechanism, it is strong enough that a 14× increase in data lost 15 points — and no amount of "more data is better" intuition survives contact with that.

Reproduction checklist

If you set out to rebuild CLAP from the paper alone, here is what you know, what you must infer, and what you must guess.

ItemStatusValue or inference
Sampling rate, window, hop, Mel bins, bandStated44.1 kHz, 1024, 320, 64, 50–8000 Hz (units corrected)
Crop length and paddingStatedRandom continuous 5 s; pad if shorter
Encoders and dimensionsStatedCNN14 (80.8M, 2048), BERT base uncased (110M, [CLS] 768), d = 1024
Text truncationStated100 characters
Optimiser, LR, schedule, epochsStatedAdam, 10−3, plateau ×10−1 patience 10, 40 epochs
Temperature handlingMust inferMultiplier = 1/τ from log-space parameter; clamp scaled logits at 100
L2 normalisationMust inferYes — otherwise the temperature and the clip do not cohere
Loss signMust inferNegative log-likelihood
Batch size of the headline modelMust guessSomewhere in 32–768; the appendix says 768 was worse, so likely 256–512
Weight decay, warmup, gradient clippingMust guessUnstated. Defaults are the only option
Which supervised setup produced each CLAP (Best)Partly statedTable 6 splits (S) and (F) for most tasks

Five stated, three inferable from internal consistency, two genuine guesses. That is a reasonably reproducible paper by 2022 standards — and the three inferable items are precisely the ones this lesson spent Chapters 3 and 4 deriving, because getting them wrong means getting a model that does not train at all.

Adding 1.7M AudioSet-derived pairs to 128k curated pairs dropped ESC50 zero-shot from 82.6% to 67.15%. Why is noisy supervision worse for contrastive training than for ordinary supervised training?

Chapter 9: Legacy and Cheat Sheet

CLAP is a four-page ICASSP-style paper with a 128k-pair dataset and two off-the-shelf encoders. Its influence is out of all proportion to its size, for a reason worth naming: it did not introduce a technique, it relocated an interface. After CLAP, the natural way to ask an audio model a question is to type the question.

What CLAP made possible

DirectionWhat CLAP contributedWhere it went
Open-vocabulary audio classificationThe whole recipe: dual encoder, shared space, prompted class namesStandard practice. Every later audio-text model reports zero-shot ESC50
Scaled successorsThe demonstration that the recipe works at 128k pairsLAION-CLAP (2023) swapped in an HTSAT audio tower and RoBERTa text tower, trained on far more pairs, and added keyword-to-caption augmentation — the direct answer to Chapter 8's data-quality problem. Microsoft's own 2023 follow-up moved to an HTSAT encoder and a larger caption corpus
Text-to-audio generationA text encoder whose embeddings are acoustically groundedDiffusion-based audio generators condition on CLAP-style text embeddings, and the "CLAP score" — cosine similarity between the generated audio and the prompt — became a standard automatic metric for whether generated audio matches its prompt
Audio-text retrievalA shared space where a sentence can query a sound archiveSound-library search, dataset curation, and caption-based filtering of training corpora
Audio language modelsThe audio-encoder-plus-projection patternLater systems keep the audio tower and the projection but replace the text tower with a full LLM, turning retrieval into conversation. See Qwen2-Audio and our audio LLMs lesson
Swappable audio towersChapter 7's finding: the text tower carries the alignment burdenMade it cheap to try every new audio encoder — AST, PaSST, Audio-MAE, BEATs — inside the same contrastive frame
The lineage

Where CLAP sits. Upstream: the encoders and the idea it borrowed. Downstream: what the recipe became. Tap any node to see what it contributed and what it fixed about its parent.

What CLAP cannot do — the honest limits

LimitationRoot cause (which chapter)What later work did about it
No temporal order — "dog then siren" ≈ "siren then dog"Clip-level pooling to one vector (Ch 3)Frame-level or token-level audio encoders feeding sequence models
No localisation — cannot say when an event occurredSame poolingSound event detection heads; frame-wise contrastive variants
Near-chance on speech content and emotionCaptions never describe linguistic content (Ch 6, Ch 8)Speech-aware corpora and speech encoders alongside the audio tower
Fixed 5-second window; long clips get a random cropSection 3.2 (Ch 2)Feature fusion over long inputs; variable-length encoders
Cannot generate text — it scores captions, it does not write themDual-encoder by design (Ch 3)Audio captioning models and audio LLMs with a decoder
Cannot abstain — softmax over candidates always sums to oneCh 0's problem, inherited (Ch 5)Threshold on raw cosine; open-set calibration
Performance depends on batch size and on caption qualityContrastive negatives come from the batch (Ch 4, Ch 8)Queue-based negatives; LLM-generated captions
8 kHz spectral ceilingSection 3.2 (Ch 2)Full-band front ends in successors

CLAP against its neighbours, on one page

CLIPWav2CLIPAudioCLIPCLAPSSL audio (wav2vec 2.0, BEATs)
Modalitiesimage + textaudio + CLIP spaceimage + text + audioaudio + textaudio only
Text supervisionweb alt-textAudioSet class labelsAudioSet class labelsfree-form human captionsnone
Pairs400M~2M (label pairs)~2M (label pairs)128,010unlabelled hours
Zero-shot open vocabulary?yespartial — inherits CLIP'spartialyesno — needs a fixed head
ESC50 zero-shot0.69400.826not applicable
Trained from scratch?both towersaudio onlyaudio onlyneither — both towers pretrainedencoder only
Main limitationdata scale requiredlabel-shaped textlabel-shaped textcaption coverage: no speech contentno semantics from language

The row that carries the argument is "text supervision". Everything else in the CLAP column is borrowed, off the shelf, or smaller than the alternatives. Change only that row and the ESC50 number moves 12 points.

A short glossary, for the terms this lesson bolded

TermOne lineFirst appeared
LogitsUnnormalised scores just before a softmax or sigmoidCh 0
Zero-shotPerforming a task with no labelled examples and no gradient steps for itCh 0
Self-supervised learningPretraining on unlabelled data with a pretext taskCh 0
SpectrogramTime on one axis, frequency on the other, magnitude as the valueCh 2
Window / hopHow many samples per frequency analysis; how far you slide between analysesCh 2
Mel scaleA frequency warp so equal steps sound like equal pitch stepsCh 2
[CLS] tokenBERT's prepended summary token; its final vector represents the sequenceCh 3
Dual encoderTwo independent towers compared only by a dot product — no cross-attentionCh 3
Representational collapseEverything maps to one point because the objective never says "not that one"Ch 4
Hard negativeA wrong pair the model currently rates highly — where nearly all the gradient goesCh 4
TemperatureThe scalar setting how sharp the softmax over similarities is; here its reciprocal multiplies the cosinesCh 4
Prompt templateA sentence frame wrapping a class name so it lands where captions liveCh 5
mAPMean average precision — a threshold-free ranking metric for multi-label tasksCh 6

The cheat sheet — every equation, every symbol

SymbolMeaningShape / value in CLAP
XaProcessed audio: the log-Mel spectrogramRF×T = R64×690 per clip
F, TNumber of spectral components (Mel bins) and time bins64 and about 690
XtThe text of the captionString, truncated to 100 characters
NBatch size — also the number of negatives per anchor, minus one32 to 768 in the appendix study
fa, ftAudio and text encodersCNN14 (80.8M) and BERT base uncased (110M)
a, X̂tEncoder outputs, before the shared spaceRN×V and RN×U, V = 2048, U = 768
La, LtLearnable linear projections into the joint space2048→1024 and 768→1024; 2.88M parameters together
Ea, EtThe joint multimodal embeddingsRN×d, d = 1024, L2-normalised in practice
τTemperature; the logits are scaled by its reciprocalLearnable, initialised 0.007, so the multiplier starts at 142.86
CSimilarity matrix — the logitsRN×N; N correct pairs on the diagonal, N2−N incorrect off it; clipped at 100
text, ℓaudioCross-entropy along the text axis (rows) and audio axis (columns)Scalars; the guessing baseline for each is ln N
LThe symmetric lossScalar; 0.375 for the worked 3×3 batch at scale 4
C (in Chapter 5)Number of candidate classes at inference — unrelated to the matrix C50 for ESC50, whatever you type
EtextStacked embeddings of the C prompted class names — the zero-shot classifier matrixRC×d; 200 KB for ESC50

The four equations, in order.

(1)  X̂a = fa(Xa) ;  X̂t = ft(Xt)
encode each modality independently — no cross-attention, ever
(2)  Ea = La(X̂a) ;  Et = Lt(X̂t)
two linear maps into one d = 1024 space; then L2-normalise
(3)  C = τ · (Et · EaT)  ∈ RN×N
every caption against every clip; the multiplier is 1/0.007, and the result is clipped at 100
(4)  L = 0.5 · ( ℓtext(C) + ℓaudio(C) ),   ℓk = −(1/N) ∑i log softmax(C)ii
rows are text-to-audio retrieval, columns are audio-to-text; the labels are 0,1,…,N−1
zero-shot:  z = Etext · Ea,   p = softmax(z) (multiclass)  or  σ(z) (multilabel)
the classifier matrix is built from strings at inference time

The numbers worth remembering

NumberWhat it is
128,010Training pairs, from FSD50K + ClothoV2 + AudioCaps + MACS — over 90,947 unique clips
82.6%ESC50 zero-shot, beating AudioCLIP's 69.40% and reported human accuracy of 81%
73.24% / 30.24 mAPUrbanSound8K and FSD50K zero-shot — the latter a 27-point mAP gain over Wav2CLIP
100%GTZAN Music vs Speech zero-shot — above the 99.2% supervised benchmark
16 tasks / 8 domainsThe evaluation suite; better than random on all of them
5 datasetsWhere CLAP's supervised setups set state of the art
0.2809 → 0.3265Average zero-shot, both encoders frozen versus both trainable
55.55%ESC50 with both encoders frozen — the projections alone
82.6 → 67.15ESC50 after adding 1.7M noisy AudioSet pairs
1024 / 2048 / 768Shared space, audio embedding, text embedding dimensions
0.007The initial temperature; the logit multiplier is its reciprocal, 142.86

Where to go from here

If you want…Go to
The vision original this borrowed fromCLIP and contrastive vision-language
The mechanics of contrastive objectives in generalContrastive learning
The audio front end in far more depthAudio representations and cepstrum and MFCC
The audio tower CLAP borrowedPANNs / CNN14
Transformer audio encoders that replaced CNN14AST, PaSST, Audio-MAE, BEATs
What happens when audio becomes tokensAudioLM and neural audio codecs
Speech at scale, and audio inside an LLMWhisper, Qwen2-Audio, audio LLMs
The classical era CLAP replacedClassical audio classification

Build it yourself — the weekend recipe

Everything in this lesson fits into one file. Here is the checklist, with the decision that matters at each step.

StepWhat to doThe decision that matters
1. PairsGrab ClothoV2 (5 captions per clip) or a few thousand of your own captioned clipsQuality over quantity — Chapter 8. A thousand honest captions beat a hundred thousand video titles
2. Front endtorchaudio.transforms.MelSpectrogram then AmplitudeToDBMatch your domain's band. Do not inherit an 8 kHz ceiling if you care about speech
3. Audio towerAny pretrained encoder — PANNs, AST, BEATs. Freeze itChapter 7 says this costs you little and saves you most of the compute
4. Text towerA sentence encoder. Unfreeze itThis is where the alignment happens. Thirty-three times the return
5. ProjectionsTwo nn.Linear layers into d = 512 or 1024, then L2-normaliseLinear, not MLP. Keep the geometry, do not re-learn it
6. Temperaturenn.Parameter(log(1/0.007)), exponentiate, clamp the logits at 100Calibrate to your d: the random-cosine spread is 1/√d
7. LossThe three-line symmetric cross-entropy from Chapter 4Log ℓtext and ℓaudio separately; their gap is a real diagnostic
8. BatchAs large as memory allows — and deduplicate by audio when samplingNegatives come from the batch. Same-clip collisions are unsatisfiable constraints
9. Sanity checkConfirm the loss drops below ln N in the first epochIf it sits at ln N, your temperature is wrong — almost always the 0.007-versus-142.86 trap
10. EvaluateESC50 zero-shot with "this is a sound of [class]"It is five lines of code and the community's shared yardstick

References worth reading next

  1. Elizalde, B., Deshmukh, S., Al Ismail, M., Wang, H. "CLAP: Learning Audio Concepts from Natural Language Supervision," 2022 — arXiv:2206.04769. The paper this lesson is built on.
  2. Radford, A. et al. "Learning Transferable Visual Models From Natural Language Supervision" (CLIP), 2021 — reference [6]. The recipe CLAP ports.
  3. Kong, Q. et al. "PANNs: Large-Scale Pretrained Audio Neural Networks for Audio Pattern Recognition," 2020 — reference [23]. CNN14, the borrowed ear.
  4. Devlin, J. et al. "BERT: Pre-training of Deep Bidirectional Transformers," 2019 — reference [24]. The donated geometry.
  5. Zhai, X. et al. "LiT: Zero-Shot Transfer with Locked-image Text Tuning," 2021 — reference [27]. The vision-side echo of Chapter 7.
  6. Wu, H.-H. et al. "Wav2CLIP," 2022 — reference [9]; Guzhov, A. et al. "AudioCLIP," 2022 — reference [10]. The label-supervised predecessors CLAP outperforms.
  7. Drossos, K. et al. "Clotho," 2020 — [20]; Kim, C. D. et al. "AudioCaps," 2019 — [21]; Fonseca, E. et al. "FSD50K," 2022 — [19]; Martín-Morató, I. & Mesaros, A. "MACS," 2021 — [22]. The four corpora that became 128,010 pairs.
  8. Turian, J. et al. "HEAR 2021: Holistic Evaluation of Audio Representations," 2022 — reference [12]. The source of many of Table 1's supervised benchmarks.
Cross-domain bridge
CLAP is a database index for sound, and zero-shot is a query
A vector database precomputes embeddings for every document, then answers a query by embedding it once and taking a nearest-neighbour search. CLAP precomputes an embedding for every clip, then answers "which of these classes?" by embedding each class name once and taking a dot product. The class list is the query set; the audio archive is the index. Swap which side you loop over and the same machine does retrieval instead of classification — find me every clip matching "glass breaking" — with no change to the model at all. If you have built a semantic search system, you have already built the inference half of CLAP; see our vector embeddings and similarity metrics lessons for the same geometry with different labels.
"What I cannot create, I do not understand."
Take a pretrained audio encoder, a sentence encoder, two nn.Linear layers, and a thousand captioned clips. Three lines of loss. You will have a working open-vocabulary sound classifier by the end of a weekend — and the 82.6% will stop being a number you read.
Exit gate — teach it back before you leave.

Without scrolling up: (1) write the shape of Xa and justify both numbers from the sampling rate, window, hop, and Mel settings; (2) write Equations (3) and (4) and say what the diagonal means; (3) compute the loss of a 2×2 batch whose cosines are 0.9 on the diagonal and 0.4 off it, at scale 4; (4) explain why unfreezing the text encoder mattered 33× more than the audio encoder; (5) explain why 1.7M extra pairs dropped ESC50 by 15 points. If any of the five stalls, its chapter is one tap away.

Which single sentence best captures why CLAP mattered more than its size suggests?