Comprendere BERT: Rappresentazioni dell'Encoder Bidirezionale dai Transformer

Diagramma che mostra l'architettura del modello BERT e le sue rappresentazioni dell'encoder bidirezionale dai transformer

Nel 2018, i ricercatori di Google hanno pubblicato un articolo fondamentale intitolato “BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding” (Devlin et al.). Questa ricerca ha cambiato radicalmente il campo del Natural Language Processing (NLP). Prima di BERT, i modelli elaboravano il testo sequenzialmente da sinistra a destra o da destra a sinistra. BERT ha introdotto un metodo per addestrare rappresentazioni linguistiche che guardano contemporaneamente al contesto da entrambe le direzioni.

Oggi, BERT e i suoi discendenti (come RoBERTa, DistilBERT e ALBERT) rimangono fondamentali per i motori di ricerca, l’analisi del sentiment, i sistemi di risposta alle domande e l’estrazione di informazioni. Questo articolo demistifica l’architettura BERT, come funziona e come viene addestrata.


1. Cos’è BERT?

BERT è l’acronimo di Bidirectional Encoder Representations from Transformers. Analizziamo questo nome:

  • Bidirezionale (Bidirectional): A differenza dei modelli linguistici tradizionali che leggono il testo da sinistra a destra (come GPT) o da destra a sinistra, BERT legge l’intera sequenza di parole contemporaneamente. Ciò gli consente di apprendere il contesto di una parola in base a tutto ciò che la circonda (sia a sinistra che a destra).
  • Rappresentazioni dell’Encoder (Encoder Representations): BERT utilizza la parte Encoder dell’architettura Transformer originale. Prende una sequenza di input e restituisce una rappresentazione vettoriale densa (embedding) per ogni token.
  • Transformer (Transformers): Il motore sottostante è la rete di attenzione del Transformer, che consente la modellazione di dipendenze a lungo raggio e il calcolo parallelo.

Il potere della bidirezionalità

Nei modelli unidirezionali, un token può prestare attenzione solo ai token precedenti. Ad esempio, nella frase: "Ha deciso di depositare il suo denaro in banca."

Se un modello unidirezionale elabora la parola “banca”, guarda solo le parole precedenti. Ma per comprendere appieno il contesto, è fondamentale guardare sia il contesto sinistro che quello destro. Mentre le LSTM bidirezionali hanno tentato questo approccio addestrando modelli separati da sinistra a destra e da destra a sinistra e concatenando gli output, BERT addestra un singolo modello profondamente bidirezionale in modo congiunto in tutti i livelli.


2. Rappresentazione dell’input di BERT

Per consentire l’addestramento su più attività a valle, la rappresentazione dell’input di BERT può rappresentare sia una singola frase che una coppia di frasi (ad esempio, <Domanda, Risposta>) in una singola sequenza di token.

Per ogni dato token, la sua rappresentazione di input viene costruita sommando tre embedding:

  1. Token Embeddings: Il testo viene tokenizzato utilizzando il vocabolario WordPiece (circa 30.000 token). Vengono aggiunti token speciali:
    • [CLS]: Inserito all’inizio di ogni sequenza. Il suo stato nascosto finale viene utilizzato per compiti di classificazione.
    • [SEP]: Utilizzato per separare le frasi o alla fine di una sequenza.
  2. Segment Embeddings: Un embedding appreso che indica se un token appartiene alla frase A o alla frase B.
  3. Position Embeddings: Vettori posizionali appresi aggiunti per dare al modello consapevolezza della posizione del token nella sequenza (fino a 512 token).

$$\text{Rappresentazione dell’Input} = \text{Token Embeddings} + \text{Segment Embeddings} + \text{Position Embeddings}$$


3. Il processo di pre-addestramento

BERT viene pre-addestrato su un enorme corpus (Wikipedia e BooksCorpus) utilizzando contemporaneamente due attività non supervisionate: Masked Language Model (MLM) e Next Sentence Prediction (NSP).

Attività 1: Masked Language Model (MLM)

Nel modello linguistico standard, la previsione della parola successiva limita i modelli ad architetture da sinistra a destra per impedire alla parola target di “vedere” se stessa. Per addestrare una rappresentazione bidirezionale profonda, BERT maschera casualmente una percentuale di token di input e li predice.

In particolare:

  1. Il 15% dei token di input viene scelto casualmente.
  2. Di quei token scelti:
    • L’80% viene sostituito con il token [MASK].
    • Il 10% viene sostituito con una parola casuale.
    • Il 10% viene mantenuto invariato.

Questa ricetta impedisce al modello di concentrarsi solo sul token [MASK] durante il fine-tuning (poiché [MASK] non appare mai durante il fine-tuning) e lo costringe a creare vettori di rappresentazione per ogni parola nel contesto.

Attività 2: Next Sentence Prediction (NSP)

Molti compiti a valle (come Question Answering e Natural Language Inference) dipendono dalla comprensione della relazione tra due frasi. Per addestrare il modello sulle relazioni tra frasi, BERT viene pre-addestrato su un compito di classificazione binaria:

Quando si scelgono le frasi $A$ e $B$ per il pre-addestramento:

  • Il 50% delle volte, $B$ è l’effettiva frase successiva a $A$ (etichettata come IsNext).
  • Il 50% delle volte, $B$ è una frase casuale del corpus (etichettata come NotNext).

Il vettore nascosto finale del token [CLS] viene passato a un livello di classificazione per predire l’etichetta.


4. Fine-Tuning di BERT

Uno dei maggiori punti di forza di BERT è la sua flessibilità. Il pre-addestramento è costoso, ma il fine-tuning è incredibilmente economico e veloce. Sostituendo il livello di output finale, BERT può essere applicato a molti compiti a valle diversi:

  • Classificazione di una singola frase: (es. analisi del sentiment). Utilizzare l’output del token [CLS].
  • Classificazione di coppie di frasi: (es. inferenza del linguaggio naturale). Utilizzare l’output del token [CLS].
  • Risposta alle domande: (es. SQuAD). Predire i token di inizio e fine dell’intervallo nel documento.
  • Tagging di una singola frase: (es. Named Entity Recognition). Utilizzare la rappresentazione di output di ogni singolo token.

5. Implementazione Python/Hugging Face

Di seguito è riportato un semplice esempio in Python che mostra come caricare un modello BERT pre-addestrato ed estrarre embedding contestuali di parole utilizzando Hugging Face Transformers e PyTorch:

import torch
from transformers import BertTokenizer, BertModel

# 1. Inizializzare tokenizzatore e modello
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertModel.from_pretrained('bert-base-uncased')

# 2. Definire il testo contenente la parola "bank" in due contesti
text_1 = "He deposited money in the bank."
text_2 = "The river bank was muddy."

# 3. Tokenizzare gli input
inputs_1 = tokenizer(text_1, return_tensors="pt")
inputs_2 = tokenizer(text_2, return_tensors="pt")

# 4. Passaggio in avanti attraverso BERT
with torch.no_grad():
    outputs_1 = model(**inputs_1)
    outputs_2 = model(**inputs_2)

# 5. Estrarre gli embedding dei token
# shape di last_hidden_state: [batch_size, sequence_length, hidden_size]
embeddings_1 = outputs_1.last_hidden_state
embeddings_2 = outputs_2.last_hidden_state

# Ispezioniamo i token e i loro indici
tokens_1 = tokenizer.convert_ids_to_tokens(inputs_1["input_ids"][0])
tokens_2 = tokenizer.convert_ids_to_tokens(inputs_2["input_ids"][0])

# Trovare l'indice della parola 'bank'
bank_idx_1 = tokens_1.index("bank")
bank_idx_2 = tokens_2.index("bank")

# Ottenere i vettori di embedding per la parola 'bank'
bank_emb_1 = embeddings_1[0, bank_idx_1]
bank_emb_2 = embeddings_2[0, bank_idx_2]

# Calcolare la similarità del coseno
cosine_sim = torch.nn.functional.cosine_similarity(bank_emb_1, bank_emb_2, dim=0)

print("Tokens 1:", tokens_1)
print("Tokens 2:", tokens_2)
print(f"Similarità del coseno tra gli embedding contestuali di 'bank': {cosine_sim.item():.4f}")

6. Configurazioni del modello BERT

Google ha rilasciato due configurazioni principali di BERT:

Iperparametro BERT-Base BERT-Large
Numero di Livelli ($L$) 12 24
Dimensione Nascosta ($H$) 768 1024
Teste di Attenzione ($A$) 12 16
Parametri Totali 110 Milioni 340 Milioni

Conclusione

BERT ha dimostrato che le rappresentazioni bidirezionali profonde addestrate su grandi quantità di testo non etichettato possono catturare strutture sintattiche e semantiche complesse. Ha stabilito un nuovo paradigma per il transfer learning in NLP, definendo il flusso di lavoro di pre-addestramento e poi fine-tuning che ha dominato l’intelligenza artificiale fino all’ascesa dei modelli autoregressivi basati solo su decoder (come GPT).


Esplora altre prospettive tecnologiche sul Blog di Ghaznix →