Transformer
Die Bauweise, auf der praktisch alle heutigen Sprachmodelle beruhen – ein erstaunlich einfacher Bauplan, sehr oft wiederholt.
Der Transformer ist eine Architektur für neuronale Netze, 2017 von Forschern bei Google im Paper „Attention Is All You Need“ vorgestellt. Er besteht aus einem Stapel gleich gebauter Blöcke; jeder Block hat zwei Teile: Aufmerksamkeit (Tokens tauschen Informationen aus) und ein Feedforward-Netz (jedes Token wird für sich weiterverarbeitet).
Sein großer Vorteil: Er verarbeitet alle Tokens eines Textes gleichzeitig statt nacheinander. Dadurch lässt er sich auf Grafikkarten extrem effizient trainieren – die Voraussetzung für die heutigen Riesenmodelle.
Was es vorher gab
Vor 2017 verarbeiteten Sprachmodelle Text meist mit rekurrenten Netzen (RNN, LSTM): Wort für Wort, wobei ein interner Zustand von Schritt zu Schritt weitergereicht wurde – wie ein Staffelstab. Das hatte zwei große Nachteile:
Rekurrentes Netz
- Kann nicht parallel rechnen – langsam im Training
- Frühe Wörter verblassen über lange Strecken
Transformer
- Im Training voll parallel – ideal für Grafikkarten
- Direkter Draht über beliebige Entfernungen
Die Reise eines Tokens
Der ganze Transformer auf einen Blick. Geh Schritt für Schritt hindurch oder klick direkt auf einen Baustein:
Woher kennt er die Reihenfolge?
Eine überraschende Eigenschaft: Die Aufmerksamkeit selbst ist blind für die Reihenfolge. Sie vergleicht Vektoren miteinander, und dabei ist egal, an welcher Stelle sie stehen. Für sie wären „Hund beißt Mann“ und „Mann beißt Hund“ dasselbe – ein Sack voller Wörter. Deshalb bekommt jedes Token zusätzlich eine Positionsinformation mit.
Der Datenstrom durch die Blöcke
Ein wichtiges Detail steckt in den unscheinbaren „+ addieren“-Schritten. Kein Block ersetzt den Vektor eines Tokens – jeder addiert nur etwas hinzu. Man spricht vom Residual Stream: einem Datenstrom, der von unten nach oben durch alle Blöcke fließt und in den jeder Block liest und schreibt.
Das hat zwei Vorteile: Informationen gehen nicht verloren, auch durch 100 Blöcke hindurch. Und das Training funktioniert überhaupt erst bei so vielen Schichten, weil die Fehlersignale über diesen direkten Weg zurückfließen können.
Aufmerksamkeit
Holt Informationen von anderen Tokens. Der einzige Ort, an dem Tokens miteinander reden.
Feedforward
Verarbeitet jedes Token einzeln weiter. Hier steckt rund zwei Drittel der Parameter – und nach heutiger Forschung ein guter Teil des gespeicherten Faktenwissens.
Normalisierung
Hält die Zahlen in einem vernünftigen Bereich, damit sie über viele Schichten nicht explodieren oder verschwinden.
Drei Varianten
Der Original-Transformer von 2017 war für Übersetzung gebaut und hatte zwei Hälften: einen Encoder, der den Ausgangstext liest, und einen Decoder, der die Übersetzung schreibt. Daraus sind drei Familien entstanden:
Textgeneratoren
Schauen nur nach hinten, erzeugen Text Token für Token. Das ist die Bauweise der heutigen Chat-Modelle, etwa der GPT- und Llama-Familien.
Textversteher
Sehen den ganzen Text in beide Richtungen, erzeugen aber keinen. Gut zum Klassifizieren und für Suchmaschinen. Bekanntestes Beispiel: BERT.
Übersetzer
Das Original-Design. Noch üblich für Übersetzung und manche Spracherkennung, z. B. T5 oder Whisper.
Kurze Geschichte
Es wird auch an Alternativen geforscht, etwa an sogenannten State-Space-Modellen, die lange Texte günstiger verarbeiten sollen, und an Mischformen aus beidem. Bisher hat aber keine den Transformer bei den großen Sprachmodellen verdrängt.
Für Entwickler übersetzt
| Begriff | Entspricht ungefähr |
|---|---|
| Transformer | eine Pipeline aus N identischen Filtern, wie eine Filter-Chain |
| Block | ein Filter mit zwei Stufen: erst Austausch zwischen allen Elementen, dann Verarbeitung jedes Elements einzeln |
| Residual Stream | x = x + f(x) statt x = f(x) – jeder Filter ergänzt, keiner ersetzt |
| Aufmerksamkeit | der einzige Schritt mit Zugriff auf die anderen Elemente der Liste |
| Feedforward | ein map() über die Liste – jedes Element unabhängig |
| Training vs. Erzeugen | Training: ganzer Text als Batch, parallel. Erzeugen: Token für Token in einer Schleife. |
// Ein kompletter Transformer-Durchlauf, stark vereinfacht
float[] naechstesToken(int[] tokenIds) {
float[][] x = embedding(tokenIds); // ein Vektor pro Token
x = plusPosition(x);
for (Block b : bloecke) { // z. B. 80 Stück
x = add(x, b.aufmerksamkeit(norm(x))); // Tokens tauschen sich aus
x = add(x, b.feedforward(norm(x))); // jedes Token für sich
}
float[] letzter = norm(x[x.length - 1]);
return ausgabeschicht(letzter); // ein Logit pro Vokabular-Eintrag
}Das ist tatsächlich die ganze Struktur. Die Komplexität steckt nicht im Code, sondern in den Milliarden Parametern in embedding, den Blöcken und der Ausgabeschicht.