ELAI S.r.l.

Se ogni documento conta uguale, perché la lunghezza cambia l’addestramento?

Media per token e per documento non sono equivalenti. Un esempio completo con cross-entropy, maschere e gradienti mostra che cosa stiamo davvero ottimizzando.

Se ogni documento conta uguale, perché la lunghezza cambia l’addestramento?

Due documenti, due modi di decidere quanto contano

Un gruppo prepara documenti di dominio per adattare un modello AI. Alcuni sono brevi, altri molto lunghi. Se dichiariamo che ogni documento è ugualmente importante, basta mescolarli nello stesso batch e fare la media della loss? Non sempre: una media su tutte le posizioni supervisionate dà più peso ai documenti che ne contengono di più. La scelta del denominatore è parte dell’obiettivo di apprendimento, non un dettaglio cosmetico del programma.

La domanda è quale quantità stiamo mediando e come cambia il gradiente. Useremo due gruppi sintetici, con 2 e 8 posizioni valide, un modello binario con un unico parametro e un calcolo completo della cross-entropy, cioè entropia incrociata. Aggiungeremo poi posizioni di padding, inserite soltanto per allineare le lunghezze. Non addestriamo un modello linguistico: isoliamo con un modello controllabile un meccanismo che conta anche nell’adattamento di modelli verticali.

Che cosa misura una singola loss

Un token è un’unità della rappresentazione testuale; una posizione supervisionata è un punto in cui chiediamo una previsione e disponiamo di un bersaglio. Per questo esempio non servono parole reali o un particolare tokenizer. Ogni posizione ha etichetta y uguale a 0 oppure 1. Il modello assegna la stessa probabilità p alla classe 1 in tutte le posizioni. È volutamente semplice: non deve imparare il linguaggio, ma mostrarci l’effetto delle regole di aggregazione.

p = sigmoid(theta) = 1 / (1 + exp(-theta)) ell(theta,y) = -y log(p) - (1-y) log(1-p)

theta è il logit, un numero reale che il modello può modificare. Quando theta vale 0, p vale 0,5. Il logaritmo è naturale, quindi la loss si esprime in nat. Se y=1 penalizziamo una probabilità p piccola; se y=0 penalizziamo una probabilità 1−p piccola. La loss non è una percentuale di risposte corrette. Possiamo avere lo stesso valore numerico della loss e gradienti differenti quando cambiamo i pesi delle osservazioni.

La media globale sceglie implicitamente il peso dei documenti

Indichiamo con n_i il numero di posizioni valide del documento i e con L_i la media delle sue loss. La media per token somma tutte le loss e divide per il totale delle posizioni valide. La media per documento calcola prima ogni L_i e poi assegna lo stesso peso ai documenti. Nella prima, il coefficiente di L_i è proporzionale a n_i. Nella seconda, è lo stesso per tutti, purché ogni documento abbia almeno una posizione valida.

L_token = sum_i n_i L_i / sum_i n_i L_document = (1/D) sum_i L_i

D è il numero di documenti. Con n_A=2 e n_B=8, la media per token è 0,2 L_A+0,8 L_B; quella per documento è 0,5 L_A+0,5 L_B. Il secondo documento pesa quattro volte il primo nel primo obiettivo, ma non nel secondo. Questo non rende automaticamente sbagliata la media per token: è coerente se vogliamo dare uguale importanza a ogni posizione. Diventa incoerente con l’intenzione dichiarata soltanto se vogliamo invece pesare ugualmente i documenti.

Il gradiente rende visibile la differenza

Ora assegniamo etichetta 1 a entrambe le posizioni del documento A ed etichetta 0 alle otto posizioni del documento B. Sono bersagli costruiti, non frequenze osservate in un corpus. Per capire come cambierà theta dobbiamo derivare la loss rispetto a quel parametro. La derivata della sigmoid è p(1−p); sostituendola nella derivata dei logaritmi, i termini si semplificano e rimane p−y. Il gradiente indica la direzione locale di aumento della loss.

d ell / d theta = -y(1-p) + (1-y)p = p-y g_token = p - 2/10 = p - 0.2 g_document = p - 1/2 = p - 0.5

Con theta=0 e p=0,5, il gradiente per token vale 0,3; quello per documento vale 0. Un passo di discesa sottrae al parametro il gradiente moltiplicato per un passo positivo: il primo criterio spinge theta verso valori negativi, il secondo è già in equilibrio. Le due loss iniziali valgono entrambe log 2, circa 0,693147 nat. Guardare soltanto quel numero non rivelerebbe che i due criteri stanno suggerendo aggiornamenti diversi.

Possiamo trovare anche gli ottimi. Poiché il gradiente è p meno la frazione pesata di etichette 1, si annulla a p=0,2 nel criterio per token e a p=0,5 in quello per documento. La derivata seconda è p(1−p), positiva per probabilità strettamente tra 0 e 1, quindi in questo modello scalare gli ottimi sono unici e finiti. Non abbiamo dimostrato che un grande modello linguistico abbia un paesaggio di loss convesso: la conclusione riguarda soltanto il modello dichiarato.

Il padding non è un nuovo esempio di classe zero

Per ottenere due righe di lunghezza 8 aggiungiamo sei posizioni artificiali ad A. Queste posizioni non hanno un bersaglio del compito: servono a organizzare i tensori. Se però le etichettiamo 0 e le includiamo nella loss come dati veri, il totale diventa 16 posizioni, soltanto 2 positive. L’ottimo passa a p=2/16=0,125. Non è cambiato il contenuto dei due documenti; abbiamo introdotto sei esempi inventati nella funzione obiettivo.

Una maschera m uguale a 1 nelle posizioni valide e 0 nel padding deve agire sia sul numeratore sia sul denominatore della media. Se aggiungiamo altri spazi artificiali con maschera 0, il valore della loss corretta e il suo gradiente rimangono invariati. Il programma verifica questa proprietà con 0,1,6 e 20 posizioni aggiunte e tre valori di theta. È una proprietà sui dati costruiti, non una misura di robustezza di un modello sul campo.

L_masked = sum_j m_j ell_j / sum_j m_j sum_j m_j = 10, not 16

Un secondo errore elimina correttamente le loss del padding dal numeratore, ma continua a dividere per 16. Il risultato è 10/16 della loss corretta. A theta=0 scende da 0,693147 a 0,433217 senza che nessuna probabilità sia migliorata; il gradiente scende da 0,3 a 0,1875. L’ottimo scalare rimane p=0,2 perché abbiamo moltiplicato tutta la funzione per una costante positiva. Cambia però la scala del passo: un numero minore sul grafico non prova una previsione migliore.

Un terzo errore usa il valore 0 come sinonimo di padding e ignora tutte le etichette 0, comprese le otto supervisioni legittime del documento B. Rimangono soltanto due etichette 1: il gradiente iniziale diventa−0,5 e spinge p verso 1. In questo caso il minimo è un limite, raggiunto mentre theta cresce senza limite, non un ottimo finito. Bisogna distinguere il valore di una classe dal ruolo artificiale di una posizione: una maschera deve descrivere quel ruolo.

CriterioLoss a theta=0(nat)Gradiente a theta=0p ottimo
Media per token0.6931470.30000.200
Media per documento0.6931470.00000.500
Padding incluso0.6931470.37500.125
Denominatore errato0.4332170.18750.200
Classe zero ignorata0.693147-0.50001(limite)

I valori della tabella descrivono funzioni obiettivo diverse, non cinque addestramenti valutati sullo stesso test. La prima distinzione, token contro documento, è una scelta esplicita di pesatura. Le altre righe introducono errori rispetto alla definizione concordata di dati validi. Con un fattore di scala costante si potrebbe compensare il passo di ottimizzazione; se la quota di padding cambia tra batch, quel fattore varia e cambia anche il peso relativo dei contributi durante l’aggiornamento.

A sinistra le curve appartengono a tre pesature differenti: non si sceglie un modello confrontando semplicemente i loro minimi numerici. A destra i gradienti allo stesso theta=0 mostrano sia cambiamenti di intensità sia un cambio di segno quando si scartano etichette 0 legittime. Dati e modello sono sintetici; nessuna accuratezza di un LLM è stata misurata.
A sinistra le curve appartengono a tre pesature differenti: non si sceglie un modello confrontando semplicemente i loro minimi numerici. A destra i gradienti allo stesso theta=0 mostrano sia cambiamenti di intensità sia un cambio di segno quando si scartano etichette 0 legittime. Dati e modello sono sintetici; nessuna accuratezza di un LLM è stata misurata.

Dividere il batch non deve cambiare di nascosto l’obiettivo

Supponiamo di elaborare A e B in due microbatch, cioè due porzioni successive, per ridurre la memoria necessaria. A theta=0 i gradienti medi delle due porzioni sono−0,5 e+0,5. Farne la media semplice dà 0: abbiamo ricostruito il criterio per documento. Per riprodurre la media globale per token occorre pesare ciascun gradiente medio con il suo numero di posizioni valide. Otteniamo(2 ×−0,5+8 × 0,5)/10=0,3, lo stesso valore del batch intero.

g_global = sum_b n_b g_b / sum_b n_b g_mean_of_means = (1/B) sum_b g_b

B qui indica il numero di microbatch. Le due formule coincidono se le numerosità valide sono uguali, oppure in altri casi particolari in cui i contributi si compensano. Non basta che i tensori abbiano la stessa lunghezza dopo il padding. Questo è un controllo dell’algebra dell’accumulo, non la denuncia di un difetto in una particolare versione di Trainer o di un framework. Un’implementazione deve essere confrontata con il suo obiettivo dichiarato e con le regole di riduzione effettive.

Dalla formula alla libreria, senza confondere i livelli

La documentazione ufficiale PyTorch 2.14 di CrossEntropyLoss distingue bersagli come indici di classe e bersagli come distribuzioni di probabilità. Nel caso con indici, ignore_index esclude bersagli dalla loss e dal gradiente; senza pesi di classe, la media usa il numero dei bersagli non ignorati. Il nostro esempio considera proprio etichette discrete e nessun peso di classe. Non estendiamo quella formula senza modifiche a etichette probabilistiche o ad altre scelte di pesatura.

In un modello linguistico causale, le posizioni valide dipendono anche dall’allineamento tra ingresso e bersaglio successivo e dalla scelta di supervisionare prompt, risposte o entrambi. La lunghezza completa del documento non coincide necessariamente con n_i. Una maschera usata dall’attenzione e una usata dalla loss rispondono a domande diverse, anche quando un’implementazione le collega. Prima di applicare i conteggi bisogna definire quali previsioni contribuiscono realmente all’obiettivo, non soltanto contare i token presenti nel tensore.

Se non rimane nessuna posizione valida, la media ha denominatore zero e non è definita dalla nostra formula. Il programma segnala esplicitamente questa condizione; non restituisce zero fingendo una previsione perfetta. Anche un documento senza bersagli rende indefinita la sua media L_i: escluderlo o trattarlo in altro modo richiede una politica dichiarata. Non attribuiamo il comportamento del nostro codice a tutte le librerie, che possono gestire questi casi in modi diversi.

Come riprodurre il ragionamento senza addestrare un LLM

Il programma usa soltanto la libreria matematica di Python per la loss e per il gradiente analitico. Calcola i logaritmi mediante una forma numericamente stabile e salva i cinque criteri confrontati. Verifica l’invarianza al padding correttamente mascherato e confronta il gradiente con una differenza finita centrale a theta=0,3. L’errore nel controllo eseguito è circa 4,1 × 10⁻¹¹, sotto la tolleranza 1 × 10⁻⁸scelta per quel controllo: non è una prova di correttezza di un sistema di autodifferenziazione.

Nel frammento breve, lengths descrive quante posizioni contribuiscono e gradients contiene il contributo medio di ciascun documento. Le due ultime medie ricostruiscono i diversi obiettivi: non richiedono GPU, pesi di modelli o dati esterni. Il costo di una somma sulle posizioni è lineare nel numero di posizioni elaborate, ma questo conteggio non misura il costo dell’inferenza o del training. La parte onerosa di un modello reale non è simulata da questa operazione scalare.

Quale unità di importanza vogliamo ottimizzare?

La lunghezza cambia l’addestramento quando cambia il peso dei contributi nella funzione obiettivo. Dare lo stesso peso ai documenti richiede una media per documento o una pesatura equivalente; dare lo stesso peso alle posizioni richiede la media per token. Nessuna delle due è universalmente migliore. Padding e bersagli validi vanno però distinti in ogni scelta, e dividere i dati in microbatch non dovrebbe introdurre una nuova pesatura non dichiarata. I risultati del modello reale richiedono infine una valutazione indipendente, che questo esempio non sostituisce.

Fonte e materiali riproducibili

PyTorch 2.14 documentation, CrossEntropyLoss: class-index and probability targets, reduction, ignore_index. Relevant technical definitions read 21 October 2026. Documentation consulted; no PyTorch execution claimed..

import math
p=0.5
lengths=[2,8]
labels=[1,0]
gradients=[p-y for y in labels]
token_gradient=sum(n*g for n,g in zip(lengths,gradients))/sum(lengths)
document_gradient=sum(gradients)/len(gradients)
assert abs(token_gradient-0.3)<1e-12
assert document_gradient==0
print(token_gradient,document_gradient)

Codice, dati e istruzioni · JSON. Calcoli didattici eseguiti con Python 3.14.0; figure con Matplotlib 3.11.2. Analisi con assistenza AI, senza dichiarare peer review o revisione umana. Copertina originale ImageGen, illustrativa: non documenta persone, sedi o installazioni EL-AI. Fonti consultate il 21 ottobre 2026.