Modelli e piattaforme di IA

Il framework di inferenza di Microsoft porta i modelli linguistici grandi a 1 bit sui dispositivi locali

mm
Aggiungi Unite.AI alle tue fonti preferite su Google

Il 17 ottobre 2024, Microsoft ha annunciato BitNet.cpp (MSFT ), un framework di inferenza progettato per eseguire modelli linguistici grandi quantizzati a 1 bit (LLM). BitNet.cpp rappresenta un notevole progresso nell’ambito dell’intelligenza artificiale generale, consentendo il deploy efficiente di LLM a 1 bit su CPU standard, senza richiedere costose GPU. Questo sviluppo democratizza l’accesso agli LLM, rendendoli disponibili su una vasta gamma di dispositivi e offrendo nuove possibilità per le applicazioni di intelligenza artificiale sui dispositivi.

Comprendere i modelli linguistici grandi a 1 bit

I modelli linguistici grandi (LLM) hanno tradizionalmente richiesto risorse computazionali significative a causa dell’utilizzo di numeri in virgola mobile ad alta precisione (tipicamente FP16 o BF16) per i pesi del modello. Questa necessità ha reso il deploy degli LLM costoso e intensivo in termini di energia.

In sostanza, i modelli linguistici grandi a 1 bit utilizzano tecniche di quantizzazione estreme per rappresentare i pesi del modello utilizzando solo tre valori possibili: -1, 0 e 1, da cui il termine “1,58 bit” (poiché richiede leggermente più di un bit per codificare tre stati).

Sistema di pesi ternari

Il concetto

La quantizzazione a 1 bit in BitNet.cpp è un sistema di pesi ternari. BitNet opera con solo tre valori possibili per ogni parametro:

  • -1 (negativo)
  • 0 (neutro)
  • 1 (positivo)

Ciò si traduce in una richiesta di archiviazione di circa 1,58 bit per parametro, da cui il nome BitNet b1.58. La riduzione drastica della larghezza del bit dei parametri comporta una riduzione impressionante dell’utilizzo della memoria e della complessità computazionale, poiché la maggior parte delle moltiplicazioni in virgola mobile vengono sostituite con semplici addizioni e sottrazioni.

Fondamento matematico

La quantizzazione a 1 bit comporta la trasformazione dei pesi e delle attivazioni nella loro rappresentazione ternaria attraverso i seguenti passaggi:

1. Binarizzazione dei pesi

La binarizzazione dei pesi comporta la centralizzazione intorno alla media (α), con conseguente rappresentazione ternaria. La trasformazione è espressa matematicamente come:

Wf​=Sign(W−α)

Dove:

  • W è la matrice dei pesi originale.
  • α è la media dei pesi.
  • Sign(x) restituisce +1 se x > 0 e -1 altrimenti.

2. Quantizzazione dell’attivazione

La quantizzazione dell’attivazione assicura che gli input siano limitati a una larghezza di bit specificata:

x^e​=Quant(x)=Clip(γx×Qb​​,−Qb​+ϵ,Qb​−ϵ)

Dove:

  • Qb = 2(b−1)2^{(b-1)} è il livello di quantizzazione massimo per la larghezza di bit b.
  • γ è il valore assoluto massimo di x (denotato come ∣∣x∣∣∞).
  • ε è un numero piccolo per prevenire il overflow durante i calcoli.

3. Operazione BitLinear

Il livello BitLinear sostituisce le moltiplicazioni matriciali tradizionali con un’operazione semplificata:

y=Wf​×x^e​×(Qb​βγ​)

Dove:

  • β è un fattore di scala utilizzato per minimizzare gli errori di approssimazione.
  • γ scala le attivazioni.
  • Q_b è il fattore di quantizzazione.

Questa trasformazione consente calcoli efficienti mantenendo le prestazioni del modello.

Implicazioni sulle prestazioni

Efficienza della memoria

Il sistema di pesi ternari riduce notevolmente le esigenze di memoria:

  • Modelli LLM tradizionali: 16 bit per peso
  • BitNet.cpp: 1,58 bit per peso

Questa riduzione si traduce in un risparmio di memoria del 90% circa rispetto ai modelli a 16 bit tradizionali, consentendo di inserire modelli più grandi all’interno degli stessi vincoli hardware.

Efficienza energetica

Velocità di inferenza, efficienza energetica (Apple M2)

 

Velocità di inferenza: più veloce su entrambe le CPU

Velocità di inferenza, efficienza energetica (i7-13700H)

1. Velocità di inferenza: più veloce su entrambe le CPU

La velocità di inferenza è rappresentata come il numero di token elaborati per secondo. Ecco una panoramica delle osservazioni:

  • Su Apple M2 Ultra: BitNet.cpp raggiunge fino a 5,07x di velocizzazione per modelli più grandi (30B) rispetto a Llama.cpp, con un picco di velocità di 593,43 token per secondo per un modello da 125M, che è un 1,37x di velocizzazione. Per modelli più grandi come il 3,8B e il 7B, BitNet.cpp mantiene una velocità superiore a 84,77 token per secondo, mostrando la sua efficienza su diverse scale.
  • Su Intel i7-13700H: BitNet.cpp raggiunge miglioramenti di velocità ancora più drammatici. Alla dimensione del modello 7B, BitNet.cpp consegna un incredibile 5,68x di velocizzazione rispetto a Llama.cpp. Per modelli più piccoli come il 125M, elabora 389,08 token per secondo, che è 2,37x più veloce di Llama.cpp.

2. Efficienza energetica: un gioco da cambiare per i dispositivi edge

I grafici forniti mostrano anche confronti di costo energetico, che mostrano una riduzione significativa del consumo di energia per token elaborato:

  • Su Apple M2 Ultra: i risparmi di energia di BitNet.cpp sono sostanziali. Per il modello da 700M, consuma 55,4% meno energia per token rispetto a Llama.cpp, scendendo da 0,314 a 0,140. Questa tendenza continua per modelli più grandi, con il modello da 70B che mostra una riduzione del 70,0% del consumo di energia.
  • Su Intel i7-13700H: BitNet.cpp consegna 71,9% di risparmi di energia per il modello da 700M, con un consumo che scende da 1,367 a 0,384. Sebbene i dati di energia per il modello da 70B in Llama.cpp non siano disponibili, BitNet.cpp rimane efficiente, con un consumo di energia a 17,33 per il modello da 70B.

3. Superare il benchmark di velocità di lettura umana

Una delle informazioni più interessanti da questi grafici è il riferimento alla velocità di lettura umana, segnata a 5-7 token per secondo. Questa linea rossa mostra che entrambe le implementazioni, in particolare BitNet.cpp, possono superare agevolmente le velocità di lettura umane anche per i modelli più grandi:

  • Su Apple M2 Ultra, BitNet.cpp supera la velocità di lettura umana per tutte le dimensioni dei modelli, con la velocità più bassa di 8,67 token per secondo per un modello da 70B.
  • Su Intel i7-13700H, il modello da 100B raggiunge 1,70 token per secondo, toccando quasi il limite inferiore della velocità di lettura umana, mentre tutti i modelli più piccoli superano questo benchmark.

Considerazioni sull’addestramento

Stimatore diretto (STE)

Poiché la quantizzazione a 1 bit introduce funzioni non differenziabili, l’addestramento coinvolge una tecnica specializzata nota come Stimatore diretto (STE). In questo approccio, i gradienti fluiscono inalterati attraverso i punti non differenziabili. Ecco un’implementazione semplificata in Python:

class StraightThroughEstimator(Function):
@staticmethod
def forward(ctx, input):
return input.sign()

<p>@staticmethod
def backward(ctx, grad_output):
return grad_output

Addestramento a precisione mista

Per mantenere la stabilità durante l’addestramento, viene utilizzata la precisione mista:

  • Pesi e attivazioni: quantizzati a precisione a 1 bit.
  • Gradiente e stati dell’ottimizzatore: archiviati in precisione più alta.
  • Pesi latenti: mantenuti in alta precisione per facilitare aggiornamenti precisi durante l’addestramento.

Strategia di apprendimento con tasso di apprendimento elevato

Una sfida unica con i modelli a 1 bit è che piccoli aggiornamenti potrebbero non influenzare i pesi binarizzati. Per mitigare questo, il tasso di apprendimento viene aumentato, garantendo una convergenza più rapida e una migliore ottimizzazione rispetto agli approcci tradizionali.

Quantizzazione e normalizzazione di gruppo

BitNet.cpp introduce la quantizzazione e normalizzazione di gruppo per migliorare il parallelismo del modello. Invece di calcolare i parametri per l’intera matrice dei pesi, BitNet divide i pesi e le attivazioni in più gruppi (G).
Questo raggruppamento consente un’elaborazione parallela efficiente senza ulteriore comunicazione tra gruppi, abilitando l’addestramento e l’inferenza di modelli su larga scala.

Note sull’implementazione e ottimizzazioni

Ottimizzazione CPU

BitNet.cpp sfrutta diverse ottimizzazioni a basso livello per raggiungere le prestazioni CPU di picco:

  • Operazioni vettorizzate: utilizza istruzioni SIMD per eseguire manipolazioni di bit in modo efficiente.
  • Accesso alla memoria friendly con la cache: struttura i dati per minimizzare gli errori di cache.
  • Elaborazione parallela: distribuisce il carico di lavoro su più core CPU in modo efficace.

Ecco un esempio di una funzione chiave che implementa la quantizzazione e l’inferenza in BitNet:

def bitlinear_forward(input, weight, scale):
# Quantizza l'input utilizzando la quantizzazione absmax
input_q = quantize(input)

<p># Esegue la moltiplicazione matriciale binaria
output = binary_matmul(input_q, weight)</p>

<p># Scala l'output per farlo corrispondere alla precisione originale
return output * scale</p>

<p>def quantize(x):
# Esegue la quantizzazione absmax
scale = torch.max(torch.abs(x))
return torch.clamp(x / scale, -1, 1) * scale

Modelli supportati

La versione attuale di BitNet.cpp supporta i seguenti modelli LLM a 1 bit disponibili su Hugging Face:

  • bitnet_b1_58-large (0,7 miliardi di parametri)
  • bitnet_b1_58-3B (3,3 miliardi di parametri)
  • Llama3-8B-1.58-100B-tokens (8,0 miliardi di parametri)

Questi modelli sono disponibili pubblicamente per dimostrare le capacità di inferenza del framework. Sebbene non siano stati addestrati o rilasciati ufficialmente da Microsoft, illustrano la versatilità del framework.

Guida all’installazione

Per iniziare a utilizzare BitNet.cpp, segui i passaggi seguenti:

Prerequisiti

  1. Python >= 3.9
  2. CMake >= 3.22
  3. Clang >= 18
  4. Conda (altamente consigliato)

Per gli utenti Windows, è necessario installare Visual Studio con i seguenti componenti abilitati:

  • Sviluppo desktop con C++
  • Strumenti C++-CMake per Windows
  • Git per Windows
  • Compilatore C++-Clang per Windows
  • Supporto MS-Build per il set di strumenti LLVM (Clang)

Per gli utenti Debian/Ubuntu, è disponibile uno script di installazione automatico:

bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)"

Installazione passo dopo passo

  1. Clona il repository:
    git clone --recursive https://github.com/microsoft/BitNet.git

    cd BitNet
  2. Installa le dipendenze:
    # Crea un nuovo ambiente Conda (consigliato)
    conda create -n bitnet-cpp python=3.9
    conda activate bitnet-cpp


    pip install -r requirements.txt
  3. Compila e prepara il progetto: puoi scaricare direttamente un modello da Hugging Face e convertirlo in formato quantizzato:
    python setup_env.py --hf-repo HF1BitLLM/Llama3-8B-1.58-100B-tokens -q i2_s

    In alternativa, puoi scaricare e convertire manualmente il modello:

    huggingface-cli download HF1BitLLM/Llama3-8B-1.58-100B-tokens --local-dir models/Llama3-8B-1.58-100B-tokens

    python setup_env.py -md models/Llama3-8B-1.58-100B-tokens -q i2_s

Eseguire l’inferenza con BitNet.cpp

Per eseguire l’inferenza utilizzando il framework, utilizza il seguente comando:

python run_inference.py -m models/Llama3-8B-1.58-100B-tokens/ggml-model-i2_s.gguf -p "Sandra viaggiò in cucina. Dov'è Sandra?" -n 6 -temp 0.7

Spiegazione:

  • -m specifica il percorso del file del modello.
  • -p definisce il testo del prompt.
  • -n imposta il numero di token da prevedere.
  • -temp regola la casualità del campionamento (temperatura) durante l’inferenza.

Esempio di output

Sandra viaggiò in cucina. Dov'è Sandra?

Risposta: Sandra è in cucina.

Dettagli tecnici di BitNet.cpp

Layer BitLinear

BitNet.cpp implementa un’architettura Transformer modificata, sostituendo le moltiplicazioni matriciali standard con operazioni BitLinear. Questo approccio centralizza i pesi a zero prima della quantizzazione e li scala per ridurre gli errori di approssimazione. La funzione di trasformazione chiave è la seguente:


<p># Funzione di binarizzazione per pesi a 1 bit
def binarize_weights(W):
alpha = W.mean()
W_binarized = np.sign(W - alpha)
return W_binarized</p>

La combinazione di pesi centralizzati e scala assicura che l’errore di quantizzazione rimanga minimo, preservando così le prestazioni.

Impatto sull’industria

BitNet.cpp potrebbe avere implicazioni di vasta portata per il deploy dei modelli linguistici grandi:

  • Accessibilità: consente ai modelli LLM di funzionare su dispositivi standard, democratizzando l’accesso all’intelligenza artificiale potente.
  • Efficienza dei costi: riduce la necessità di costose GPU, abbassando la barriera per l’adozione.
  • Efficienza energetica: salva energia sfruttando l’inferenza basata su CPU standard.
  • Innovazione: apre nuove possibilità per le applicazioni di intelligenza artificiale sui dispositivi, come la traduzione linguistica in tempo reale, gli assistenti vocali e le applicazioni focalizzate sulla privacy senza dipendenza dal cloud.

Sfide e direzioni future

Sebbene i modelli LLM a 1 bit mostrino promesse, diverse sfide rimangono. Tra queste vi sono lo sviluppo di modelli robusti a 1 bit per compiti diversi, l’ottimizzazione dell’hardware per il calcolo a 1 bit e l’incoraggiamento degli sviluppatori ad adottare questo nuovo paradigma. Inoltre, esplorare la quantizzazione a 1 bit per compiti di visione artificiale o audio rappresenta una direzione futura emozionante.

Conclusione

Il lancio di BitNet.cpp da parte di Microsoft rappresenta un notevole progresso. Abilitando l’inferenza efficiente a 1 bit su CPU standard, BitNet.cpp crea l’accessibilità e la sostenibilità dell’intelligenza artificiale. Questo framework prepara il terreno per modelli LLM più portatili e a basso costo, spingendo i limiti di ciò che è possibile con l’intelligenza artificiale sui dispositivi.

Ho trascorso gli ultimi cinque anni immergendomi nel mondo affascinante del Machine Learning e del Deep Learning. La mia passione e la mia esperienza mi hanno portato a contribuire a oltre 50 progetti di ingegneria del software diversi, con un focus particolare su AI/ML. La mia curiosità in corso mi ha anche portato verso l'elaborazione del linguaggio naturale, un campo che sono ansioso di esplorare ulteriormente.