Attention visualisiert: Das Herzstück des Transformers [Video]
(3blue1brown.com)- Die Attention eines Transformers ist ein Mechanismus, der Token-Embeddings kontextabhängig aktualisiert und dasselbe Wort je nach umgebenden Wörtern in einen Vektor mit anderer Bedeutung verschiebt
- Ein Attention-Head erzeugt aus jedem Token query/key/value-Vektoren und berechnet mit Key-Query-Skalarprodukten und Softmax ein Attention Pattern, also Relevanzgewichte zwischen Wörtern
- Autoregressive Modelle im GPT-Stil nutzen Masking, damit spätere Tokens frühere Tokens nicht beeinflussen können; da die Größe des Attention Pattern quadratisch mit der Kontextlänge wächst, ist die Erweiterung auf große Context Windows aufwendig
- Im GPT-3-Beispiel haben Key- und Query-Matrizen jeweils 1.572.864 Parameter; die Value Map wird in Low-Rank-Transformationen aufgeteilt, sodass ein Head auf etwa 6,3 Millionen Parameter kommt
- Transformer, die viele Attention-Heads und Blöcke wiederholen, lernen verschiedene Arten der Kontextaktualisierung; ein wesentlicher Erfolgsfaktor ist die Parallelisierbarkeit, mit der viele Berechnungen auf GPUs schnell verarbeitet werden können
Die Rolle von Attention im Transformer
- Transformer nutzen den Eingabetext zur Vorhersage des nächsten Tokens; die Eingabe wird zunächst tokenisiert und in Wörter oder Wortstücke zerlegt
- Jedes Token wird in ein Embedding umgewandelt, einen hochdimensionalen Vektor
- Richtungen in diesem Embedding-Raum können Bedeutungen entsprechen
- Beispielsweise kann eine Verschiebung in eine bestimmte Richtung das Embedding eines männlichen Nomens zum entsprechenden weiblichen Nomen verschieben
- Ziel von Attention ist es, die initialen Embeddings schrittweise anzupassen, sodass sie nicht nur Informationen über einzelne Wörter, sondern reichere kontextuelle Bedeutung enthalten
Warum dasselbe Wort je nach Kontext unterschiedlich wird
- In „American shrew mole“, „One mole of carbon dioxide“ und „Take a biopsy of the mole“ hat mole jeweils unterschiedliche Bedeutungen
- In der ersten Embedding-Phase ist der Vektor von mole eher wie ein Lookup-Table ohne Kontext und daher in allen drei Fällen gleich
- Im nächsten Schritt, dem Attention Block, können die umgebenden Embeddings Informationen an das mole-Embedding übertragen und dessen Wert aktualisieren
- Ein gut trainiertes Modell verknüpft die verschiedenen Bedeutungen von mole mit unterschiedlichen Richtungen im Embedding-Raum und berechnet kontextabhängig, was dem allgemeinen Embedding hinzugefügt werden soll
- Wie bei „Eiffel tower“ und „miniature Eiffel tower“ kann das Embedding eines Wortes nicht nur durch nahe Wörter, sondern auch durch Informationen aus weit entfernten Tokens aktualisiert werden
- Für die Vorhersage des nächsten Wortes wird nur der letzte Vektor verwendet; daher muss das Embedding des letzten Wortes einer langen Eingabe zu einem gewissen Grad die gesamte für die Vorhersage nötige Kontextinformation enthalten
Rechenablauf eines einzelnen Attention-Heads
- Die grundlegende Erklärung bezieht sich auf einen single head of attention
- Im Beispielsatz „A fluffy blue creature roamed the verdant forest.“ wird angenommen, dass Adjektive die initialen Embeddings der zugehörigen Nomen aktualisieren
- Dieses Beispiel soll zeigen, welche Art von Verhalten ein Attention-Head ausführen kann
- Das tatsächliche Verhalten eines Heads ist schwer zu interpretieren, da viele Parameter so angepasst werden, dass sie die Kostenfunktion verringern
- Initiale Embeddings enthalten neben Wortinformationen auch Positionsinformationen und werden als
\vec{E}bezeichnet - Ziel ist es, aus dem bestehenden Embedding ein neues, kontextbezogenes Embedding
\vec{E}'zu erzeugen -
Query
- Im ersten Schritt wird jedes Token-Embedding mit der Query Matrix
W_Qmultipliziert, um einen Query-Vektor\vec{Q}zu erzeugen - Man kann sich das so vorstellen, dass ein Nomen eine Frage stellt wie: „Gibt es davor ein Adjektiv?“
- Die Elemente von
W_Qsind gelernte Modellparameter, und was ein bestimmter Head tatsächlich tut, ist schwer zu interpretieren - Anschaulich kann man sagen, dass Nomen-Embeddings in eine Richtung abgebildet werden, die „Adjektive an früheren Positionen sucht“
- Im ersten Schritt wird jedes Token-Embedding mit der Query Matrix
-
Key
- Gleichzeitig wird jedes Embedding mit der Key Matrix
W_kmultipliziert, um einen Key-Vektor\vec{K}zu erzeugen - Keys können als potenzielle Antworten auf Queries betrachtet werden und liegen im selben, kleineren dimensionalen Raum wie die Queries
- Wie stark Key und Query ausgerichtet sind, wird mit dem Skalarprodukt gemessen
- Je größer das Skalarprodukt, desto stärker sind die beiden Vektoren ausgerichtet
- Wenn die Keys von fluffy und blue gut zur Query von creature passen, erhalten sie große positive Werte
- Berechnet man die Skalarprodukte aller Key-Query-Paare, entsteht ein Raster von Scores, das zeigt, wie relevant ein Wort für die Bedeutungsaktualisierung eines anderen Wortes ist
- Gleichzeitig wird jedes Embedding mit der Key Matrix
Attention Pattern und Softmax
- Da Skalarprodukt-Scores Werte von
-\inftybis\inftyannehmen können, wird auf jede Spalte Softmax angewendet, um sie auf Werte zwischen 0 und 1 zu normalisieren - Das normalisierte Raster heißt Attention Pattern
- Jede Spalte kann als Gewichtung dafür verstanden werden, wie relevant das linke Wort für die Aktualisierung des oberen Wortes ist
- Das ursprüngliche Transformer-Paper schreibt dies kompakter
QundKsind die vollständigen Arrays der Query- und Key-VektorenK^TQbezeichnet das Raster aller möglichen Key-Query-Skalarprodukte- In der Notation des Papers stehen Queries und Keys in Zeilen und werden als
QK^Tgeschrieben, sodass die Form gegenüber der hier beschriebenen Darstellung entlang der Diagonalen gespiegelt ist
- Für numerische Stabilität enthält die Formel einen Term, der durch
\sqrt{d_k}teilt, die Quadratwurzel der Dimension des Key-Query-Raums - Softmax umfasst zwar den gesamten Ausdruck, wird der Bedeutung nach aber auf jede Spalte angewendet
Masking und Beschränkungen der Kontextgröße
- Beim Training sagt das Modell nicht nur ein einzelnes nächstes Token für einen gegebenen Text vorher, sondern gleichzeitig auch die möglichen nächsten Tokens nach jeder Teilsequenz
- Ein einzelnes Textbeispiel funktioniert dadurch wie mehrere Trainingsbeispiele, was die Effizienz erhöht
- Im GPT-Beispiel könnte es die richtige Antwort auf das nächste Token verraten, wenn spätere Tokens frühere Tokens beeinflussen; daher wird Masking verwendet
- Vor Softmax werden die Werte an den betreffenden Positionen auf negativ unendlich gesetzt
- Nach Softmax werden diese Positionen zu 0, während die Spalte weiterhin normalisiert bleibt
- Es gibt nicht nur Attention, bei der Masking immer angewendet wird; im GPT-Beispiel wird es aber stets genutzt, damit spätere Tokens frühere Tokens nicht beeinflussen
- Die Größe des Attention Pattern entspricht dem Quadrat der Context Size
- Daher kann die Context Size bei großen Sprachmodellen zu einer wichtigen Einschränkung werden
- Für größere Context Windows sind Varianten entstanden, die den Attention-Mechanismus besser skalierbar machen, hier wird jedoch nur die Grundform behandelt
Wie Values die Embeddings tatsächlich aktualisieren
- Das Attention Pattern liefert Gewichtungen dafür, welches Wort welches andere Wort aktualisiert; der nächste Schritt besteht darin, die tatsächliche Änderung des Embeddings zu erzeugen
- Jedes Embedding wird mit einer Value Matrix
W_Vmultipliziert, um einen Value-Vektor zu erzeugen- Value-Vektoren liegen im selben hochdimensionalen Raum wie die Embeddings
- Sie geben an, welche konkrete Änderung hinzugefügt werden soll, wenn ein relevantes Wort die Bedeutung eines anderen Wortes anpasst
- Multipliziert man in jeder Spalte die Value-Vektoren mit den jeweiligen Gewichten des Attention Pattern und addiert alles, erhält man die Änderung
\Delta \vec{E} - Addiert man diese Änderung zum ursprünglichen Embedding, entsteht ein neues, kontextbezogenes Embedding
\vec{E}'- Im Beispiel nimmt creature Informationen von fluffy und blue auf und enthält dadurch eine Bedeutung, die näher an „fluffy blue creature“ liegt
- Wendet man denselben Prozess auf alle Spalten an, kommen aus dem Attention Block verfeinerte Embeddings für die gesamte Token-Sequenz heraus
- Ein einzelner Attention-Head wird durch drei Arten gelernter Parametermatrizen parametrisiert: Key Matrix, Query Matrix und Value Matrix
Parameterberechnung auf Basis von GPT-3
- Im GPT-3-Beispiel haben Key- und Query-Matrizen jeweils 12.288 Spalten, entsprechend der Embedding-Dimension, und 128 Zeilen, entsprechend der Dimension des Key-Query-Raums
- Jede Matrix hat 1.572.864 Parameter
- Würde man die Value Matrix als quadratische 12.288×12.288-Matrix anlegen, kämen 150.994.944 Parameter hinzu, also deutlich mehr als bei Key/Query
- In der Praxis ist es effizienter, die Value Map in zwei kleinere Matrizen zu zerlegen und die Parameterzahl damit ungefähr auf das Niveau von Key/Query zu bringen
- Die erste Matrix projiziert den großen Embedding-Raum nach unten in einen kleineren Raum, etwa mit 128 Dimensionen
- Die zweite Matrix projiziert aus dem kleinen Raum wieder zurück in den Embedding-Raum
- Aus Sicht der linearen Algebra wird damit die gesamte Value Map auf eine Low-Rank-Transformation beschränkt
- In dieser Erklärung werden die beiden Matrizen
Value_\downarrowundValue_\uparrowgenannt, dies sind jedoch keine konventionellen Bezeichnungen - Zusammengenommen hat ein Attention-Head mit den vier Matrizen etwa 6,3 Millionen Parameter
Self-Attention und Cross-Attention
- Die bisher beschriebene Struktur entspricht genauer einem Self-Attention Head
- Ein Cross-Attention Head kommt in Modellen vor, die zwei unterschiedliche Datensätze verarbeiten
- In einem Übersetzungsmodell könnten zum Beispiel Keys aus einer Sprache und Queries aus einer anderen Sprache stammen
- Das Attention Pattern kann zeigen, wie Wörter einer Sprache Wörtern einer anderen Sprache entsprechen
- Cross-Attention unterscheidet sich von Self-Attention dadurch, dass Key- und Query-Maps auf unterschiedliche Datensätze wirken
- In Settings wie der Übersetzung gibt es normalerweise kein Masking, weil es dort kein Konzept gibt, dass spätere Tokens frühere Tokens beeinflussen
Multi-Headed Attention und wiederholte Blöcke
- Ein tatsächlicher Attention Block besteht aus Multi-Headed Attention, bei der mehrere Heads parallel ausgeführt werden
- GPT-3 verwendet in jedem Block 96 Attention-Heads
- 96 verschiedene Key/Query-Matrizen erzeugen 96 verschiedene Attention Patterns
- Jeder Head erzeugt mit seinen eigenen Value-Matrizen eine Sequenz von Value-Vektoren
- Für jede Token-Position werden die von allen Heads vorgeschlagenen Änderungen
\Delta \vec{E}addiert und zum ursprünglichen Embedding hinzugefügt
- Wenn mehrere Heads parallel laufen, erhält das Modell die Kapazität, viele verschiedene Arten zu lernen, wie Kontext Bedeutung verändert
- Ein Multi-Headed-Attention-Block mit 96 Heads hat auf GPT-3-Basis etwa 600 Millionen Parameter
- In Papers und tatsächlichen Implementierungen werden die Matrizen, die
Value_\uparrowder einzelnen Heads entsprechen, zu einer großen Output Matrix zusammengefasst und mit dem gesamten Multi-Headed-Attention-Block verbunden- Wenn man normalerweise von der Value Matrix eines bestimmten Heads spricht, meint man hier die erste Projektionsstufe, die als
Value_\downarrowbezeichnet wurde
- Wenn man normalerweise von der Value Matrix eines bestimmten Heads spricht, meint man hier die erste Projektionsstufe, die als
Wie sich Bedeutung in tieferen Transformern akkumuliert
- Die internen Daten eines Transformers durchlaufen nicht nur einen einzelnen Attention Block, sondern mehrere Attention Blocks und ein Multi-Layer Perceptron
- Auch nachdem ein Wort-Embedding einen Teil des Kontexts aufgenommen hat, erhält es weiterhin Gelegenheiten, von den bereits verfeinerten umgebenden Embeddings beeinflusst zu werden
- Je tiefer das Netzwerk wird, desto mehr Bedeutung nimmt jedes Embedding aus anderen Embeddings auf und desto mehr Kapazität hat es, abstraktere Merkmale wie Stimmung, Ton oder die Frage, ob etwas ein Gedicht ist, zu kodieren
- GPT-3 enthält 96 Layer; die Parameter im Zusammenhang mit Key/Query/Value werden insgesamt als weniger als 58 Milliarden beschrieben
- Das ist etwa ein Drittel der gesamten Netzwerkparameter, der Großteil des Rests stammt aus den Blöcken zwischen den Attention-Schichten
- Ein großer Teil des Erfolgs des Attention-Mechanismus liegt nicht in einem einzelnen bestimmten Verhalten, sondern in seiner hohen Parallelisierbarkeit, durch die viele Berechnungen in kurzer Zeit auf GPUs ausgeführt werden können
- Weil Deep Learning die Lektion vermittelt hat, dass Skalierung die Modellleistung qualitativ stark verbessern kann, haben parallelisierbare Architekturen, die Skalierung ermöglichen, einen großen Vorteil
1 Kommentare
Meinungen auf Hacker News
Aus Sicht von jemandem, der Quantenchemie und etwas Machine Learning betrieben hat, fielen mir beim Anschauen dieses Videos die Ähnlichkeiten zwischen Transformer-Modellen und Quantenmechanik ziemlich deutlich auf.
In der Quantenmechanik wird der Zustand eines gesamten physikalischen Systems als sehr hochdimensionaler normalisierter Vektor codiert, genauer als Halbgerade im Hilbert-Raum, und die zeitliche Entwicklung übernimmt grob ein Zeitverschiebungsoperator, den man als unitäre Matrix U = exp(-iHt) ansehen kann.
Im Video heißt es, dass die Vorhersage des nächsten Tokens dadurch entschieden wird, dass allein aus dem letzten kontextbewussten Einbettungsvektor der nächste kontextbewusste Einbettungsvektor berechnet wird; das wirkt wie das Ergebnis der Anwendung einer linearen Zustandsfunktion auf einen hochdimensionalen Vektor.
Es fühlt sich ähnlich an, als würde man den Hamiltonian des Gesamtsystems offline aus den Trainingsdaten erzeugen, dann ein bestimmtes Teilsystem, nämlich das Kontextfenster, in eine zu diesem Hamiltonian passende Basis reparametrisieren, eine Zeitverschiebung um einen Schritt anwenden und anschließend in die ursprüngliche Basis zurückwechseln.
Allerdings sieht für jemanden, der in einem bestimmten Feld geforscht hat, jedes Problem wie ein Nagel für den Hammer dieses Feldes aus; deshalb würde mich interessieren, ob diese Ähnlichkeit auch anderen auffällt oder ob das zu sehr erzwungen ist.
Wenn eine Anwendung des Operators den Zustand des Universums um eine Planck-Zeit voranbringt, frage ich mich, ob wir den Unterschied zwischen einem solchen Universum und einem Universum mit kontinuierlicher Zeit beobachten könnten.
Die Verbindung zu dem, was damals in der Physik passiert ist, fällt mir erst jetzt ein.
Das YouTube-Video von CodeEmporium war leichter nachzuvollziehen: https://www.youtube.com/watch?v=Nw_PJdmydZY
Transformer lassen sich schwer mit Analogien erklären, und eigentlich gibt es auch keine gute Erklärung dafür, warum sie funktionieren. Vielleicht ist es daher besser, einfach den Mechanismus zu zeigen und die Interpretation den Zuschauenden zu überlassen.
Außerdem ist es einfacher, das Skalarprodukt als Projektion von Vektoren aufeinander zu erklären.
Der Grund, warum nach „the cat sat on the ...“ „mat“ kommt, ist, dass es im Datensatz das am häufigsten vorkommende Wort ist; das neuronale Netz ist ein Modell solcher Häufigkeiten.
Dass es „London in UK“ zu kennen scheint, aber nicht „London in France“, liegt ebenfalls daran, dass „UK“ im Datensatz viel häufiger vorkommt.
Der Algorithmus selbst tut nichts besonders Interessantes, außer die Berechnungen so anzuordnen, dass sie zur Hardware passen. Der Wert entsteht aus der bedingten Wahrscheinlichkeitsstruktur in den Daten, und diese Struktur ist das Ergebnis davon, dass Menschen Wörter nützlich angeordnet haben, um einander Informationen zu vermitteln.
Ich weiß, dass das eine unvollständige Erklärung ist, aber besser als gar keine.
Es gibt eine überzeugende Visualisierung, die zeigt, wie ein LLM bei der Bearbeitung einer einfachen Anfrage funktioniert: https://bbycroft.net/llm
Sie ergänzt die ausführliche Erklärung von 3blue1brown sehr gut.
Hervorragendes Video. Es zeigt gut, warum die Q*K-Matrixmultiplikation ein Flaschenhals ist. Wenn die Sequenz, also die Länge des Kontextfensters, S beträgt, muss die SxS-Matrix der Ergebnisse aller Queries mit allen Keys im Speicher gehalten werden.
Eine neu-ish Idee zur Verbesserung dieses Flaschenhalses ist Ring Attention, und dieser Artikel erklärt sie gut: https://learnandburn.ai/p/how-to-build-a-10m-token-context
Den Artikel habe ich redigiert.
Bei Unsloth wächst der Speicherverbrauch dank Flash Attention linear statt quadratisch, das Fine-Tuning wird doppelt so schnell, der VRAM-Verbrauch sinkt um 80 %, und auch die Inferenz wird doppelt so schnell. Die Rechenkomplexität bleibt allerdings O(N^2).
Für lange Kontexte schafft das neueste Unsloth-Release mit nur +1,9 % Overhead viermal längere Kontexte als HF+FA2 und ermöglicht auf H100 einen 228K-Kontext.
Der frühere Artikel „But what is a GPT?“ ist ebenfalls wirklich gut: https://www.3blue1brown.com/lessons/gpt
Dank dieses Videos ist mir klar geworden, dass der Attention-Mechanismus weniger eine bestimmte Funktion ist, sondern eher eine Art Meta-Funktion.
Wenn ich es richtig verstanden habe, ermöglichen Attention + gelernte Gewichte dem Transformer, bis zu einem gewissen Grad beliebige Funktionen zu lernen, und diese Funktion enthält dann Matching-Mechanismen wie scaled dot-product.
Deshalb glaube ich, dass Linear Attention der Leistungsfähigkeit von Standard-Attention niemals wirklich nahekommen kann. Der quadratische Term, der alle Eingabe-Ausgabe-Paare durchsucht, ist ein wesentliches Merkmal.
Dass dieses Video so leicht verdaulich war, lag zu einem großen Teil an den Animationen. Wie sie passend zum gesprochenen Timing expandieren, kontrahieren und sich entfalten, ist sehr gut gemacht.
Ich arbeite in einem eng verwandten Bereich, und dieses Video ist direkt in unsere Onboarding-Dokumentation für das Team gewandert.
Wichtig ist auch, dass ein großer Teil des Visualisierungscodes auf GitHub steht: https://github.com/3b1b/videos/tree/master/_2024/transformers
Endlich habe ich es verstanden. Keine Ahnung, warum andere Videos das so verwirrend gemacht haben.
Ich frage mich allmählich, ob Lehrfähigkeit und Forschungsfähigkeit im Großen und Ganzen nicht gegenseitig ausschließende Fähigkeiten sind.
Erstens ist die Standardterminologie schlecht. „Attention“ ist gerade noch intuitiv, „Self-Attention“ ist schlechter, und von „Key“ und „Value“ ganz zu schweigen.
Zweitens waren die zentralen Papers wie „Attention is All You Need“ und das BERT-Paper nicht gut geschrieben. Das soll die Leistung nicht schmälern; auch ein einflussreiches Paper mit einem gewaltigen Durchbruch kann schlecht erklären, und ich denke, genau das war der Fall.
Drittens wurden diese Strukturen im Wesentlichen dadurch entdeckt, dass man vieles ausprobiert und geschaut hat, was gut funktioniert. Es gab nicht zuerst einen Reflexionsprozess, der zu der Vorhersage führte, dass diese Struktur gut funktionieren würde, und den man dann experimentell überprüft hätte; es war von Anfang bis Ende empirisch.
Deshalb verstehen wir nicht vollständig, warum sie so gut funktionieren; alle Erklärungen sind eher nachträgliche Rationalisierungen, und es gibt neuere Arbeiten, die andeuten, dass bei ausreichendem Tuning auch andere Strukturen ähnlich gut funktionieren können. Etwas zu erklären, das man nicht vollständig versteht, ist schwierig.
Ich frage mich, ob es Referenzen dazu gibt, wie sich die heutige Architektur entwickelt hat. Ich würde gern den Weg von einer sehr einfachen Kernidee bis zum berühmten „all you need“-Paper sehen.
Andernfalls wirken viele Bausteine, als würden sie plötzlich aus dem Nichts auftauchen: viel Rechnen, wenig Intuition.
Jeremy Howard sagte auf Twitter, er habe verschiedene Versionen dieser Idee schon mehrfach gesehen; das klingt für mich so, als sei es eine naheliegende Idee gewesen. Beispiele dafür, wie diese Idee anderswo entstanden ist, könnten helfen, Intuition aufzubauen.
Dieser RNN/LSTM-Ansatz hatte die Schwäche einer Repräsentation fester Größe und außerdem die Schwäche, dass schwer zu entscheiden war, welche Teile der Eingabesequenz beim Erzeugen eines bestimmten Teils der Ausgabe verwendet werden sollten. Bahdanau et al. lösten das, indem sie einen Encoder-Decoder-RNN mit einem Attention-Mechanismus kombinierten und nicht nur den Endzustand, sondern alle früheren Zustände des RNN betrachten ließen.
RNNs waren ineffizient zu trainieren, daher suchte Jakob Uszkoreit nach Wegen, groß angelegte parallele Hardware besser zu nutzen, und stellte fest, dass Sprache nicht nur sequenziell, sondern auch hierarchisch ist. Er schlug eine geschichtete Struktur vor, bei der in jeder Schicht die Tokens von Teilsequenzen parallel verarbeitet werden und zugleich Bahdanau-artige Attention beibehalten wird, sodass Tokens einander über Self-Attention referenzieren, um die nächste Schicht vorherzusagen.
Die frühe Implementierung funktionierte, war aber nicht besser als andere Ansätze jener Zeit, etwa Faltungen. Später entwickelte Noam Shazeer die Idee weiter und baute eine Struktur, die deutlich besser funktionierte; nach Experimenten, bei denen unnötige Komponenten entfernt wurden, wurde daraus meines Wissens der ursprüngliche Transformer. Ich weiß nicht genau, wer die Key-basierte Attention-Form der endgültigen Architektur erdacht hat.
Der ursprüngliche Transformer aus dem Paper „Attention is All You Need“ hatte, den früheren RNN-basierten Ansätzen folgend, getrennte Encoder und Decoder und wurde auch in frühen Modellen wie Googles BERT verwendet. Für Sprachmodelle ist das aber nicht zwingend nötig, daher verwendete OpenAIs GPT nur den Decoder-Teil, und heute nutzen im Großen und Ganzen alle diesen Ansatz. Bei Decoder-only-Transformern geht der Eingabesatz in die unterste Schicht, wird dann durch jede Schicht hindurch schrittweise transformiert und kommt oben heraus. An das Ende der Eingabesequenz wird ein End-Token angehängt, und dieses wird in das nächste Token der Ausgabesequenz umgewandelt, also in das letzte Token.