Wie ein Sprachmodell Text liest
Tokenisierung zerlegt einen Text in Stücke, die Tokens heißen, und Byte-Pair-Encoding (BPE) ist der übliche Weg, diese Stücke zu wählen. Jeder Satz, den Sie in einen Chatbot tippen, wird so zerlegt, bevor das Modell ihn sieht.
Die Stücke bestimmen, wie viel Text hineinpasst, was mit seltenen Wörtern geschieht und was das Modell buchstabieren kann.
Am Ende dieser Lektion
Notiz
Ich kann einen kurzen Text mit Paar-Fusionen in Tokens zerlegen.
Schlüsselwörter
| Begriff | Was er bedeutet | Beispiel |
|---|---|---|
| Token | ein Stück Text, das das Modell als Einheit behandelt | see |
| Vokabular | die Liste aller Tokens, die das Modell kennt | |
| Paar | zwei Tokens, die nebeneinander stehen | s e |
| Fusion | ein Paar zu einem neuen Token verbinden | |
| Byte-Pair-Encoding | Tokens bauen, indem man immer wieder das häufigste Paar verbindet | |
| Token-ID | die Zahl, die für ein Token steht |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Wörter oder Zeichen: zwei einfache Zerlegungen
Im Modul Verarbeitung natürlicher Sprache haben Sie Text in Wörter zerlegt. Ein Sprachmodell braucht aber ein festes Vokabular, und Wörter machen das schwer. Ein neues Wort, etwa ein Name, ein Tippfehler oder eine neue Zusammensetzung, ist einfach unbekannt.
Zeichen lösen das, denn ein paar Dutzend davon schreiben jedes Wort. Dafür wird ein Satz sehr lang, und lange Eingaben kosten mehr Rechenarbeit.
Durchgerechnetes Beispiel: ein Text, zwei Zerlegungen
| Zerlegt in | Tokens in „see seerose rose see“ | Vokabular | Kann es „rosen“ schreiben? |
|---|---|---|---|
| Wörter | 4 | 3: see, seerose, rose | Nein, das Wort ist unbekannt |
| Zeichen | 17 | 4: s, e, r, o | Nur mit dem neuen Buchstaben n |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Beide Arten von Tokens zählen
text = "see seerose rose see"
woerter = text.split()
zeichen = []
for wort in woerter:
for z in wort:
zeichen.append(z)
wort_vokabular = []
for wort in woerter:
if wort not in wort_vokabular:
wort_vokabular.append(wort)
zeichen_vokabular = []
for z in zeichen:
if z not in zeichen_vokabular:
zeichen_vokabular.append(z)
print("Wort-Tokens:", len(woerter), "Vokabular:", wort_vokabular)
print("Zeichen-Tokens:", len(zeichen), "Vokabular:", zeichen_vokabular)
print("Ist rosen ein bekanntes Wort?", "rosen" in wort_vokabular)
# Fügen Sie das Wort rosen in den Text ein und starten Sie erneut.
# Welches Vokabular wächst, und um wie viel?
Byte-Pair-Encoding verbindet das häufigste Paar
Byte-Pair-Encoding liegt zwischen Wörtern und Zeichen. Man beginnt mit Zeichen und zählt jedes Paar benachbarter Tokens innerhalb eines Wortes. Das häufigste Paar wird zu einem neuen Token und kommt ins Vokabular. Bei Gleichstand gewinnt das zuerst gezählte Paar.
Dann zählt man neu und verbindet wieder. Häufige Wörter werden so kürzer. Seltene Wörter bleiben kleinere Stücke, also ist nie etwas unbekannt.
Durchgerechnetes Beispiel: die Paare zählen
| Paar | Wo es vorkommt | Anzahl |
|---|---|---|
| s e | see, seerose (zweimal), rose, see | 5 |
| e e | see, seerose, see | 3 |
| r o | seerose, rose | 2 |
| o s | seerose, rose | 2 |
| e r | seerose | 1 |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Die Paare im Lab zählen
docker exec jupyter python3 -c "from collections import Counter; woerter = 'see seerose rose see'.split(); print(Counter(w[i:i + 2] for w in woerter for i in range(len(w) - 1)).most_common(3))"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Durchgerechnetes Beispiel: vier Fusionen
| Fusion | Neues Token | see | seerose | rose |
|---|---|---|---|---|
| Start | keins | s e e | s e e r o s e | r o s e |
| 1: s e (5) | se | se e | se e r o se | r o se |
| 2: se e (3) | see | see | see r o se | r o se |
| 3: r o (2, zuerst gezählt) | ro | see | see ro se | ro se |
| 4: ro se (2) | rose | see | see rose | rose |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Die erste Fusion ausführen
text = "see seerose rose see"
woerter = []
for wort in text.split():
woerter.append(list(wort))
links = "s"
rechts = "e"
verschmolzen = []
for tokens in woerter:
neu = []
i = 0
while i < len(tokens):
# Das Paar wird ein Token, dann springen wir über beide.
if i + 1 < len(tokens) and tokens[i] == links and tokens[i + 1] == rechts:
neu.append(links + rechts)
i = i + 2
else:
neu.append(tokens[i])
i = i + 1
verschmolzen.append(neu)
print(verschmolzen)
# Ändern Sie das Paar in "e" und "e" und starten Sie erneut.
# Wie viele Tokens hat das Wort rose jetzt?
Zusammengesetzte Wörter zerfallen in bekannte Teile
Nach vier Fusionen ist „seerose“ kein eigenes Token. Es besteht aus „see“ und „rose“, zwei Teilen, die das Vokabular schon kennt.
Das passt gut zum Deutschen. Ein neues Kompositum wie „Seerosenteich“ steht in keinem Wortvokabular. Mit BPE wird es aus häufigen Teilen gebaut, statt unbekannt zu sein.
Ein häufiger Fehler
Warnung
Viele denken, ein Token sei ein Wort. Mit Byte-Pair-Encoding ist ein häufiges Wort ein Token, ein seltenes aber mehrere. Zählen Sie darum Tokens und nicht Wörter, wenn Sie fragen, wie viel Text in ein Modell passt.
Jedes Token wird zu einer Zahl
Das Modell sieht nie Buchstaben. Jedes Token im Vokabular bekommt eine Token-ID, seinen Platz in der Liste. Nach den vier Fusionen heißt das Vokabular s, e, r, o, se, see, ro und rose, nummeriert von 0 bis 7.
So wird „seerose esse“ zu see, rose, e, s, se, also zu den IDs 5, 7, 1, 0, 4. Das sind fünf Tokens statt elf Zeichen.
Tokens in IDs umwandeln
docker exec jupyter python3 -c "vokabular = ['s', 'e', 'r', 'o', 'se', 'see', 'ro', 'rose']; print([vokabular.index(t) for t in ['see', 'rose', 'e', 's', 'se']])"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.