Tutorial sui Vision Transformer (ViT): architettura ed esempi di codice
Scopri come i Vision Transformer (ViT) sfruttano patch embedding e self-attention per superare le CNN nella classificazione moderna delle immagini. Questo tutorial approfondito scompone l’architettura ViT, fornisce codice Python passo-passo e mostra quando scegliere i ViT per progetti di computer vision reali.
Sappiamo tutti che i Transformer sono diventati fondamentali nell’elaborazione del linguaggio naturale e stanno ora prendendo piede anche nella computer vision. I Vision Transformer (ViT) offrono un approccio innovativo alla comprensione delle immagini usando gli stessi principi dei modelli basati su testo; Large Language Models.
I ViT sono stati introdotti per la prima volta nel 2020 da Google Research con il paper “An Image is Worth 16×16 Words”, mostrando che i transformer addestrati su grandi dataset di immagini possono eguagliare o superare le CNN. Da allora, varianti pratiche come DeiT e Swin ne hanno ampliato l’uso in molti task di visione.
In questo tutorial, ti guiderò tra i concetti chiave, i componenti dell’architettura e le applicazioni pratiche dei vision transformer (la variante vanilla/originale). Alla fine, capiremo non solo come funzionano i ViT, ma anche come implementarli nei nostri progetti di computer vision. Ti consiglio anche di dare un’occhiata alla mia guida su multi-head attention.
Che cos’è un Vision Transformer (ViT)?
Iniziamo con un’introduzione graduale ai vision transformer.
Questi modelli trattano un’immagine come una sequenza di dati, in modo simile a come un modello linguistico elabora le parole in una frase. L’immagine viene poi divisa in patch di dimensione fissa, ciascuna delle quali viene appiattita ed embedded in un vettore.
Questi vettori vengono quindi passati a un encoder transformer standard, che modella in modo globale le relazioni tra patch usando il meccanismo di attention.
Confronto con le convolutional neural network
Questo è fondamentalmente diverso dalle convolutional neural networks (CNN), che si concentrano su caratteristiche locali e si basano su un’estrazione gerarchica delle feature.
Visto che stiamo parlando di CNN, vediamo quali sono le differenze tra loro e i ViT:
Caratteristica
Convolutional Neural Networks (CNN)
Vision Transformer (ViT)
Architettura
Usa layer di Convolution + Pooling
Usa Transformer Encoder con Self-Attention
Campo recettivo
Locale, ma si espande con la profondità
Globale fin dall’inizio
Consapevolezza posizionale
Implicita tramite la struttura
Esplicita tramite positional encoding
Requisiti di dati
Abbastanza efficaci con dataset piccoli
Richiedono dataset su larga scala
Bias induttivo
Forte
Minimo ma più flessibile
Potenziale di parallelismo
Moderato
Molto elevato
Scalabilità del modello
Meno scalabili a modelli grandi
Altamente scalabili
Interpretabilità
Tramite i layer di pooling, ma comunque difficile
Può essere migliorata con la visualizzazione dell’attention, ma anch’essa piuttosto difficile
Ovviamente non abbiamo ancora coperto i vision transformer in ogni dettaglio, ma è utile rivedere alcuni punti che potrebbero non essere chiari fin da subito.
Per esempio, bias induttivo e campi recettivi sono termini importanti ma che potresti non aver sentito prima.
Spiegazione del bias induttivo
Il bias induttivo è l’insieme di assunzioni che un modello fa per aiutarlo a imparare dai dati. Può sembrare confuso, ma dovrebbe chiarirsi con questa analogia.
Immagina di fare insieme un puzzle. Possiamo pensare che i pezzi si incastrino in base a forma e colore. Questa assunzione ci aiuta a comporre il puzzle più velocemente. È così che funziona un modello CNN.
Fa supposizioni intelligenti assumendo che parti vicine in un’immagine siano correlate, proprio come i pezzi del puzzle vicini spesso appartengono alla stessa parte della figura. Assume anche che se spostiamo una forma, rimanga la stessa forma. Queste ipotesi utili sono chiamate forti bias induttivi.
Ora immagina di avere una grande pila di pezzi di puzzle, ma senza sapere come sia l’immagine finale. Non sappiamo nemmeno se guardare la forma o il colore o magari qualcos’altro. Quindi iniziamo a provare di tutto e lentamente capiamo cosa funziona.
Questo è ciò che fa un modello Transformer. Non fa assunzioni forti. Impara i pattern osservando una grande quantità di dati. Questo si chiama bias induttivo minimo. Dà al modello più libertà ma richiede più dati e più tempo per imparare.
Spiegazione del campo recettivo
L’immagine sopra mostra come cambia il campo recettivo di un modello CNN. Ricorda, in una CNN ci sono molteplici layer di convoluzione, quindi man mano che andiamo più in profondità nella rete, ciascun neurone del layer è influenzato da una regione progressivamente più ampia dell’input.
Questo campo recettivo in espansione permette ai layer più profondi di rilevare caratteristiche più complesse e globali, come mostrato nella figura sopra (dall’orecchio al muso fino all’intero cane).
Questo è piuttosto diverso dal campo recettivo di un Vision Transformer:
Nell’illustrazione sopra, possiamo vedere che il campo recettivo in un ViT (vanilla) è globale, quindi tutte le patch si “attendono” a vicenda con intensità diverse (mostrate dallo spessore delle frecce).
Per semplicità, ho mostrato che la patch (in verde) è attesa dalle altre patch, ma in realtà tutte le patch si attendono reciprocamente (sarebbe stato troppo caotico da disegnare!).
Quando usare CNN vs vision transformer
Capire quando usare una CNN rispetto a un vision transformer è importante per fare scelte architetturali efficaci nei nostri workflow di computer vision.
Entrambi i modelli hanno punti di forza (e debolezze!), ma rendono meglio in condizioni diverse a seconda di dimensione dei dati, risorse computazionali e complessità dei pattern visivi che stiamo cercando di modellare.
Io tendo a riferirmi a questi punti quando scelgo tra i due:
Dovresti usare le CNN quando:
Lavori con pochi dati - Abbiamo già detto che le CNN hanno forti bias induttivi come la località, che le aiutano a generalizzare bene anche con dataset piccoli. Questo le rende una scelta affidabile quando è impraticabile raccogliere grandi volumi di dati etichettati.
Le prestazioni real-time sono importanti - Le CNN tendono ad avere una latenza di inferenza più bassa e sono più efficienti dal punto di vista computazionale su hardware standard, specialmente su dispositivi mobile ed edge. La loro architettura è ottimizzata per prestazioni con meno parametri e minor uso di memoria.
Il budget computazionale è limitato - Addestrare una CNN da zero o fare fine-tuning di una pretrained richiede risorse significativamente inferiori rispetto ai ViT. Possiamo addestrare una buona CNN con una singola GPU e memoria moderata, cosa non sempre vera per i modelli basati su transformer.
Dovresti usare i Vision Transformer quando:
Hai accesso a grandi dataset etichettati e a un’infrastruttura di calcolo solida - Come detto nella tabella, i vision transformer sono avidi di dati e richiedono molto tempo di training e memoria, soprattutto nella loro forma vanilla. Con abbastanza dati e calcolo, possono superare le CNN in molti benchmark.
Serve catturare relazioni spaziali a lungo raggio - A differenza delle CNN, che elaborano localmente (ricorda la sezione sul campo recettivo), i ViT sfruttano la self-attention per modellare le relazioni tra tutte le patch dell’immagine, risultando particolarmente utili quando conta il contesto spaziale dell’intera immagine.
Vuoi usare modelli pretrained e transfer learning - Possiamo accedere a ViT pretrained (ad esempio tramite HuggingFace o timm) e quindi il fine-tuning diventa molto più pratico. In questo caso, anche dataset di medie dimensioni possono darci ottimi risultati senza addestrare da zero.
Quindi, riassumendo: se ti trovi in un contesto a basse risorse o hai bisogno di risultati rapidi e affidabili con pochi dati, le CNN sono la scelta più sicura ed efficiente.
D’altra parte, se il tuo progetto richiede ragionamento globale profondo sullo spazio visivo e hai la potenza di calcolo per sostenerlo, i vision transformer sono l’opzione migliore.
Componenti di un Vision Transformer
Passiamo ora all’architettura vera e propria del Vision Transformer. Dato che ci sono più fasi (cinque per la precisione), esploriamole una per una.
Fase 1: Suddivisione in patch
Questa è la prima trasformazione, in cui dobbiamo convertire un’immagine in una forma che il transformer possa comprendere.
Supponiamo di avere un’immagine 224x224. Invece di darle in pasto intera, la dividiamo in patch più piccole e di dimensione fissa. Se ogni patch è 16x16 (come proposto nel paper originale), allora l’immagine viene suddivisa in 14×14 = 196 patch, dato che (224/16 = 14).
Un modo semplice per capirlo è pensare di tagliare una fotografia in tessere quadrate perfettamente uguali. Ogni patch contiene informazioni localizzate e fungerà da “parola” in una frase.
Nell’illustrazione sopra, puoi vedere che l’immagine di un lupo viene suddivisa in patch quadrate (e uguali) più piccole — 196 per l’esattezza.
Potresti però avere una domanda qui:
“L’immagine è RGB, quindi che fine fanno i 3 canali di colore?”
Questo è un punto importante: ogni patch è in realtà un blocco di dati che, nel nostro caso, ha la forma 16x16x3. 16x16 sono altezza e larghezza, e 3 sono i canali di colore, il che rende ogni patch un tensore tridimensionale.
Questo rende ogni patch una rappresentazione compatta sia delle informazioni spaziali sia del colore provenienti da una regione locale dell’immagine.
Questa divisione in patch trasforma la struttura spaziale 2D dell’immagine in una sequenza 1D di dati multidimensionali, adatti a un modello transformer.
Fase 2: Patch embedding
Successivamente, dobbiamo trasformare ogni patch in una rappresentazione numerica che il transformer possa usare.
Ogni patch RGB 16x16 viene appiattita in un singolo vettore. Nel nostro esempio, 16×16×3 = 768 valori. In sostanza, “srotoliamo” tutti i pixel e i valori di colore in una singola riga di numeri.
Questi vettori grezzi, pur informativi, non sono ancora in uno spazio adatto all’apprendimento. Quindi li passiamo ciascuno attraverso un layer di proiezione lineare addestrabile. Pensalo come un layer denso che mappa ogni input di dimensione 768 in un nuovo spazio di embedding di dimensione D (spesso anch’esso 768, ma non sempre).
Perché?
Questa proiezione è importante perché allinea tutti i token di patch in un formato coerente e apprendibile che l’encoder del transformer si aspetta. Fino a questo punto, abbiamo avuto una sequenza di vettori a lunghezza fissa, in cui ogni vettore rappresenta una patch dell’immagine.
Questo processo trasforma patch ricche di informazione spaziale e cromatica in una sequenza unificata di “token” (analoga agli embedding delle parole in NLP), permettendo al transformer di trattare l’immagine come una serie strutturata di entità apprendibili.
Fase 3: Positional encoding
Manca una cosa prima di inviare questi token al nostro encoder. Potresti averla già indovinata se hai già studiato gli LLM!
I Transformer sono intrinsecamente agnostici alla posizione.
Ciò significa che trattano le sequenze di input come collezioni non ordinate, senza un meccanismo interno per comprendere l’ordine o la posizione dei token. Ed è un grosso problema nell’analisi di immagini, dove sia la struttura spaziale sia il layout sono cruciali!
Parliamone in dettaglio.
Nel contesto delle immagini, ogni patch rappresenta una regione specifica dell’immagine originale. Se forniamo al modello una sequenza di patch embedding senza indicare da dove provenga ciascuna patch, non ha modo di sapere se una patch arriva dall’angolo in alto a sinistra o dal basso a destra.
Questa mancanza di consapevolezza spaziale limiterebbe la capacità del modello di comprendere pattern, forme, strutture, ecc.
Per risolvere questo problema, aggiungiamo a ciascun patch embedding il cosiddetto positional encoding. Si tratta di un vettore che funge da “tag spaziale”; un vettore che codifica la posizione originale della patch all’interno dell’immagine. Questi vettori posizionali vengono sommati direttamente agli embedding delle patch prima che la sequenza entri nel transformer.
Esistono due tipi comuni di positional encoding:
Positional encoding fisso (sinusoidale): usa funzioni seno e coseno a frequenze diverse per codificare l’informazione posizionale. È deterministico e non richiede apprendimento. È anche ciò che è stato usato nel famoso paper “Attention is All You Need”.
Positional encoding appreso: sono parametri addestrabili che il modello apprende durante il training. Ogni posizione nella sequenza ha il proprio vettore apprendibile.
Se sei confuso a questo punto, un modo facile per afferrare il concetto è pensare ai positional encoding come a coordinate GPS per le patch.
Dicono al transformer la posizione originale del token. Includendo questa informazione, permettiamo al meccanismo di self-attention di modellare sia il contenuto di ciascuna patch sia la sua posizione relativa o assoluta nell’immagine.
Questo passaggio è cruciale: senza di esso, il Vision Transformer non riuscirebbe a ricostruire la struttura di un’immagine, per quanto potente sia il meccanismo di attention.
Fase 4: Blocco di Transformer encoder
Siamo arrivati al punto in cui avviene il deep learning — scoperta di pattern, modellazione del contesto e fusione delle feature.
Ci sono diversi di questi blocchi Encoder impilati uno sull’altro a comporre il Vision Transformer Encoder completo. Vediamo cosa contiene ciascun blocco encoder:
Multi-head self-attention (MHSA): questo meccanismo consente a ogni patch di interagire con tutte le altre patch. Aiuta il modello a determinare quali parti dell’immagine sono più rilevanti tra loro.
Invece di guardare una patch isolatamente, la MHSA le fornisce un contesto globale.
Più teste di attention osservano aspetti diversi delle relazioni, offrendo un’interpretazione più ricca dell’immagine.
Feedforward neural network (FFN): è un piccolo Multi-Layer Perceptron che elabora ciascun token indipendentemente dopo l’attention. Lo facciamo per migliorare la capacità del modello di apprendere pattern complessi e non lineari.
Connessioni residue e layer norm: stabilizzano l’addestramento e aiutano il flusso dei gradienti attraverso la rete.
Nel complesso, questi blocchi encoder sono impilati in layer (ad es., 12 nel ViT-Base), con cui a ogni layer si apprendono rappresentazioni dell’immagine più profonde.
Fase 5: Token di classificazione e MLP head
Ci siamo quasi! Passiamo ora all’ultima fase del ViT (vanilla).
Dopo tutti i layer dell’encoder, ci serve un modo per riassumere tutto e fare una previsione.
Introduciamo quindi uno speciale token [CLS] all’inizio della sequenza di patch. È un embedding apprendibile che interagisce con tutti gli altri token durante l’encoding.
Man mano che attraversa i layer del transformer, raccoglie informazioni globali. Alla fine, estraiamo questo token e lo passiamo attraverso un’altra testa MLP (multilayer perceptron), di solito un paio di layer densi seguiti da una softmax (per la classificazione).
Questo passaggio finale ci dà l’etichetta prevista, ad esempio “questa immagine è un cane”, in base alle informazioni raccolte dal token [CLS]. È importante notare che solo il token [CLS] viene inviato a questa MLP Head finale e quindi usato per la classificazione, non gli altri token!
Architetture di Vision Transformer degne di nota
Vediamo ora alcune architetture di Vision Transformer rivoluzionarie.
ViT (Google Brain) - il vision transformer originale (quello che abbiamo seguito in tutto l’articolo) che ha introdotto il modello a patch per la classificazione di immagini usando grandi dataset come ImageNet-21k.
DeiT (Data-Efficient Image Transformer) - introdotto da Facebook AI, migliora l’efficienza dei dati incorporando tecniche di knowledge distillation, permettendo l’addestramento su dataset più piccoli.
Swin Transformer - usa un’architettura gerarchica e finestre “shifted” per ridurre il computo mantenendo l’accuratezza. È particolarmente efficace in task di predizione densa come l’object detection.
Altre varianti - modelli come BEiT, CvT e MobileViT incorporano vari miglioramenti progettuali per aumentare l’efficienza di training, la compattezza del modello o la velocità di inferenza.
Uso di Vision Transformer pre-addestrati
Molto spesso non alleneremo un ViT da zero! Vediamo quindi come usare modelli ViT pre-addestrati dalle più note librerie di deep learning.
Libreria Hugging Face Transformers
Uno dei modi più semplici e affidabili per usare i vision transformer è tramite la libreria Hugging Face Transformers. Fornisce modelli ViT pretrained pronti all’uso con poche righe di codice.
Qui ho scritto un po’ di codice per scaricare e usare il modello ViT Base originale:
# Imports neededfrom transformers import ViTImageProcessor, ViTForImageClassificationfrom PIL import Imageimport torchimport requests# Here I am loading and preprocessing an image - but you can use any image of your choiceimage = Image.open(requests.get(https://huggingface.co/datasets/huggingface/cats-image?image-viewer=ED6CB286C90CF5F1FAF278077DF091477DF05416', stream=True).raw)# Here, we load and process the ViT modelprocessor = ViTImageProcessor.from_pretrained('google/vit-base-patch16-224')model = ViTForImageClassification.from_pretrained('google/vit-base-patch16-224')# Preprocessing the image so it gets it into the necessary formatinputs = processor(images=image, return_tensors='pt')# Forward pass - with no backpropagationwith torch.no_grad(): outputs = model(**inputs)# Here we get the predicted labels (since we are performing classification)logits = outputs.logits predicted_class = logits.argmax(-1) # Selects the index of the class with the highest logit score (highest predicted probability)print(f"Predicted class index: {predicted_class.item()}")Offerto da
Parliamo un po’ più in profondità di questo codice. Innanzitutto, potresti chiederti perché scaricare due componenti separati. Sono separati, ma complementari:
ViTImageProcessor – è responsabile della pre-elaborazione dell’immagine prima che venga passata al modello. Gestisce il ridimensionamento, la normalizzazione e la conversione dell’immagine nel formato atteso dal vision transformer. Il modo migliore per pensarci è come l’equivalente visivo di un tokenizer in NLP!
ViTForImageClassification – è il vero e proprio modello che esegue l’inferenza. Si aspetta input in uno specifico formato tensoriale e restituisce previsioni (ad es., logit o probabilità di classe).
Un altro dubbio che potresti avere riguarda output.logitse più specificamente cosa siano i logit.
Nei modelli di machine learning — specialmente nei modelli di classificazione — i logit sono i valori grezzi prodotti dallo strato finale prima di applicare qualsiasi funzione di attivazione come la softmax. Rappresentano punteggi non normalizzati per ciascuna classe.
Un buon modo per pensarci è come i livelli di confidenza interni del modello per ciascuna classe. Questi valori possono essere positivi o negativi e non sono vincolati a sommare a uno.
Per convertire i logit in probabilità, dobbiamo applicare la funzione softmax, che ridimensiona i valori in una distribuzione di probabilità.
Quindi, quando usiamo argmax(logits, -1), stiamo semplicemente selezionando l’indice (classe) con il punteggio grezzo più alto, che di solito equivale a quello con la probabilità più alta dopo la softmax.
Uso della libreria timm
Un’altra ottima e famosa libreria per usare i vision transformer è timm (di Ross Wightman). Offre anche un’ampia varietà di varianti ViT pretrained ed è ideale per sperimentazioni rapide o fine-tuning. Ecco come possiamo caricare e usare un modello ViT per l’inferenza:
# Relevant importsimport timmimport torchfrom torchvision import transformsfrom PIL import Imageimport requests# Loading an imageurl = 'https://huggingface.co/datasets/huggingface/cats-image?image-viewer=ED6CB286C90CF5F1FAF278077DF091477DF05416'image = Image.open(requests.get(url, stream=True).raw)# Here we have defined the transformation we are going to do on the imagetransform = transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])])image_tensor = transform(image).unsqueeze(0) # Adding batch dimension# Loading the ViT modelmodel = timm.create_model('vit_base_patch16_224', pretrained=True)model.eval() # Setting it to evaluation mode# Inference componentwith torch.no_grad(): outputs = model(image_tensor) predicted_class = outputs.argmax(dim=1) # Obtaining the class with the highest probabilityprint(f"Predicted class index: {predicted_class.item()}")Offerto da
Dovresti ora vedere la somiglianza tra timm e la libreria transformers. Entrambe forniscono modelli ViT pretrained, permettono l’elaborazione delle immagini (anche se in timm abbiamo usato codice PyTorch standard) e alla fine otteniamo la classe con il logit più alto.
Conclusione
In generale, i vision transformer hanno ridefinito la computer vision trasformando le immagini in “frasi” di patch e usando la self-attention per catturare il contesto globale fin dal primo layer. In questo tutorial, abbiamo visto:
Perché i ViT differiscono dalle CNN — bias induttivo minimo, campi recettivi globali, enorme scalabilità, ecc.
Quando scegliere ciascun modello — le CNN eccellono con pochi dati e budget di latenza ridotti, mentre i ViT rendono meglio quando abbiamo molti dati e hardware potente.
Architettura di base dei ViT — abbiamo coperto le diverse fasi, dal patching dell’immagine e positional encoding appresi alla multi-head self-attention, ai percorsi residui e al token [CLS] per la classificazione.
Implementazione pratica — come caricare modelli pretrained da librerie diverse (Hugging Face o timm), pre-elaborare le immagini ed estrarre le previsioni.
Se vuoi imparare entrambe le cose insieme mentre metti le mani in pasta, il nostro corso Transformer Models with PyTorch è il posto giusto.
Domande frequenti sui Vision Transformer
Perché i Vision Transformer tagliano le immagini in patch 16 × 16 invece di leggere i pixel grezzi?⌄
Il patching trasforma l’immagine 2D in una “frase” 1D di token, permettendo al transformer di applicare gli stessi trucchi di self-attention che alimentano i modelli linguistici.
I ViT hanno sempre bisogno di milioni di immagini per funzionare bene?⌄
Non sempre: possiamo partire da un ViT pretrained e fare fine-tuning. Per questo, di solito poche migliaia di immagini etichettate possono bastare per ottimi risultati.
Come fanno i ViT a “sapere” da dove proviene ciascuna patch?⌄
Aggiungono positional encoding a ogni token di patch, dando al modello un senso dell’ordine spaziale.
Quando dovrei scegliere ancora una CNN invece di un ViT?⌄
Dovremmo scegliere le CNN quando i dati sono scarsi o ci serve un’inferenza ultra-rapida e leggera in memoria su dispositivi edge.
Posso visualizzare su cosa si concentra un ViT?⌄
Sì, possiamo estrarre le attention map, scalarle e sovrapporle come heatmap per mostrare quali patch guidano la previsione.
Scopri i 15 migliori server MCP remoti che stanno trasformando lo sviluppo AI nel 2026. Scopri come migliorano automazione, ragionamento, sicurezza e velocità dei workflow.
Addestrare e mettere a punto i più recenti modelli di intelligenza artificiale per la produzione, compresi gli LLM come Llama 3. Inizia oggi il tuo percorso per diventare un ingegnere AI!
Sappiamo tutti che i Transformer sono diventati fondamentali nell’elaborazione del linguaggio naturale e stanno ora prendendo piede anche nella computer vision. I Vision Transformer (ViT) offrono un approccio innovativo alla comprensione delle immagini usando gli stessi principi dei modelli basati su testo; Large Language Models.
I ViT sono stati introdotti per la prima volta nel 2020 da Google Research con il paper “An Image is Worth 16×16 Words”, mostrando che i transformer addestrati su grandi dataset di immagini possono eguagliare o superare le CNN. Da allora, varianti pratiche come DeiT e Swin ne hanno ampliato l’uso in molti task di visione.
In questo tutorial, ti guiderò tra i concetti chiave, i componenti dell’architettura e le applicazioni pratiche dei vision transformer (la variante vanilla/originale). Alla fine, capiremo non solo come funzionano i ViT, ma anche come implementarli nei nostri progetti di computer vision. Ti consiglio anche di dare un’occhiata alla mia guida su multi-head attention.
Che cos’è un Vision Transformer (ViT)?
Iniziamo con un’introduzione graduale ai vision transformer.
Questi modelli trattano un’immagine come una sequenza di dati, in modo simile a come un modello linguistico elabora le parole in una frase. L’immagine viene poi divisa in patch di dimensione fissa, ciascuna delle quali viene appiattita ed embedded in un vettore.
Questi vettori vengono quindi passati a un encoder transformer standard, che modella in modo globale le relazioni tra patch usando il meccanismo di attention.
Confronto con le convolutional neural network
Questo è fondamentalmente diverso dalle convolutional neural networks (CNN), che si concentrano su caratteristiche locali e si basano su un’estrazione gerarchica delle feature.
Visto che stiamo parlando di CNN, vediamo quali sono le differenze tra loro e i ViT:
Caratteristica
Convolutional Neural Networks (CNN)
Vision Transformer (ViT)
Architettura
Usa layer di Convolution + Pooling
Usa Transformer Encoder con Self-Attention
Campo recettivo
Locale, ma si espande con la profondità
Globale fin dall’inizio
Consapevolezza posizionale
Implicita tramite la struttura
Esplicita tramite positional encoding
Requisiti di dati
Abbastanza efficaci con dataset piccoli
Richiedono dataset su larga scala
Bias induttivo
Forte
Minimo ma più flessibile
Potenziale di parallelismo
Moderato
Molto elevato
Scalabilità del modello
Meno scalabili a modelli grandi
Altamente scalabili
Interpretabilità
Tramite i layer di pooling, ma comunque difficile
Può essere migliorata con la visualizzazione dell’attention, ma anch’essa piuttosto difficile
Ovviamente non abbiamo ancora coperto i vision transformer in ogni dettaglio, ma è utile rivedere alcuni punti che potrebbero non essere chiari fin da subito.
Per esempio, bias induttivo e campi recettivi sono termini importanti ma che potresti non aver sentito prima.
Spiegazione del bias induttivo
Il bias induttivo è l’insieme di assunzioni che un modello fa per aiutarlo a imparare dai dati. Può sembrare confuso, ma dovrebbe chiarirsi con questa analogia.
Immagina di fare insieme un puzzle. Possiamo pensare che i pezzi si incastrino in base a forma e colore. Questa assunzione ci aiuta a comporre il puzzle più velocemente. È così che funziona un modello CNN.
Fa supposizioni intelligenti assumendo che parti vicine in un’immagine siano correlate, proprio come i pezzi del puzzle vicini spesso appartengono alla stessa parte della figura. Assume anche che se spostiamo una forma, rimanga la stessa forma. Queste ipotesi utili sono chiamate forti bias induttivi.
Ora immagina di avere una grande pila di pezzi di puzzle, ma senza sapere come sia l’immagine finale. Non sappiamo nemmeno se guardare la forma o il colore o magari qualcos’altro. Quindi iniziamo a provare di tutto e lentamente capiamo cosa funziona.
Questo è ciò che fa un modello Transformer. Non fa assunzioni forti. Impara i pattern osservando una grande quantità di dati. Questo si chiama bias induttivo minimo. Dà al modello più libertà ma richiede più dati e più tempo per imparare.
Spiegazione del campo recettivo
L’immagine sopra mostra come cambia il campo recettivo di un modello CNN. Ricorda, in una CNN ci sono molteplici layer di convoluzione, quindi man mano che andiamo più in profondità nella rete, ciascun neurone del layer è influenzato da una regione progressivamente più ampia dell’input.
Questo campo recettivo in espansione permette ai layer più profondi di rilevare caratteristiche più complesse e globali, come mostrato nella figura sopra (dall’orecchio al muso fino all’intero cane).
Questo è piuttosto diverso dal campo recettivo di un Vision Transformer:
Nell’illustrazione sopra, possiamo vedere che il campo recettivo in un ViT (vanilla) è globale, quindi tutte le patch si “attendono” a vicenda con intensità diverse (mostrate dallo spessore delle frecce).
Per semplicità, ho mostrato che la patch (in verde) è attesa dalle altre patch, ma in realtà tutte le patch si attendono reciprocamente (sarebbe stato troppo caotico da disegnare!).
Quando usare CNN vs vision transformer
Capire quando usare una CNN rispetto a un vision transformer è importante per fare scelte architetturali efficaci nei nostri workflow di computer vision.
Entrambi i modelli hanno punti di forza (e debolezze!), ma rendono meglio in condizioni diverse a seconda di dimensione dei dati, risorse computazionali e complessità dei pattern visivi che stiamo cercando di modellare.
Io tendo a riferirmi a questi punti quando scelgo tra i due:
Dovresti usare le CNN quando:
Dovresti usare i Vision Transformer quando:
Quindi, riassumendo: se ti trovi in un contesto a basse risorse o hai bisogno di risultati rapidi e affidabili con pochi dati, le CNN sono la scelta più sicura ed efficiente.
D’altra parte, se il tuo progetto richiede ragionamento globale profondo sullo spazio visivo e hai la potenza di calcolo per sostenerlo, i vision transformer sono l’opzione migliore.
Componenti di un Vision Transformer
Passiamo ora all’architettura vera e propria del Vision Transformer. Dato che ci sono più fasi (cinque per la precisione), esploriamole una per una.
Fase 1: Suddivisione in patch
Questa è la prima trasformazione, in cui dobbiamo convertire un’immagine in una forma che il transformer possa comprendere.
Supponiamo di avere un’immagine 224x224. Invece di darle in pasto intera, la dividiamo in patch più piccole e di dimensione fissa. Se ogni patch è 16x16 (come proposto nel paper originale), allora l’immagine viene suddivisa in 14×14 = 196 patch, dato che (224/16 = 14).
Un modo semplice per capirlo è pensare di tagliare una fotografia in tessere quadrate perfettamente uguali. Ogni patch contiene informazioni localizzate e fungerà da “parola” in una frase.
Nell’illustrazione sopra, puoi vedere che l’immagine di un lupo viene suddivisa in patch quadrate (e uguali) più piccole — 196 per l’esattezza.
Potresti però avere una domanda qui:
“L’immagine è RGB, quindi che fine fanno i 3 canali di colore?”
Questo è un punto importante: ogni patch è in realtà un blocco di dati che, nel nostro caso, ha la forma 16x16x3. 16x16 sono altezza e larghezza, e 3 sono i canali di colore, il che rende ogni patch un tensore tridimensionale.
Questo rende ogni patch una rappresentazione compatta sia delle informazioni spaziali sia del colore provenienti da una regione locale dell’immagine.
Questa divisione in patch trasforma la struttura spaziale 2D dell’immagine in una sequenza 1D di dati multidimensionali, adatti a un modello transformer.
Fase 2: Patch embedding
Successivamente, dobbiamo trasformare ogni patch in una rappresentazione numerica che il transformer possa usare.
Ogni patch RGB 16x16 viene appiattita in un singolo vettore. Nel nostro esempio, 16×16×3 = 768 valori. In sostanza, “srotoliamo” tutti i pixel e i valori di colore in una singola riga di numeri.
Questi vettori grezzi, pur informativi, non sono ancora in uno spazio adatto all’apprendimento. Quindi li passiamo ciascuno attraverso un layer di proiezione lineare addestrabile. Pensalo come un layer denso che mappa ogni input di dimensione 768 in un nuovo spazio di embedding di dimensione D (spesso anch’esso 768, ma non sempre).
Perché?
Questa proiezione è importante perché allinea tutti i token di patch in un formato coerente e apprendibile che l’encoder del transformer si aspetta. Fino a questo punto, abbiamo avuto una sequenza di vettori a lunghezza fissa, in cui ogni vettore rappresenta una patch dell’immagine.
Questo processo trasforma patch ricche di informazione spaziale e cromatica in una sequenza unificata di “token” (analoga agli embedding delle parole in NLP), permettendo al transformer di trattare l’immagine come una serie strutturata di entità apprendibili.
Fase 3: Positional encoding
Manca una cosa prima di inviare questi token al nostro encoder. Potresti averla già indovinata se hai già studiato gli LLM!
I Transformer sono intrinsecamente agnostici alla posizione.
Ciò significa che trattano le sequenze di input come collezioni non ordinate, senza un meccanismo interno per comprendere l’ordine o la posizione dei token. Ed è un grosso problema nell’analisi di immagini, dove sia la struttura spaziale sia il layout sono cruciali!
Parliamone in dettaglio.
Nel contesto delle immagini, ogni patch rappresenta una regione specifica dell’immagine originale. Se forniamo al modello una sequenza di patch embedding senza indicare da dove provenga ciascuna patch, non ha modo di sapere se una patch arriva dall’angolo in alto a sinistra o dal basso a destra.
Questa mancanza di consapevolezza spaziale limiterebbe la capacità del modello di comprendere pattern, forme, strutture, ecc.
Per risolvere questo problema, aggiungiamo a ciascun patch embedding il cosiddetto positional encoding. Si tratta di un vettore che funge da “tag spaziale”; un vettore che codifica la posizione originale della patch all’interno dell’immagine. Questi vettori posizionali vengono sommati direttamente agli embedding delle patch prima che la sequenza entri nel transformer.
Esistono due tipi comuni di positional encoding:
Se sei confuso a questo punto, un modo facile per afferrare il concetto è pensare ai positional encoding come a coordinate GPS per le patch.
Dicono al transformer la posizione originale del token. Includendo questa informazione, permettiamo al meccanismo di self-attention di modellare sia il contenuto di ciascuna patch sia la sua posizione relativa o assoluta nell’immagine.
Questo passaggio è cruciale: senza di esso, il Vision Transformer non riuscirebbe a ricostruire la struttura di un’immagine, per quanto potente sia il meccanismo di attention.
Fase 4: Blocco di Transformer encoder
Siamo arrivati al punto in cui avviene il deep learning — scoperta di pattern, modellazione del contesto e fusione delle feature.
Ci sono diversi di questi blocchi Encoder impilati uno sull’altro a comporre il Vision Transformer Encoder completo. Vediamo cosa contiene ciascun blocco encoder:
Nel complesso, questi blocchi encoder sono impilati in layer (ad es., 12 nel ViT-Base), con cui a ogni layer si apprendono rappresentazioni dell’immagine più profonde.
Fase 5: Token di classificazione e MLP head
Ci siamo quasi! Passiamo ora all’ultima fase del ViT (vanilla).
Dopo tutti i layer dell’encoder, ci serve un modo per riassumere tutto e fare una previsione.
Introduciamo quindi uno speciale token [CLS] all’inizio della sequenza di patch. È un embedding apprendibile che interagisce con tutti gli altri token durante l’encoding.
Man mano che attraversa i layer del transformer, raccoglie informazioni globali. Alla fine, estraiamo questo token e lo passiamo attraverso un’altra testa MLP (multilayer perceptron), di solito un paio di layer densi seguiti da una softmax (per la classificazione).
Questo passaggio finale ci dà l’etichetta prevista, ad esempio “questa immagine è un cane”, in base alle informazioni raccolte dal token [CLS]. È importante notare che solo il token [CLS] viene inviato a questa MLP Head finale e quindi usato per la classificazione, non gli altri token!
Architetture di Vision Transformer degne di nota
Vediamo ora alcune architetture di Vision Transformer rivoluzionarie.
Uso di Vision Transformer pre-addestrati
Molto spesso non alleneremo un ViT da zero! Vediamo quindi come usare modelli ViT pre-addestrati dalle più note librerie di deep learning.
Libreria Hugging Face Transformers
Uno dei modi più semplici e affidabili per usare i vision transformer è tramite la libreria Hugging Face Transformers. Fornisce modelli ViT pretrained pronti all’uso con poche righe di codice.
Qui ho scritto un po’ di codice per scaricare e usare il modello ViT Base originale:
Parliamo un po’ più in profondità di questo codice. Innanzitutto, potresti chiederti perché scaricare due componenti separati. Sono separati, ma complementari:
ViTImageProcessor– è responsabile della pre-elaborazione dell’immagine prima che venga passata al modello. Gestisce il ridimensionamento, la normalizzazione e la conversione dell’immagine nel formato atteso dal vision transformer. Il modo migliore per pensarci è come l’equivalente visivo di un tokenizer in NLP!ViTForImageClassification– è il vero e proprio modello che esegue l’inferenza. Si aspetta input in uno specifico formato tensoriale e restituisce previsioni (ad es., logit o probabilità di classe).Un altro dubbio che potresti avere riguarda
output.logitse più specificamente cosa siano i logit.Nei modelli di machine learning — specialmente nei modelli di classificazione — i logit sono i valori grezzi prodotti dallo strato finale prima di applicare qualsiasi funzione di attivazione come la softmax. Rappresentano punteggi non normalizzati per ciascuna classe.
Un buon modo per pensarci è come i livelli di confidenza interni del modello per ciascuna classe. Questi valori possono essere positivi o negativi e non sono vincolati a sommare a uno.
Per convertire i logit in probabilità, dobbiamo applicare la funzione softmax, che ridimensiona i valori in una distribuzione di probabilità.
Quindi, quando usiamo
argmax(logits, -1), stiamo semplicemente selezionando l’indice (classe) con il punteggio grezzo più alto, che di solito equivale a quello con la probabilità più alta dopo la softmax.Uso della libreria timm
Un’altra ottima e famosa libreria per usare i vision transformer è
timm(di Ross Wightman). Offre anche un’ampia varietà di varianti ViT pretrained ed è ideale per sperimentazioni rapide o fine-tuning. Ecco come possiamo caricare e usare un modello ViT per l’inferenza:Dovresti ora vedere la somiglianza tra
timme la libreriatransformers. Entrambe forniscono modelli ViT pretrained, permettono l’elaborazione delle immagini (anche se intimmabbiamo usato codice PyTorch standard) e alla fine otteniamo la classe con il logit più alto.Conclusione
In generale, i vision transformer hanno ridefinito la computer vision trasformando le immagini in “frasi” di patch e usando la self-attention per catturare il contesto globale fin dal primo layer. In questo tutorial, abbiamo visto:
Per continuare a imparare, ti consiglio questo articolo su Come funzionano i Transformer, che ti insegnerà la teoria dietro i Transformer. Per consolidare, poi, esplora come costruire un transformer da zero.
Se vuoi imparare entrambe le cose insieme mentre metti le mani in pasta, il nostro corso Transformer Models with PyTorch è il posto giusto.