Kürzlich hat ein Neuseeländer, Brendan Bycroft, in der Technologiebranche für Aufsehen gesorgt. Ein von ihm ins Leben gerufenes Projekt mit dem Namen „Large Model 3D Visualization“ stand nicht nur ganz oben auf der Liste der Hacker News, sondern seine schockierende Wirkung ist sogar noch umwerfender. Durch dieses Projekt werden Sie in nur wenigen Sekunden vollständig verstehen, wie LLM (Large Language Model) funktioniert.
Ob Sie ein Technologie-Enthusiast sind oder nicht, dieses Projekt wird Ihnen ein beispielloses visuelles Fest und kognitive Erleuchtung bescheren. Lassen Sie uns gemeinsam diese atemberaubende Kreation erkunden!
In diesem Projekt analysierte Bycroft im Detail ein leichtes GPT-Modell namens Nano-GPT, das vom OpenAI-Wissenschaftler Andrej Karpathy entwickelt wurde. Als reduzierte Version des GPT-Modells verfügt das Modell nur über 85.000 Parameter. Obwohl dieses Modell viel kleiner ist als GPT-3 oder GPT-4 von OpenAI, kann man natürlich sagen, dass „ein Spatz klein ist, aber alle inneren Organe hat“.
Nano-GPT GitHub: https://github.com/karpathy/nanoGPT
Um die Demonstration jeder Schicht des Transformer-Modells zu erleichtern, hat Bycroft eine sehr einfache Zielaufgabe für das Nano-GPT-Modell arrangiert: das Modell Die Eingabe besteht aus 6 Buchstaben „CBABBC“, die Ausgabe ist eine in alphabetischer Reihenfolge angeordnete Folge, zum Beispiel die Ausgabe „ABBBCC“.
Wir nennen jeden Buchstaben ein Token, und diese verschiedenen Buchstaben bilden den Wortschatz:
Für diese Tabelle wird jedem Buchstaben ein tiefgestellter Token-Index zugewiesen. Die aus diesen Indizes zusammengesetzte Sequenz kann als Eingabe des Modells verwendet werden: 2 1 0 1 1 2
In der 3D-Visualisierung stellt jede grüne Zelle eine berechnete Zahl dar, während jede blaue Zelle das Gewicht des Modells darstellt .
Bei der Sequenzverarbeitung wird jede Zahl zunächst in einen C-dimensionalen Vektor umgewandelt. Dieser Vorgang wird als Einbettung bezeichnet. Bei Nano-GPT beträgt die Dimension dieser Einbettung normalerweise 48 Dimensionen. Durch diesen Einbettungsvorgang wird jede Zahl als Vektor im C-dimensionalen Raum dargestellt, was eine bessere nachfolgende Verarbeitung und Analyse ermöglicht.
Einbettung wird über eine Reihe von Zwischenmodellschichten berechnet, die im Allgemeinen als Transformatoren bezeichnet werden, und erreicht schließlich die unterste Schicht.
„Was ist also die Ausgabe?“
Die Ausgabe des Modells ist das nächste Token in der Sequenz. Am Ende erhalten wir also den Wahrscheinlichkeitswert, dass der nächste Token A B C ist. In diesem Beispiel gibt das Modell der 6. Position A mit hoher Wahrscheinlichkeit aus. Jetzt können wir A als Eingabe an das Modell übergeben und den gesamten Vorgang wiederholen. GPT-2- und GPT-3-Visualisierungen werden ebenfalls angezeigt.GPT-3 verfügt über 175 Milliarden Parameter und die Modellebene verfügt über 8 Spalten, die den gesamten Bildschirm dicht abdecken.
Verschiedene Parameterversionen des GPT-2-Modells weisen große architektonische Unterschiede auf. Hier nehmen wir als Beispiele die 15 Milliarden Parameter von GPT-2 (XL) und die 124 Millionen Parameter von GPT-2 (Small).
Es ist zu beachten, dass sich diese Visualisierung hauptsächlich auf die Modellinferenz (Inferenz) und nicht auf das Training konzentriert und daher nur einen kleinen Teil des gesamten maschinellen Lernprozesses darstellt. Darüber hinaus wird hier davon ausgegangen, dass die Gewichte des Modells vorab trainiert wurden, und dann wird die Modellinferenz verwendet, um eine Ausgabe zu generieren.
EinbettungWie bereits erwähnt, wie man eine einfache Nachschlagetabelle verwendet, um Token einer Reihe von Ganzzahlen zuzuordnen.Diese Ganzzahlen, der Token-Index, sind das erste und einzige Mal, dass wir Ganzzahlen im Modell sehen. Danach werden Operationen mit Gleitkommazahlen (Dezimalzahlen) ausgeführt.
Nehmen Sie hier das 4. Token (Index 3) als Beispiel, um zu sehen, wie es zum Generieren des 4. Spaltenvektors der Eingabeeinbettung verwendet wird.
Verwenden Sie zunächst den Token-Index (hier wird B = 1 als Beispiel genommen), um die zweite Spalte aus der Token-Einbettungsmatrix auszuwählen und einen Spaltenvektor der Größe C = 48 (48 Dimensionen) zu erhalten, der aufgerufen wird Token-Einbettung.
Wählen Sie dann die vierte Spalte aus der Positionseinbettungsmatrix aus („Da wir uns hier hauptsächlich den (t = 3) Token B an der 4. Position ansehen“), erhalten wir auf ähnliche Weise eine Größe von C=48 (48 Dimensionen) Spaltenvektor, sogenannte Positionseinbettung.
Es ist zu beachten, dass Positionseinbettungen und Tokeneinbettungen beide durch Modelltraining erhalten werden (blau gekennzeichnet). Da wir nun diese beiden Vektoren haben, können wir durch Addition einen neuen Spaltenvektor der Größe C=48 erhalten.
Verarbeiten Sie als Nächstes alle Token in der Reihenfolge im selben Prozess und erstellen Sie einen Satz von Vektoren, die die Token-Werte und ihre Positionen enthalten.
Wie aus der obigen Abbildung ersichtlich ist, führt die Ausführung dieses Prozesses für alle Token in der Eingabesequenz zu einer Matrix der Größe TxC. Unter diesen repräsentiert T die Sequenzlänge. C steht für Kanal, wird aber auch Feature oder Dimension oder Einbettungsgröße genannt, die in diesem Fall 48 beträgt. Diese Länge C ist einer von mehreren „Hyperparametern“ des Modells, die vom Designer ausgewählt wurden, um einen Kompromiss zwischen Modellgröße und Leistung zu erzielen.
Diese Matrix mit der Dimension TxC ist die Eingabeeinbettung und wird durch das Modell weitergegeben.
Kleiner Tipp: Fahren Sie gerne mit der Maus über eine einzelne Zelle in der Eingabeeinbettung, um die Berechnung und ihre Quelle anzuzeigen.
Die zuvor erhaltene Eingabe-Einbettungsmatrix ist die Eingabe der Transformer-Schicht.
Der erste Schritt der Transformer-Ebene besteht darin, eine Ebenennormalisierung für die Eingabeeinbettungsmatrix durchzuführen. Dies ist eine Operation zum Normalisieren der Werte jeder Spalte der Eingabematrix.
Normalisierung ist ein wichtiger Schritt beim Training tiefer neuronaler Netze, der dazu beiträgt, die Stabilität des Modells während des Trainingsprozesses zu verbessern.
Wir können die Spalten der Matrix separat betrachten. Die vierte Spalte dient unten als Beispiel.
Das Ziel der Normalisierung besteht darin, dass der Wert jeder Spalte einen Mittelwert von 0 und eine Standardabweichung von 1 aufweist. Um dies zu erreichen, berechnen Sie den Mittelwert und die Standardabweichung jeder Spalte, subtrahieren dann den entsprechenden Mittelwert und dividieren durch die entsprechende Standardabweichung für jede Spalte.
Hier wird E[x] verwendet, um den Mittelwert darzustellen, und Var[x] wird verwendet, um die Varianz (das Quadrat der Standardabweichung) darzustellen. epsilon(ε = 1×10^-5) soll Fehler bei der Division durch 0 verhindern.
Berechnen und speichern Sie das normalisierte Ergebnis, multiplizieren Sie es dann mit dem Lerngewichtsgewicht (γ) und addieren Sie den Bias Bias (β), um das endgültige normalisierte Ergebnis zu erhalten.
Führen Sie abschließend eine Normalisierungsoperation für jede Spalte der Eingabeeinbettungsmatrix durch, um die normalisierte Eingabeeinbettung zu erhalten, und übergeben Sie sie an die Selbstaufmerksamkeitsschicht (Selbstaufmerksamkeit).
Die Selbstaufmerksamkeitsschicht ist wahrscheinlich der Kernbestandteil des Transformers. In dieser Phase können die Spalten in der Eingabeeinbettung miteinander „kommunizieren“, während in anderen Phasen jede Spalte unabhängig existiert.
Die Selbstaufmerksamkeitsebene besteht aus mehreren Selbstaufmerksamkeitsköpfen. In diesem Beispiel gibt es drei Selbstaufmerksamkeitsköpfe. Die Eingabe jedes Headers macht 1/3 der Eingabeeinbettung aus, und wir konzentrieren uns jetzt nur auf einen davon.
Der erste Schritt besteht darin, aus Spalte C der normalisierten Eingabeeinbettungsmatrix drei Vektoren für jede Spalte zu generieren. Diese sind QKV:
Um diese Vektoren zu erzeugen, wird eine Matrix-Vektor-Multiplikation plus eine Vorspannung verwendet. Jede Ausgabeeinheit ist eine lineare Kombination von Eingabevektoren.
Zum Beispiel wird der Abfragevektor durch die Skalarproduktoperation zwischen einer Zeile der Q-Gewichtsmatrix und einer Spalte der Eingabematrix vervollständigt.
Die Funktionsweise des Skalarprodukts ist sehr einfach: Multiplizieren Sie einfach die entsprechenden Elemente und addieren Sie sie dann.
Dies ist eine allgemeine und einfache Möglichkeit, sicherzustellen, dass jedes Ausgabeelement von allen Elementen im Eingabevektor beeinflusst wird (dieser Einfluss wird durch das Gewicht bestimmt). Daher kommt es häufig in neuronalen Netzen vor.
In neuronalen Netzen tritt dieser Mechanismus häufig auf, da er es dem Modell ermöglicht, bei der Verarbeitung der Daten jeden Teil der Eingabesequenz zu berücksichtigen. Dieser umfassende Aufmerksamkeitsmechanismus ist das Herzstück vieler moderner neuronaler Netzwerkarchitekturen, insbesondere bei der Verarbeitung sequentieller Daten wie Text oder Zeitreihen.
Wir wiederholen dies für jede Ausgabeeinheit in den Vektoren Q, K, V:
Wie verwenden wir unsere Vektoren Q (Abfrage), K (Schlüssel) und V (Wert)? Ihre Benennung gibt uns einen Hinweis: „Schlüssel“ und „Wert“ erinnern an Wörterbuchtypen, wobei Schlüssel Werten zugeordnet sind. Dann verwenden wir „Abfrage“, um den Wert zu ermitteln.
Im Fall von Selbstaufmerksamkeit geben wir statt eines einzelnen Vektors (Begriffs) eine gewichtete Kombination von Vektoren (Begriffen) zurück. Um dieses Gewicht zu finden, berechnen wir das Skalarprodukt zwischen einem Q-Vektor und jedem K-Vektor, gewichten und normalisieren es und multiplizieren es schließlich mit dem entsprechenden V-Vektor und addieren sie.
Am Beispiel der 6. Spalte (t=5) beginnt die Abfrage in dieser Spalte:
Aufgrund der Existenz einer Aufmerksamkeitsmatrix können die ersten 6 Spalten von KV abgefragt werden, und Der Q-Wert ist die aktuelle Zeit.
Berechnen Sie zunächst das Skalarprodukt zwischen dem Q-Vektor der aktuellen Spalte (t=5) und dem K-Vektor der vorherigen Spalten (die ersten 6 Spalten). Dies wird dann in der entsprechenden Zeile (t=5) der Aufmerksamkeitsmatrix gespeichert.
Die Größe des Skalarprodukts misst die Ähnlichkeit zwischen zwei Vektoren. Je größer das Skalarprodukt, desto ähnlicher sind sie.
Und nur der Q-Vektor wird mit dem vergangenen K-Vektor operiert, was ihn zu einer kausalen Selbstaufmerksamkeit macht. Mit anderen Worten: Token können keine „zukünftigen Informationen sehen“.
Nachdem Sie das Skalarprodukt gefunden haben, teilen Sie es durch sqrt(A), wobei A die Länge des QKV-Vektors ist. Diese Skalierung wird durchgeführt, um zu verhindern, dass große Werte den nächsten Schritt der Normalisierung (Softmax) dominieren.
Als nächstes wird die Softmax-Operation ausgeführt, um den Wertebereich auf 0 bis 1 zu reduzieren.
Schließlich kann der Ausgabevektor dieser Spalte (t=5) erhalten werden. Schauen Sie sich die Zeile (t=5) der normalisierten Aufmerksamkeitsmatrix an und multiplizieren Sie jedes Element mit dem entsprechenden V-Vektor der anderen Spalte.
Wir können diese Vektoren dann addieren, um den Ausgabevektor zu erhalten. Daher wird der Ausgabevektor vom V-Vektor mit hoher Auflösung dominiert.
Jetzt wenden wir es auf alle Spalten an.
Dies ist der Verarbeitungsprozess eines Headers in der Selbstaufmerksamkeitsebene. „Das Hauptziel von Self Attention besteht also darin, dass jede Spalte relevante Informationen aus anderen Spalten finden und ihren Wert extrahieren möchte. Dies geschieht durch den Vergleich ihres Abfragevektors mit den Schlüsseln dieser anderen Spalten. Die zusätzliche Einschränkung besteht darin, dass dies nur möglich ist Schauen Sie in die Vergangenheit. „
Nach der Selbstaufmerksamkeitsoperation erhalten wir von jedem Kopf eine Ausgabe. Bei diesen Ausgängen handelt es sich um V-Vektoren, die entsprechend gemischt und von den Q- und K-Vektoren beeinflusst werden. Um die Ausgabevektoren jedes Kopfes zusammenzuführen, stapeln wir sie einfach. Daher werden wir bei t=4 3 Vektoren mit der Länge A=16 überlagern, um 1 Vektor mit der Länge C=48 zu bilden.
Es ist erwähnenswert, dass in GPT die Länge des Vektors innerhalb des Kopfes (A=16) gleich C/num_heads ist. Dadurch wird sichergestellt, dass wir beim erneuten Stapeln die ursprüngliche Länge C erhalten.
Auf dieser Grundlage führen wir eine Projektion durch und erhalten die Ausgabe dieser Ebene. Dies ist eine einfache Matrix-Vektor-Multiplikation pro Spalte plus einem Bias.
Jetzt haben wir den Output von Self Attention.
Anstatt diese Ausgabe direkt an die nächste Stufe weiterzuleiten, fügen wir sie als Element zur Eingabeeinbettung hinzu. Dieser durch den grünen vertikalen Pfeil dargestellte Vorgang wird Restverbindung oder Restpfad genannt.
Wie die Schichtnormalisierung sind auch Restnetze von entscheidender Bedeutung, um ein effektives Lernen tiefer neuronaler Netze zu erreichen.
Da wir nun das Ergebnis der Selbstaufmerksamkeit haben, können wir es an die nächste Ebene von Transformer weitergeben: das Feedforward-Netzwerk.
Nach Self Attention ist der nächste Teil des Transformer-Moduls MLP (Multilayer Perceptron), hier handelt es sich um ein einfaches neuronales Netzwerk mit zwei Schichten.
Genau wie bei der Selbstaufmerksamkeit müssen wir eine Ebenennormalisierung durchführen, bevor der Vektor in das MLP eintritt.
Gleichzeitig muss in MLP die folgende Verarbeitung (unabhängig) für jeden Spaltenvektor der Länge C=48 durchgeführt werden:
Verfolgen wir einen der Vektoren:
Der MLP-Prozess ist wie folgt:
Führen Sie zunächst eine Matrix-Vektor-Multiplikation durch und fügen Sie Offsets hinzu, um den Vektor in eine Matrix der Länge 4*C zu erweitern. (Beachten Sie, dass die Ausgabematrix hier zur Visualisierung transponiert ist)
Als nächstes wenden Sie die GELU-Aktivierungsfunktion auf jedes Element des Vektors an. Dies ist ein wichtiger Bestandteil jedes neuronalen Netzwerks. Wir müssen eine gewisse Nichtlinearität in das Modell einführen. Die speziell verwendete Funktion GELU ähnelt stark der ReLU-Funktion max(0, x), weist jedoch eine glatte Kurve anstelle scharfer Ecken auf.
Projizieren Sie dann den Vektor über eine weitere voreingenommene Matrix-Vektor-Multiplikation zurück auf die Länge C.
Auch hier gibt es ein Restnetzwerk. Wie beim Teil Selbstaufmerksamkeit + Projektion fügen wir die Ergebnisse des MLP in der Reihenfolge der Elemente zur Eingabe hinzu.
Wiederholen Sie diese Vorgänge.
Dies ist das Ende der MLP-Schicht und wir erhalten endlich die Ausgabe des Transformators.
Dies ist ein vollständiges Transformer-Modul!
Diese verschiedenen Module bilden den Hauptteil jedes GPT-Modells, und der Ausgang jedes Moduls ist der Eingang des nächsten Moduls.
Wie beim Deep Learning üblich, ist es schwierig, genau zu sagen, was jede dieser Schichten tut, aber wir haben einige allgemeine Ideen: Frühere Schichten neigen dazu, sich auf das Erlernen von Merkmalen und Mustern auf niedriger Ebene zu konzentrieren, während spätere Schichten auf das Erkennen und Verstehen höherer Ebenen abzielen Abstraktionen und Beziehungen auf -Ebene. Im Kontext der Verarbeitung natürlicher Sprache können niedrigere Schichten Grammatik, Syntax und einfache lexikalische Assoziationen lernen, während höhere Schichten komplexere semantische Beziehungen, Diskursstrukturen und kontextabhängige Bedeutungen erfassen können.
Der letzte Schritt ist die Softmax-Operation, die die vorhergesagte Wahrscheinlichkeit jedes Tokens ausgibt.
Endlich erreichen wir das Ende des Modells. Die Ausgabe des letzten Transformers durchläuft eine Regularisierungsschicht, gefolgt von einer unverzerrten linearen Transformation.
Diese letzte Transformation wandelt jeden unserer Spaltenvektoren von der Länge C in die wortschatzgroße Länge nvocab um. Es werden also tatsächlich für jedes Wort im Vokabular Score-Logits generiert.
Um diese Ergebnisse in intuitivere Wahrscheinlichkeitswerte umzuwandeln, müssen sie zuerst durch Softmax verarbeitet werden. Für jede Spalte erhalten wir also die Wahrscheinlichkeit, dass das Modell jedem Wort im Vokabular zugeordnet ist.
In diesem speziellen Modell hat es tatsächlich alle Antworten zur Reihenfolge der drei Buchstaben gelernt, sodass die Wahrscheinlichkeiten stark in Richtung der richtigen Antwort tendieren.
Wenn wir das Modell im Laufe der Zeit voranschreiten lassen, müssen wir die Wahrscheinlichkeit der letzten Spalte verwenden, um über den nächsten hinzugefügten Token in der Sequenz zu entscheiden. Wenn wir beispielsweise sechs Token in das Modell eingeben, würden wir die Ausgabewahrscheinlichkeiten in Spalte sechs verwenden.
Die Ausgabe dieser Spalte ist eine Reihe von Wahrscheinlichkeitswerten, und wir müssen tatsächlich einen davon als nächsten Token in der Sequenz auswählen. Dies erreichen wir durch „Stichproben aus der Verteilung“, das heißt durch die zufällige Auswahl eines Tokens basierend auf seiner Wahrscheinlichkeit. Beispielsweise hat ein Token mit einer Wahrscheinlichkeit von 0,9 eine Wahrscheinlichkeit von 90 %, ausgewählt zu werden. Wir haben jedoch auch andere Möglichkeiten, wie zum Beispiel immer den Token mit der höchsten Wahrscheinlichkeit zu wählen.
Wir können die „Glätte“ der Verteilung auch über den Temperaturparameter steuern. Höhere Temperaturen führen zu einer gleichmäßigeren Verteilung, während niedrigere Temperaturen zu einer stärkeren Konzentration auf die Token mit der höchsten Wahrscheinlichkeit führen.
Wir passen die Logits (die Ausgabe der linearen Transformation) mithilfe des Temperaturparameters an, bevor wir Softmax anwenden, da die Potenzierung in Softmax einen deutlich verstärkenden Effekt auf größere Werte hat und eine Annäherung aller Werte diesen Effekt verringert.
Bilder
Das obige ist der detaillierte Inhalt vonDurchbrechen Sie die Informationsbarriere! Schockierendes großformatiges 3D-Visualisierungstool wird veröffentlicht!. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!