ELAI S.r.l.

L’AI non può leggere nulla: perché una maschera vuota può farle leggere tutto

L’AI non può leggere nulla: perché una maschera vuota può farle leggere tutto Un esempio svolto chiarisce metodo, ipotesi e limiti.

L’AI non può leggere nulla: perché una maschera vuota può farle leggere tutto

Una riga senza informazioni ammesse

Un modello deve leggere soltanto alcuni elementi del contesto. Una maschera impedisce di usare gli altri: per esempio token di riempimento o contenuti fuori dalla finestra consentita. Ma se per una richiesta non rimane nessun elemento valido, quale risposta deve produrre l’attenzione? Una sostituzione numerica apparentemente innocua può trasformare “non leggere nulla” in “fai la media di tutto”. Studiamo questo caso limite con tre valori, una formula trasparente e una politica di errore dichiarata.

Pesi, valori e un denominatore che deve esistere

Chiamiamo s_i il punteggio di compatibilità con l’elemento i e v_i il valore da combinare. La softmax trasforma i punteggi in pesi positivi che sommano a uno; l’uscita è la somma pesata dei valori. Nel caso guida s=(0,1,2), v=(10,20,90), tutti senza unità. Non eseguiamo una rete addestrata: isoliamo una sola operazione, senza dropout, proiezioni o connessioni residue. Questo rende controllabile la differenza tra formula matematica e decisione del software.

w_i = exp(s_i) / Σ_j exp(s_j); y = Σ_i w_i v_i

Con una maschera definiamo l’insieme A delle posizioni ammesse. Il denominatore deve sommare soltanto quelle; una posizione esclusa riceve peso zero. Per evitare overflow, sottraiamo il massimo m dei punteggi ammessi prima dell’esponenziale. Il fattore exp(−m) compare sia sopra sia sotto e si cancella, quindi in aritmetica esatta i pesi non cambiano. Questo argomento richiede però A non vuoto: senza elementi ammessi non esiste il massimo su cui abbiamo costruito il passaggio.

w_i = 1_(i∈A) exp(s_i−m) / Σ_(j∈A) exp(s_j−m), m=max_(j∈A) s_j

Se ammettiamo soltanto la prima e la terza posizione, i pesi sono 1/(1+e²), zero, e²/(1+e²). L’uscita è (10+90e²)/(1+e²), circa 80,464. Il valore centrale 20 non partecipa. Possiamo verificare una proprietà utile: i pesi esclusi sono esattamente zero e quelli ammessi sommano a uno. La maschera è quindi una restrizione del supporto, non soltanto una piccola penalità ai punteggi.

Quando tutti sono esclusi, la softmax ordinaria non decide

Per A vuoto, la somma di esponenziali ammessi vale zero e non esiste una distribuzione di probabilità normalizzata su quell’insieme. Scrivere punteggi tutti uguali a meno infinito non risolve la definizione: la versione stabilizzata tenta −∞−(−∞), un’operazione non definita; una normalizzazione diretta arriva a 0/0. È un problema del dominio della formula, non una quantità che “dovrebbe essere quasi zero”. Il programma deve decidere come rappresentare l’assenza di un’uscita valida.

Un espediente frequente sostituisce ogni punteggio escluso con un numero finito molto negativo, per esempio −10^9. Se tutti sono sostituiti con lo stesso numero, sottrarre il massimo dà tre zeri; l’esponenziale dà tre uno; ogni peso diventa 1/3. L’uscita è (10+20+90)/3=40. Abbiamo letto tutti i valori che intendevamo escludere. Se invece aggiungiamo la stessa penalità finita ai punteggi originali, la softmax ne conserva le differenze: è ancora una politica diversa, non una maschera rigorosa.

CasoValidoUscita
1180.463766
2040
300
La maschera parziale, la sostituzione finita e la politica vuota producono operazioni diverse; zero nel terzo caso richiede anche valid=False. Calcoli didattici.
La maschera parziale, la sostituzione finita e la politica vuota producono operazioni diverse; zero nel terzo caso richiede anche valid=False. Calcoli didattici.

Una politica esplicita, non una probabilità inventata

Nell’esperimento scegliamo di restituire un vettore di pesi zero, uscita zero e valid=False quando A è vuoto. Non chiamiamo quei pesi una distribuzione: sommano a zero. Il controllo viene prima del massimo e della divisione, evitando di produrre valori non validi per poi nasconderli. Un’altra applicazione può rifiutare la richiesta o usare un elemento di fallback esplicitamente consentito. La scelta dipende dal contratto e deve essere preservata anche nel calcolo dei gradienti, che qui non eseguiamo.

Il flag è importante: uno zero può essere anche un valore autentico, quindi da solo non distingue “nessuna informazione” da “informazione con media zero”. Inoltre un contributo d’attenzione nullo non rende nullo tutto il blocco: bias, proiezioni e connessioni residue possono aggiungere altri termini. Il grafico confronta soltanto l’operazione isolata descritta. Non dimostra che un modello completo non possa propagare informazione attraverso altri percorsi o produrre un testo plausibile senza evidenza ammessa.

Il contratto della libreria va controllato separatamente

La documentazione PyTorch 2.14 mostra la costruzione con maschera e softmax e specifica che True indica una posizione ammessa in scaled_dot_product_attention, mentre una diversa API di padding usa la convenzione inversa. Non abbiamo eseguito PyTorch né verificato i suoi kernel sul caso vuoto: il risultato del nostro codice non è un benchmark o una promessa sul backend. Dtype, versione, esportazione e percorso di esecuzione vanno provati nella piattaforma scelta con casi vuoti, parziali e completi.

La risposta alla domanda iniziale è dunque un requisito di progetto: se nessun elemento è leggibile, la softmax ordinaria non fornisce da sola una risposta. Un numero molto negativo non equivale automaticamente a un divieto. Dichiarare e testare il comportamento vuoto impedisce che un risultato finito e apparentemente ragionevole nasconda una lettura non voluta. È un controllo piccolo nel codice, ma modifica il significato dell’operazione.

PyTorch 2.14 — Attention and mask semantics.

import math,json,sys
from pathlib import Path
scores=[0.,1.,2.];values=[10.,20.,90.]
def attention(allowed):
 if not any(allowed):return dict(valid=False,weights=[0.]*3,output=0.)
 m=max(s for s,a in zip(scores,allowed) if a);e=[math.exp(s-m) if a else 0. for s,a in zip(scores,allowed)];z=sum(e);w=[x/z for x in e]
 return dict(valid=True,weights=w,output=sum(x*v for x,v in zip(w,values)))
partial=attention([True,False,True]);empty=attention([False]*3)
assert empty['output']==0 and not empty['valid'];assert partial['weights'][1]==0
assert abs(partial['output']-(10+90*math.exp(2))/(1+math.exp(2)))<1e-12
uniform=dict(valid=False,weights=[1/3]*3,output=sum(values)/3)
assert uniform['output']==40
r=dict(python=sys.version.split()[0],seed=None,scope='Explicit educational softmax policies, not execution of a PyTorch backend or trained model',scores=scores,values=values,partial=partial,emptyPolicy=empty,finiteReplacement=uniform,allNegativeInfinity='Stable subtraction attempts -inf-(-inf): undefined, not ordinary probability normalisation')
Path(__file__).with_name('results.json').write_text(json.dumps(r,indent=2),encoding='utf8')

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 25 ottobre 2026.