Normalisierung
Wenn zwei Texte miteinander verglichen werden sollen, rechnet ein System sie zuerst in Zahlenlisten (Vektoren) um. Haben diese Vektoren unterschiedliche Längen, verfälscht das den Vergleich. Normalisierung bringt alle Vektoren auf dieselbe Länge, sodass nur noch die Richtung zählt.
In Embedding-Systemen erzeugen Modelle für jeden Text einen Vektor. Dieser Vektor ist eine geordnete Liste von Dezimalzahlen, die die Bedeutung des Textes in einem hochdimensionalen Raum repräsentiert. Je nach Modell variiert die Länge (auch Norm oder Betrag genannt) dieser Vektoren erheblich: Ein Modell liefert Vektoren mit einer durchschnittlichen Länge von 16, ein anderes mit 1,0, ein drittes mit 24.
Normalisierung ist die mathematische Operation, die jeden Vektor durch seinen eigenen Betrag teilt. Das Ergebnis ist ein Vektor mit Länge 1,0. Solche Vektoren heißen Einheitsvektoren. Ihre Richtung im Raum bleibt erhalten, nur die Länge ändert sich.
Warum die Länge eines Vektors den Vergleich verfälscht
Die gebräuchlichste Methode zum Vergleich zweier Vektoren ist die Cosine Similarity. Sie berechnet den Kosinus des Winkels zwischen zwei Vektoren. Bei normalisierten Vektoren (Länge 1,0) vereinfacht sich diese Berechnung zum reinen Skalarprodukt (Dot Product), weil der Nenner der Kosinusformel wegfällt.
Beispiel: Zwei Vektoren repräsentieren die Sätze "Vertrag kündigen" und "Vertrag beenden". Ohne Normalisierung hat Vektor A eine Länge von 18,3 und Vektor B eine Länge von 4,7. Das Skalarprodukt liefert einen Wert von 62,4. Nach Normalisierung (beide Länge 1,0) liefert dasselbe Skalarprodukt 0,91. Erst dieser Wert ist als Ähnlichkeitsmaß interpretierbar.
Beispiel: Ein Retrieval-System durchsucht 500.000 Dokumente. Die Embedding-Vektoren stammen aus zwei verschiedenen Indexierungsläufen. Der erste Lauf erzeugte Vektoren mit durchschnittlicher Länge 12, der zweite mit Länge 8. Ohne Normalisierung bevorzugt ein Dot-Product-basierter Vergleich systematisch Dokumente aus dem ersten Lauf, unabhängig von der inhaltlichen Relevanz.
Die mathematische Operation im Detail
Für einen Vektor v mit den Komponenten (v₁, v₂, ..., vₙ) berechnet sich der Betrag (die euklidische Norm, geschrieben als ||v||) als Quadratwurzel der Summe aller quadrierten Komponenten. Der normalisierte Vektor ist v̂ = v / ||v||.
Beispiel: Ein zweidimensionaler Vektor (3, 4) hat den Betrag √(9 + 16) = √25 = 5. Der normalisierte Vektor ist (3/5, 4/5) = (0,6, 0,8). Die Länge prüft man mit √(0,36 + 0,64) = √1,0 = 1,0.
Beispiel: In der Praxis haben Embedding-Vektoren 384 bis 4096 Dimensionen. Ein 768-dimensionaler Vektor aus einem Transformer-Modell hat 768 Komponenten. Die Normalisierung teilt jede einzelne Komponente durch denselben Betrag. Die Rechenzeit ist linear zur Dimensionszahl: 768 Divisionen plus eine Quadratwurzel.
Fachliche Einordnung: Die hier beschriebene Normalisierung ist die L2-Normalisierung (euklidische Norm). Es gibt andere Normen (L1, L∞), die in spezifischen Kontexten relevant sind. In Embedding-Systemen ist L2-Normalisierung der De-facto-Standard, weil sie die direkte Beziehung zwischen Cosine Similarity und Dot Product herstellt.
Welche Modelle normalisieren und welche nicht
Ob ein Modell bereits normalisierte Vektoren liefert, hängt von seiner Architektur und seinem Training ab. Modelle, die mit einer Cosine-Similarity-basierten Loss-Funktion trainiert werden, normalisieren ihre Ausgaben in der Regel während des Trainings. Bei anderen Modellen muss die Anwendung die Normalisierung selbst durchführen.
Beispiel: OpenAI-Embedding-Modelle (text-embedding-3-small, text-embedding-3-large) liefern normalisierte Vektoren. Jeder Vektor hat nach der API-Antwort bereits eine Länge von 1,0. Eine zusätzliche Normalisierung ist nicht nötig und verändert den Vektor nicht.
Beispiel: BERT-Basismodelle liefern nicht-normalisierte Vektoren. Wird ein solches Modell für semantische Suche eingesetzt, muss jeder Vektor nach der Erzeugung explizit normalisiert werden. Sentence-Transformers (etwa das Modell all-MiniLM-L6-v2) bieten dafür einen Parameter normalize_embeddings=True.
Die Modelldokumentation gibt in der Regel Auskunft darüber, ob die Ausgaben normalisiert sind. Im Zweifelsfall lässt sich das prüfen, indem man den Betrag eines Ausgabevektors berechnet. Liegt er bei 1,0 (mit einer Toleranz von etwa 0,001), ist der Vektor normalisiert.
Normalisierung in Retrieval-Pipelines
In einem typischen Retrieval-System wird eine Nutzerfrage (Query) gegen eine Sammlung von Dokumenten verglichen. Beide Seiten durchlaufen dasselbe Embedding-Modell. Die Qualität der Ergebnisse hängt davon ab, dass Query-Vektor und Dokument-Vektoren auf derselben Skala liegen.
Beispiel: Ein Kundensupport-System indexiert 10.000 FAQ-Artikel. Ein Nutzer fragt: "Wie kann ich mein Passwort zurücksetzen?" Das System erzeugt einen Query-Vektor und vergleicht ihn per Dot Product mit allen Artikel-Vektoren. Sind alle Vektoren normalisiert, entspricht das Dot Product der Cosine Similarity. Der Artikel mit dem höchsten Wert ist der ähnlichste.
Beispiel: Eine Chunking-Pipeline zerlegt lange Dokumente in Abschnitte von 256 Tokens. Kurze Abschnitte (50 Tokens) und lange Abschnitte (256 Tokens) erzeugen Vektoren mit unterschiedlichen Betragsbereichen. Normalisierung gleicht diese Unterschiede aus, sodass die Länge eines Chunks nicht über dessen Ranking entscheidet.
Normalisierung in Vektordatenbanken
Vektordatenbanken speichern Millionen bis Milliarden von Vektoren und müssen bei jeder Abfrage effizient die ähnlichsten finden. Die Wahl der Distanzmetrik (Cosine Similarity, Dot Product, euklidische Distanz) hängt direkt davon ab, ob die Vektoren normalisiert sind.
Beispiel: In einer Vektordatenbank wie Qdrant oder Milvus wird beim Erstellen einer Collection die Distanzmetrik festgelegt. Sind alle Vektoren normalisiert, liefern Cosine Similarity und Dot Product identische Rankings. Dot Product ist rechnerisch günstiger (kein Nenner), weshalb viele Systeme bei normalisierten Vektoren die Metrik "Inner Product" empfehlen.
Beispiel: Ein Unternehmen migriert von einem Embedding-Modell (Modell A, normalisiert) auf ein neueres (Modell B, nicht normalisiert). Die bestehende Collection nutzt Dot Product als Metrik. Nach der Migration liefern Abfragen schlechtere Ergebnisse, weil die neuen Vektoren unterschiedliche Beträge haben. Die Lösung: Normalisierung vor dem Einfügen in die Datenbank, oder Umstellung der Metrik auf Cosine Similarity.
Normalisierung im Modelltraining
Beim Training von Embedding-Modellen spielt Normalisierung eine doppelte Rolle: Sie beeinflusst die Loss-Funktion und damit das Lernverhalten des Modells.
Viele Embedding-Modelle werden mit einer Contrastive-Loss-Funktion trainiert. Diese Funktion bestraft das Modell, wenn ähnliche Texte weit auseinander liegen und unähnliche Texte nah beieinander. Die Ähnlichkeit wird über Cosine Similarity gemessen. Damit Cosine Similarity stabil funktioniert, normalisiert die Loss-Funktion die Vektoren vor dem Vergleich.
Beispiel: Beim Fine-Tuning eines Sentence-Transformer-Modells mit MultipleNegativesRankingLoss werden die Vektoren intern normalisiert, bevor die Cosine Similarity berechnet wird. Das Modell lernt dadurch, ähnliche Texte in ähnliche Richtungen zu projizieren, unabhängig von der Vektorlänge.
Beispiel: Ein Team trainiert ein Embedding-Modell mit einer Dot-Product-Loss-Funktion ohne Normalisierung. Das Modell lernt, häufigen Texten längere Vektoren zuzuweisen, weil längere Vektoren bei Dot Product höhere Werte erzeugen. Das Ergebnis ist ein Bias zugunsten häufiger Texte, nicht zugunsten relevanter.
Implementierung in der Praxis
Die Normalisierung eines Vektors ist in jeder Programmiersprache mit wenigen Zeilen umsetzbar. Die meisten Frameworks bieten dafür optimierte Funktionen.
In Python mit NumPy: v_norm = v / np.linalg.norm(v). In PyTorch: v_norm = torch.nn.functional.normalize(v, dim=-1). Beide Varianten führen dieselbe L2-Normalisierung durch.
Beispiel: Eine Anwendung verarbeitet 100.000 Dokumente. Jedes Dokument wird durch ein Embedding-Modell geschickt, das nicht-normalisierte Vektoren liefert. Die Normalisierung aller 100.000 Vektoren (768 Dimensionen) dauert auf einer Standard-CPU unter 0,5 Sekunden mit NumPy. Der Rechenaufwand der Normalisierung ist gegenüber der Embedding-Erzeugung vernachlässigbar.
Beispiel: Ein Entwickler setzt normalize_embeddings=True im Sentence-Transformers-Aufruf. Diese Option normalisiert jeden Vektor direkt nach der Erzeugung. Ein separater Normalisierungsschritt in der Pipeline entfällt. Das reduziert die Code-Komplexität und eliminiert eine potenzielle Fehlerquelle (vergessene Normalisierung einzelner Vektoren).
Grenzen und Einschränkungen der Normalisierung
Normalisierung verwirft bewusst eine Information: die Länge des Vektors. In den meisten Embedding-Anwendungen ist die Länge irrelevant und störend. Es gibt jedoch Szenarien, in denen die Länge eines Vektors eine eigenständige Aussagekraft hat.
Beispiel: Einige Forschungsarbeiten zeigen, dass die Länge von BERT-Vektoren mit der "Sicherheit" des Modells korreliert. Vektoren für eindeutige Texte ("Die Hauptstadt von Frankreich ist Paris") sind tendenziell länger als Vektoren für mehrdeutige Texte. Normalisierung entfernt dieses Signal.
Beispiel: In Anomalie-Erkennungs-Systemen kann ein ungewöhnlich kurzer oder langer Vektor auf einen Ausreißer im Eingabetext hinweisen (z. B. ein Dokument in einer unerwarteten Sprache). Nach Normalisierung ist dieser Hinweis nicht mehr erkennbar.
Normalisierung setzt voraus, dass alle Vektoren aus demselben Modell stammen. Vektoren verschiedener Modelle in denselben Raum zu normalisieren ist nicht sinnvoll, da die Modelle unterschiedliche Bedeutungsräume aufspannen. Richtungen, die in Modell A "Finanzen" repräsentieren, haben in Modell B keine definierte Bedeutung.
Fachliche Einordnung: Aktuelle Forschung (Matryoshka Representation Learning, 2022) untersucht, ob kürzere Vektoren (mit weniger Dimensionen) nach Normalisierung vergleichbare Ergebnisse liefern. Dieser Ansatz ermöglicht adaptive Genauigkeit: hohe Dimensionszahl für präzise Abfragen, niedrige für schnelle Vorfilterung. OpenAI und Cohere bieten diese Funktion in ihren neuesten Modellen an.