Hoppa till innehållet
AI-grafen
E· Universitettransformerarkitektur· ca 60 min· utvecklande· verifierad 2026-09-20

Vision Transformer (ViT)

Kunna förklara patch-embeddings och träna en liten ViT.

Förkunskaper

Intuition

En transformer vill ha en sekvens av tokens. En bild är ett rutnät av pixlar. ViT:s lösning är nästan provocerande enkel:

  1. Klipp bilden i kvadratiska rutor — 16 × 16 pixlar är standard.
  2. Platta ut varje ruta till en vektor och kör den genom ett linjärt lager. Nu är varje ruta en «token».
  3. Lägg till en inlärd positionsembedding, eftersom transformern annars inte vet var rutorna satt.
  4. Lägg till en extra [CLS]-token som ska samla ihop helheten.
  5. Kör en helt vanlig transformer-encoder.
  6. Klassificera utifrån [CLS]-tokenen.

En 224 × 224-bild med 16 × 16-patchar blir 14 × 14 = 196 tokens. Det är en kort sekvens med språkmodellmått mätt.

Det överraskande resultatet: det fungerar bättre än CNN — men bara med tillräckligt mycket data.

Formellt

Induktiv bias är den centrala skillnaden.

Ett CNN har två antaganden inbyggda i arkitekturen: lokalitet (närliggande pixlar hör ihop) och translationsekvivarians (samma filter överallt). De antagandena är sanna om bilder, och de är gratis — nätet behöver inte lära sig dem.

En ViT har nästan inga antaganden. Attention kopplar vilken patch som helst till vilken annan som helst redan i första lagret. Det betyder att den måste lära sig att närliggande patchar hör ihop — vilket kräver data.

TräningsdataVinnare
~1 000 bilderCNN, med stor marginal
ImageNet-1k (1,3 M)jämnt, CNN något före utan tricks
ImageNet-21k (14 M)ViT
JFT-300MViT, tydligt

Slutsatsen är inte «ViT är bättre» utan att induktiv bias kan ersättas av data — och att det är en dålig affär när data är få. Med litet dataset: använd en förtränad ViT och finjustera, eller ta ett CNN.

Tricks som gör ViT hanterbar på små dataset:

TrickEffekt
Kraftig augmentering (RandAugment, Mixup, CutMix)störst enskild effekt
Distillation från ett CNN (DeiT)för in CNN:ets bias via läraren
Mindre patchar på små bilder (4 × 4 på CIFAR)fler tokens, mer lokal information
Uppvärmning av lärhastigheten + kraftig weight decayViT är känsligare än CNN

Beräkningskostnaden är kvadratisk i antalet patchar. Fördubblad upplösning ger fyra gånger fler patchar och sexton gånger dyrare attention — därav hierarkiska varianter som Swin, som gör attention lokalt i fönster.

Kod

import torch, torch.nn as nn

class PatchEmbed(nn.Module):
    """Patchning och projektion är samma sak som en faltning med stride = patchstorlek."""
    def __init__(self, bild=32, patch=4, kanaler=3, d=192):
        super().__init__()
        self.n = (bild // patch) ** 2
        self.proj = nn.Conv2d(kanaler, d, kernel_size=patch, stride=patch)

    def forward(self, x):
        return self.proj(x).flatten(2).transpose(1, 2)        # (B, n, d)

class ViT(nn.Module):
    def __init__(self, n_klasser=10, bild=32, patch=4, d=192, djup=6, huvuden=3):
        super().__init__()
        self.patch = PatchEmbed(bild, patch, 3, d)
        self.cls = nn.Parameter(torch.zeros(1, 1, d))
        self.pos = nn.Parameter(torch.randn(1, self.patch.n + 1, d) * 0.02)
        lager = nn.TransformerEncoderLayer(d, huvuden, d * 4, dropout=0.1,
                                           batch_first=True, norm_first=True,
                                           activation="gelu")
        self.enc = nn.TransformerEncoder(lager, djup)
        self.norm = nn.LayerNorm(d)
        self.huvud = nn.Linear(d, n_klasser)

    def forward(self, x):
        z = self.patch(x)
        z = torch.cat([self.cls.expand(z.size(0), -1, -1), z], dim=1) + self.pos
        return self.huvud(self.norm(self.enc(z))[:, 0])

m = ViT()
print(m(torch.randn(2, 3, 32, 32)).shape)                      # torch.Size([2, 10])
print(sum(p.numel() for p in m.parameters()) / 1e6, "M parametrar")   # ~2.7 M
print("tokens:", m.patch.n + 1)                                # 65

Två detaljer värda att lägga märke till:

  • nn.Conv2d med stride=patch ÄR patch-embeddingen. Att klippa ut rutor och projicera dem linjärt är exakt samma operation som en faltning utan överlapp. Det är effektivare och mindre kod.
  • norm_first=True (pre-LN). ViT tränar betydligt stabilare med normalisering före attention än efter — samma erfarenhet som i språkmodeller.

Utan kraftig augmentering kommer den här modellen att överanpassa CIFAR-10 inom några epoker. Det är inte ett fel i koden, utan poängen med avsnittet om induktiv bias.

Behärskning innebär

  • Förklarar hur en bild blir en tokensekvens
  • Jämför ViT och CNN i induktiv bias och datakrav
  • Tränar en liten ViT på ett litet dataset

Logga in för att göra övningarna och bygga upp din behärskning.

Källor

Alla källor och licenser