Positional encoding: conta l’ordine delle parole

Come fanno i Transformer a sapere in che ordine arrivano le parole? Il positional encoding è la risposta, e spiega anche perché la context window ha dei limiti.
Immagine realizzata con IA
Le immagini presenti nel post possono essere realizzate o elaborate con strumenti di Intelligenza Artificiale. Questa scelta nasce anche dalla necessità di prevenire le continue contestazioni e richieste economiche improprie che ricevo relative a fotografie utilizzate che sono sempre state acquistate con regolare licenza.
Contenuti dell'articolo

Prendi la frase “il cane morde l’uomo” e girala come un calzino: “l’uomo morde il cane”. Le parole sono identiche, l’ordine no: il significato cambia completamente. Per un essere umano è ovvio. Per un Transformer, almeno in teoria, non lo è affatto.

Il motivo sta nel cuore dell’architettura. Il meccanismo di attenzione guarda le parole a coppie e calcola quanto ciascuna deve pesare sulle altre. Lo fa con somme e prodotti, operazioni che non si accorgono di chi viene prima e chi viene dopo.

Il positional encoding esiste per risolvere esattamente questo problema: dare a ogni token un’informazione sulla sua posizione, senza rinunciare alla parallelizzazione che ha reso i Transformer così veloci. È un dettaglio tecnico che sembra marginale e invece decide se un modello capisce “non ho detto che lui ha ragione” oppure “ho detto che lui non ha ragione”.

L’attenzione da sola è cieca all’ordine

La self-attention funziona così: ogni token produce una query, una chiave e un valore. Le query si confrontano con le chiavi di tutti gli altri token, si ottengono dei pesi e si combinano i valori. Il risultato per ogni posizione è una media pesata dei valori presenti nella sequenza.

Se permuti le parole, i pesi si permutano allo stesso modo e il risultato si permuta con loro. La sostanza non cambia. In gergo si dice che l’attenzione è permutation invariant: non distingue “cane morde uomo” da “uomo morde cane”.

Per un modello che deve generare testo, tradurre o rispondere a domande, è un problema serio. La grammatica vive di ordine. L’italiano distingue “lo chiama” da “chiamalo”, l’inglese distingue “the dog bit the man” da “the man bit the dog”. Senza posizione, il modello vedrebbe un sacchetto di parole.

Qualcuno potrebbe obiettare che l’ordine è già dentro gli embedding. Non è così: gli embedding rappresentano il significato di una parola, non il posto che occupa nella frase. La parola “cane” ha lo stesso vettore sia come soggetto sia come oggetto.

Tip. Un modo veloce per capire se un’architettura ha bisogno di positional encoding: chiediti se mescolando l’input l’output cambia. Se la risposta è no, manca l’informazione posizionale. Le reti ricorrenti non ne avevano bisogno perché leggevano un token alla volta, in sequenza. I Transformer hanno rinunciato alla sequenza per guadagnare parallelismo, quindi hanno dovuto reintrodurre l’ordine per altre vie.

Un esempio concreto, senza matematica

Immagina tre token con embedding bidimensionali: “gatto” = (1, 0), “mangia” = (0, 1), “pesce” = (1, 1). Se sommi i tre vettori ottieni (2, 2), qualunque sia l’ordine. La somma è commutativa, quindi il modello non ha modo di sapere chi è arrivato primo.

Ora aggiungi a ciascun token un vettore di posizione diverso: p1 per il primo, p2 per il secondo, p3 per il terzo. La somma diventa (1, 0) + p1 + (0, 1) + p2 + (1, 1) + p3. Il totale ora dipende da quale vettore di posizione è abbinato a quale parola. Cambiando l’ordine, cambia il risultato.

Questo è tutto il trucco: non si cambia l’architettura, si arricchisce l’input. Il positional encoding è un vettore della stessa dimensione dell’embedding, che si somma al token prima che entri nei blocchi di attenzione. Da quel momento in poi il modello può imparare a distinguere la posizione usando le normali trasformazioni che già conosce.

La somma invece della concatenazione è una scelta pratica: mantenere la dimensione fissa semplifica tutto il resto della rete. Il costo è che l’informazione posizionale e quella semantica finiscono nello stesso spazio, mescolate. Funziona lo stesso, perché la rete impara a separarle.

La formula classica: seni e coseni

La versione originale, quella del paper “Attention Is All You Need” del 2017, usa una funzione deterministica. Per ogni posizione e per ogni dimensione del vettore si calcola un seno o un coseno con frequenze diverse.

Le dimensioni pari usano il seno, quelle dispari il coseno. La frequenza cambia lungo il vettore: le prime dimensioni oscillano in fretta, le ultime oscillano lentissime, quasi come un contatore che si muove a malapena. Il risultato è una sorta di codice a barre continuo, diverso per ogni posizione.

  • Nessun parametro da addestrare: la formula è fissa, quindi non consuma memoria né si può “dimenticare” durante il training.
  • Valori sempre tra -1 e 1: nessuna esplosione numerica, nessuna normalizzazione da inventare.
  • Generalizzazione alle sequenze più lunghe: la formula si può calcolare per una posizione 500 anche se in training il modello non l’ha mai vista.
Schema del positional encoding: cinque token, ognuno con il proprio vettore di posizione e il contributo che si somma all'embedding

C’è un dettaglio elegante che spesso sfugge. Poiché seno e coseno si combinano con le formule di addizione, la rappresentazione di una posizione relativa si può ottenere con una semplice rotazione applicata al vettore. In pratica il modello può imparare a ragionare in termini di “tre token prima” e non solo di “posizione assoluta 47”.

Perché seno e coseno funzionano bene

La prima ragione è la regolarità. Due posizioni vicine producono vettori simili, due posizioni lontane producono vettori diversi. Il modello può così distinguere il vicinato dalla distanza lunga senza dover memorizzare una tabella.

La seconda è la multiscala. Le frequenze alte codificano differenze fini, quelle basse codificano la posizione globale. È lo stesso principio delle lancette di un orologio: la lancetta dei secondi dice il dettaglio, quella delle ore dice il contesto. Insieme danno un’informazione completa.

La terza è la compatibilità con l’attenzione. I prodotti scalari tra query e chiavi possono sfruttare le differenze tra i vettori posizionali, quindi il modello può imparare a dare più peso ai token vicini oppure a quelli a distanza fissa, a seconda di cosa serve.

Non è tutto oro. Il positional encoding sinusoidale non dice al modello quanto è lunga la frase, non segnala la fine di un periodo e non ha idea di cosa sia un paragrafo. È un’informazione di posizione pura. Il resto lo devono fare gli altri componenti.

Positional embedding imparati: la svolta di BERT e GPT

Con BERT e GPT-2 arriva una variante più semplice: invece di calcolare la posizione con una formula, si crea una tabella con una riga per ogni posizione possibile e si lascia che sia il training a riempirla. È lo stesso meccanismo degli embedding delle parole, applicato alle posizioni.

Il vantaggio è l’adattabilità. Il modello può decidere che certe posizioni hanno un ruolo speciale, per esempio la prima, dove spesso compare il soggetto, o le ultime, dove di solito si chiude il ragionamento. Lo svantaggio è il limite fisso: la tabella ha un numero massimo di righe.

GPT-2 si fermava a 1024 posizioni, BERT a 512. Superata quella soglia non c’è riga da leggere e il modello non sa cosa fare. Non è un caso che per anni la “memoria” dei modelli sia stata descritta in token: era un vincolo architetturale, non una scelta di marketing.

Questi vettori sono anche difficili da estendere. Se allunghi la tabella e inizializzi le nuove righe a caso, il modello va in crisi, perché non ha mai imparato a interpretarle. Serve un fine tuning, che spesso non basta.

RoPE: la posizione diventa una rotazione

La soluzione diventata standard nei modelli più recenti si chiama Rotary Position Embedding, abbreviata RoPE. L’idea è diversa: non si somma nulla all’embedding, si ruotano le componenti della query e della chiave di un angolo proporzionale alla posizione.

Ruotare due vettori non cambia la loro lunghezza, cambia solo l’orientamento. E il prodotto scalare tra due vettori ruotati dipende dall’angolo tra loro, cioè dalla differenza di posizione. In questo modo l’attenzione diventa sensibile alla distanza relativa in modo naturale.

Il vantaggio pratico è enorme: il modello può gestire sequenze più lunghe di quelle viste in training con un degrado graduale invece di un crollo. Non è magia, è geometria. La posizione non è un’etichetta appiccicata al token, è una relazione tra token.

RoPE è usato da buona parte dei modelli open weight moderni, da LLaMA a Qwen passando per molte varianti. Le tecniche di scaling, come l’aumento della base delle frequenze, servono proprio a stirare la rotazione su contesti più lunghi senza rovinare quanto appreso.

ALiBi e le alternative leggere

ALiBi prende una strada ancora più diretta: non modifica gli embedding, aggiunge un bias ai punteggi di attenzione. Più due token sono distanti, più il bias è negativo. Il modello parte quindi con una preferenza per i vicini. Poi impara a ignorarla quando serve.

È un metodo economico, senza parametri aggiuntivi. Funziona bene per l’estrapolazione: addestrato su sequenze corte, regge anche su sequenze più lunghe. Modelli come BLOOM e MPT lo hanno usato con risultati rispettabili.

Esistono anche versioni ibride e varianti come le posizioni relative di T5, che imparano un bias per ogni distanza entro un certo raggio. Il panorama è frammentato, ma il principio comune è sempre lo stesso: dire al meccanismo di attenzione chi sta dove, con il minor costo possibile.

Tip. Se leggi un paper e trovi “NoPE”, non è un refuso. È un esperimento in cui il positional encoding viene tolto del tutto e la posizione emerge comunque, grazie alla maschera causale dei modelli autoregressivi. Funziona su certi compiti, ma non è ancora lo standard.

Cosa cambia per chi usa i modelli

Il positional encoding spiega molte cose che si notano usando ChatGPT o Claude tutti i giorni. La prima è la context window: il numero massimo di token che il modello può vedere in una volta. Non è solo una questione di memoria, è anche una questione di come la posizione viene codificata.

La seconda è il fenomeno noto come “lost in the middle”: le informazioni messe al centro di un contesto molto lungo vengono recuperate peggio di quelle all’inizio o alla fine. Le posizioni non sono tutte uguali. I modelli addestrati su certe lunghezze tendono a fidarsi di più degli estremi.

La terza riguarda i prompt. Se metti un’istruzione importante in mezzo a un documento enorme, stai scommettendo sul fatto che il modello la pesi abbastanza. Spostarla in alto o in basso, oppure ripeterla alla fine, spesso cambia il risultato. Non è superstizione: è il modo in cui l’informazione posizionale interagisce con l’attenzione.

Infine c’è il tema dei modelli che “dimenticano” l’inizio di una conversazione lunga. Non è che cancellano i messaggi, è che la rappresentazione della posizione diventa meno precisa man mano che ci si allontana. I token iniziali perdono peso relativo.

Tre confusioni frequenti

La prima: positional encoding e positional embedding non sono la stessa cosa. Il primo è la famiglia di tecniche, il secondo è la variante in cui i vettori di posizione vengono imparati durante il training. Usare i termini come sinonimi è comune, ma tecnicamente sbagliato.

La seconda: la posizione non è il token. Un contatore che dice “questo è il token numero 12” è un’informazione, non un significato. Il modello deve imparare a combinarla con il contenuto. Ci riesce perché la somma finisce dentro la stessa rappresentazione.

La terza: più contesto non significa automaticamente più qualità. Aumentare la finestra senza un positional encoding adatto produce un modello che “vede” più token ma li interpreta peggio. È come allargare il campo visivo di un binocolo senza mettere a fuoco.

Come riconoscere il positional encoding in un’architettura

Quando leggi la documentazione di un modello, cerca tre indizi. Il primo è la presenza di un parametro chiamato max_position_embeddings: se c’è, quasi certamente le posizioni sono imparate e c’è un limite fisso.

Il secondo è la presenza di parametri legati a RoPE, come rope_theta o rope_scaling. Se li trovi, il modello usa rotazioni e puoi aspettarti un comportamento più elastico sui contesti lunghi.

Il terzo è la lunghezza dichiarata del contesto rispetto a quella usata in training. Se il modello dichiara 128.000 token ma è stato addestrato su 8.000, c’è stato un lavoro di estensione. I risultati sui token lontani vanno presi con le pinze.

Questi dettagli non servono a programmare, servono a capire cosa aspettarsi. Un modello con posizioni imparate e contesto corto non diventerà un lettore di documenti enormi solo perché gli hai dato un prompt più lungo. Un modello con RoPE e scaling è progettato per quel lavoro. Si vede.

Domande frequenti sul positional encoding

Il positional encoding è ancora necessario nei Transformer moderni?

Sì, nella grande maggioranza dei casi. Cambia la forma, non la necessità. I modelli attuali usano rotazioni come RoPE o bias come ALiBi invece di seni e coseni, ma l’obiettivo resta identico: rendere il meccanismo di attenzione sensibile all’ordine delle parole.

Perché non si concatenano posizione ed embedding invece di sommarli?

Concatenare funziona, ma raddoppia la dimensione del vettore e quindi il costo di ogni strato. La somma mantiene tutto compatto e nella pratica basta, perché la rete impara a distinguere le due componenti. È un compromesso tra pulizia teorica ed efficienza.

Quanti token può gestire un positional encoding sinusoidale?

In teoria infiniti, perché la formula si calcola per qualsiasi posizione. In pratica i modelli addestrati su sequenze corte non hanno imparato a interpretare posizioni molto lontane, quindi la qualità cala anche se la formula continua a funzionare.

RoPE è meglio delle posizioni imparate?

Per i contesti lunghi sì, quasi sempre. RoPE gestisce meglio l’estensione e mantiene l’informazione relativa in modo naturale. Le posizioni imparate restano valide per modelli compatti con finestre fisse, dove il limite non è un problema.

Il positional encoding c’entra con le allucinazioni?

In modo indiretto. Se il modello perde il filo della posizione in un contesto lungo, può attribuire un’informazione al posto sbagliato e inventare collegamenti. Non è la causa principale delle allucinazioni, ma è uno dei fattori che peggiorano la precisione su testi lunghi.

Posso aumentare la context window solo cambiando il positional encoding?

No. Serve anche addestrare il modello su sequenze lunghe, altrimenti il positional encoding esteso codifica posizioni che il modello non ha mai imparato a usare. L’estensione senza training dà risultati deludenti, a volte peggiori del contesto originale.

Se vuoi consolidare le basi, vale la pena rileggere cosa sono gli embedding e come i tensori diventano il formato in cui viaggiano queste informazioni. Per capire come più teste di attenzione lavorano insieme, c’è la lezione sulla multi-head attention. E se ti interessa lo spazio in cui i concetti prendono forma, passa da vettori, dimensioni e spazi latenti.

Newsletter settimanale con le ultime novità sull’intelligenza artificiale

Corso gratuito sull’Intelligenza Artificiale, dalle nozioni base ai concetti più complessi

Condividi:

Potrebbero interessarti