4. Attention Mechanisms
Aufmerksamkeitsmechanismen und Selbstaufmerksamkeit in neuronalen Netzwerken
Aufmerksamkeitsmechanismen ermöglichen es neuronalen Netzwerken, sich auf spezifische Teile der Eingabe zu konzentrieren, wenn sie jeden Teil der Ausgabe generieren. Sie weisen verschiedenen Eingaben unterschiedliche Gewichte zu, was dem Modell hilft zu entscheiden, welche Eingaben für die jeweilige Aufgabe am relevantesten sind. Dies ist entscheidend bei Aufgaben wie maschineller Übersetzung, bei denen das Verständnis des Kontexts des gesamten Satzes für eine genaue Übersetzung notwendig ist.
Das Ziel dieser vierten Phase ist sehr einfach: Wenden Sie einige Aufmerksamkeitsmechanismen an. Diese werden viele wiederholte Schichten sein, die die Beziehung eines Wortes im Vokabular zu seinen Nachbarn im aktuellen Satz, der zum Trainieren des LLM verwendet wird, erfassen. Es werden viele Schichten dafür verwendet, sodass viele trainierbare Parameter diese Informationen erfassen werden.
Verständnis der Aufmerksamkeitsmechanismen
In traditionellen Sequenz-zu-Sequenz-Modellen, die für die Sprachübersetzung verwendet werden, kodiert das Modell eine Eingabesequenz in einen kontextuellen Vektor fester Größe. Dieser Ansatz hat jedoch Schwierigkeiten mit langen Sätzen, da der kontextuelle Vektor fester Größe möglicherweise nicht alle notwendigen Informationen erfasst. Aufmerksamkeitsmechanismen beheben diese Einschränkung, indem sie es dem Modell ermöglichen, alle Eingabetoken zu berücksichtigen, wenn es jedes Ausgabetoken generiert.
Beispiel: Maschinelle Übersetzung
Betrachten Sie die Übersetzung des deutschen Satzes "Kannst du mir helfen diesen Satz zu übersetzen" ins Englische. Eine wortwörtliche Übersetzung würde keinen grammatikalisch korrekten englischen Satz ergeben, da es Unterschiede in den grammatikalischen Strukturen zwischen den Sprachen gibt. Ein Aufmerksamkeitsmechanismus ermöglicht es dem Modell, sich auf relevante Teile des Eingabesatzes zu konzentrieren, wenn es jedes Wort des Ausgabesatzes generiert, was zu einer genaueren und kohärenteren Übersetzung führt.
Einführung in die Selbstaufmerksamkeit
Selbstaufmerksamkeit, oder Intra-Aufmerksamkeit, ist ein Mechanismus, bei dem Aufmerksamkeit innerhalb einer einzelnen Sequenz angewendet wird, um eine Darstellung dieser Sequenz zu berechnen. Sie ermöglicht es jedem Token in der Sequenz, auf alle anderen Tokens zu achten, was dem Modell hilft, Abhängigkeiten zwischen Tokens unabhängig von ihrer Entfernung in der Sequenz zu erfassen.
Schlüsselkonzepte
Tokens: Einzelne Elemente der Eingabesequenz (z. B. Wörter in einem Satz).
Embeddings: Vektorielle Darstellungen von Tokens, die semantische Informationen erfassen.
Aufmerksamkeitsgewichte: Werte, die die Bedeutung jedes Tokens im Verhältnis zu anderen bestimmen.
Berechnung der Aufmerksamkeitsgewichte: Ein Schritt-für-Schritt-Beispiel
Betrachten wir den Satz "Hello shiny sun!" und repräsentieren jedes Wort mit einem 3-dimensionalen Embedding:
Hello:
[0.34, 0.22, 0.54]
shiny:
[0.53, 0.34, 0.98]
sun:
[0.29, 0.54, 0.93]
Unser Ziel ist es, den Kontextvektor für das Wort "shiny" mithilfe von Selbstaufmerksamkeit zu berechnen.
Schritt 1: Berechnung der Aufmerksamkeitswerte
Multiplizieren Sie einfach jeden Dimensionswert der Abfrage mit dem entsprechenden Wert jedes Tokens und addieren Sie die Ergebnisse. Sie erhalten 1 Wert pro Token-Paar.
Für jedes Wort im Satz berechnen Sie den Aufmerksamkeitswert in Bezug auf "shiny", indem Sie das Skalarprodukt ihrer Embeddings berechnen.
Aufmerksamkeitswert zwischen "Hello" und "shiny"
Aufmerksamkeitswert zwischen "shiny" und "shiny"
Aufmerksamkeitswert zwischen "sun" und "shiny"
Schritt 2: Normalisieren der Aufmerksamkeitswerte zur Ermittlung der Aufmerksamkeitsgewichte
Verlieren Sie sich nicht in den mathematischen Begriffen, das Ziel dieser Funktion ist einfach, normalisieren Sie alle Gewichte, sodass sie insgesamt 1 ergeben.
Darüber hinaus wird die Softmax-Funktion verwendet, da sie Unterschiede aufgrund des exponentiellen Teils verstärkt, was es einfacher macht, nützliche Werte zu erkennen.
Wenden Sie die Softmax-Funktion auf die Aufmerksamkeitswerte an, um sie in Aufmerksamkeitsgewichte umzuwandeln, die sich auf 1 summieren.
Berechnung der Exponentialwerte:
Berechnung der Summe:
Berechnung der Aufmerksamkeitsgewichte:
Schritt 3: Berechnung des Kontextvektors
Nehmen Sie einfach jedes Aufmerksamkeitsgewicht und multiplizieren Sie es mit den entsprechenden Token-Dimensionen und summieren Sie dann alle Dimensionen, um nur 1 Vektor (den Kontextvektor) zu erhalten.
Der Kontextvektor wird als gewichtete Summe der Embeddings aller Wörter unter Verwendung der Aufmerksamkeitsgewichte berechnet.
Berechnung jeder Komponente:
Gewichtetes Embedding von "Hello":
* **Gewichtetes Embedding von "shiny"**:
* **Gewichtetes Embedding von "sun"**:
Summierung der gewichteten Embeddings:
context vector=[0.0779+0.2156+0.1057, 0.0504+0.1382+0.1972, 0.1237+0.3983+0.3390]=[0.3992,0.3858,0.8610]
Dieser Kontextvektor repräsentiert das angereicherte Embedding für das Wort "shiny", das Informationen aus allen Wörtern im Satz integriert.
Zusammenfassung des Prozesses
Berechnung der Aufmerksamkeitswerte: Verwenden Sie das Skalarprodukt zwischen dem Embedding des Zielworts und den Embeddings aller Wörter in der Sequenz.
Normalisieren der Werte zur Ermittlung der Aufmerksamkeitsgewichte: Wenden Sie die Softmax-Funktion auf die Aufmerksamkeitswerte an, um Gewichte zu erhalten, die sich auf 1 summieren.
Berechnung des Kontextvektors: Multiplizieren Sie das Embedding jedes Wortes mit seinem Aufmerksamkeitsgewicht und summieren Sie die Ergebnisse.
Selbstaufmerksamkeit mit trainierbaren Gewichten
In der Praxis verwenden Selbstaufmerksamkeitsmechanismen trainierbare Gewichte, um die besten Darstellungen für Abfragen, Schlüssel und Werte zu lernen. Dies beinhaltet die Einführung von drei Gewichtsmatrizen:
Die Abfrage ist die zu verwendende Daten wie zuvor, während die Schlüssel- und Wertematrizen einfach zufällige, trainierbare Matrizen sind.
Schritt 1: Berechnung von Abfragen, Schlüsseln und Werten
Jedes Token hat seine eigene Abfrage-, Schlüssel- und Wertematrix, indem es seine Dimensionswerte mit den definierten Matrizen multipliziert:
Diese Matrizen transformieren die ursprünglichen Embeddings in einen neuen Raum, der für die Berechnung der Aufmerksamkeit geeignet ist.
Beispiel
Angenommen:
Eingabedimension
din=3
(Embedding-Größe)Ausgabedimension
dout=2
(gewünschte Dimension für Abfragen, Schlüssel und Werte)
Initialisieren Sie die Gewichtsmatrizen:
Berechne Abfragen, Schlüssel und Werte:
Schritt 2: Berechnung der skalierten Dot-Produkt-Attention
Berechnung der Aufmerksamkeitswerte
Ähnlich wie im vorherigen Beispiel, aber diesmal verwenden wir anstelle der Werte der Dimensionen der Tokens die Schlüsselmatrix des Tokens (bereits unter Verwendung der Dimensionen berechnet):. Für jede Abfrage qi
und Schlüssel kj
:
Skalierung der Werte
Um zu verhindern, dass die Dot-Produkte zu groß werden, skalieren Sie sie durch die Quadratwurzel der Schlüssel-Dimension dk
:
Der Wert wird durch die Quadratwurzel der Dimensionen geteilt, da Dot-Produkte sehr groß werden können und dies hilft, sie zu regulieren.
Anwendung von Softmax zur Ermittlung der Aufmerksamkeitsgewichte: Wie im ursprünglichen Beispiel, normalisieren Sie alle Werte, sodass sie 1 ergeben.
Schritt 3: Berechnung der Kontextvektoren
Wie im ursprünglichen Beispiel, summieren Sie einfach alle Wertematrizen und multiplizieren jede mit ihrem Aufmerksamkeitsgewicht:
Codebeispiel
Ein Beispiel von https://github.com/rasbt/LLMs-from-scratch/blob/main/ch03/01_main-chapter-code/ch03.ipynb zeigt diese Klasse, die die Selbst-Attention-Funktionalität implementiert, über die wir gesprochen haben:
Beachten Sie, dass anstelle der Initialisierung der Matrizen mit zufälligen Werten nn.Linear
verwendet wird, um alle Gewichte als Parameter zum Trainieren zu kennzeichnen.
Kausale Aufmerksamkeit: Zukünftige Wörter verbergen
Für LLMs möchten wir, dass das Modell nur die Tokens berücksichtigt, die vor der aktuellen Position erscheinen, um das nächste Token vorherzusagen. Kausale Aufmerksamkeit, auch bekannt als maskierte Aufmerksamkeit, erreicht dies, indem der Aufmerksamkeitsmechanismus so modifiziert wird, dass der Zugriff auf zukünftige Tokens verhindert wird.
Anwendung einer kausalen Aufmerksamkeitsmaske
Um kausale Aufmerksamkeit zu implementieren, wenden wir eine Maske auf die Aufmerksamkeitswerte vor der Softmax-Operation an, sodass die verbleibenden Werte immer noch 1 ergeben. Diese Maske setzt die Aufmerksamkeitswerte zukünftiger Tokens auf negative Unendlichkeit, wodurch sichergestellt wird, dass nach der Softmax ihre Aufmerksamkeitsgewichte null sind.
Schritte
Berechnung der Aufmerksamkeitswerte: Wie zuvor.
Maske anwenden: Verwenden Sie eine obere Dreiecksmatrix, die über der Diagonalen mit negativer Unendlichkeit gefüllt ist.
Softmax anwenden: Berechnen Sie die Aufmerksamkeitsgewichte mit den maskierten Werten.
Maskierung zusätzlicher Aufmerksamkeitsgewichte mit Dropout
Um Überanpassung zu verhindern, können wir Dropout auf die Aufmerksamkeitsgewichte nach der Softmax-Operation anwenden. Dropout setzt zufällig einige der Aufmerksamkeitsgewichte während des Trainings auf null.
Ein regulärer Dropout liegt bei etwa 10-20%.
Codebeispiel
Codebeispiel von https://github.com/rasbt/LLMs-from-scratch/blob/main/ch03/01_main-chapter-code/ch03.ipynb:
Erweiterung der Ein-Kopf-Attention zur Mehr-Kopf-Attention
Mehr-Kopf-Attention besteht in der Praxis darin, mehrere Instanzen der Selbst-Attention-Funktion auszuführen, wobei jede ihre eigenen Gewichte hat, sodass unterschiedliche endgültige Vektoren berechnet werden.
Codebeispiel
Es wäre möglich, den vorherigen Code wiederzuverwenden und einfach einen Wrapper hinzuzufügen, der ihn mehrere Male ausführt, aber dies ist eine optimierte Version von https://github.com/rasbt/LLMs-from-scratch/blob/main/ch03/01_main-chapter-code/ch03.ipynb, die alle Köpfe gleichzeitig verarbeitet (was die Anzahl der teuren Schleifen reduziert). Wie im Code zu sehen ist, werden die Dimensionen jedes Tokens in verschiedene Dimensionen entsprechend der Anzahl der Köpfe aufgeteilt. Auf diese Weise, wenn ein Token 8 Dimensionen hat und wir 3 Köpfe verwenden möchten, werden die Dimensionen in 2 Arrays mit 4 Dimensionen aufgeteilt, und jeder Kopf verwendet eines davon:
Für eine weitere kompakte und effiziente Implementierung könnten Sie die torch.nn.MultiheadAttention
Klasse in PyTorch verwenden.
Kurze Antwort von ChatGPT, warum es besser ist, die Dimensionen der Tokens auf die Köpfe zu verteilen, anstatt dass jeder Kopf alle Dimensionen aller Tokens überprüft:
Obwohl es vorteilhaft erscheinen mag, dass jeder Kopf alle Einbettungsdimensionen verarbeitet, da jeder Kopf Zugriff auf die vollständigen Informationen hätte, ist die gängige Praxis, die Einbettungsdimensionen auf die Köpfe zu verteilen. Dieser Ansatz balanciert die rechnerische Effizienz mit der Modellleistung und ermutigt jeden Kopf, vielfältige Darstellungen zu lernen. Daher wird das Aufteilen der Einbettungsdimensionen im Allgemeinen bevorzugt, anstatt dass jeder Kopf alle Dimensionen überprüft.
References
Last updated