Quantizzazione GPTQ su un modello Llama 2 7B fine-tuned con HuggingFace

Quantizzazione GPTQ su modello Llama 2 7B con HuggingFace

Guida facile da seguire su come quantizzare un LLM

Immagine di Milad Fakurian su Unsplash

Nel mio articolo precedente, ti ho mostrato come istruzionare il nuovo modello Llama 2, appena rilasciato da Meta AI, per costruire un generatore di codice Python in poche righe di codice. Questa volta, descriveremo come quantizzare questo modello utilizzando la quantizzazione GPTQ ora integrata con transformers.

La scorsa settimana, Hugging Face ha annunciato la compatibilità delle sue librerie transformers con la libreria AutoGPTQ, che ci consente di quantizzare un grande modello di linguaggio in 2, 3 o 4 bit utilizzando la metodologia GPTQ.

GPTQ: Quantizzazione post-training su modelli generativi

In un innovativo articolo [1], i ricercatori hanno presentato GPTQ, un nuovo metodo di quantizzazione post-training che ha il potenziale per ridefinire il mondo della compressione dei modelli di linguaggio. GPTQ è efficiente al punto da poter essere applicato a modelli che vantano centinaia di miliardi di parametri e può raggiungere una precisione notevole comprimendo questi modelli a soli 2, 3 o 4 bit per parametro senza sacrificare una precisione significativa.

Questa tecnica all’avanguardia è dimostrata dalla sua capacità di quantizzare modelli massicci, come OPT-175B e BLOOM-176B, in poche ore di GPU mantenendo una perplessità minima, una misura stringente della precisione. Sul fronte pratico, i ricercatori hanno sviluppato un sistema di esecuzione che consente un’efficace operazione dei modelli compressi per compiti generativi. In modo notevole, hanno raggiunto l’obiettivo di eseguire il modello compresso OPT-175B su una singola GPU NVIDIA A100, o con soli altri due cost-effective GPU NVIDIA A6000. Inoltre, la compressione ottimizzata tramite kernel GPU su misura porta a significativi miglioramenti delle prestazioni, aumentando ulteriormente la praticità di questi modelli compressi.

Ciò che rende GPTQ eccezionale è la sua capacità di quantizzare modelli di linguaggio con centinaia di miliardi di parametri nell’intervallo di 3-4 bit/componente. Questo è un notevole salto in avanti, poiché i metodi precedenti avevano difficoltà a mantenere una precisione inferiore a 8 bit e si concentravano tipicamente su modelli più piccoli. Tuttavia, lo studio sottolinea anche i complessi compromessi tra perplessità, larghezza di bit e dimensione del modello indotti dalla compressione. Ma presenta anche delle limitazioni. Attualmente, GPTQ non offre velocizzazioni per le moltiplicazioni effettive a causa della mancanza di supporto hardware per gli operandi a precisione mista su architetture mainstream. La quantizzazione delle attivazioni non è inclusa nei risultati attuali, ma può essere affrontata tramite tecniche ortogonali.

In sintesi, la capacità di GPTQ di comprimere modelli di linguaggio estremamente precisi a livelli senza precedenti segna una pietra miliare significativa nel campo dell’apprendimento automatico e della modellazione del linguaggio. Apre la strada a un’applicazione più efficiente e accessibile di questi modelli colossali, indicando ulteriori possibilità di ricerca nel campo della compressione dei modelli.

I metodi di quantizzazione nell’apprendimento automatico possono essere suddivisi in due approcci distinti, ognuno con i suoi vantaggi unici:

  1. Quantizzazione post-training (PTQ): Nel PTQ, i modelli pre-addestrati vengono quantizzati utilizzando risorse relativamente moderate, come un dataset di calibrazione e qualche ora di tempo di calcolo. Questo metodo è particolarmente vantaggioso per modelli di grandi dimensioni, in cui il riaddestramento completo o il fine-tuning possono essere troppo costosi.
  2. Quantizzazione-Aware Training (QAT): D’altra parte, il QAT coinvolge la quantizzazione applicata prima dell’addestramento del modello o durante il successivo fine-tuning.

L’approccio innovativo di GPTQ: GPTQ rientra nella categoria PTQ, rendendolo una scelta convincente per modelli massicci. Ciò che distingue GPTQ è l’adozione di uno schema di quantizzazione misto int4/fp16. Qui, i pesi del modello vengono quantizzati come int4, mentre le attivazioni vengono mantenute come float16. Durante l’elaborazione, i pesi vengono dequantizzati dinamicamente e i calcoli effettivi vengono eseguiti come float16.

Questo approccio innovativo promette risparmi di memoria fino a 4 volte per la quantizzazione int4 e possibili velocizzazioni dovute all’utilizzo di una larghezza di banda inferiore per i pesi. In pratica, GPTQ è un metodo di quantizzazione progettato per modelli già fine-tuning e pronti per la distribuzione. Questo metodo è particolarmente efficace nel ridurre la precisione dei pesi del modello a 4 bit o 3 bit, anche se viene principalmente utilizzato per la quantizzazione a 4 bit.

Una caratteristica chiave di GPTQ è la sua capacità di quantizzare modelli senza la necessità di caricare l’intero modello in memoria. Invece, quantizza il modello modulo per modulo, riducendo significativamente i requisiti di memoria durante il processo di quantizzazione. Tuttavia, è necessario un piccolo campione di dati per la calibrazione, una fase che può richiedere più di un’ora su una tipica GPU per consumatori.

Immagine da Pythonfix nella descrizione del pacchetto Auto-GPTQ.

Per una spiegazione dettagliata su GPTQ, puoi leggere l’articolo straordinario di Maxime Labonne, “Quantizzazione a 4 bit con GPTQ”, pubblicato da Towards Data Science. È un articolo che approfondisce gli aspetti più tecnici per coloro che desiderano comprendere i dettagli di questo processo.

E consiglio vivamente l’utile articolo “GPTQ o bitsandbytes: quale metodo di quantizzazione utilizzare per i LLM – Esempi con Llama 2” di Benjamin Marie. Lì puoi vedere un confronto tra la quantizzazione di GPTQ e bitsandbytes, i pro e i contro, in modo da poter comprendere meglio quando è più conveniente applicare ciascuna di queste tecniche.

Quando dovresti utilizzare GPTQ?

La risposta a questa domanda dipenderà da ogni caso specifico e dal modello di base da utilizzare, ma un approccio che viene applicato a numerosi modelli e che è indicato da HuggingFace e dall’articolo che ho menzionato in precedenza è il seguente:

  • Aggiusta il modello LLM originale con bitsandbytes in 4 bit, nf4 e QLoRa per un’efficace sintonizzazione fine.
  • Unisci l’adattatore nel modello originale
  • Quantizza il modello risultante con GPTQ a 4 bit

Ho eseguito i primi due passaggi nel mio articolo precedente [3] e ora che la libreria AutoGPT è integrata nell’ecosistema di Huggingface, eseguiremo il terzo passaggio in modo estremamente semplice.

AutoGPT integrato con Hugging Face transformers

La libreria AutoGPTQ emerge come un potente strumento per la quantizzazione dei modelli di Transformer, utilizzando il metodo efficiente di GPTQ. Alcuni sforzi come GPTQ-for-LLaMa, Exllama e llama.cpp si concentrano sulla quantizzazione dell’architettura Llama, ma AutoGPTQ si distingue offrendo un supporto senza soluzione di continuità per una vasta gamma di architetture di trasformatori.

Il team di Hugging Face ha compiuto un passo significativo per migliorare l’accessibilità a GPTQ e ha integrato un API inclusivo di Transformers, semplificando il processo di quantizzazione dei modelli a basso livello (LLM) per un pubblico più ampio. Questa integrazione include opzioni di ottimizzazione essenziali, come i kernel CUDA, che si adattano a casi d’uso comuni.

Per gli utenti che cercano opzioni di quantizzazione più avanzate, la libreria Auto-GPTQ rimane una risorsa preziosa, offrendo funzionalità come i kernel Triton e la compatibilità con l’attenzione fusa, garantendo versatilità e adattabilità nel mondo della quantizzazione dei modelli di trasformatori.

La nostra integrazione di AutoGPTQ ha molti vantaggi:

I modelli quantizzati sono serializzabili e possono essere condivisi sul Hub.

GPTQ riduce drasticamente i requisiti di memoria per eseguire LLM, mentre la latenza di inferenza è paragonabile all’inferenza FP16.

AutoGPTQ supporta i kernel Exllama per una vasta gamma di architetture.

L’integrazione include il supporto nativo di RoCm per le GPU AMD.

È disponibile il fine-tuning con PEFT.

Estratto dall’articolo del blog di Huggingface “Rendere i LLM più leggeri con AutoGPTQ e transformers” [5].

Il nostro approccio a questo compito

Prima di tutto, caricheremo il nostro modello Llama 2 7B 4-bit Python coder sintonizzato in una sessione di Colab utilizzando una T4 con RAM extra. Il modello viene caricato a 4 bit con bitsandbytes e quindi eseguiamo circa 12 esempi per misurare il tempo di inferenza. Al fine di effettuare una semplice valutazione delle prestazioni durante il tempo di inferenza, abbiamo preso come esempi quelli il cui testo di input era più lungo di 500 caratteri e in questo modo cercheremo di apprezzare meglio l’impatto della quantizzazione durante l’inferenza.

Puoi estrarre il codice per caricare questo modello dalla descrizione del modello nell’Hugging Face Hub. Nel mio notebook, descriveremo come eseguire l’inferenza sugli esempi menzionati.

Quantizza il modello utilizzando auto-gptq, 🤗 transformers e optimum

La quantizzazione GPTQ consuma molta VRAM della GPU, per questo motivo è necessario eseguirla su una GPU A100 in Colab. Ci vogliono circa 45 minuti per quantizzare il modello, meno di $1 in Colab. Puoi trovare il codice in questo notebook nel mio repository.

Prima di tutto, è necessario installare le librerie come consigliato nel tutorial di huggingface:

!pip install -q -U transformers peft accelerate optimum!pip install auto-gptq --extra-index-url https://huggingface.github.io/autogptq-index/whl/cu117/# Per ora, fino alla prossima versione di AutoGPTQ, costruiremo la libreria dal codice sorgente!

Optimum library, il toolkit di Hugging Face per l’ottimizzazione dell’addestramento e dell’inferenza, fornisce l’integrazione di AutoGPTQ in Transformers.

L’algoritmo GPTQ richiede la calibrazione dei pesi quantizzati del modello effettuando inferenze sul modello quantizzato. Per quantizzare un modello utilizzando auto-gptq, è necessario passare un dataset al quantizzatore. Questo può essere ottenuto passando un dataset predefinito supportato tra ['wikitext2','c4','c4-new','ptb','ptb-new'] o una lista di stringhe che verranno utilizzate come tuo dataset personalizzato.

Ora devi solo caricare il modello utilizzando una configurazione GPTQ impostando i parametri desiderati, come al solito quando si lavora con transformers, è molto facile:

from transformers import AutoModelForCausalLM, AutoTokenizer, GPTQConfigimport torch# Imposta il modello da caricarehf_model_repo='edumunozsala/llama-2-7b-int4-python-code-20k'# Carica il tokenizertokenizer = AutoTokenizer.from_pretrained(hf_model_repo, use_fast=True)# Imposta la configurazione di quantizzazionequantization_config = GPTQConfig(     bits=4,     group_size=128,     dataset="c4",     desc_act=False,     tokenizer=tokenizer)# Carica il modello da HFquant_model = AutoModelForCausalLM.from_pretrained(hf_model_repo,                 quantization_config=quantization_config, device_map='auto')

Come menzionato, questo codice richiede circa 45 minuti per essere eseguito e consuma un picco di 32 GB di VRAM della GPU. “È necessaria una GPU per quantizzare un modello. Metteremo il modello nella CPU e sposteremo i moduli avanti e indietro nella GPU per quantizzarli. Se vuoi massimizzare l’utilizzo delle tue GPU utilizzando lo scarico della CPU, puoi impostare device_map = "auto"” [6], documentazione di Hugging Face.

I parametri sono autoesplicativi, quantizzazione a 4 bit, dataset C4 e il tokenizzatore da utilizzare durante la quantizzazione. Gli altri due parametri assumono i valori di default:

  • group_size: La dimensione del gruppo da utilizzare per la quantizzazione. Il valore consigliato è 128 e -1 utilizza la quantizzazione per colonna
  • desc_act: Se quantizzare le colonne in ordine di dimensione di attivazione decrescente. Impostando a False può velocizzare significativamente l’inferenza ma la perplessità potrebbe peggiorare leggermente. Conosciuto anche come act-order.

Una volta che hai quantizzato il tuo modello, è il momento di caricarlo nell’Huggin Face Hub e condividerlo con la community.

quant_model.push_to_hub("edumunozsala/llama-2-7b-int4-GPTQ-python-code-20k")tokenizer.push_to_hub("edumunozsala/llama-2-7b-int4-GPTQ-python-code-20k")

Nel mio esperimento utilizzando GPTQ, la riduzione delle dimensioni del modello è sorprendente. Il mio modello Llama 2 7B finemente tarato con pesi a 4 bit occupava 13.5 GB su disco, ma dopo la quantizzazione, la sua dimensione è stata drasticamente ridotta a soli 3.9 GB, un terzo delle dimensioni originali. Questa caratteristica è molto interessante durante il rilascio di modelli di linguaggio di grandi dimensioni.

Caricamento del modello GPTQ dall’Hugging Face Hub e realizzazione di alcune inferenze

Probabilmente, tutti voi sapete come fare questo, ma nel caso pensiate che possa essere più “complicato” rispetto ad altri modelli, vi mostreremo che è come al solito.

Ricordate che è necessario caricare tutte le librerie, comprese optimum, accelerate e, ovviamente, auto-gptq.

!pip install -q -U transformers peft accelerate optimum!pip install auto-gptq

Poi potete caricare il tokenizer e il modello nel vostro notebook in una T4 GPU su Google Colab:

import torchfrom transformers import AutoModelForCausalLM, AutoTokenizermodel_id = "edumunozsala/llama-2-7b-int4-GPTQ-python-code-20k"tokenizer = AutoTokenizer.from_pretrained(model_id)model = AutoModelForCausalLM.from_pretrained(model_id,                   torch_dtype=torch.float16, device_map="auto")

Ora possiamo controllare la nostra GPU per confermare quanto spazio di memoria stiamo utilizzando e, infatti, possiamo vedere che il modello occupa 5,053 GB.

Ripetiamo la valutazione delle prestazioni che abbiamo menzionato in precedenza, facendo inferenze su un gruppo di esempi lunghi per confrontarli con il modello originale. Entrambi i processi di inferenza sono stati eseguiti su una GPU T4, il modello di base ha impiegato circa 17-19 secondi per inferenza mentre il modello quantizzato ha impiegato circa 8-9 secondi per inferenza, la metà.

Tutto il codice e gli esempi sono ben spiegati nel suo notebook nel mio repository. Ogni suggerimento o correzione di bug è benvenuto.

Riferimenti

[1] Articolo ICLR 2023 “GPTQ: Accurate Post-Training Quantization for Generative Pre-Trained Transformers”

[2] “GPTQ o bitsandbytes: quale metodo di quantizzazione utilizzare per LLM – Esempi con Llama 2” di Benjamin Marie.

[3] “Fine-Tuning di un modello Llama 2 7B per la generazione di codice Python” di Eduardo Muñoz

[4] Modello fine-tuned originale in Huggingface “edumunozsala/llama-2-7b-int4-python-code-20k”

[5] Articolo del blog di Hugging Face “Rendere i LLM più leggeri con AutoGPTQ e transformers”

[6] Documentazione ufficiale di Hugging Face su GPTQConfig

[7] “Quantizzazione a 4 bit con GPTQ” di Maxime Labonne.