KI-Modelle und Plattformen

Microsofts Inferenzframework bringt 1-Bit-Großsprachmodelle auf lokale Geräte

mm
Unite.AI zu deinen bevorzugten Quellen auf Google hinzufügen

Am 17. Oktober 2024 kündigte Microsoft (MSFT ) BitNet.cpp an, ein Inferenzframework, das für die Ausführung von 1-Bit-quantifizierten Großsprachmodellen (LLMs) konzipiert ist. BitNet.cpp ist ein bedeutender Fortschritt im Bereich der künstlichen Intelligenz, da es die effiziente Ausführung von 1-Bit-LLMs auf Standard-CPUs ermöglicht, ohne dass teure GPUs erforderlich sind. Diese Entwicklung demokratisiert den Zugang zu LLMs und macht sie auf einer breiten Palette von Geräten verfügbar, wodurch neue Möglichkeiten für On-Device-KI-Anwendungen entstehen.

Verständnis von 1-Bit-Großsprachmodellen

Großsprachmodelle (LLMs) erforderten traditionell aufgrund ihrer Verwendung von Hochpräzisions-Gleitkommazahlen (in der Regel FP16 oder BF16) für Modellgewichte erhebliche Rechenressourcen. Diese Notwendigkeit hat die Bereitstellung von LLMs teuer und energieintensiv gemacht.

Im Kern verwenden 1-Bit-LLMs extreme Quantisierungstechniken, um Modellgewichte mit nur drei möglichen Werten darzustellen: -1, 0 und 1, daher der Begriff “1,58-Bit” (da er slightly mehr als ein Bit benötigt, um drei Zustände zu kodieren).

Ternäres Gewichtssystem

Das Konzept

Die 1-Bit-Quantisierung in BitNet.cpp ist ein ternäres Gewichtssystem. BitNet arbeitet mit nur drei möglichen Werten für jeden Parameter:

  • -1 (negativ)
  • 0 (neutral)
  • 1 (positiv)

Dies führt zu einem Speicherbedarf von etwa 1,58 Bits pro Parameter, daher der Name BitNet b1.58. Diese drastische Reduzierung der Parameter-Bitbreite führt zu einer beeindruckenden Reduzierung des Speicherbedarfs und der Rechenkomplexität, da die meisten Gleitkommamultiplikationen durch einfache Additionen und Subtraktionen ersetzt werden.

Mathematische Grundlage

1-Bit-Quantisierung beinhaltet die Transformation von Gewichten und Aktivierungen in ihre ternäre Darstellung durch die folgenden Schritte:

1. Gewichtsbinarisierung

Die Binarisierung der Gewichte beinhaltet die Zentrierung um den Mittelwert (α), was zu einer ternären Darstellung führt. Die Transformation wird mathematisch wie folgt ausgedrückt:

Wf​=Sign(W−α)

Wo:

  • W ist die ursprüngliche Gewichtsmatrix.
  • α ist der Mittelwert der Gewichte.
  • Sign(x) gibt +1 zurück, wenn x > 0 und -1 sonst.

2. Aktivierungsquantisierung

Die Quantisierung der Aktivierungen stellt sicher, dass die Eingaben auf eine bestimmte Bitbreite beschränkt sind:

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

Wo:

  • Qb = 2(b−1)2^{(b-1)} ist der maximale Quantisierungsgrad für die b-Bit-Breite.
  • γ ist der maximale absolute Wert von x (bezeichnet als ∣∣x∣∣∞).
  • ε ist eine kleine Zahl, um Überläufe während der Berechnungen zu vermeiden.

3. BitLinear-Operation

Die BitLinear-Schicht ersetzt traditionelle Matrixmultiplikationen durch eine vereinfachte Operation:

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

Wo:

  • β ist ein Skalierungsfaktor, der verwendet wird, um Approximationsfehler zu minimieren.
  • γ skaliert die Aktivierungen.
  • Q_b ist der Quantisierungsfaktor.

Diese Transformation ermöglicht effiziente Berechnungen, während die Modellleistung erhalten bleibt.

Leistungsimplikationen

Speichereffizienz

Das ternäre Gewichtssystem reduziert den Speicherbedarf erheblich:

  • Traditionelle LLMs: 16 Bits pro Gewicht
  • BitNet.cpp: 1,58 Bits pro Gewicht

Diese Reduzierung entspricht einer Speicherersparnis von etwa 90% im Vergleich zu traditionellen 16-Bit-Modellen, wodurch größere Modelle innerhalb der gleichen Hardware-Beschränkungen untergebracht werden können.

Energieeffizienz

Inferenzgeschwindigkeit, Energieeffizienz (Apple [securities_stock_price_tag symbol="AAPL" exchange="NASDAQ"] M2)

 

Inferenzgeschwindigkeit: Schneller auf beiden CPUs

Inferenzgeschwindigkeit, Energieeffizienz (i7-13700H)

1. Inferenzgeschwindigkeit: Schneller auf beiden CPUs

Die Inferenzgeschwindigkeit wird als Anzahl der pro Sekunde verarbeiteten Token dargestellt. Hier ist eine Zusammenfassung der Beobachtungen:

  • Auf Apple M2 Ultra: BitNet.cpp erreicht bis zu 5,07-fache Geschwindigkeitssteigerung für größere Modelle (30B) im Vergleich zu Llama.cpp, mit einer Spitzenleistung von 593,43 Token pro Sekunde für ein 125M-Modell, was eine 1,37-fache Steigerung darstellt. Für größere Modelle wie 3,8B und 7B hält BitNet.cpp eine Geschwindigkeit von über 84,77 Token pro Sekunde, was seine Effizienz über verschiedene Größen hinweg zeigt.
  • Auf Intel (INTC ) i7-13700H: BitNet.cpp erreicht noch dramatischere Geschwindigkeitssteigerungen. Bei einer Modellgröße von 7B liefert BitNet.cpp eine atemberaubende 5,68-fache Steigerung im Vergleich zu Llama.cpp. Für kleinere Modelle wie 125M verarbeitet es 389,08 Token pro Sekunde, was 2,37-mal schneller ist als Llama.cpp.

2. Energieeffizienz: Ein Game-Changer für Edge-Geräte

Die bereitgestellten Grafiken enthalten auch Energiekostenvergleiche, die eine signifikante Reduzierung des Energieverbrauchs pro verarbeitetem Token zeigen:

  • Auf Apple M2 Ultra: Die Energieeinsparungen von BitNet.cpp sind erheblich. Für das 700M-Modell verbraucht es 55,4% weniger Energie pro Token im Vergleich zu Llama.cpp, von 0,314 auf 0,140. Diese Tendenz setzt sich für größere Modelle fort, wobei das 70B-Modell eine 70,0-prozentige Reduzierung des Energieverbrauchs zeigt.
  • Auf Intel i7-13700H: BitNet.cpp liefert 71,9-prozentige Energieeinsparungen für das 700M-Modell, wobei der Verbrauch von 1,367 auf 0,384 sinkt. Obwohl Energie-Daten für das 70B-Modell in Llama.cpp nicht verfügbar sind, bleibt BitNet.cpp effizient, mit einem Energieverbrauch von 17,33 für das 70B-Modell.

3. Überschreitung der menschlichen Lesegeschwindigkeits-Benchmark

Eine der interessantesten Erkenntnisse aus diesen Grafiken ist der Verweis auf die menschliche Lesegeschwindigkeit, die bei 5-7 Token pro Sekunde markiert ist. Diese rote Linie zeigt, dass beide Implementierungen, insbesondere BitNet.cpp, die menschliche Lesegeschwindigkeit für die größten Modelle mühelos überschreiten:

  • Auf Apple M2 Ultra überschreitet BitNet.cpp die menschliche Lesegeschwindigkeit für alle Modellgrößen, wobei die niedrigste Geschwindigkeit 8,67 Token pro Sekunde für ein 70B-Modell beträgt.
  • Auf Intel i7-13700H erreicht das 100B-Modell immer noch 1,70 Token pro Sekunde, was fast den unteren Bereich der menschlichen Lesegeschwindigkeit erreicht, während alle kleineren Modelle diese Benchmark überschreiten.

Trainingsüberlegungen

Straight-Through-Estimator (STE)

Da die 1-Bit-Quantisierung nicht differenzierbare Funktionen einführt, beinhaltet das Training eine spezielle Technik, die als Straight-Through-Estimator (STE) bekannt ist. Bei diesem Ansatz fließen die Gradienten unverändert durch nicht differenzierbare Punkte. Hier ist eine vereinfachte Implementierung in Python:

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

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

Mixed-Precision-Training

Um die Stabilität während des Trainings zu erhalten, wird Mixed Precision eingesetzt:

  • Gewichte und Aktivierungen: Quantisiert auf 1-Bit-Präzision.
  • Gradienten und Optimiererzustände: In höherer Präzision gespeichert.
  • Latente Gewichte: In hoher Präzision beibehalten, um genaue Updates während des Trainings zu ermöglichen.

Große Lernrate-Strategie

Eine besondere Herausforderung bei 1-Bit-Modellen ist, dass kleine Updates die binarisierten Gewichte möglicherweise nicht beeinflussen. Um dies zu überwinden, wird die Lernrate erhöht, um eine schnellere Konvergenz und bessere Optimierung im Vergleich zu herkömmlichen Ansätzen zu gewährleisten.

Gruppenquantisierung und -normalisierung

BitNet.cpp führt Gruppenquantisierung und -normalisierung ein, um die Modellparallelisierung zu verbessern. Anstatt Parameter für die gesamte Gewichtsmatrix zu berechnen, teilt BitNet die Gewichte und Aktivierungen in mehrere Gruppen (G) auf.
Dieses Gruppieren ermöglicht eine effiziente parallele Verarbeitung ohne zusätzliche Kommunikation zwischen den Gruppen, wodurch das Training und die Inferenz großer Modelle ermöglicht werden.

Implementierungsnotizen und Optimierungen

CPU-Optimierung

BitNet.cpp nutzt mehrere niedrigstufige Optimierungen, um die Spitzenleistung auf CPUs zu erzielen:

  • Vektorisierte Operationen: Nutzt SIMD-Anweisungen, um Bit-Manipulationen effizient durchzuführen.
  • Cache-freundlicher Speicherzugriff: Strukturiert Daten, um Cache-Verfehlungen zu minimieren.
  • Parallele Verarbeitung: Verteilt die Arbeitslast effektiv auf mehrere CPU-Kerne.

Hier ist ein Beispiel für eine Schlüsseleigenschaft, die die Quantisierung und Inferenz in BitNet implementiert:


def bitlinear_forward(input, weight, scale):
# Quantisiere die Eingabe mithilfe der Absmax-Quantisierung
input_q = quantize(input)

# Führe binäre Matrixmultiplikation durch
output = binary_matmul(input_q, weight)

# Skaliere die Ausgabe, um die ursprüngliche Präzision zu erreichen
return output * scale

def quantize(x):
# Führe Absmax-Quantisierung durch
scale = torch.max(torch.abs(x))
return torch.clamp(x / scale, -1, 1) * scale
[/code]

Unterstützte Modelle

Die aktuelle Version von BitNet.cpp unterstützt die folgenden 1-Bit-LLMs, die auf Hugging Face verfügbar sind:

  • bitnet_b1_58-large (0,7 Mrd. Parameter)
  • bitnet_b1_58-3B (3,3 Mrd. Parameter)
  • Llama3-8B-1.58-100B-tokens (8,0 Mrd. Parameter)

Diese Modelle sind öffentlich verfügbar, um die Inferenzfähigkeiten des Frameworks zu demonstrieren. Obwohl sie nicht offiziell von Microsoft trainiert oder veröffentlicht wurden, veranschaulichen sie die Vielseitigkeit des Frameworks.

Installationsanleitung

Um mit BitNet.cpp zu beginnen, folgen Sie den Schritten unten:

Voraussetzungen

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

Für Windows-Benutzer sollte Visual Studio mit den folgenden Komponenten installiert werden:

  • Desktop-Entwicklung mit C++
  • C++-CMake-Tools für Windows
  • Git für Windows
  • C++-Clang-Compiler für Windows
  • MS-Build-Unterstützung für LLVM-Toolset (Clang)

Für Debian/Ubuntu-Benutzer ist ein automatisches Installations-Skript verfügbar:

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

Schritt-für-Schritt-Installation

  1. Repository klonen:
    git clone --recursive https://github.com/microsoft/BitNet.git

    cd BitNet
  2. Abhängigkeiten installieren:
    # Erstelle eine neue Conda-Umgebung (empfehlenswert)
    conda create -n bitnet-cpp python=3.9
    conda activate bitnet-cpp


    pip install -r requirements.txt
  3. Projekt aufbauen und vorbereiten: Sie können ein Modell direkt von Hugging Face herunterladen und in ein quantisiertes Format umwandeln:
    python setup_env.py --hf-repo HF1BitLLM/Llama3-8B-1.58-100B-tokens -q i2_s

    Alternativ können Sie das Modell manuell herunterladen und umwandeln:

    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

Inferenz mit BitNet.cpp ausführen

Um Inferenz mit dem Framework durchzuführen, verwenden Sie den folgenden Befehl:

python run_inference.py -m models/Llama3-8B-1.58-100B-tokens/ggml-model-i2_s.gguf -p "Sandra reiste in die Küche. Wo ist Sandra?" -n 6 -temp 0.7

Erklärung:

  • -m gibt den Modell-Dateipfad an.
  • -p definiert den Prompt-Text.
  • -n legt die Anzahl der zuvorherzusagenden Token fest.
  • -temp passt die Stichprobenzufälligkeit (Temperatur) während der Inferenz an.

Ausgabebeispiel

Sandra reiste in die Küche. Wo ist Sandra?

Antwort: Sandra ist in der Küche.

Technische Details von BitNet.cpp

BitLinear-Schicht

BitNet.cpp implementiert eine modifizierte Transformer-Architektur, bei der Standard-Matrixmultiplikationen durch BitLinear-Operationen ersetzt werden. Dieser Ansatz zentriert die Gewichte auf Null, bevor sie quantisiert werden, und skaliert sie, um Approximationsfehler zu minimieren. Die Schlüsseltransformation sieht wie folgt aus:


<p># Binarisierungsfunktion für 1-Bit-Gewichte
def binarize_weights(W):
alpha = W.mean()
W_binarized = np.sign(W - alpha)
return W_binarized</p>

Die Kombination aus zentrierten Gewichten und Skalierung stellt sicher, dass der Quantisierungsfehler minimal bleibt, wodurch die Leistung erhalten bleibt.

Branchenwirkung

BitNet.cpp könnte weitreichende Auswirkungen auf die Bereitstellung von LLMs haben:

  • Zugänglichkeit: Ermöglicht es LLMs, auf Standardgeräten zu laufen, wodurch der Zugang zu leistungsfähiger KI demokratisiert wird.
  • Kosten-Effizienz: Reduziert den Bedarf an teuren GPUs, wodurch die Einstiegshürde für die Übernahme gesenkt wird.
  • Energie-Effizienz: Spart Energie, indem es die CPU-basierte Inferenz nutzt.
  • Innovation: Ermöglicht neue Möglichkeiten für On-Device-KI, wie Echtzeit-Übersetzung, Sprachassistenten und Datenschutz-orientierte Anwendungen ohne Cloud-Abhängigkeit.

Herausforderungen und zukünftige Richtungen

Während 1-Bit-LLMs vielversprechend sind, bleiben einige Herausforderungen bestehen. Dazu gehören die Entwicklung robuster 1-Bit-Modelle für verschiedene Aufgaben, die Optimierung von Hardware für 1-Bit-Berechnungen und die Förderung der Übernahme dieses neuen Paradigmas durch Entwickler. Darüber hinaus stellt die Erforschung von 1-Bit-Quantisierung für Computer-Vision- oder Audio-Aufgaben eine spannende zukünftige Richtung dar.

Schlussfolgerung

Microsofts Einführung von BitNet.cpp ist ein bedeutender Fortschritt. Durch die Ermöglichung effizienter 1-Bit-Inferenz auf Standard-CPUs schafft BitNet.cpp Zugänglichkeit und Nachhaltigkeit von KI. Dieses Framework ebnet den Weg für portablere und kostengünstigere LLMs und erweitert die Möglichkeiten von On-Device-KI.

Ich habe die letzten fünf Jahre damit verbracht, mich in die faszinierende Welt des Machine Learning und Deep Learning zu vertiefen. Mein Engagement und meine Expertise haben mich dazu geführt, an über 50 verschiedenen Software-Entwicklungsprojekten mit einem besonderen Fokus auf AI/ML beizutragen. Meine anhaltende Neugier hat mich auch zum Bereich der Natural Language Processing hingezogen, einem Feld, das ich weiter erforschen möchte.