Nachricht

Tausende Wörter technischer Informationen! Visuelle Illustrationen sind ein unverzichtbarer Quantifizierungsleitfaden für LLM-Ingenieure und zeigen, wie große Modelle komprimiert werden

2024-07-31

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina


Neuer Weisheitsbericht

Herausgeber: Redaktion

[Einführung in die neue Weisheit] Angesichts der allmählich wachsenden Parameterskala von LLM haben Entwickler und Forscher ohne H100 viele Möglichkeiten gefunden, dies auszugleichen, und die „Quantifizierungs“-Technologie ist eine davon. Dieser visuelle Leitfaden fasst anhand verschiedener Abbildungen die Grundkonzepte und Zweigmethoden der „Quantifizierung“ umfassend zusammen.

Große Sprachmodelle (LLMs) sind oft zu groß, um auf Consumer-Hardware ausgeführt zu werden. Diese Modelle können mehr als Milliarden Parameter haben und erfordern oft GPUs mit großem Speicher, um den Inferenzprozess zu beschleunigen.

Daher konzentrieren sich immer mehr Forschungsarbeiten darauf, wie das Modell verkleinert werden kann, beispielsweise durch die Verbesserung der Trainingsmethoden oder die Verwendung von Adaptern. Eine der Haupttechniken in diesem Bereich ist die sogenannte Quantisierung.

Der ML-Ingenieur Maarten Grootendorst hat einen Blogbeitrag geschrieben, der speziell die Quantifizierungstechnologie im Kontext der Sprachmodellierung vorstellt und verwandte Konzepte nacheinander mithilfe visueller Methoden untersucht, um uns dabei zu helfen, ein intuitives Verständnis der Technologie aufzubauen.


In diesem Blogbeitrag untersucht Maarten verschiedene Methoden, Anwendungsfälle und die Prinzipien der Quantifizierung.

Das Inhaltsverzeichnis und der Inhalt des Artikels sind in der folgenden Abbildung dargestellt. Es werden hauptsächlich die beiden Methoden der Post-Training-Quantifizierung (PTQ) und des quantisierungsbewussten Trainings (QAT) vorgestellt. Lesern mit Grundkenntnissen in KI wird empfohlen, zu springen direkt zum symmetrischen Quantisierungsteil:


Erster Teil: Das „Problem“ von LLM

„Große Sprachmodelle“ sind hinsichtlich der Anzahl der Modellparameter groß und erreichen normalerweise einen Maßstab von mehreren Milliarden (hauptsächlich Gewichte).

Die Speicherkosten dieser Parameter sind nicht nur recht hoch, sondern auch der Rechenaufwand in der Inferenzphase ist groß.

Während der Inferenz ist der Aktivierungswert das Produkt aus Eingabe und Gewichtung. Je größer die Anzahl der Gewichtungen, desto größer der Aktivierungswert.


Daher möchten wir Milliarden von Werten so effizient wie möglich darstellen und so den Platzbedarf zum Speichern von Parametern minimieren.

Beginnen wir am Anfang und untersuchen wir, wie Werte vor der Optimierung dargestellt werden.

So stellen Sie numerische Werte dar

Numerische Werte werden normalerweise als Gleitkommazahlen (oder einfach Floats) gespeichert: eine positive oder negative Zahl mit einem Dezimalpunkt.

Diese Werte werden durch Binärziffern für jedes Bit dargestellt.

Der IEEE-754-Standard beschreibt, wie die Ziffern auf jeder Ziffer einen bestimmten Wert darstellen. Konkret gibt es drei Zuordnungen: Vorzeichen, Exponent oder Dezimalzahl (Mantisse).


Diese drei Teile können kombiniert werden, um den dargestellten Wert basierend auf einer Reihe von Bitwerten zu berechnen:


Je mehr Ziffern verwendet werden, desto genauer ist der numerische Wert. Beispielsweise kann die FP32-Form auf mehr Nachkommastellen genau sein als FP16:


Speicherlimit

Je mehr Ziffern zur Verfügung stehen, desto genauer ist der Wert, sondern desto größer ist auch der darstellbare Wertebereich.


Bei gegebener Bitzahl und Darstellung wird der darstellbare Wertebereich als Dynamikbereich und der Abstand zwischen zwei benachbarten Werten als Präzision bezeichnet.


Ein nettes Merkmal dieser Darstellung ist, dass wir berechnen können, wie viel Speicher das Gerät zum Speichern eines bestimmten Werts benötigt.

Da jedes Byte im Speicher 8 Bits enthält, können wir für die meisten Formen von Gleitkommazahlen eine Grundformel erstellen:


In realen Anwendungen gibt es viele weitere Faktoren, die sich auf die Menge an Grafik/Speicher auswirken, die während der Inferenz benötigt wird, wie zum Beispiel die Kontextgröße und die Modellarchitektur.

Stellen Sie sich nun vor, wir hätten ein Modell mit 70 Milliarden Parametern. Die meisten Modelle selbst werden mithilfe von 32-Bit-Gleitkommazahlen (oft als volle Genauigkeit bezeichnet) dargestellt, was zum Laden des Modells 280 GB Speicher erfordert.


Wenn jedoch alle Parameter als 16-Bit-Gleitkommazahlen ausgedrückt werden können, kann die erforderliche Speichergröße direkt um ein Mal reduziert werden.

Daher ist es sehr attraktiv, die Anzahl der Darstellungen von Modellparametern zu minimieren (nicht nur für Inferenz, sondern auch für das Training).

Allerdings ist dieser Ansatz nicht ohne Kosten. Die Genauigkeit des Modells nimmt typischerweise mit abnehmender Anzahl der Darstellungsbits ab, was zu einer geringeren Genauigkeit führt.

Wir möchten die Anzahl der Ziffern reduzieren, die zur Darstellung eines Werts verwendet werden, und gleichzeitig die Genauigkeit beibehalten. Hier bieten sich Quantisierungstechniken an.

Teil 2: Einführung in die Quantifizierung

Wir wissen jetzt, dass der Zweck der Quantisierung darin besteht, die Genauigkeit von Modellparametern von höheren Bitbreiten (z. B. 32-Bit-Gleitkommazahlen) auf niedrigere Bitbreiten (z. B. 8-Bit-Ganzzahlen) zu verringern.


Wenn die Anzahl der Bits reduziert wird, die die ursprünglichen Parameter darstellen, geht normalerweise ein gewisser Verlust an Präzision (Granularität) einher.

Um diesen Effekt intuitiver zu gestalten, können wir Fotofarben als Analogie verwenden. Wählen Sie beispielsweise ein beliebiges Bild aus (links), verwenden Sie jedoch nur 8 Farben (rechts):


Beachten Sie, dass der vergrößerte Keks „körniger“ aussieht als das Original.

In ähnlicher Weise besteht das Hauptziel der Quantisierung darin, die Anzahl der Bits (Farben) zu reduzieren, die zur Darstellung der ursprünglichen Parameter erforderlich sind, und gleichzeitig die größtmögliche Präzision der ursprünglichen Parameter beizubehalten.

Gängige Datentypen

Schauen wir uns zunächst gängige Datentypen und die Auswirkungen ihrer Verwendung anstelle der 32-Bit-Darstellung (Full-Precision oder FP32 genannt) an.

FP16

Das erste ist ein Beispiel für den Wechsel von 32-Bit- zu 16-Bit-Gleitkommazahlen (halbe Genauigkeit oder FP16 genannt):


Der Bereich der möglichen Werte ist für FP16 deutlich kleiner als der für FP32.

BF16

Um einen ähnlichen Zahlenbereich wie beim ursprünglichen FP32 zu erhalten, wurde bfloat 16 als „truncated FP32“-Typ eingeführt:


BF16 verwendet die gleiche Anzahl von Bits wie FP16, fügt jedoch ein exponentielles Bit hinzu, sodass ein größerer Wertebereich erzielt werden kann, und wird häufig im Bereich Deep Learning verwendet.

INT8

Wenn Sie die Anzahl der Bits weiter reduzieren, nähert sich die Darstellung eher einer Ganzzahl als einer Gleitkommazahl an. Wenn Sie beispielsweise von FP32 zu INT8 wechseln, das nur 8 Bits hat, nur 1/4 der ursprünglichen Anzahl an Bits:


Jedes Mal, wenn die Anzahl der Bits reduziert wird, wird eine Zuordnung durchgeführt, um die ursprüngliche FP32-Darstellung in weniger Bits zu „komprimieren“.

Im tatsächlichen Betrieb müssen wir jedoch nicht den gesamten FP32-Bereich [-3.4e38, 3.4e38] in INT8 abbilden. Wir müssen nur einen Weg finden, den Datenbereich der tatsächlichen Modellparameter in INT8 abzubilden.

Zu den gängigen Komprimierungs-/Zuordnungsmethoden gehören die symmetrische Quantisierung und die asymmetrische Quantisierung, bei denen es sich beide um eine lineare Abbildung handelt.

Was wir als nächstes besprechen werden, ist die Quantisierungsmethode von FP32 bis INT8.

Symmetrische Quantisierung

Bei der symmetrischen Quantisierung wird der Bereich des ursprünglichen Gleitkommawerts auf einen symmetrischen Bereich abgebildet, der im Quantisierungsraum auf Null zentriert ist, wobei Null der Mittelpunkt des Bereichs vor und nach der Quantisierung ist.

Dies bedeutet, dass der ursprüngliche Nullpunkt im Gleitkommaraum nach der Abbildung auf den quantisierten Raum genau Null ist.


Ein typisches Beispiel für eine symmetrische Quantisierung ist die Quantisierung mit dem absoluten Maximum (absmax).

Bei einer gegebenen Werteliste nehmen wir den höchsten Absolutwert (α) als Bereich für die lineare Abbildung.


[-127, 127] stellt den eingeschränkten Bereich dar, und der uneingeschränkte Bereich ist [-128, 127], abhängig von der Quantisierungsmethode

Da es sich um eine lineare Karte handelt, deren Mittelpunkt bei Null liegt, ist die Formel einfach.

Berechnen Sie zunächst den/die Skalierungsfaktor(en) mit folgender Formel:

- b ist die Anzahl der Bytes, die wir auf (8) quantisieren möchten.

- α ist der höchste absolute Wert

Wir verwenden dann s, um die Eingabe x zu quantisieren:


Wie in der Abbildung oben gezeigt, beträgt der maximale Absolutwert α 10,8. Bei der Zuordnung von FP32 zu INT8 wird die folgende Formel erhalten:


Wenn Sie die ursprünglichen FP32-Werte wiederherstellen möchten, können Sie auch die zuvor berechneten Skalierungsfaktoren für die inverse Quantisierung verwenden.


Zuerst quantisieren und dann dequantisieren, um den ursprünglichen Wert wiederherzustellen. Der gesamte Vorgang ist wie folgt:


Sie können sehen, dass einige Werte, z. B. 3,08 und 3,02, beide 36 sind, wenn sie auf INT8 quantisiert werden. Wenn sie also wieder auf FP32 dequantisiert werden, verlieren sie etwas an Präzision und sind nicht mehr unterscheidbar.

Diese Differenz zwischen dem Originalwert und dem invers quantisierten Wert wird Quantisierungsfehler genannt. Generell gilt: Je weniger Bits das Quantisierungsergebnis hat, desto größer ist der Fehler.


asymmetrische Quantisierung

Im Gegensatz zur symmetrischen Quantisierung handelt es sich bei der asymmetrischen Quantisierung nicht um eine Nullpunktsymmetrie. Stattdessen werden die minimalen (β) und maximalen (α) Werte des Gleitkommabereichs auf die minimalen bzw. maximalen Werte des quantisierten Bereichs abgebildet.

Die Methode, die wir hier untersuchen, wird Nullpunktquantisierung genannt.


Beachten Sie, wie sich die Position 0 verschoben hat. Deshalb spricht man von asymmetrischer Quantisierung. Im Bereich [-7,59, 10,8] liegen die Maximal- und Minimalwerte in unterschiedlichen Abständen von 0.

Aufgrund des Versatzes der Nullpunktposition müssen wir den Nullpunkt im INT8-Bereich berechnen, um eine lineare Abbildung durchzuführen. Wie zuvor müssen wir auch den/die Skalierungsfaktor(en) berechnen, allerdings unter Verwendung der Differenz im INT8-Bereich [-128, 127].


Dies ist etwas kompliziert, da der Nullpunkt (z) im INT8-Bereich berechnet werden muss, um die Gewichte zu verschieben.

Füllen wir wie zuvor die Formel aus:


Um den quantisierten Wert von INT8 zurück auf FP32 zu dequantisieren, müssen wir den zuvor berechneten Skalierungsfaktor (s) und den Nullpunkt (z) verwenden.

Ansonsten ist die Dequantisierung einfach:


Wenn wir symmetrische und asymmetrische Quantisierung nebeneinander stellen, können wir schnell den Unterschied zwischen den beiden Methoden erkennen:


Im Bild oben sehen wir die Nullzentrumscharakteristik der symmetrischen Quantisierung und den Versatz der asymmetrischen Quantisierung.

Bereichszuordnung und Clipping (Clipping)

Im vorherigen Beispiel haben wir untersucht, wie ein Wertebereich in einem bestimmten Vektor einer Low-Bit-Darstellung zugeordnet wird. Damit kann zwar der gesamte Bereich von Vektorwerten abgebildet werden, es gibt jedoch einen großen Nachteil: Ausreißer.

Stellen Sie sich vor, Sie haben einen Vektor, der die folgenden Werte enthält:


Ein Wert, der viel größer ist als alle anderen, kann als Ausreißer betrachtet werden. Wenn wir den gesamten Vektorbereich abbilden, werden alle kleinen Werte derselben Darstellung niedriger Ordnung zugeordnet und verlieren ihre Unterscheidungskraft:


Dies ist die zuvor verwendete Absmax-Methode.Das Gleiche passiert bei asymmetrischer Quantisierung ohne Clipping

Stattdessen können wir bestimmte Werte abschneiden. Unter Clipping versteht man das Festlegen eines anderen Dynamikbereichs der Originalwerte, sodass alle Ausreißer auf den gleichen Wert gesetzt werden.

Im folgenden Beispiel stellen wir den Dynamikbereich manuell auf [-5, 5] ein und alle Werte außerhalb dieses Bereichs werden unabhängig von ihrem tatsächlichen Wert auf -127 oder 127 abgebildet:


Der Hauptvorteil dieses Ansatzes besteht darin, dass der Quantisierungsfehler für Nicht-Ausreißer deutlich reduziert wird. Dies führt jedoch zu einem erhöhten Quantisierungsfehler für Ausreißer.

Kalibrierung

Im obigen Beispiel haben wir den Dynamikbereich zufällig auf [-5, 5] eingestellt, aber die Entscheidung sollte durch einen „Kalibrierungsprozess“ getroffen werden, um einen geeigneten Bereich zu finden, der so viele Werte wie möglich umfasst und gleichzeitig den Quantisierungsfehler minimiert.

Die konkrete Ausführung der Kalibrierungsschritte ist für verschiedene Parametertypen unterschiedlich.

Gewichtungen (und Vorurteile)

Wir können uns die Gewichtungen und Verzerrungen eines großen Sprachmodells (LLM) als statische Werte vorstellen, da sie vor der Ausführung des Modells bekannt sind. Beispielsweise besteht die ~20-GB-Datei von Llama 3 hauptsächlich aus seinen Gewichtungen und Bias.

Da die Anzahl der Bias-Variablen (Millionen) deutlich geringer ist als die Gewichte (Milliarden), behalten Bias normalerweise eine höhere Genauigkeit bei (wie INT16), während sich die Hauptarbeit zur Quantisierung auf Gewichte konzentriert.

Für bekannte statische Gewichte umfassen Kalibrierungstechniken zur Auswahl des Bereichs:

- Perzentile des Eingabebereichs manuell auswählen

- Optimieren Sie den mittleren quadratischen Fehler (MSE) zwischen Originalgewichten und quantisierten Gewichten

- Minimieren Sie die Entropie zwischen dem ursprünglichen Wert und dem quantisierten Wert (KL-Divergenz).


Die Auswahl eines Perzentils führt beispielsweise zu einem Clipping-Verhalten, das dem ähnelt, was wir zuvor gesehen haben.

Aktivierungswert

Die Eingaben, die in einem großen Sprachmodell ständig aktualisiert werden, werden oft als Aktivierungen bezeichnet.


Sie werden Aktivierungswerte genannt, da sie normalerweise eine Aktivierungsfunktion wie Sigmoid oder Relu durchlaufen

Im Gegensatz zu Gewichten ändern sich Aktivierungen während der Inferenz mit den Eingabedaten und sind daher schwer genau zu quantifizieren.

Da diese Werte nach jeder verborgenen Schicht aktualisiert werden, sind ihre spezifischen Werte während der Inferenzphase erst bekannt, wenn die Eingabedaten das Modell durchlaufen.


Im Allgemeinen gibt es zwei Methoden zur Kalibrierung von Gewichten und Aktivierungen, die in verschiedenen Phasen des Modells angewendet werden:

- Quantisierung nach dem Training (PTQ)

- Wie der Name schon sagt, handelt es sich um eine Quantifizierung nach dem Training

- Quantisierungsbewusstes Training (QAT)

- Quantisierung während des Trainings/Feinabstimmung

Teil 3: Quantifizierung nach dem Training (PTQ)

Die Post-Training-Quantisierung (PTQ) ist eine der beliebtesten Quantisierungstechniken. Es quantifiziert die Parameter des Modells (einschließlich Gewichtungen und Aktivierungswerte), nachdem das Modelltraining abgeschlossen ist.

Die Quantisierung von Gewichten kann symmetrische Quantisierung oder asymmetrische Quantisierung verwenden.

Die Quantifizierung von Aktivierungswerten erfordert jedoch eine Inferenzphase, um ihre zugrunde liegende Verteilung zu erhalten, da wir ihren Bereich nicht im Voraus kennen.

Es gibt zwei Formen der Quantisierung von Aktivierungswerten:

- dynamische Quantisierung

- statische Quantisierung

dynamische Quantisierung

Nachdem die Daten die verborgene Schicht durchlaufen haben, werden ihre Aktivierungswerte erfasst und der Maximalwert (α) und der Minimalwert (β) jeder Schicht verglichen:


Die Verteilung dieser Aktivierungen wird dann verwendet, um die für die quantisierte Ausgabe erforderlichen Werte für Nullpunkt (z) und Skalierungsfaktor (s) zu berechnen:


Dieser Vorgang wiederholt sich jedes Mal, wenn die Daten eine neue Netzwerkschicht durchlaufen. Daher hat jede Schicht ihre eigenen unabhängigen z- und s-Werte und verwendet somit ein anderes Quantisierungsschema.

statische Quantisierung

Im Gegensatz zur dynamischen Quantisierung berechnet die statische Quantisierung den Nullpunkt (z) und den Skalierungsfaktor (s) nicht während der Inferenz, sondern berechnet diese Werte vor der Inferenz.

Um diese Werte zu finden, verwenden wir einen Kalibrierungsdatensatz und geben ihn in das Modell ein, um diese zugrunde liegenden Verteilungen der Aktivierungswerte zu erfassen.


Sobald diese Verteilungen erfasst sind, können die für die Quantifizierung während der Inferenz erforderlichen s- und z-Werte berechnet werden.

Zum tatsächlichen Inferenzzeitpunkt werden die s- und z-Werte nicht neu berechnet, sondern global über alle Aktivierungen hinweg verwendet, um sie zu quantisieren.

Insgesamt ist die dynamische Quantisierung, die s- und z-Werte für jede verborgene Schicht berechnet, tendenziell genauer. Dies kann jedoch die Berechnungszeit verlängern, da diese Werte zu jedem Inferenzzeitpunkt berechnet werden müssen.

Im Gegensatz dazu ist die statische Quantisierung zwar nicht so genau wie die dynamische Quantisierung, aber schneller, da sie die für die Quantisierung verwendeten s- und z-Werte bereits im Voraus kennt.

Quantitatives 4-Bit-Feld

Die Quantisierung unter 8 Bit war schon immer eine Herausforderung, da der Quantisierungsfehler mit jedem verlorenen Bit zunimmt. Glücklicherweise gibt es mehrere clevere Möglichkeiten, die Anzahl der Bits auf 6, 4 oder sogar 2 Bit zu reduzieren (obwohl eine Reduzierung der Bitanzahl unter 4 Bit im Allgemeinen nicht empfohlen wird).

Wir werden zwei gängige Methoden bei HuggingFace untersuchen:

- GPTQ (vollständiges Modell läuft auf GPU)

- GGUF (verlagert möglicherweise Schichten auf die CPU)

GPTQ

GPTQ kann als eine der bekanntesten 4-Bit-Quantisierungsmethoden in praktischen Anwendungen bezeichnet werden.

Es verwendet asymmetrische Quantisierung und verarbeitet sie Schicht für Schicht, wobei jede Schicht unabhängig verarbeitet wird, bevor mit der nächsten Schicht fortgefahren wird:


Bei diesem schichtweisen Quantisierungsprozess werden zunächst die Gewichte der Schichten in inverse Hesse-Matrizen umgewandelt. Die inverse Hesse-Matrix ist die zweite Ableitung der Modellverlustfunktion und stellt die Empfindlichkeit der Modellausgabe gegenüber jeder Gewichtsänderung dar.

Einfach ausgedrückt zeigt es im Wesentlichen die Wichtigkeit (inverse Wichtigkeit) der Gewichte in jeder Schicht.

Kleinere Wertgewichte in der Hessischen Matrix sind wichtiger, da kleine Änderungen dieser Gewichte zu erheblichen Änderungen der Modellleistung führen können.


In der inversen hessischen Matrix stellen niedrigere Werte „wichtigere“ Gewichte dar

Als nächstes quantisieren und dequantisieren wir die erste Zeile der Gewichtsmatrix:


Dieser Prozess ermöglicht es uns, den Quantisierungsfehler (q) zu berechnen, den wir mit dem zuvor berechneten inversen Hesse-Wert (h_1) gewichten können.

Im Wesentlichen erstellen wir einen gewichteten quantisierten Fehler basierend auf der Bedeutung der Gewichte:


Als nächstes verteilen wir diesen gewichteten Quantisierungsfehler auf die anderen Gewichte der Zeile. Dies trägt dazu bei, die Gesamtfunktionalität und Leistung des Netzwerks aufrechtzuerhalten.

Wenn wir dies beispielsweise für das zweite Gewicht tun (d. h. x_2=0,3), multiplizieren wir den Quantisierungsfehler (q) mit dem inversen Hesse-Wert des zweiten Gewichtes (h_2) und addieren dazu:


Als nächstes fahren Sie mit dem gleichen Vorgang für das dritte Gewicht in einer bestimmten Zeile fort:


Dieser Vorgang der Umverteilung des gewichteten Quantisierungsfehlers q wird wiederholt, bis alle Werte quantisiert wurden.

Diese Methode funktioniert, weil Gewichte normalerweise miteinander in Beziehung stehen. Wenn daher ein Gewicht einen Quantisierungsfehler aufweist, wird das zugehörige Gewicht entsprechend durch die inverse Hesse-Funktion aktualisiert.

GGUF

Obwohl GPTQ eine gute Quantisierungsmethode zum Ausführen des gesamten großen Sprachmodells (LLM) auf der GPU ist, kann jede Schicht des LLM auch über GGUF auf die CPU verlagert werden, wenn keine entsprechenden Hardwarebedingungen vorliegen.

Dies entspricht der gleichzeitigen Ausführung des Modells auf der CPU und der GPU, um den Mangel an Videospeicher (VRAM) auszugleichen.

Die Quantisierungsmethode GGUF wird häufig aktualisiert und hängt von der spezifischen Anzahl der Quantisierungsbits ab. Das Grundprinzip ist jedoch wie folgt.

Zunächst werden die Gewichte einer bestimmten Schicht in „Superblöcke“ unterteilt, von denen jeder eine Reihe von „Unterblöcken“ enthält. Aus diesen „Unterblöcken“ berechnen wir den/die Skalierungsfaktor(en) und den Alphawert:


Um einen bestimmten „Unterblock“ zu quantisieren, können Sie die zuvor erwähnte Absmax-Quantisierung verwenden, indem Sie das angegebene Gewicht mit dem Skalierungsfaktor (s_sub) multiplizieren:


Der Skalierungsfaktor s_sub wird anhand der Informationen im „Sub-Block“ berechnet, jedoch anhand der Informationen s_super im „Super-Block“ quantisiert:


Zusammenfassend lässt sich sagen, dass diese blockweise Quantisierung den Skalierungsfaktor des „Superblocks“ (s_super) verwendet, um den Skalierungsfaktor des „Unterblocks“ (s_sub) zu quantisieren.

Der Quantisierungsgrad jedes Skalierungsfaktors kann unterschiedlich sein, und „Superblock“-Skalierungsfaktoren weisen im Allgemeinen eine höhere Präzision auf als „Subblock“-Skalierungsfaktoren.

Um dies zu veranschaulichen, untersuchen wir verschiedene Quantisierungsstufen (2-Bit, 4-Bit und 6-Bit):


Je nach Quantisierungsart ist zur Anpassung des Nullpunkts zusätzlich ein Mindestwert (m) erforderlich, diese werden ebenso quantisiert wie der/die Skalierungsfaktor(en)

Teil 4: Quantitatives Bewusstseinstraining (QAT)

Im dritten Teil wird beschrieben, wie das Modell nach dem Training quantisiert wird. Der Nachteil dieser Methode besteht darin, dass sie den tatsächlichen Trainingsprozess nicht berücksichtigt.

Hier bietet sich das Quantitative Awareness Training (QAT) an. Im Gegensatz zur Post-Training-Quantifizierung (PTQ) besteht das Ziel von QAT darin, den Quantisierungsprozess während des Trainings zu erlernen.


QAT ist tendenziell genauer als PTQ, da die Quantisierung bereits während des Trainingsprozesses berücksichtigt wird. So funktioniert das:

Während des Trainingsprozesses wird die sogenannte „falsche“ Quantisierung eingeführt. Quantisieren Sie beispielsweise zuerst die Gewichte in INT4 und dequantisieren Sie sie dann zurück in FP32:


Dieser Prozess ermöglicht es dem Modell, den Quantisierungsfehler bei der Berechnung von Verlusten und der Aktualisierung von Gewichten während der Trainingsphase zu berücksichtigen.

Wie in der folgenden Abbildung dargestellt, versucht QAT, den Verlustwert bei „breiten“ Minima zu untersuchen, um Quantisierungsfehler zu reduzieren, da „schmale“ Minima häufig zu größeren Quantisierungsfehlern führen.


Unter der Annahme, dass die Quantisierung während der Rückausbreitung nicht berücksichtigt wird, wählt der Gradientenabstiegsprozess das Gewicht mit dem kleinsten Verlustwert aus. Wenn es jedoch in einem „engen“ Minimum liegt, führt dies zu größeren Quantisierungsfehlern.

Wenn wir dagegen die Quantisierung berücksichtigen, wird in den „breiten“ Minima ein anderes Aktualisierungsgewicht gewählt, mit einem viel kleineren Quantisierungsfehler.


Obwohl die PTQ-Methode einen niedrigen Verlustwert bei hoher Präzision (z. B. FP32) aufweist, weist QAT daher auch einen niedrigen Verlustwert bei niedriger Präzision (z. B. INT4) auf, was wir verfolgen.

1-Bit-Ära: BitNet

Wir haben zuvor gesehen, dass die Reduzierung der Quantisierungsgenauigkeit auf 4 Bit bereits recht gering ist, aber was wäre, wenn wir sie noch weiter reduzieren?

Hier kommt BitNet ins Spiel. Es stellt die Gewichte eines Modells als einzelnes Bit dar, entweder -1 oder 1, und fügt den Quantisierungsprozess direkt in die Transformer-Architektur ein.

Die Transformer-Architektur ist die Grundlage der meisten LLMs und besteht aus Berechnungen mit linearen Schichten:


Diese linearen Ebenen werden normalerweise mit höherer Präzision dargestellt, z. B. FP16, und dort befinden sich die meisten Gewichte.

BitNet ersetzt diese linearen Schichten durch BitLinear-Schichten:


BitLinear-Layer funktionieren genauso wie normale lineare Layer und multiplizieren Gewichte mit Aktivierungswerten, um die Ausgabe zu berechnen.

Der Unterschied besteht jedoch darin, dass die BitLinear-Schicht nur 1 Bit verwendet, um das Gewicht des Modells darzustellen, und INT8 verwendet, um den Aktivierungswert darzustellen:


BitLinear-Schichten führen wie das quantisierungsbewusste Training (QAT) während des Trainings eine Art „falsche“ Quantisierung durch, um den Quantisierungseffekt von Gewichtungen und Aktivierungen zu analysieren:


Lassen Sie uns BitLinear Schritt für Schritt verstehen.

Gewichtsquantifizierung

Während des Trainings werden Gewichte als INT8 gespeichert und dann mithilfe einer Grundstrategie namens Signum-Funktion auf 1 Bit quantisiert.

Im Wesentlichen verschiebt es die Verteilung der Gewichte so, dass sie bei 0 zentriert ist, und weist dann alle Werte kleiner als 0 zu -1 und alle Werte größer als 0 zu 1 zu:


Darüber hinaus verfolgt es einen Wert β (mittlerer Absolutwert), den wir später im inversen Quantisierungsprozess verwenden werden.

Aktivierungsquantisierung

Um Aktivierungen zu quantifizieren, ermöglicht BitLinear die Methode des absoluten Maximalwerts (absmax), um Aktivierungen von FP16 in INT8 zu konvertieren, da sie eine Matrixmultiplikation (×) mit höherer Präzision erfordern.


Darüber hinaus verfolgt es einen Wert α (maximaler Absolutwert), den wir später im Dequantisierungsprozess verwenden werden.

inverse Quantisierung

Wir verfolgen α (den maximalen Absolutwert der Aktivierungen) und β (den durchschnittlichen Absolutwert der Gewichtungen), was uns dabei helfen wird, die Aktivierungen zurück auf FP16 zu dequantisieren.

Die Ausgabeaktivierungen werden mit {α, γ} neu skaliert, um sie auf die ursprüngliche Genauigkeit zu dequantisieren:


Dieser Prozess ist relativ einfach und ermöglicht die Darstellung des Modells mit nur zwei Werten, -1 oder 1.

Bei diesem Ansatz stellten die Autoren fest, dass mit zunehmender Modellgröße die Leistungslücke zwischen 1-Bit-Training und FP16-Training immer kleiner wird.

Dies gilt jedoch nur für größere Modelle (>30B Parameter), die Lücke zwischen kleineren Modellen ist immer noch groß.

Alle LLMs sind 1,58 Bit

Um die zuvor erwähnten Skalierbarkeitsprobleme zu verbessern, wurde BitNet 1.58b eingeführt.

Bei diesem neuen Ansatz kann jedes Gewicht des Modells nicht nur -1 oder 1 sein, sondern auch 0 annehmen, wodurch jede Variable zu einer Ternärvariablen wird.

Interessanterweise ist das Hinzufügen von 0 ein einfacher Vorgang, der BitNet erheblich verbessert und den Berechnungsprozess beschleunigt.

0 Leistung

Warum ist das Hinzufügen von 0 eine signifikante Verbesserung?

Das hat mit Matrixmultiplikation zu tun!

Lassen Sie uns zunächst die grundlegende Funktionsweise der Matrixmultiplikation untersuchen.

Bei der Berechnung der Ausgabe multiplizieren wir die Gewichtsmatrix mit dem Eingabevektor. Hier ist eine Visualisierung der ersten Zeilenmultiplikation der ersten Ebene der Gewichtsmatrix:


Diese Multiplikation umfasst zwei Aktionen: die Multiplikation einer einzelnen Gewichtung mit der Eingabe und die anschließende Addition aller.

Im Gegensatz dazu gelingt es BitNet 1.58b, den Vorgang der Multiplikation zu vermeiden, da dreiwertige Gewichte Ihnen im Wesentlichen Folgendes sagen:

- 1: Ich möchte diesen Wert hinzufügen

- 0: Ich möchte diesen Wert nicht

- -1: Ich möchte diesen Wert subtrahieren

Wenn Ihre Gewichte also auf 1,58 Bit quantisiert sind, müssen Sie nur die Addition durchführen:


Dies beschleunigt nicht nur die Berechnungen erheblich, sondern ermöglicht auch die Filterung von Merkmalen.

Das Festlegen einer bestimmten Gewichtung auf 0 entspricht dem Ignorieren der Eingabe, anstatt den Eingabewert wie 1 Bit zu addieren oder zu subtrahieren.

Quantifizieren

Um eine Gewichtsquantisierung durchzuführen, verwendet BitNet 1.58b die mittlere Absolutwertquantisierung (absmean), eine Variante der maximalen Absolutwertquantisierung (absmax), die wir zuvor gesehen haben.

Es komprimiert lediglich die Gewichtsverteilung und verwendet den absoluten Mittelwert (α), um die Werte zu quantifizieren. Dann runden Sie sie auf -1, 0 oder 1:


Im Vergleich zu BitNet ist die Aktivierungsquantisierung bis auf einen Aspekt dieselbe: Anstatt Aktivierungen auf den Bereich [0, 2ᵇ⁻¹] zu skalieren, verwenden wir die Methode des maximalen Absolutwerts, um auf [-2ᵇ⁻¹, 2ᵇ⁻¹] zu skalieren.

Zusammenfassend umfasst die 1,58-Bit-Quantisierung hauptsächlich zwei Techniken:

- Addiere 0, um eine dreiwertige Darstellung zu erstellen [-1, 0, 1]

- Absolute mittlere Quantifizierung der Gewichte

Das BitNet-Papier kommt zu folgendem Schluss: „13B BitNet b1.58 ist hinsichtlich Latenz, Speichernutzung und Energieverbrauch effizienter als 3B FP16 LLM.“


Papieradresse: https://arxiv.org/abs/2402.17764

Mit nur 1,58 recheneffizienten Bits erhalten wir ein leichtes Modell.

Verweise:

https://newsletter.maartengrootendorst.com/p/a-visual-guide-to-quantization