A pure Vision Transformer with no convolution at all — applied directly to spectrogram patches. By treating audio as an image and transferring ImageNet-pretrained weights, AST set a new state of the art on AudioSet (mAP ~0.485) and proved that the convolution-free recipe of ViT carries over to sound.
You are building a model that listens to a ten-second clip and tags everything it hears: a dog barking, a car passing, a child laughing, rain on a window. This is audio event classification on AudioSet — 527 overlapping labels, 2 million clips. In 2020 the recipe was settled and nobody questioned it: take the audio, compute a spectrogram, and feed it to a convolutional neural network (a CNN), almost always one borrowed from computer vision.
That recipe worked, but it carried an awkward dependency. The best audio models were not really "audio architectures" at all — they were image CNNs (ResNet, EfficientNet) wearing a spectrogram as a costume. And to squeeze out the last few points of accuracy, the leading systems (PSLA, the 2020 state of the art) stapled attention pooling on top of the CNN. So the field had quietly arrived at a contradiction: the most important operation for tagging long sounds — relating an event early in the clip to an event late in the clip — was being done by attention, while the CNN underneath fought to provide that attention with a long enough reach.
Why does a CNN struggle with reach? A convolution is local by construction. A 3×3 kernel only sees a 3×3 patch of the spectrogram. To relate a sound at second 1 to a sound at second 9, the signal must climb through many convolutional layers, each widening the receptive field a little, until — many layers deep — the two events finally fall inside the same field of view. The path between two distant points on the spectrogram is long, and long paths are exactly where information leaks and gradients fade.
Top: a CNN's receptive field grows one layer at a time — to connect a bark at the start to a bark at the end takes many stacked layers. Bottom: a Transformer connects every patch to every other patch in a single attention step. Click "Animate" to grow the receptive field and watch attention reach the end instantly.
| Property | CNN on spectrogram | AST (pure Transformer) |
|---|---|---|
| Receptive field | Local — grows layer by layer | Global from layer 1 — every patch sees every patch |
| Path between distant events | O(depth) — many layers deep | O(1) — one attention hop |
| Inductive bias | Strong (locality + translation) | Weak — must be supplied by pretraining |
| Convolutions | Many | Zero — not a single one |
| AudioSet mAP (full) | ~0.474 (PSLA, CNN + attention) | ~0.485 (single model) |
This is the whole paper in one sentence: AST is the Vision Transformer (ViT/DeiT) applied directly to audio spectrogram patches, with ImageNet-pretrained weights transferred across the modality gap. It is convolution-free, it is conceptually simpler than the CNN stacks it replaced, and it won. Within the paper it set new records on AudioSet, ESC-50, and Speech Commands. Let us build it piece by piece, starting with the question that makes the whole thing possible: in what sense is a sound an image?
A raw waveform is a one-dimensional signal — a single number (air pressure) sampled tens of thousands of times per second. AST never touches the waveform directly. It first turns the sound into a picture: a spectrogram, a 2-D map where one axis is time, the other axis is frequency, and the brightness of each cell is how much energy that frequency carried at that moment.
Concretely, AST uses the same front end as a modern speech system. The audio is converted to a log-mel filterbank: a 25 ms analysis window slides forward every 10 ms (a 10 ms hop), and at each step the energy is collected into 128 mel-frequency bins. "Mel" means the frequency bins are spaced the way human hearing perceives pitch — fine resolution low down, coarse resolution up high. The result for a clip is a matrix of shape [frequency = 128, time = T].
How big is T? The hop is 10 ms, so one second of audio produces 100 time frames. AudioSet clips are about 10 seconds, giving roughly 1000 frames. AST's default input is therefore a [128 × 1024] matrix — 128 frequency bins by 1024 time frames. This is, for all the model cares, a 128×1024 single-channel grayscale image. The "pixels" happen to be acoustic energies instead of light intensities, but the data type — a 2-D grid of real numbers — is identical.
It is tempting to think of the spectrogram as just an image, but the two axes mean very different things, and this asymmetry matters later. The time axis is translation-equivariant in the way images are — a bark at second 2 and the same bark at second 7 look identical, just shifted. The frequency axis is not: shifting a sound up in frequency changes what it is (a low rumble is not a high whistle). So while AST treats the spectrogram as an image to reuse ViT machinery, the model must learn — through the data — that "shift along time = same event, shift along frequency = different event."
Top: a raw waveform — a 1-D signal of air pressure. Bottom: its log-mel spectrogram — a 2-D image of frequency (vertical) vs time (horizontal), brightness = energy. Drag the slider to add events at different times and frequencies and watch them appear as bright patches in the "image" AST will see.
Let us nail down the numbers, because every later tensor shape descends from them. Sample rate 16 kHz, hop 10 ms means 160 samples per hop, so a 10.24-second clip is 1024 hops → T = 1024 frames. The mel front end produces F = 128 bins. Input matrix: [128, 1024]. If instead you classify the short ESC-50 clips (5 s) you get T ~ 512; for Speech Commands (1 s) you get T ~ 128. AST simply changes T — the rest of the architecture is identical. That flexibility is the payoff of treating audio as an image: one architecture, many tasks, only the input grid resizes.
Here is the heart of the paper, and the mechanism you will implement in the Code Labs. A Transformer encoder consumes a sequence of vectors, not a 2-D image. So AST must turn the [128 × 1024] spectrogram into a sequence of token vectors. It does this exactly the way the Vision Transformer turns a photo into tokens: patchify, then linearly embed.
Slide a 16×16 window over the spectrogram and cut it into square patches. AST uses a patch size of 16×16 and — crucially — overlapping patches, with a stride of 6 in 6 in time, instead of the non-overlapping 16-stride of vanilla ViT. We will treat the non-overlapping case first because the arithmetic is cleaner, then explain why overlap helps.
With non-overlapping 16×16 patches over a [128 × 1024] spectrogram, the patch grid is (128/16) × (1024/16) = 8 × 64 = 512 patches. Each patch is a 16×16 = 256-number tile. So the image becomes a sequence of N = 512 tiles, each a 256-vector. The general formula for the count of patches along an axis of length L with patch size P and stride s is:
With overlap (stride 6), along time L=1024 gives nt = ⌊(1024−16)/6⌋+1 = 169, and along frequency L=128 gives nf = ⌊(128−16)/6⌋+1 = 19 (with the exact mel/time settings the paper reports about 12 frequency × 101 time = 1212 patches for the 10 s case). The exact count shifts with the front-end settings; what matters is the recipe: more overlap → more patches → finer coverage → better accuracy, at higher compute. Setting s = P recovers the non-overlapping ViT count.
Each patch is flattened from 16×16 to a 256-dimensional vector, then multiplied by a single learned weight matrix E to produce a d-dimensional token. AST uses d = 768 (the ViT-Base / DeiT width). So:
Stack all N patch tokens and you have the sequence the encoder wants: a matrix of shape [N, 768] (e.g. [512, 768] in the non-overlapping case). That is the entire "feature extractor" of AST. No convolution stack, no residual CNN blocks — one linear projection turns each spectrogram tile into a token. Vaswani's encoder does the rest.
Conv2d(1, 768, kernel=16, stride=16) — it is the same numbers. The point is that there is exactly one such layer and it never overlaps deep convolutional hierarchies; all the relational work happens in attention.Take a tiny 4×4 spectrogram and 2×2 non-overlapping patches (P=2, s=2). The grid is (4/2)×(4/2) = 2×2 = 4 patches. Patch 0 is the top-left 2×2 block; flattened in row-major order it is [a₀₀, a₀₁, a₁₀, a₁₁], a 4-vector. With an embedding matrix E of shape [4, d], token 0 is that 4-vector times E. Repeat for all four patches and you have a [4, d] token matrix. Scale this up — 16×16 patches, 256-vectors, [256, 768] embedding, ~512 patches — and you have exactly AST's input pipeline. Nothing more elaborate happens.
The spectrogram is sliced into a grid of patches. Each patch (a small tile of time×frequency) is flattened and linearly projected to a 768-vector token. Drag the slider to change patch size / stride and watch the patch count and token sequence length change — fewer, larger patches vs many, small overlapping patches.
python # AST patch embedding: spectrogram -> token sequence import torch import torch.nn as nn # Input: 1 clip, 1 channel, 128 mel bins, 1024 time frames spec = torch.randn(1, 1, 128, 1024) # [B, C, F, T] # Patch embedding = ONE strided conv. kernel 16, stride 16 -> non-overlap # (AST uses stride 6 for OVERLAP; 16 shown for clean arithmetic) patch_embed = nn.Conv2d(1, 768, kernel_size=16, stride=16) x = patch_embed(spec) # [1, 768, 8, 64] = 8x64 patch grid x = x.flatten(2) # [1, 768, 512] flatten the grid x = x.transpose(1, 2) # [1, 512, 768] N=512 tokens, d=768 # That's it. 512 tokens, each a 768-vector, ready for the encoder. print(x.shape) # torch.Size([1, 512, 768])
We now have a sequence of N patch tokens. Two things are missing before the encoder. First, attention is permutation-invariant — it has no idea that patch 5 sits to the right of patch 4 — so we must inject position. Second, the model needs a single fixed slot to read out the final classification, so AST prepends a learnable [CLS] token, exactly as BERT and ViT do.
AST prepends one extra learnable vector — call it xcls, shape [768] — to the front of the patch sequence. It corresponds to no patch; it is a blank slot the model fills in. As it passes through the encoder it attends to every patch token and accumulates a summary of the whole clip. After the final layer, AST reads only the [CLS] output and feeds it to the classifier. So the [CLS] token is a learnable "pooling query": instead of average-pooling the patch outputs, the model learns, through attention, how to aggregate them into one clip-level vector.
The sequence length becomes N+1 (one [CLS] plus N patches). With N=512 that is 513 tokens, each 768-dimensional: a [513, 768] matrix enters the encoder.
AST adds a learnable position embedding Epos to every token (including [CLS]). Here is the elegant part. AST does not train these from scratch — it inherits them from a ViT/DeiT model pretrained on ImageNet. But ImageNet ViT was trained on a 14×14 = 196-patch grid (one [CLS] + 196 = 197 positions), whereas AST's spectrogram patch grid is a different shape, e.g. 8×64. The position embeddings cannot be copied directly because the grids do not match.
AST's solution is a 2-D interpolation of the position embeddings. Reshape ViT's 196 position vectors back into a 14×14 grid of vectors, then bilinearly resize that grid to AST's target shape (e.g. 8×64), then flatten back to a sequence. Now every AST patch position gets a sensible starting embedding derived from the image-pretrained one, rather than a random vector. This single trick — cut-and-interpolate position embeddings across grid shapes — is what makes weight transfer from a square image model to a wide spectrogram model actually work.
Left: ViT's square position-embedding grid (pretrained on ImageNet). Right: AST's target grid — wider in time, shorter in frequency. The colors flow from the source grid to the target via 2-D bilinear interpolation. Drag the slider to change AST's target time length and watch the embeddings re-grid.
ImageNet ViT-Base: 197 position embeddings (1 [CLS] + 14×14 patches), each 768-dim. AST with an 8×64 patch grid: 513 position embeddings (1 [CLS] + 8×64). The [CLS] position is copied straight across; the 196 patch positions are reshaped to 14×14, bilinearly resized to 8×64 = 512, and flattened. Every number in the encoder weights — attention projections, FFN, layer norms — is copied directly; only the position embeddings need this re-gridding, because they are the only weights whose shape depends on the patch-grid geometry.
Everything after the patch+position step is a standard Transformer encoder — the very same one from "Attention Is All You Need," with no audio-specific modification. AST uses the ViT-Base / DeiT-Base configuration: 12 encoder layers, 12 attention heads, embedding dimension 768. Each layer is the familiar block: multi-head self-attention, then a position-wise feed-forward network, each wrapped with residual connections and layer normalization.
Trace the shapes. The input z0 is [513, 768] (1 CLS + 512 patches). Multi-head self-attention forms a [513, 513] attention matrix — every token, [CLS] included, attends to every other token — and the output stays [513, 768]. The FFN expands 768 → 3072 → 768. Twelve such layers, shape preserved, output z12 still [513, 768]. Because attention is global, the [CLS] token at layer 12 has — in principle through stacked layers, and directly through the [513,513] matrix at every layer — gathered information from every time-frequency patch in the clip. That global reach from layer one is the whole reason for dropping the CNN.
Take the [CLS] output vector z12[0], shape [768]. A single linear layer maps it to the label logits. AudioSet has 527 classes, so the head is a [768, 527] matrix. Critically, AudioSet is multi-label — a clip can be "dog" AND "speech" AND "music" at once — so AST does NOT use softmax. It applies an independent sigmoid to each of the 527 logits and trains with binary cross-entropy, treating each label as its own yes/no question:
For single-label tasks (ESC-50, Speech Commands) AST swaps the sigmoid/BCE head for a softmax + cross-entropy head. The encoder is untouched; only the final layer and loss change with the task.
Because AudioSet is multi-label and hugely imbalanced (most clips have a handful of the 527 labels), plain accuracy is meaningless — a model predicting "all negative" would score high. The metric is mAP, mean average precision: for each class, sort all clips by the model's score for that class, compute the area under the precision-recall curve, then average over the 527 classes. AST's headline result, ~0.485 mAP, is this number.
Step through AST end to end — spectrogram → patches → tokens → +CLS+pos → 12 encoder layers → CLS readout → sigmoid head. Click "Next" to advance and watch the tensor shape transform at each stage. The CLS token (warm) is the slot that becomes the prediction.
python import torch import torch.nn as nn class AST(nn.Module): def __init__(self, n_classes=527, d=768, depth=12, heads=12): super().__init__() self.patch = nn.Conv2d(1, d, kernel_size=16, stride=16) # patch embed self.cls = nn.Parameter(torch.zeros(1, 1, d)) # [CLS] token self.pos = nn.Parameter(torch.zeros(1, 513, d)) # 1 CLS + 512 patch layer = nn.TransformerEncoderLayer(d, heads, 3072, batch_first=True) self.enc = nn.TransformerEncoder(layer, depth) self.norm = nn.LayerNorm(d) self.head = nn.Linear(d, n_classes) # [768, 527] def forward(self, spec): # spec: [B, 1, 128, 1024] x = self.patch(spec) # [B, 768, 8, 64] x = x.flatten(2).transpose(1, 2) # [B, 512, 768] cls = self.cls.expand(x.size(0), -1, -1) x = torch.cat([cls, x], dim=1) # [B, 513, 768] prepend CLS x = x + self.pos # add position embeddings x = self.enc(x) # [B, 513, 768] 12 layers cls_out = self.norm(x[:, 0]) # read ONLY the CLS slot return self.head(cls_out) # [B, 527] logits -> sigmoid
A pure Transformer has very little built-in structure — no locality, no translation bias, nothing that says "nearby pixels are related." That is a strength (it can learn any relationship) and a weakness (it must learn everything from data, and so it is famously data-hungry). The original ViT needed enormous datasets (JFT-300M) to beat CNNs from scratch. AudioSet is large for audio but tiny next to that. Train AST from random initialization on AudioSet and it underperforms the CNNs it was meant to beat.
The paper's central practical contribution is the answer: do not train from scratch — transfer the weights of a Vision Transformer pretrained on ImageNet. Because AST's architecture is byte-for-byte a ViT (patch embed, [CLS], position embeddings, 12 encoder layers), nearly every parameter can be copied directly from an ImageNet-pretrained DeiT model. AST specifically uses DeiT (a ViT trained efficiently on ImageNet with distillation), which transfers better than vanilla ViT.
| Mismatch | ImageNet ViT | AST (audio) | Fix |
|---|---|---|---|
| Channels | 3 (RGB) | 1 (grayscale spec) | Average the 3 RGB patch-embedding kernels into 1 |
| Input size | 224×224 (square) | 128×1024 (wide) | Different patch grid; only position embeddings care |
| Patch grid | 14×14 = 196 | e.g. 8×64 = 512 | 2-D interpolate the 196 position embeddings to the new grid |
| Normalization | ImageNet RGB mean/std | Spectrogram mean/std | Re-normalize spectrogram input to roughly match the pretrained scale |
Channel fix in detail. ViT's patch embedding expects 3 channels; its kernel has shape [768, 3, 16, 16]. A spectrogram has 1 channel. AST averages the kernel across the RGB dimension: the new [768, 1, 16, 16] kernel is the mean of the three color kernels. Averaging (rather than picking one channel) preserves the expected output scale, so the downstream activations land in the range the pretrained encoder expects.
Position fix in detail. As shown in Chapter 3: reshape the 196 patch position embeddings into 14×14, bilinearly resize to the audio grid, flatten. The [CLS] position copies directly.
Everything else — all 12 layers of attention projections, the FFN weights, the layer norms, the [CLS] vector itself — is copied verbatim, then the whole model is fine-tuned end to end on the audio task. That is the recipe.
Two training curves on AudioSet: a randomly initialized AST (warm) plateaus far below; the ImageNet-pretrained AST (teal) starts higher and converges to a much better mAP. Drag the slider to change pretraining strength and watch the gap. This is the single most important ablation in the paper.
AST is evaluated on three benchmarks spanning the breadth of audio classification: AudioSet (the big multi-label event-tagging set), ESC-50 (environmental sounds, single label), and Speech Commands V2 (keyword spotting). The story is the same on all three: the convolution-free, image-pretrained Transformer sets a new state of the art.
On the full AudioSet, a single AST model reaches roughly 0.485 mAP, surpassing the previous best (PSLA, a CNN with attention pooling, around 0.474). Ensembling several AST models pushes it higher still (the paper reports roughly 0.485 single / ~0.459 on the balanced set and higher with ensembles). The exact decimals matter less than the qualitative result: a model with zero convolutions beats the carefully engineered CNN-plus-attention systems it replaced.
| Benchmark | Task | Metric | Prior best | AST |
|---|---|---|---|---|
| AudioSet (full) | 527-way multi-label tagging | mAP | ~0.474 (PSLA, CNN+attn) | ~0.485 (single model) |
| ESC-50 | 50-way environmental sounds | Accuracy | ~94.7% (CNN) | ~95.6% (AudioSet-pretrained) |
| Speech Commands V2 | 35-way keyword spotting | Accuracy | ~97.4% (CNN) | ~98.1% |
Notice the transfer chain in the ESC-50 row: best results come from a model pretrained on ImageNet, then on AudioSet, then fine-tuned on ESC-50. Each stage hands down structure to the next — image structure to audio-event structure to environmental-sound structure. The Transformer's lack of built-in bias, which forced it to need pretraining, turns out to make it an excellent vehicle for stacking transfers.
Why care about 0.474 → 0.485, a gain of ~0.011 mAP? Because on a saturated, fiercely contested benchmark like full AudioSet, a one-point mAP gain typically represents a substantial jump up the leaderboard — and AST achieves it while being simpler (one architecture, no convolutions, no hand-tuned pooling). The result is not "slightly better numbers"; it is "a simpler model that is also better," which is why the architecture was widely adopted.
Bars compare AST (teal) against the prior best CNN-based system (warm) on each benchmark, normalized so the differences are visible. Click a benchmark to switch. AST leads on every one — while using zero convolutions.
A result is only convincing if you know which ingredient produced it. AST's ablation study isolates each design choice. The findings are unusually clean and they tell you exactly how to reproduce the model — and where the easy points are.
Remove the cross-modal transfer and train AST from random initialization on AudioSet: the mAP drops sharply, below the CNN baselines. This is by far the largest ablation effect in the paper. The conclusion is blunt: for a convolution-free model on a dataset the size of AudioSet, pretraining is not a nice-to-have, it is the load-bearing wall.
AST uses overlapping patches (stride 6 in time and frequency rather than 16). Increasing overlap raises accuracy because each time-frequency location is covered by several patches, giving the model a finer, more redundant view — at the cost of more patches and thus more compute (the sequence length grows). The ablation shows a smooth accuracy-vs-overlap trade. Setting stride = patch size (no overlap) recovers vanilla ViT tokenization and is cheaper but slightly worse.
How you adapt the pretrained position embeddings matters. Reinitializing them from scratch (discarding the image prior) hurts. Naively reusing them without re-gridding fails because the grids do not match. The 2-D bilinear interpolation that respects the time×frequency layout is what works — confirming that the spatial structure in the pretrained position embeddings is genuinely useful for audio.
AST transfers best from DeiT (the distillation-trained ViT) rather than the original ViT, and the Base size is the sweet spot for AudioSet — large enough to absorb the pretraining, small enough not to overfit the audio data.
| Ablation | Variant | Effect on mAP | Takeaway |
|---|---|---|---|
| Pretraining | From scratch vs ImageNet | Large drop without it | Load-bearing — do not skip |
| Patch overlap | Stride 16 vs 6 | Overlap helps | Accuracy ⇄ compute knob |
| Position embed | Reinit vs 2-D interp | Interp clearly better | Preserve the image prior |
| Backbone | ViT vs DeiT | DeiT better | Distilled weights transfer better |
Start from the full AST and toggle each ingredient off to see the mAP fall. Pretraining is the cliff; overlap and position-interpolation are smaller but real. Click a toggle to remove that ingredient.
This is the payoff. Below is the full AST pipeline as one interactive instrument. You place sound events on a spectrogram; the explorer patchifies it, runs a (toy) attention pass where the [CLS] token attends to every patch, and shows you the resulting [CLS] attention map and the per-class scores. Move the controls and watch the [CLS] token concentrate its attention on the bright, event-bearing patches — which is exactly how the real AST builds a clip-level prediction.
Add events with the buttons (each drops a bright blob onto the spectrogram at a different time/frequency). The grid overlay shows the patch tokenization. The [CLS] attention heat shows how strongly the classification token attends to each patch — brighter = more weight. The bars on the right are the per-class scores the [CLS] readout produces. Use the temperature slider to sharpen or soften the attention.
Things to try. Add a single bark, low on the frequency axis: the [CLS] attention lights up on the low patches and the "Animal" score rises. Add a whistle high up: attention splits between the two regions and a second class activates. Crank the temperature down: attention sharpens to a near one-hot peak on the single brightest patch (the saturation regime). Increase the patch-grid density: more, smaller patches give finer attention localization — the same overlap-vs-resolution trade from the ablations, live.
AST proved a thesis: the convolution-free Vision Transformer recipe transfers to audio, and cross-modal pretraining makes it win. But the vanilla model has real limitations, and the field moved quickly to address them.
| Component | What it is | Shape / value |
|---|---|---|
| Input | Log-mel spectrogram (128 bins, 10 ms hop) | [128, ~1024] |
| Patchify | 16×16 tiles, overlapping (stride 6) | ~hundreds–1000+ patches |
| Patch embed | One linear / strided-conv projection | [256] → [768] per patch |
| [CLS] token | Learnable readout slot, prepended | +1 token, [768] |
| Position embed | ViT's, 2-D interpolated to audio grid | [N+1, 768] |
| Encoder | Standard Transformer, ViT-Base config | 12 layers, 12 heads, d=768 |
| Head | CLS readout → linear → sigmoid (BCE) | [768, 527] for AudioSet |
| Pretraining | DeiT (ImageNet) weights, cross-modal transfer | ~88M params |
| Result | AudioSet full | ~0.485 mAP |