Cerchi un modello da sette miliardi di parametri e ne trovi nove versioni: una in FP16, due marcate GPTQ, una AWQ, tre GGUF con sigle come Q4_K_M, una FP8 e una W8A8. Nessuna spiega a chi serve. È il momento in cui la maggior parte delle persone scarica quella con più download e spera bene — scelta ragionevole, che però spreca prestazioni tutte le volte in cui il proprio caso non assomiglia a quello della maggioranza.
La scelta è meno arbitraria di come appare. Si riduce a una domanda sola: che cosa ti sta costando di più, la memoria o il calcolo? Le due grandi famiglie di quantizzazione post-addestramento rispondono a due bisogni diversi, e confonderle produce lavoro sprecato.
A sinistra la quantizzazione dei soli pesi: il modello occupa meno spazio, ma il conto vero si fa ancora in virgola mobile. A destra pesi e attivazioni insieme: il conto passa agli interi, e con esso il guadagno di velocità.
La domanda che decide: memoria o calcolo
Con una sola richiesta alla volta — un assistente sul portatile, un servizio interno con pochi utenti — la GPU passa la maggior parte del tempo a leggere i pesi dalla memoria, non a moltiplicare. Rimpicciolire i pesi accorcia proprio quella lettura, e il modello che prima non entrava nella scheda ora ci entra. È il caso della quantizzazione dei soli pesi.
Con molte richieste servite insieme il quadro si rovescia: i pesi si leggono una volta e si riusano per tutto il lotto, mentre le moltiplicazioni si moltiplicano con esso. Lì il guadagno viene dal far lavorare le unità intere della GPU invece di quelle in virgola mobile, e questo richiede che anche le attivazioni siano a 8 bit.
Qui si sceglie e si esegue; che cosa succede davvero quando si passa da sedici bit a quattro — la griglia, il fattore di scala, l’errore che si introduce — è il capitolo del libro sull’efficienza.
Solo i pesi: AWQ
AWQ sta per Activation-aware Weight Quantization (Lin e altri, 2023). L’idea che gli dà il nome: non tutti i pesi contano allo stesso modo, e quelli che contano non si riconoscono guardando i pesi — si riconoscono guardando le attivazioni che li attraversano. Gli autori riportano che basta proteggere all’incirca l’1% dei pesi, individuati così, per abbattere di molto l’errore di quantizzazione; e riportano una velocità circa tripla rispetto all’implementazione FP16 di Hugging Face, su GPU sia desktop sia mobili, con Llama-2 da 70 miliardi di parametri portato a girare su GPU mobili.
Attenzione alla libreria. Quasi tutti i tutorial in circolazione usano AutoAWQ, che è stata archiviata nel maggio 2025 e non è più mantenuta; la documentazione di vLLM lo dichiara e indirizza altrove. Il posto giusto oggi è llm-compressor, dove la stessa funzione è stata adottata dal progetto vLLM.
pip install llmcompressor
from transformers import AutoModelForCausalLM, AutoTokenizer
from llmcompressor import oneshot
from llmcompressor.modifiers.awq import AWQModifier
from llmcompressor.modifiers.quantization import QuantizationModifier
modello_id = "meta-llama/Meta-Llama-3-8B-Instruct"
modello = AutoModelForCausalLM.from_pretrained(modello_id, torch_dtype="auto")
tok = AutoTokenizer.from_pretrained(modello_id)
ricetta = [
AWQModifier(), # calcola le scale guardando le attivazioni
QuantizationModifier( # e poi quantizza davvero
targets=["Linear"], scheme="W4A16_ASYM", ignore=["lm_head"],
),
]
oneshot(model=modello, recipe=ricetta, dataset="…", num_calibration_samples=512)
modello.save_pretrained("Llama-3-8B-AWQ", save_compressed=True)
tok.save_pretrained("Llama-3-8B-AWQ")
Due dettagli che nel codice sembrano rumore e non lo sono. ignore=["lm_head"] lascia in virgola mobile l’ultimo strato, quello che produce un punteggio per ogni token del vocabolario: è grande, è delicato, e quantizzarlo costa in qualità più di quanto renda in spazio. E la calibrazione — quei 512 esempi — non è addestramento: serve solo a far passare del testo attraverso il modello per osservare quali attivazioni sono grandi. Ma osservare testo inglese generico e poi servire clienti italiani su documenti tecnici significa proteggere i pesi sbagliati: la calibrazione va fatta sul proprio dominio.
Pesi e attivazioni: SmoothQuant
Portare anche le attivazioni a 8 bit è più difficile, e la ragione è asimmetrica: i pesi di un modello linguistico sono distribuiti in modo ragionevole, le attivazioni no. In alcuni canali compaiono valori enormi rispetto agli altri, e una griglia a 8 bit che debba contenerli schiaccia tutto il resto vicino allo zero.
SmoothQuant (Xiao e altri, 2022; ICML 2023) risolve con una mossa elegante: sposta la difficoltà. Divide le attivazioni per un fattore per canale e moltiplica per lo stesso fattore i pesi corrispondenti — una trasformazione matematicamente equivalente, che lascia il risultato identico ma rende le attivazioni docili e i pesi appena più ruvidi, che è un buon scambio perché i pesi partivano facili. Gli autori riportano fino a 1,56 volte di velocità e metà della memoria con perdita di accuratezza trascurabile, e un modello da 530 miliardi di parametri servito da un solo nodo.
from llmcompressor.modifiers.quantization import GPTQModifier
from llmcompressor.modifiers.transform.smoothquant import SmoothQuantModifier
ricetta = [
SmoothQuantModifier(smoothing_strength=0.8), # sposta la difficoltà
GPTQModifier(targets="Linear", scheme="W8A8", ignore=["lm_head"]),
]
smoothing_strength è il parametro con cui si decide quanta difficoltà spostare: a zero non si sposta nulla e le attivazioni restano intrattabili, a uno si scarica tutto sui pesi e a soffrire diventano loro. Lo 0,8 dell’esempio ufficiale è un punto di partenza, non una costante di natura: su modelli diversi conviene provarne due o tre e misurare.
Misurare sul proprio compito, non sulla classifica
Il collaudo che quasi tutti fanno è la perplexity su un testo di riferimento, ed è utile perché costa poco: se peggiora molto, qualcosa è andato storto in modo evidente. Ma è una media su testo generico, e le medie nascondono esattamente ciò che ti interessa. Un modello quantizzato può conservare la perplexity e perdere la capacità di produrre JSON valido, o di seguire istruzioni lunghe, o di ragionare in italiano invece che scivolare in inglese.
Il collaudo che conta è cinquanta esempi del tuo compito reale, fatti girare sul modello prima e dopo, confrontati a mano. Costa un’ora e trova regressioni che nessun benchmark aggregato mostra. Vale la pena misurare anche la velocità nella tua condizione d’uso: una quantizzazione che dà tre volte la velocità con un utente può darne una e mezza sotto carico, o viceversa, e il numero del paper è stato ottenuto su hardware che quasi certamente non è il tuo.
Cosa portarti a casa
La regola pratica sta in due righe. Se il problema è farci stare il modello — un portatile, una scheda da 24 GB, un utente per volta — prendi la quantizzazione dei soli pesi a 4 bit, AWQ o GPTQ. Se il problema è quanto costa servirlo a molti utenti insieme, guarda W8A8 con SmoothQuant, o le varianti FP8 dove l’hardware le supporta.
Non esiste la versione «quantizzata bene» di un modello: esiste quella giusta per il collo di bottiglia che hai tu.
E vale la pena rifare il giro ogni tanto, perché è un settore in cui gli strumenti muoiono in fretta: la libreria che ogni tutorial del 2024 dava per standard è archiviata da più di un anno, e il codice che si trova copiando dai post più letti installa oggi un pacchetto che nessuno aggiorna più. Sono i casi in cui leggere la documentazione, invece del primo risultato del motore di ricerca, fa una differenza misurabile in ore.

I commenti sono riservati agli iscritti.
Accedi per commentare