Seguici sui social

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

Intelligenza Artificiale

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

mm
Informazioni sugli LLM a 1 bit e sul framework BitNet.cpp di Microsoft

A ottobre 17, 2024, Microsoft ha annunciato BitNet.cpp, un framework di inferenza progettato per eseguire Large Language Model (LLM) quantizzati a 1 bit. BitNet.cpp rappresenta un progresso significativo nella Gen AI, consentendo l'implementazione efficiente di LLM a 1 bit su CPU standard, senza richiedere GPU costose. Questo sviluppo democratizza l'accesso agli LLM, rendendoli disponibili su un'ampia gamma di dispositivi e offrendo nuove possibilità nelle applicazioni AI sui dispositivi.

Comprensione dei modelli linguistici di grandi dimensioni a 1 bit

I Large Language Model (LLM) hanno tradizionalmente richiesto notevoli risorse computazionali a causa dell'uso di numeri in virgola mobile ad alta precisione (tipicamente FP16 o BF16) per i pesi del modello. Questa necessità ha reso l'implementazione di LLM costosa e ad alta intensità energetica.

In sostanza, gli LLM a 1 bit utilizzano tecniche di quantizzazione estrema per rappresentare i pesi del modello utilizzando solo tre valori possibili: -1, 0 e 1, da cui il termine "1.58 bit" (poiché è necessario poco più di un bit per codificare tre stati).

Sistema di pesi ternario

Il concetto

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

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

Ciò comporta un requisito di archiviazione di circa 1.58 bit per parametro, da cui il nome Versione di BitNet b1.58Questa drastica riduzione della larghezza dei bit dei parametri porta a 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 del peso

La binarizzazione dei pesi implica la loro centralizzazione attorno alla media (α), risultante in una rappresentazione ternaria. La trasformazione è espressa matematicamente come:

Wf =Segno(W-α)

Dove:

  • W è la matrice dei pesi originale.
  • α è la media dei pesi.
  • Segno(x) problemi +1 if x > 0 e -1 altrimenti.

2. Quantizzazione di attivazione

La quantizzazione delle attivazioni garantisce che gli input siano limitati a una larghezza di bit specificata:

Dove:

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

3. Operazione BitLinear

Il livello BitLinear sostituisce le tradizionali moltiplicazioni di matrici con un'operazione semplificata:

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

Dove:

  • β è un fattore di scala utilizzato per ridurre al minimo gli errori di approssimazione.
  • γ ridimensiona le attivazioni.
  • Q_b è il fattore di quantizzazione.

Questa trasformazione consente calcoli efficienti preservando le prestazioni del modello.

Implicazioni sulle prestazioni

Efficienza della memoria

Il sistema di pesi ternari riduce notevolmente i requisiti di memoria:

  • LLM tradizionali: 16 bit per peso
  • BitNet.cpp: 1.58 bit per peso

Questa riduzione si traduce in un risparmio di memoria di circa rispetto ai tradizionali modelli a 16 bit, consentendo ai modelli più grandi di rientrare negli stessi vincoli hardware.

Energy Efficiency

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

Velocità di inferenza è rappresentato dal numero di token elaborati al secondo. Ecco una ripartizione delle osservazioni:

  • Su Apple M2 Ultra: BitNet.cpp raggiunge fino a 5.07x accelerazione per modelli più grandi (30B) rispetto a Llama.cpp, con una velocità di picco di 593.43 gettoni al secondo per un modello 125M, che è un 1.37x speedup. Per modelli più grandi come 3.8B e 7B, BitNet.cpp mantiene una velocità di oltre 84.77 token al secondo, dimostrando la sua efficienza su tutte le scale.
  • Su Intel i7-13700H: BitNet.cpp raggiunge miglioramenti di velocità ancora più drammatici. Con la dimensione del modello 7B, BitNet.cpp offre un incredibile accelerazione di 5.68x rispetto a Llama.cpp. Per modelli più piccoli come 125M, elabora 389.08 gettoni al secondo, Che ha 2.37x più veloce di Llama.cpp.

2. Efficienza energetica: un fattore di svolta per i dispositivi edge

I grafici forniti includono anche confronti dei costi energetici, che mostra una significativa riduzione del consumo energetico per token elaborato:

  • Su Apple M2 Ultra: Il risparmio energetico di BitNet.cpp è notevole. Per il modello 700M, consuma 55.4% di energia in meno per token rispetto a Llama.cpp, passando da da 0.314 a 0.140Questa tendenza continua per i modelli più grandi, con il modello 70B che mostra un Riduzione del 70.0% dei consumi energetici.
  • Su Intel i7-13700H: BitNet.cpp fornisce Risparmio energetico del 71.9% per il modello 700M, con consumi in calo da 1.367 a 0.384Sebbene i dati energetici per il modello 70B in Llama.cpp non siano disponibili, BitNet.cpp rimane efficiente, con un consumo energetico pari a 17.33 per il modello 70B.

3. Superare il benchmark della velocità di lettura umana

Una delle intuizioni più interessanti di questi grafici è il riferimento a velocità di lettura umana, contrassegnato a 5-7 token al secondoQuesta linea rossa mostra che entrambe le implementazioni, in particolare BitNet.cpp, possono tranquillamente superare la velocità di lettura umana anche per i modelli più grandi:

  • On Mela M2 Ultra, BitNet.cpp supera la velocità di lettura umana per tutte le dimensioni del modello, con la velocità più bassa 8.67 gettoni al secondo per un modello 70B.
  • On Intel i7-13700H, il modello 100B raggiunge ancora 1.70 gettoni al secondo, sfiorando quasi la soglia minima della velocità di lettura umana, mentre tutti i modelli più piccoli superano questo parametro di riferimento.

Considerazioni sulla formazione

Stima diretta (STE)

Poiché la quantizzazione a 1 bit introduce funzioni non differenziabili, l'addestramento comporta una tecnica specializzata nota come Stima diretta (STE). In questo approccio, i gradienti scorrono inalterati attraverso punti non differenziabili. Ecco un'implementazione semplificata in Python:

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

    @staticmethod
    def backward(ctx, grad_output):
        return grad_output

Allenamento di precisione mista

Per mantenere la stabilità durante l'allenamento, precisione mista è impiegato:

  • Pesi e attivazioni: Quantizzato con precisione a 1 bit.
  • Gradienti e stati di ottimizzazione: Memorizzato con maggiore precisione.
  • Pesi latenti: Mantenuto con elevata precisione per facilitare aggiornamenti accurati durante l'addestramento.

Strategia di alto tasso di apprendimento

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

Quantizzazione e normalizzazione di gruppo

BitNet.cpp introduce Quantizzazione e normalizzazione di gruppo per migliorare il parallelismo del modello. Invece di calcolare i parametri per l'intera matrice dei pesi, BitNet divide pesi e attivazioni in più gruppi (G).

Questo raggruppamento consente un'elaborazione parallela efficiente senza ulteriori comunicazioni tra gruppi, consentendo l'addestramento e l'inferenza di modelli su larga scala.

Note di implementazione e ottimizzazioni

Ottimizzazione della CPU

BitNet.cpp sfrutta diverse ottimizzazioni di basso livello per raggiungere le massime prestazioni della CPU:

  • Operazioni vettorizzate: Utilizza istruzioni SIMD per eseguire manipolazioni di bit in modo efficiente.
  • Accesso alla memoria compatibile con la cache: Struttura i dati per ridurre al minimo le mancanze di cache.
  • Elaborazione parallela: Distribuisce efficacemente il carico di lavoro su più core della CPU.

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

 
def bitlinear_forward(input, weight, scale):
    # Quantize the input using absmax quantization
    input_q = quantize(input)
    
    # Perform binary matrix multiplication
    output = binary_matmul(input_q, weight)
    
    # Scale the output to match the original precision
    return output * scale

def quantize(x):
    # Perform absmax quantization
    scale = torch.max(torch.abs(x))
    return torch.clamp(x / scale, -1, 1) * scale

I modelli supportati

La versione corrente di BitNet.cpp supporta quanto segue LLM a 1 bit disponibili su Hugging Face:

  • bitnet_b1_58-grande (0.7 miliardi di parametri)
  • bitnet_b1_58-3B (3.3 miliardi di parametri)
  • Llama3-8B-1.58-100B-gettoni (8.0 miliardi di parametri)

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

Guida all'installazione

Per iniziare a usare BitNet.cpp, segui i passaggi sottostanti:

Prerequisiti

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

Da Windows utenti, Visual Studio deve essere installato 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)

Da Debian / Ubuntu utenti, è disponibile uno script di installazione automatica:

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

Installazione passo passo

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

    cd BitNet
  2. Installa dipendenze:
    # Create a new Conda environment (recommended)
    conda create -n bitnet-cpp python=3.9
    conda activate bitnet-cpp


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

    In alternativa, 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

Esecuzione dell'inferenza con BitNet.cpp

Per eseguire l'inferenza utilizzando il framework, utilizzare il seguente comando:

python run_inference.py -m models/Llama3-8B-1.58-100B-tokens/ggml-model-i2_s.gguf -p "Sandra journeyed to the kitchen. Where is Sandra?" -n 6 -temp 0.7

Spiegazione:

  • -m specifica il percorso del file 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 uscita

Sandra journeyed to the kitchen. Where is Sandra?

Answer: Sandra is in the kitchen.

Dettagli tecnici di BitNet.cpp

Strato BitLineare

BitNet.cpp implementa un'architettura Transformer modificata, sostituendo le moltiplicazioni di matrice standard con BitLinear operazioni. Questo approccio centralizza i pesi a zero prima della quantizzazione e li ridimensiona per ridurre gli errori di approssimazione. La funzione di trasformazione chiave appare così:

# Binarization function for 1-bit weights
def binarize_weights(W):
    alpha = W.mean()
    W_binarized = np.sign(W - alpha)
    return W_binarized

La combinazione di pesi centralizzati e ridimensionamento garantisce che l'errore di quantizzazione rimanga minimo, preservando così le prestazioni.

Impatto sul settore

BitNet.cpp potrebbe avere implicazioni di vasta portata per l'implementazione di LLM:

  • Accessibilità: Consente agli LLM di funzionare su dispositivi standard, democratizzando l'accesso a una potente intelligenza artificiale.
  • Efficienza dei costi: Riduce la necessità di costose GPU, abbassando la barriera all'adozione.
  • Energy Efficiency: Risparmia energia sfruttando l'inferenza standard basata sulla CPU.
  • Innovazione: Apre nuove possibilità per l'intelligenza artificiale sui dispositivi, come la traduzione linguistica in tempo reale, gli assistenti vocali e le applicazioni incentrate sulla privacy senza dipendenze dal cloud.

Sfide e direzioni future

Sebbene gli LLM a 1 bit siano promettenti, restano diverse sfide. Tra queste, lo sviluppo di modelli a 1 bit robusti per attività diverse, l'ottimizzazione dell'hardware per il calcolo a 1 bit e l'incoraggiamento degli sviluppatori ad adottare questo nuovo paradigma. Inoltre, l'esplorazione della quantizzazione a 1 bit per attività di visione artificiale o audio rappresenta un'entusiasmante direzione futura.

Conclusione

Il lancio di BitNet.cpp da parte di Microsoft rappresenta un progresso significativo. Abilitando un'efficace inferenza a 1 bit su CPU standard, BitNet.cpp crea l'accessibilità e la sostenibilità dell'IA. Questo framework prepara il terreno per LLM più portatili e convenienti, spingendo ciò che è possibile con l'IA sul dispositivo.

Ho trascorso gli ultimi cinque anni immergendomi nell'affascinante mondo del Machine Learning e del Deep Learning. La mia passione e competenza mi hanno portato a contribuire a oltre 50 diversi progetti di ingegneria del software, con un focus particolare su AI/ML. La mia continua curiosità mi ha anche attirato verso l'elaborazione del linguaggio naturale, un campo che non vedo l'ora di esplorare ulteriormente.