Quantisierung kann als der Prozess der Abbildung von Werten aus einer großen Menge reeller Zahlen auf Werte in einer kleinen diskreten Menge definiert werden. Typischerweise geht es dabei um die Abbildung kontinuierlicher Eingaben auf feste Werte am Ausgang. Eine übliche Methode, dies zu erreichen, ist das Runden oder Abschneiden. Beim Runden berechnen wir die nächste ganze Zahl. Beispielsweise wird ein Wert von 1,8 zu 2. Ein Wert von 1,2 wird jedoch zu 1. Im Falle einer Kürzung entfernen wir blind die Werte nach der Dezimalstelle, um die Eingabe in eine ganze Zahl umzuwandeln.
Wie auch immer wir vorgehen, die Hauptmotivation hinter der Quantisierung tiefer neuronaler Netze besteht darin, die Inferenzgeschwindigkeit zu verbessern, da die Inferenz und das Training neuronaler Netze selbstverständlich rechenintensiv sind. Mit dem Aufkommen großer Sprachmodelle nimmt die Anzahl der Parameter in diesen Modellen immer weiter zu, was bedeutet, dass der Speicherbedarf immer größer wird.
Angesichts der Geschwindigkeit, mit der sich diese neuronalen Netze weiterentwickeln, steigt die Nachfrage, diese neuronalen Netze auf unseren Laptops oder Mobiltelefonen und sogar auf winzigen Geräten wie Uhren auszuführen. Ohne Quantisierung ist das alles nicht möglich.
Bevor wir uns mit der Quantisierung befassen, sollten wir nicht vergessen, dass trainierte neuronale Netze lediglich schwebende Zahlen sind, die im Speicher des Computers gespeichert sind.
Einige der bekanntesten Darstellungen oder Formate zum Speichern von Zahlen in Computern sind float32 oder FP32, float16 oder FP16, int8, bfloat16, wobei B für Google Brain oder neuerdings Tensor Float 32 oder TF32 steht, ein spezielles Format für den Umgang mit Matrix oder Tensor Operationen. Jedes dieser Formate belegt einen anderen Teil des Speichers. Beispielsweise weist float32 1 Bit für das Vorzeichen, 8 Bit für den Exponenten und 23 Bit für die Mantisse zu.
In ähnlicher Weise weist float16 oder FP16 1 Bit für das Vorzeichen, aber nur 5 Bit für den Exponenten und 10 Bit für die Mantisse zu. Andererseits reserviert BF16 8 Bits für den Exponenten und nur 7 Bits für die Mantisse.
Genug der Darstellungen. Ich möchte damit sagen, dass die Konvertierung von einem höheren Speicherformat in ein niedrigeres Speicherformat Quantisierung genannt wird. In Bezug auf Deep Learning wird Float32 als einfache oder volle Präzision bezeichnet, und Float16 und BFloat16 werden als halbe Präzision bezeichnet. Standardmäßig werden Deep-Learning-Modelle mit voller Präzision trainiert und gespeichert. Die am häufigsten verwendete Konvertierung ist von voller Präzision in ein int8-Format.
Die Quantisierung kann einheitlich oder uneinheitlich sein. Im einheitlichen Fall ist die Zuordnung von der Eingabe zur Ausgabe eine lineare Funktion, die zu gleichmäßig verteilten Ausgaben für gleichmäßig verteilte Eingaben führt. Im ungleichmäßigen Fall ist die Zuordnung von der Eingabe zur Ausgabe eine nichtlineare Funktion, sodass die Ausgaben für eine einheitliche Eingabe nicht gleichmäßig verteilt sind.
Beim Eintauchen in den einheitlichen Typ kann die lineare Abbildungsfunktion eine Skalierungs- und Rundungsoperation sein. Somit beinhaltet eine gleichmäßige Quantisierung einen Skalierungsfaktor S in der Gleichung.
Beachten Sie bei der Konvertierung beispielsweise von float16 in int8, dass wir uns immer auf Werte zwischen -127 und plus 127 beschränken und sicherstellen können, dass der Nullpunkt der Eingabe perfekt auf den Nullpunkt der Ausgabe abgebildet wird, was zu einer symmetrischen Abbildung führt und diese Quantisierung daher als symmetrisch bezeichnet wird Quantisierung .
Andererseits, wenn die Werte auf beiden Seiten von Null nicht gleich sind, beispielsweise zwischen -128 und +127. Wenn wir außerdem den Nullpunkt des Eingangs auf einen anderen Wert als Null am Ausgang abbilden, spricht man von asymmetrischer Quantisierung . Da wir nun den Nullwert in der Ausgabe verschoben haben, müssen wir dies in unserer Gleichung berücksichtigen, indem wir den Nullfaktor Z in die Gleichung einbeziehen.
Um zu erfahren, wie wir den Skalierungsfaktor und den Nullpunkt wählen können, nehmen wir eine Beispieleingabe, die wie in der obigen Abbildung auf der reellen Zahlenachse verteilt ist. Der Skalierungsfaktor unterteilt im Wesentlichen den gesamten Eingabebereich vom Minimalwert r_min bis zum Maximalwert r_max in gleichmäßige Partitionen. Wir können diese Eingabe jedoch irgendwann abschneiden, beispielsweise Alpha für negative Werte und Beta für positive Werte. Jeder Wert, der über Alpha und Beta hinausgeht, ist nicht aussagekräftig, da er der gleichen Ausgabe wie Alpha entspricht. In diesem Beispiel sind es -127 und +127. Der Prozess der Auswahl dieser Clipping-Werte Alpha und Beta und damit des Clipping-Bereichs wird als Kalibrierung bezeichnet.
Um übermäßiges Clipping zu verhindern, könnte die einfachste Option darin bestehen, Alpha auf r_min und Beta auf r_max zu setzen. Und wir können problemlos den Skalierungsfaktor S berechnen, indem wir diese r_min- und r_max- Werte verwenden. Dies kann jedoch dazu führen, dass die Ausgabe asymmetrisch ist. Beispielsweise könnte r_max in der Eingabe 1,5 sein, r_min jedoch nur -1,2. Um also eine symmetrische Quantisierung zu gewährleisten, müssen Alpha und Beta die Maximalwerte der beiden sein und natürlich den Nullpunkt auf 0 setzen.
Bei der Quantisierung neuronaler Netzwerkgewichte wird genau die symmetrische Quantisierung verwendet, da die trainierten Gewichte bereits während der Inferenz vorberechnet werden und sich während der Inferenz nicht ändern. Die Berechnung ist im Vergleich zum asymmetrischen Fall auch einfacher, da der Nullpunkt auf 0 gesetzt ist.
Sehen wir uns nun ein Beispiel an, bei dem die Eingaben in eine Richtung verzerrt sind, beispielsweise zur positiven Seite. Dies ähnelt der Ausgabe einiger der erfolgreichsten Aktivierungsfunktionen wie ReLU oder GeLU. Darüber hinaus ändern sich die Ausgaben von Aktivierungen mit der Eingabe. Beispielsweise ist die Ausgabe von Aktivierungsfunktionen ganz anders, wenn wir zwei Bilder einer Katze zeigen. Die Frage lautet nun: „Wann kalibrieren wir den Bereich für die Quantisierung?“ Ist es während des Trainings? Oder während der Schlussfolgerung und wenn wir die Daten für die Vorhersage erhalten?
Diese Frage führt zu verschiedenen Quantisierungsmodi, insbesondere bei der Post-Training-Quantisierung (PTQ). Beim PTQ beginnen wir mit einem vorab trainierten Modell, ohne zusätzliches Training durchzuführen. Zu den entscheidenden Daten, die das Modell benötigt, gehören Kalibrierungsdaten, die zur Berechnung des Clipping-Bereichs und anschließend des Skalierungsfaktors (S) und des Nullpunkts (Z) verwendet werden. Typischerweise werden diese Kalibrierungsdaten aus den Modellgewichten abgeleitet. Nach dem Kalibrierungsprozess können wir mit der Quantisierung des Modells fortfahren, was zum quantisierten Modell führt.
Beim Quantization Aware Training oder kurz QAT quantisieren wir das trainierte Modell mithilfe eines Standardverfahrens, führen dann jedoch eine weitere Feinabstimmung oder ein erneutes Training durch, indem wir frische Trainingsdaten verwenden, um das quantisierte Modell zu erhalten. QAT wird normalerweise durchgeführt, um die Parameter des Modells anzupassen, um die verlorene Genauigkeit oder jede andere Metrik, die uns während der Quantisierung Sorgen macht, wiederherzustellen. Daher liefert QAT tendenziell bessere Modelle als die Post-Training-Quantisierung.
Um eine Feinabstimmung durchführen zu können, muss das Modell differenzierbar sein. Die Quantisierungsoperation ist jedoch nicht differenzierbar. Um dies zu überwinden, verwenden wir gefälschte Quantisierer wie Straight-Through-Schätzer. Bei der Feinabstimmung schätzen diese Schätzer den Quantisierungsfehler und die Fehler werden zusammen mit dem Trainingsfehler kombiniert, um das Modell für eine bessere Leistung zu optimieren. Während der Feinabstimmung werden die Vorwärts- und Rückwärtsdurchgänge am quantisierten Modell im Gleitkommaformat durchgeführt. Allerdings werden die Parameter nach jeder Gradientenaktualisierung quantisiert.
Schauen Sie sich das Video unten an, in dem die Modellquantisierung beim Deep Learning erklärt wird
Das deckt so ziemlich die Grundlagen der Quantisierung ab. Wir begannen mit der Notwendigkeit der Quantisierung und den verschiedenen Quantisierungsarten wie symmetrisch und asymmetrisch. Wir haben auch schnell gelernt, wie wir die Quantisierungsparameter auswählen können, nämlich den Skalierungsfaktor und den Nullpunkt. Und wir endeten mit verschiedenen Quantisierungsmodi. Aber wie wird das alles in PyTorch oder TensorFlow implementiert? Das ist für einen anderen Tag. Ich hoffe, dieses Video hat Ihnen einen Einblick in die Quantisierung im Deep Learning gegeben.
Ich hoffe, wir sehen uns in meinem nächsten. Bis dahin, aufgepasst!