# Come funzionano i Transformer?

<CourseFloatingBanner
    chapter={1}
    classNames="absolute z-10 right-0 top-0"
/>

In questa sezione, vedremo in maniera approfondita l'architettura dei modelli Transformer.

## Un po' di storia dei Transformer

Ecco alcuni punti di riferimento nella (breve) storia dei modelli Transformer:

<div class="flex justify-center">
<img class="block dark:hidden" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/transformers_chrono.svg" alt="A brief chronology of Transformers models.">
<img class="hidden dark:block" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/transformers_chrono-dark.svg" alt="A brief chronology of Transformers models.">
</div>

L'[architettura Transformer](https://arxiv.org/abs/1706.03762) è stata introdotta in giugno 2017. Il focus della ricerca di partenza era sui compiti di traduzione. A questa seguì l'introduzione di numerosi modelli influenti, tra cui figurano:

- **giugno 2018**: [GPT](https://cdn.openai.com/research-covers/language-unsupervised/language_understanding_paper.pdf), il primo modello Transformer pre-addestrato, viene usato per affinare diversi compiti di NLP e ottiene risultati all'avanguardia

- **ottobre 2018**: [BERT](https://arxiv.org/abs/1810.04805), un altro ampio modello pre-addestrato, questa volta progettato per produrre riassunti di frasi migliori (ne scopriremo di più nel prossimo capitolo!)

- **febbraio 2019**: [GPT-2](https://cdn.openai.com/better-language-models/language_models_are_unsupervised_multitask_learners.pdf), una versione (migliorata e ingrandita) di GPT che non fu distribuita immediatamente al pubblico a causa di preoccupazioni etiche

- **ottobre 2019**: [DistilBERT](https://arxiv.org/abs/1910.01108), una versione distillata di BERT che è il 60% più rapida e il 40% più leggera in memoria, pur conservando il 97% della performance di BERT

- **ottobre 2019**: [BART](https://arxiv.org/abs/1910.13461) e [T5](https://arxiv.org/abs/1910.10683), due grossi modelli pre-addestrati che utilizzano la stessa architettura del modello Transformer originale (nonché i primi a farlo)

- **maggio 2020**, [GPT-3](https://arxiv.org/abs/2005.14165), una versione ancora più ampia di GPT-2, con buone prestazioni in vari compiti e nessun bisogno di fine-tuning (il cosiddetto _zero-shot learning_)

La lista è tutto fuorché esaustiva ed è volta solo a mettere in evidenza alcuni dei diversi tipi di modelli Transformer. In genere, questi possono essere raggruppati in tre categorie:

- Modelli in stile GPT (detti anche modelli Transformer _auto-regressive_)
- Modelli in stile BERT (detti anche modelli Transformer _auto-encoding_) 
- Modelli in stile BART/T5 (detti anche modelli Transformer _sequence-to-sequence_)

Studieremo queste famiglie più nel dettaglio in seguito.

## I Transformer sono modelli linguistici

Tutti i modelli Transformer menzionati qui sopra (GPT, BERT, BART, T5, ecc.) sono stati addestrati come modelli linguistici (*language models*). Ciò significa che sono stati addestrati su grandi quantità di testo grezzo in stile auto-supervisionato (*self-supervising*). L'apprendimento auto-supervisionato è un tipo di apprendimento il cui obbiettivo viene computato direttamente dagli input del modello. Ciò significa che non è richiesto alcun intervento umano per etichettare i dati!

Un modello di questo tipo sviluppa una comprensione statistica della lingua alla quale è stato addestrato, ma non è molto utile in compiti pratici e precisi. Per questa ragione, il modello pre-addestrato generale viene in seguito sottoposto a un processo detto *transfer learning*. Durante questo processo, il modello viene affinato per un determinato compito in maniera supervisionata (ossia utilizzando etichette generate da umani).

Un esempio di compito è la previsione della parola seguente in una frase di cui sono state lette *n* parole precedenti. Quest'operazione si chiama *causal language modeling* perché il suo output dipende dagli input presenti e passati, ma non da quelli futuri.

<div class="flex justify-center">
<img class="block dark:hidden" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/causal_modeling.svg" alt="Example of causal language modeling in which the next word from a sentence is predicted.">
<img class="hidden dark:block" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/causal_modeling-dark.svg" alt="Example of causal language modeling in which the next word from a sentence is predicted.">
</div>

Un altro esempio è il *masked language modeling*, in cui il modello prevede una parola occultata della frase.

<div class="flex justify-center">
<img class="block dark:hidden" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/masked_modeling.svg" alt="Example of masked language modeling in which a masked word from a sentence is predicted.">
<img class="hidden dark:block" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/masked_modeling-dark.svg" alt="Example of masked language modeling in which a masked word from a sentence is predicted.">
</div>

## I Transformers sono modelli enormi

A parte per alcune eccezioni (come DistilBERT), la strategia generale per ottenere performance migliori consiste nell'aumentare la taglia dei modelli, nonché la quantità di dati utilizzati per il pre-addestramento.

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/model_parameters.png" alt="Number of parameters of recent Transformers models" width="90%">
</div>

Sfortunatamente, l'addestramento di un modello, e specialmente di un modello grosso, richiede grandi quantità di dati. Ciò si rivela molto costoso in termini di tempo, risorse informatiche e impatto ambientale, come mostrano i grafici qui sotto.

<div class="flex justify-center">
<img class="block dark:hidden" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/carbon_footprint.svg" alt="The carbon footprint of a large language model.">
<img class="hidden dark:block" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/carbon_footprint-dark.svg" alt="The carbon footprint of a large language model.">
</div>

<Youtube id="ftWlj4FBHTg"/>

Questi dati si riferiscono a un progetto per un modello (molto grande) condotto da un team che provava consciamente a ridurre l'impatto ambientale del pre-addestramento. L'impronta di trials volti a ottenere i miglior iperparamenti possibili sarebbe ancora più importante.

Immagina cosa succederebbe se ogni volta che un gruppo di ricerca, un'organizzazione studentesca o un'azienda vuole addestrare un modello lo facesse da zero! I costi globali sarebbero inutilmente enormi!

Questo è il motivo per cui la condivisione di modelli linguistici è fondamentale: lavorare a partire da modelli già addestrati riduce i costi informatici complessivi e l'impatto ambientale della comunità.


## Transfer Learning

<Youtube id="BqqfQnyjmgg" />

Il pre-addestramento è l'atto di addestrare un modello da zero: i pesi sono inizializzati in maniera casuale, e l'addestramento inizia senza alcuna conoscenza pregressa.

<div class="flex justify-center">
<img class="block dark:hidden" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/pretraining.svg" alt="The pretraining of a language model is costly in both time and money.">
<img class="hidden dark:block" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/pretraining-dark.svg" alt="The pretraining of a language model is costly in both time and money.">
</div>

Questo pre-addestramento è solitamente fatto su enormi quantità di dati. Di conseguenza, l'addestramento richiede un corpus di dati molto ampio e può prendere diverse settimane.

L'affinamento (*fine-tuning*), al contrario, è un addestramento che ha luogo **dopo** che il modello è stato pre-addestrato. Per poter effettuare un fine-tuning, è necessario acquisire un modello linguistico pre-addestrato e addestrarlo ulteriormente con una base dati adatta al compito in questione. Ma perché non addestrare direttamente al compito finale? Esistono alcune ragioni:

*  Il modello pre-addestrato è già addestrato su basi dati che contengono similarità con la base dati usata per il fine-tuning. Il processo di fine-tuning riesce quindi ad beneficiare della conoscenza acquisita dal modello iniziale durante il pre-addestramento (ad esempio, nei problemi di NLP, il modello pre-addestrato avrà già conoscenze statistiche della lingua utilizzata nel compito).
*  Siccome il modello pre-addestrato è stato addestrato usando moltissimi dati, il fine-tuning richiede molto meno dati per ottenere buoni risultati.
*  Per la stessa ragione, occorrono molto meno tempo e risorse per ottenere buoni risultati.

Ad esempio, è possibile approfittare di un modello pre-addestrato per la lingua inglese e poi affinarlo usando un corpus arXiv, ottenendo così un modello specifico per la scienza/ricerca. L'affinamento non richiederà che una quantità limitata di dati: le conoscenze acquisite dal modello pre-addestrato sono "trasferite", come riflette il nome *transfer learning*.

<div class="flex justify-center">
<img class="block dark:hidden" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/finetuning.svg" alt="The fine-tuning of a language model is cheaper than pretraining in both time and money.">
<img class="hidden dark:block" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/finetuning-dark.svg" alt="The fine-tuning of a language model is cheaper than pretraining in both time and money.">
</div>

Il fine-tuning di un modello ha quindi costi ridotti in termini di dati, finanze e impatto ambientale. Iterare su diversi schemi di fine-tuning è anche più rapido e semplice, in quanto l'addestramento è meno restrittivo di un pre-addestramento completo.

Questo processo permette anche di ottenere risultati migliori di un addestramento da zero (a meno di non essere in possesso di moltissimi dati), motivo per cui bisognerebbe sempre partire da un modello pre-addestrato (quanto possibile compatibile con il compito da eseguire) e affinarlo.

## Architettura generale

In questa sezione, vedremo l'architettura generale del modello Transformer. Non preoccuparti se non capisci tutti i concetti: più avanti, troverai sezioni dettagliate per ogni componente.

<Youtube id="H39Z_720T5s" />

## Introduzione

Il modello si compone principalmente di due blocchi:

* **Encoder (sinistra)**: L'encoder riceve un input e ne costruisce una rappresentazione, le features. Ciò significa che il modello è ottimizzato per la comprensione dell'input.
* **Decoder (destra)**: Il decoder utilizza la rappresentazione dell'encoder (le features) assieme ad ulteriori input per generare la sequenza target. Ciò significa che il modello è ottimizzato per la generazione di output.

<div class="flex justify-center">
<img class="block dark:hidden" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/transformers_blocks.svg" alt="Architecture of a Transformers models">
<img class="hidden dark:block" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/transformers_blocks-dark.svg" alt="Architecture of a Transformers models">
</div>

Ognuna di queste parti può essere utilizzata indipendentemente, in base al compito: 

* **Modelli Encoder-only**: Ottimi per compiti che richiedono una comprensione dell'input, come la classificazione frasale e il riconoscimento delle entità nominate.
* **Modelli Decoder-only**: Ottimi per compiti generativi come la generazione testuale.
* **Modelli Encoder-decoder** o **modelli sequence-to-sequence**: Ottimi per compiti generativi che richiedono un input, come la traduzione o il riassunto.

Analizzeremo ciascuna di queste architetture indipendentemente più tardi nel corso.

## Attention layers

Una caratteristica chiave dei modelli Transformer è che sono basati su strati speciali detti *attention layers*. Non a caso, il titolo del paper che introdusse l'architettura Transformer era ["Attention Is All You Need"](https://arxiv.org/abs/1706.03762)! Esploreremo gli attention layer nel dettaglio più avanti in questo corso; per ora, tutto ciò che hai bisogno di sapere è che un layer dirà al modello di prestare particolare attenzione a certe parole nella frase input (ignorando praticamente le altre) quando si occupa della rappresentazione delle singole parole.

Come esempio concreto, pensa ad un compito di traduzione testuale dall'inglese al francese. Dato l'input "You like this course", un modello di traduzione dovrà fare riferimento alla parola adiacente "You" per fornire la traduzione corretta della parola "like", perché in francese la coniugazione del verbo "like" cambia in base al soggetto. Diversamente, il resto della frase non è utile alla sua traduzione di quella precisa parola. In maniera simile, durante la traduzione di "this" il modello dovrà prestare attenzione alla parola "course", in quanto "this" ha traduzioni diverse se associato con nomi femminili o maschili. Di nuovo, il resto delle parole della frase non contribuiscono alla corretta traduzione di "this". Con frasi più complesse (e regole grammaticali più complesse), il modello potrebbe aver bisogno di prestare particolare attenzione a parole ben più lontane nella frase per tradurre correttamente ogni parola.

Lo stesso concetto si applica a qualsiasi compito che ha a che fare con il linguaggio naturale: una parola ha un senso a sé stante, ma tale senso è profondamente influenzato dal contesto, il quale è costituito da una qualsiasi parola (o parole) che precede o segue la parola sotto osservazione.

Ora che sai cosa sono gli attention layer, guardiamo un po' più nel dettaglio all'architettura Transformer.

## L'architettura originale

All'origine, l'architettura Transformer fu creata per la traduzione. In fase di addestramento, l'encoder riceve degli input (frasi) in una certa lingua, mentre il decoder riceve le stesse frasi nella lingua target d'elezione. Nell'encoder, gli attention layer sono in grado di utilizzare qualsiasi parola in una data frase (dato che, come abbiamo appena visto, la traduzione di una determinata parola può dipendere da ciò che la precede o segue nella frase). Diversamente, decoder procede in maniera sequenziale ed è capace di prestare attenzione solo alle parole della frase che ha già tradotto (ossia, solo le parole che precedono la parola che sta generando). Ad esempio, una volta predette le prime tre parole della frase target, le passiamo al decoder  che utilizza tutti gli input dell'encoder per provare a predirre la quarta parola.

Per accelerare il processo di addestramento (quando il modello ha accesso alle frasi target), l'intero target viene fornito al decoder, che però non è in grado di accedere alle parole future (se avesse accesso alla parola in seconda posizione mentre cerca di predirre la parola in seconda posizione, il problema cesserebbe di essere complesso). Ad esempio, mentre prova a predirre la quarta parola, l'attention layer avrà accesso solo alle posizioni tra la prima e la terza.

L'architettura Transformer originale aveva la struttura qui sotto, con l'encoder a sinistra e il decoder a destra:

<div class="flex justify-center">
<img class="block dark:hidden" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/transformers.svg" alt="Architecture of a Transformers models">
<img class="hidden dark:block" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/transformers-dark.svg" alt="Architecture of a Transformers models">
</div>

Nota che il primo attention layer in un *decoder block* presta attenzione a tutti gli input (passati) al decoder, mentre il secondo attention layer utilizza l'output del encoder. Gli è perciò possibile avere accesso a tutta la frase input per meglio prevedere la parola corrente. Questa caratteristica è molto utile in quanto lingue diverse possono avere regole grammaticali diverse piazzano le parole in ordini diversi, oppure perché il contesto che compare più tardi nella frase potrebbe essere utile nella determinazione della migliore traduzione di una data parola.

L'*attention mask* può essere utilizzato anche nell'encoder/decoder per evitare che il modello presti attenzione a certe parole speciali, come ad esempio parole riempitive utilizzate per rendere tutti gli input della stessa lunghezza.

##  Architetture vs. checkpoint

Durante questo viaggio nel mondo dei modelli Transformer, incontrerai menzioni di *architetture* e *checkpoint*, nonché di *modelli*. Questi termini hanno significati leggermente diversi: 

* **Architettura**: Lo scheletro del modello, ossia la definizione di ogni livello e operazione che compare nel modello. 
* **Checkpoint**: I pesi che verranno caricati in una determinata architettura.
* **Modello**: Un termine generico meno preciso di "architettura" o "checkpoint", in quanto può significare entrambi. In questo corso faremo la distinzione tra *architettura* e *checkpoint* quando sarà necessario ridurre le ambiguità.

Ad esempio, BERT è un'architettura, mentre `bert-base-cased`, un set di pesi (*weights*) addestrati dal team di Google per la prima versione di BERT, è un checkpoint. Ciononostante, è possibile dire "il modello BERT" e "il modello `bert-base-cased`."
