Faza 04 · lecția 14
Transformere vizuale (ViT)
Scopul lecției: Decupați imaginea în patch-uri, tratați fiecare patch ca pe un cuvânt, rulați un Transformer standard. Nu priviți înapoi.
Versiunea curentă AlexBred.com: primele 100 de lecții ale programului în limba română.
Cuprinsul lecției
- Obiective de învățare
- Problema
- Conceptul
- Fluxul de procesare
- Încorporarea patch-urilor
- Tokenul de clasă
- Încorporarea pozițională
- Blocul de codificator Transformer
- De ce pre-LN
- Compromisul dimensiunii patch-ului
- Rețeta DeiT pentru antrenarea ViT pe ImageNet-1k
- Swin vs. ConvNeXt
- Preantrenarea MAE
- Construiți
- Pasul 1: Încorporarea patch-urilor
- Pasul 2: Blocul Transformer
- Pasul 3: ViT-ul
- Pasul 4: Verificare de plauzibilitate — inferența unei singure imagini
- Utilizați
- Livrați
- Exerciții
- Termeni-cheie
- Lecturi suplimentare
Decupați imaginea în patch-uri, tratați fiecare patch ca pe un cuvânt, rulați un Transformer standard. Nu priviți înapoi.
Tip: Construiți Limbaje: Python Cerințe prealabile: Faza 7 Lecția 02 (Autoatenție), Faza 4 Lecția 04 (Clasificarea imaginilor) Timp: ~45 de minute
Obiective de învățare
- Implementați de la zero încorporarea patch-urilor, încorporarea pozițională învățată, tokenul de clasă și blocurile de codificator Transformer pentru a construi un ViT minimal
- Explicați de ce s-a considerat că ViT are nevoie de date masive de preantrenare până când DeiT și MAE au demonstrat altfel
- Comparați ViT, Swin și ConvNeXt după părtinirile lor arhitecturale (niciuna, atenție locală pe ferestre, backbone convoluțional)
- Ajustați fin un ViT preantrenat pe un set de date mic cu
timmși rețeta standard linear-probe / fine-tune
Problema
Timp de un deceniu, convoluția a fost sinonimă cu viziunea computerizată. CNN-urile aveau părtiniri inductive puternice — localitate, echivarianță la translație — despre care nimeni nu credea că pot fi înlocuite. Apoi Dosovitskiy et al. (2020) au arătat că un Transformer simplu, aplicat patch-urilor de imagine aplatizate, fără niciun mecanism convoluțional, putea egala sau depăși cele mai bune CNN-uri la scară mare.
Problema era expresia „la scară mare”. ViT pe ImageNet-1k pierdea în fața ResNet. ViT preantrenat pe ImageNet-21k sau JFT-300M și apoi ajustat fin pe ImageNet-1k îl depășea. Concluzia era că Transformerele nu aveau părtiniri utile, însă le puteau învăța din suficiente date. Lucrările ulterioare (DeiT, MAE, DINO) au arătat că, prin rețetele de antrenare potrivite — augmentare puternică, preantrenare auto-supervizată, distilare — ViT-urile se antrenează bine și cu date puține.
Notă tehnică a traducerii: ViT-ul simplu nu are părtinirile convoluționale de localitate și echivarianță la translație, dar împărțirea regulată în patch-uri, proiecția partajată și codarea pozițională sunt tot alegeri structurale. Rezultatele ViT, DeiT și MAE sunt observații pentru datele și protocoalele lor de antrenare; nu demonstrează că toate părtinirile sunt învățate exclusiv din volum de date sau că orice set de date mic va produce același rezultat.
În 2026, CNN-urile pure rămân competitive pe dispozitive de margine (ConvNeXt este cel mai puternic), însă Transformerele domină în toate celelalte: segmentare (Mask2Former, SegFormer), detectare (DETR, RT-DETR), multimodal (CLIP, SigLIP), video (VideoMAE, VJEPA). Structura blocului ViT este cea care trebuie cunoscută.
Notă tehnică a traducerii: Nu există un câștigător universal pentru producție. Alegerea dintre CNN, ViT și un Transformer ierarhic depinde de sarcină, date, rezoluție, accelerator, precizie, latență, memorie, consum și constrângerile de implementare; afirmațiile despre un model „cel mai puternic” sau dominant trebuie citite ca instantanee dependente de benchmark, nu ca regulă generală.
Conceptul
Fluxul de procesare
Șapte pași. Patch-uri -> tokenuri -> atenție -> clasificator. Fiecare variantă (DeiT, Swin, ConvNeXt, preantrenarea MAE) modifică unul sau doi dintre cei șapte și lasă restul neschimbat.
Notă tehnică a traducerii: Aceasta este o schemă didactică, nu o clasificare arhitecturală completă. DeiT este în primul rând o rețetă de antrenare și de distilare pentru ViT; Swin este un Transformer ierarhic cu ferestre deplasate; ConvNeXt rămâne un CNN; iar MAE este un obiectiv de preantrenare cu codificator–decodor. Ele nu diferă doar prin una sau două substituții independente în același flux de procesare.
Încorporarea patch-urilor
Prima convoluție este secretul. Dimensiunea kernelului este 16, stride-ul este 16, astfel încât o imagine de 224x224 devine o grilă de 14x14 patch-uri de 16x16, fiecare proiectat într-o încorporare cu 768 de dimensiuni. Acea singură convoluție atât împarte în patch-uri, cât și proiectează liniar.
Intrare: (3, 224, 224)
Conv (3 -> 768, k=16, s=16, fără padding):
Ieșire: (768, 14, 14)
Aplatizare spațială: (196, 768)
196 de patch-uri = 196 de tokenuri. Dimensiunea caracteristicilor fiecărui token este 768 (ViT-B), 1024 (ViT-L) sau 1280 (ViT-H).
Tokenul de clasă
Un singur vector învățat, adăugat la începutul secvenței:
tokens = [CLS; patch_1; patch_2; ...; patch_196] formă (197, 768)
După N blocuri Transformer, ieșirea [CLS] este reprezentarea globală a imaginii. Capul de clasificare citește doar acest vector.
Încorporarea pozițională
Transformerele nu au o noțiune încorporată despre poziția spațială. Adăugați un vector învățat fiecărui token:
tokens = tokens + learned_pos_embedding (tot forma (197, 768))
Încorporarea este un parametru al modelului; antrenarea bazată pe gradient o adaptează la structura 2D a imaginii. Există alternative sinusoidale 2D, însă sunt rareori utilizate în practică.
Notă tehnică a traducerii: Încorporările poziționale absolute învățate sunt legate de lungimea secvenței sau de grila din preantrenare; o schimbare de rezoluție poate necesita adaptarea lor, de exemplu prin interpolare. Există și codări relative ale poziției, iar Swin folosește un bias de poziție relativă; de aceea nu este corect să se considere că o singură variantă pozițională acoperă practica curentă.
Blocul de codificator Transformer
Standard. Autoatenție multi-head, MLP, conexiuni reziduale, pre-LayerNorm.
x = x + MSA(LN(x))
x = x + MLP(LN(x))
MLP are două straturi cu GELU: Linear(d -> 4d) -> GELU -> Linear(4d -> d)
ViT-B/16 suprapune 12 dintre aceste blocuri, fiecare cu 12 capete de atenție, însumând 86M de parametri.
Notă tehnică a traducerii: „ViT-B/16” desemnează de regulă configurația Base cu patch-uri de 16 pixeli; aproximarea de 86M depinde de configurație și de capul de clasificare. Rezoluția 224 este o alegere frecventă de preantrenare, nu o proprietate intrinsecă a blocului; ea schimbă numărul de patch-uri și compatibilitatea încorporărilor poziționale.
De ce pre-LN
Transformerele timpurii foloseau post-LN (x = LN(x + sublayer(x))) și se antrenau greu dincolo de 6–8 straturi fără warmup. Pre-LN (x = x + sublayer(LN(x))) antrenează stabil rețele mai adânci fără warmup. Fiecare ViT și fiecare LLM modern folosește pre-LN.
Notă tehnică a traducerii: Pre-LN poate îmbunătăți comportamentul gradientului la inițializare și poate elimina necesitatea warmup-ului în anumite configurații studiate; stabilitatea depinde însă de arhitectură și de rețeta de antrenare. De asemenea, modelele moderne folosesc mai multe variante de normalizare, inclusiv RMSNorm, astfel încât afirmația despre o singură convenție universală este prea amplă.
Compromisul dimensiunii patch-ului
- Patch-uri 16x16 -> 196 de tokenuri, standard.
- Patch-uri 32x32 -> 49 de tokenuri, mai rapide, dar cu rezoluție mai mică.
- Patch-uri 8x8 -> 784 de tokenuri, mai fine, însă costul atenției O(n^2) crește nefavorabil.
Patch-uri mai mari = mai puține tokenuri = mai rapid, dar cu mai puține detalii spațiale. SwinV2 folosește patch-uri 4x4 în ferestre ierarhice.
Rețeta DeiT pentru antrenarea ViT pe ImageNet-1k
ViT-ul original avea nevoie de JFT-300M pentru a depăși CNN-urile. DeiT (Touvron et al., 2020) a antrenat ViT-B până la 81,8% top-1 numai pe ImageNet-1k cu patru schimbări:
- Augmentare intensă: RandAugment, Mixup, CutMix, Random Erasing.
- Adâncime stocastică (eliminarea aleatoare a unor blocuri întregi în timpul antrenării).
- Augmentare repetată (aceeași imagine este eșantionată de 3 ori per lot).
- Distilare de la un profesor CNN (opțională, crește în continuare acuratețea).
Fiecare rețetă modernă de antrenare ViT descinde din DeiT.
Notă tehnică a traducerii: Valoarea de 81,8% este legată de varianta DeiT, rezoluție, augmentări și protocolul de evaluare; lucrarea DeiT raportează mai multe rezultate, inclusiv rezultate diferite pentru distilare. Ea nu este o acuratețe garantată pentru orice ViT-B sau set de date. DeiT a influențat multe rețete, dar nu este originea exclusivă a tuturor tehnicilor moderne de antrenare ViT.
Swin vs. ConvNeXt
- Swin (Liu et al., 2021) — atenție bazată pe ferestre. Fiecare bloc acordă atenție într-o fereastră locală; blocurile alternative deplasează fereastra pentru a amesteca informația între ferestre. Readuce o părtinire de localitate asemănătoare CNN-urilor, păstrând operatorul de atenție.
- ConvNeXt (Liu et al., 2022) — CNN reproiectat care egalează alegerile arhitecturale ale Swin (convoluții depthwise, LayerNorm, GELU, bottleneck inversat). A arătat că diferența nu este „atenție versus convoluție”, ci „rețetă modernă de antrenare + arhitectură”.
În 2026, ConvNeXt-V2 și Swin-V2 sunt ambele pregătite pentru producție; alegerea corectă depinde de fluxul de inferență (ConvNeXt se compilează mai bine pentru margine) și de corpusul de preantrenare.
Notă tehnică a traducerii: Lucrarea Swin demonstrează eficiența atenției locale pe ferestre și a ierarhiei la sarcinile evaluate, iar lucrarea ConvNeXt compară o familie CNN modernizată cu Transformere în propriul protocol. Aceste rezultate nu justifică o regulă independentă de hardware că unul dintre ele se compilează sau rulează mai bine pe orice dispozitiv de margine.
Preantrenarea MAE
Masked Autoencoder (He et al., 2022): mascați aleatoriu 75% dintre patch-uri, antrenați codificatorul să proceseze numai 25% vizibile, antrenați un decodor mic să reconstruiască patch-urile mascate din ieșirea codificatorului. După preantrenare, eliminați decodorul și ajustați fin codificatorul.
MAE face ViT antrenabil numai pe ImageNet-1k, atinge SOTA și este rețeta auto-supervizată implicită actuală.
Notă tehnică a traducerii: În MAE, 75% este o proporție exemplificată de lucrare, nu definiția obligatorie a metodei. Codificatorul operează pe patch-urile vizibile, iar decodorul ușor reconstruiește imaginea din reprezentarea latentă și tokenurile de mască. Lucrarea raportează rezultate competitive în protocolul evaluat, însă nu există o rețetă implicită universală: alegerea metodei și performanța depind de arhitectură, date, obiectiv și protocolul de evaluare.
Construiți
Pasul 1: Încorporarea patch-urilor
import torch
import torch.nn as nn
class PatchEmbedding(nn.Module):
def __init__(self, in_channels=3, patch_size=16, dim=192, image_size=64):
super().__init__()
assert image_size % patch_size == 0
self.proj = nn.Conv2d(in_channels, dim, kernel_size=patch_size, stride=patch_size)
num_patches = (image_size // patch_size) ** 2
self.num_patches = num_patches
def forward(self, x):
x = self.proj(x)
return x.flatten(2).transpose(1, 2)
O convoluție, o aplatizare, o transpunere. Aceasta este întreaga etapă imagine-la-tokenuri.
Pasul 2: Blocul Transformer
Pre-LN, autoatenție multi-head, MLP cu GELU, conexiuni reziduale.
class Block(nn.Module):
def __init__(self, dim, num_heads, mlp_ratio=4, dropout=0.0):
super().__init__()
self.ln1 = nn.LayerNorm(dim)
self.attn = nn.MultiheadAttention(dim, num_heads, dropout=dropout, batch_first=True)
self.ln2 = nn.LayerNorm(dim)
self.mlp = nn.Sequential(
nn.Linear(dim, dim * mlp_ratio),
nn.GELU(),
nn.Dropout(dropout),
nn.Linear(dim * mlp_ratio, dim),
nn.Dropout(dropout),
)
def forward(self, x):
a, _ = self.attn(self.ln1(x), self.ln1(x), self.ln1(x), need_weights=False)
x = x + a
x = x + self.mlp(self.ln2(x))
return x
nn.MultiheadAttention gestionează împărțirea în capete, produsul scalar scalat și proiecția ieșirii. batch_first=True, deci formele sunt (N, seq, dim).
Notă tehnică a traducerii: Pentru intrări batched,
batch_first=Truestabilește forma(N, seq, dim); pentru o intrare neîmpachetată parametrul este ignorat. Cuneed_weights=False, apelul nu solicită ponderile atenției și poate folosi implementări optimizate; acest bloc este o implementare demonstrativă, nu o garanție că reproduce toate detaliile unui checkpoint ViT preantrenat.
Pasul 3: ViT-ul
class ViT(nn.Module):
def __init__(self, image_size=64, patch_size=16, in_channels=3,
num_classes=10, dim=192, depth=6, num_heads=3, mlp_ratio=4):
super().__init__()
self.patch = PatchEmbedding(in_channels, patch_size, dim, image_size)
num_patches = self.patch.num_patches
self.cls_token = nn.Parameter(torch.zeros(1, 1, dim))
self.pos_embed = nn.Parameter(torch.zeros(1, num_patches + 1, dim))
self.blocks = nn.ModuleList([
Block(dim, num_heads, mlp_ratio) for _ in range(depth)
])
self.ln = nn.LayerNorm(dim)
self.head = nn.Linear(dim, num_classes)
nn.init.trunc_normal_(self.pos_embed, std=0.02)
nn.init.trunc_normal_(self.cls_token, std=0.02)
def forward(self, x):
x = self.patch(x)
cls = self.cls_token.expand(x.size(0), -1, -1)
x = torch.cat([cls, x], dim=1)
x = x + self.pos_embed
for blk in self.blocks:
x = blk(x)
x = self.ln(x[:, 0])
return self.head(x)
vit = ViT(image_size=64, patch_size=16, num_classes=10, dim=192, depth=6, num_heads=3)
x = torch.randn(2, 3, 64, 64)
print(f"output: {vit(x).shape}")
print(f"params: {sum(p.numel() for p in vit.parameters()):,}")
Aproximativ 2,8M de parametri — un ViT mic, fezabil pe CPU. ViT-B real are 86M; aceeași definiție de clasă cu dim=768, depth=12, num_heads=12.
Pasul 4: Verificare de plauzibilitate — inferența unei singure imagini
logits = vit(torch.randn(1, 3, 64, 64))
print(f"logits: {logits}")
print(f"probs: {logits.softmax(-1)}")
Ar trebui să ruleze fără eroare. Probabilitățile însumează 1.
Utilizați
timm oferă fiecare variantă ViT cu ponderi preantrenate pe ImageNet. O singură linie:
import timm
model = timm.create_model("vit_base_patch16_224", pretrained=True, num_classes=10)
timm este opțiunea implicită pentru producție pentru Transformere vizuale în 2026. Oferă ViT, DeiT, Swin, Swin-V2, ConvNeXt, ConvNeXt-V2, MaxViT, MViT, EfficientFormer și zeci de altele prin același API.
Notă tehnică a traducerii: În API-ul documentat,
pretrained=Trueîncarcă ponderile ImageNet-1k asociate configurației disponibile. Argumentulnum_classes=10creează un cap de clasificare pentru cele 10 clase, care trebuie antrenat pentru sarcina nouă; disponibilitatea modelelor și checkpoint-urilor depinde de versiuneatimm, configurație și licență.
Pentru lucru multimodal (imagine + text), transformers oferă CLIP, SigLIP, BLIP-2, LLaVA. Codificatorul de imagine din toate acestea este o variantă ViT.
Notă tehnică a traducerii: Această generalizare este prea largă. CLIP este un model cu codificator de imagine și codificator de text, iar lucrarea originală studiază atât codificatoare vizuale ResNet, cât și ViT. Familiile BLIP-2, LLaVA și SigLIP au configurații și checkpoint-uri distincte; înainte de utilizare verificați modelul, procesorul de imagine și rezoluția cerută de checkpoint-ul ales.
Livrați
Această lecție produce:
outputs/prompt-vit-vs-cnn-picker.md— un prompt care alege între un ViT, un ConvNeXt sau un Swin pe baza dimensiunii setului de date, a calculului disponibil și a fluxului de inferență.outputs/skill-vit-patch-and-pos-embed-inspector.md— o aptitudine care verifică dacă formele încorporărilor patch și poziționale ale unui ViT se potrivesc cu lungimea de secvență așteptată de model, detectând cele mai frecvente erori de portare.
Exerciții
- (Ușor) Afișați formele fiecărui tensor intermediar pentru o trecere înainte prin ViT-ul mic de mai sus. Confirmați: intrare
(N, 3, 64, 64)-> patch-uri(N, 16, 192)-> cu CLS(N, 17, 192)-> intrarea clasificatorului(N, 192)-> ieșire(N, num_classes). - (Mediu) Ajustați fin un
timmViT-S/16 preantrenat pe setul de date synthetic-CIFAR din Lecția 4. Comparați cu ajustarea fină a ResNet-18 pe aceleași date. Raportați timpul de antrenare și acuratețea finală. - (Dificil) Implementați preantrenarea MAE pentru ViT-ul mic: mascați 75% dintre patch-uri, antrenați codificatorul + un decodor mic să reconstruiască patch-urile mascate. Evaluați acuratețea linear-probe pe datele sintetice înainte și după preantrenare.
Notă tehnică a traducerii: În mod uzual, linear probing îngheață codificatorul preantrenat și antrenează numai capul liniar, iar fine-tuning actualizează o parte sau toate ponderile. Pentru o comparație validă între ViT și ResNet, păstrați aceeași împărțire de date, preprocesare, augmentare, număr de epoci și buget de căutare a hiperparametrilor.
Termeni-cheie
| Termen | Cum este numit în practică | Ce înseamnă de fapt |
|---|---|---|
| Încorporare patch-uri | „Prima convoluție” | O convoluție cu dimensiunea kernelului = stride = dimensiunea patch-ului; transformă imaginea într-o grilă de încorporări de tokenuri |
| Token de clasă | „[CLS]” | Un vector învățat adăugat la începutul secvenței de tokenuri; ieșirea lui finală este reprezentarea globală a imaginii |
| Încorporare pozițională | „Poziție învățată” | Un vector învățat adăugat fiecărui token, astfel încât Transformerul să știe de unde provine fiecare patch |
| Pre-LN | „LayerNorm înainte de sub-strat” | Varianta stabilă de Transformer: x + sublayer(LN(x)) în loc de LN(x + sublayer(x)) |
| Atenție multi-head | „Atenție paralelă” | Atenție Transformer standard împărțită în subspații independente num_heads, concatenate ulterior |
| ViT-B/16 | „Base, patch 16” | Dimensiunea canonică: dim=768, depth=12, heads=12, patch_size=16, image=224; ~86M parametri |
| DeiT | „ViT eficient în date” | ViT antrenat numai pe ImageNet-1k cu augmentare puternică; a arătat că seturile masive de date pentru preantrenare nu sunt strict necesare |
| MAE | „Autoencoder mascat” | Preantrenare auto-supervizată: mascați 75% dintre patch-uri, reconstruiți; rețeta dominantă de preantrenare ViT |
Lecturi suplimentare
- An Image is Worth 16x16 Words (Dosovitskiy et al., 2020) — lucrarea ViT
- DeiT: Data-efficient Image Transformers (Touvron et al., 2020) — cum se antrenează ViT numai pe ImageNet-1k
- Masked Autoencoders are Scalable Vision Learners (He et al., 2022) — preantrenarea MAE
- Documentația timm — referința pentru fiecare Transformer vizual utilizat în producție
Sursă: Originalul în limba engleză
Navigare: ← Lecția 04.13 — Viziune 3D — nori de puncte și NeRF-uri · Faza 4 — Viziune computerizată · Catalog complet · Lecția 04.15 — Viziune în timp real — implementare la marginea rețelei →