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

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.
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:
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
- Python > = 3.9
- CMake > = 3.22
- clangore > = 18
- 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:
Installazione passo passo
- Clona il repository:
- Installa dipendenze:
- Costruire e preparare il progetto: Puoi scaricare un modello direttamente da Hugging Face e convertirlo in un formato quantizzato:
In alternativa, scaricare e convertire manualmente il modello:
Esecuzione dell'inferenza con BitNet.cpp
Per eseguire l'inferenza utilizzando il framework, utilizzare il seguente comando:
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
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.