ist eine häufig verwendete Metrik zur Operationalisierung von Aufgaben wie semantischer Such- und Dokumentvergleich im Bereich der Verarbeitung natürlicher Sprache (NLP). Einführende NLP-Kurse bieten häufig nur eine hochrangige Rechtfertigung für die Verwendung von Cosinus-Ähnlichkeit bei solchen Aufgaben (im Gegensatz zu beispielsweise euklidischer Distanz), ohne die zugrunde liegende Mathematik zu erklären, sodass viele Datenwissenschaftler ein ziemlich vage Verständnis des Themas haben. Um diese Lücke zu lösen, legt der folgende Artikel die mathematische Instinct hinter der Kosinus-Ähnlichkeitsmetrik fest und zeigt, wie dies uns helfen kann, Ergebnisse in der Praxis mit praktischen Beispielen in Python zu interpretieren.
Notiz: Alle Zahlen und Formeln in den folgenden Abschnitten wurden vom Autor dieses Artikels erstellt.
Mathematische Instinct
Die Kosinus -Ähnlichkeitsmetrik basiert auf der Cosinus -Funktion, an die sich die Leser aus der Mathematik der Excessive Faculty erinnern können. Die Kosinusfunktion zeigt ein sich wiederholendes Wellenmuster, dessen Vollzyklus in Abbildung 1 unten für den Bereich 0 <= dargestellt ist X <= 2*Pi. Der Python -Code, der zur Erzeugung der Abbildung verwendet wird, wird ebenfalls als Referenz enthalten.
import numpy as np
import matplotlib.pyplot as plt
# Outline the x vary from 0 to 2*pi
x = np.linspace(0, 2 * np.pi, 500)
y = np.cos(x)
# Create the plot
plt.determine(figsize=(8, 4))
plt.plot(x, y, label='cos(x)', colour='blue')
# Add notches on the x-axis at pi/2 and three*pi/2
notch_positions = (0, np.pi/2, np.pi, 3*np.pi/2, 2*np.pi)
notch_labels = ('0', 'pi/2', 'pi', '3*pi/2', '2*pi')
plt.xticks(ticks=notch_positions, labels=notch_labels)
# Add customized horizontal gridlines solely at y = -1, 0, 1
for y_val in (-1, 0, 1):
plt.axhline(y=y_val, colour='grey', linestyle='--', linewidth=0.5)
# Add vertical gridlines at specified x-values
for x_val in notch_positions:
plt.axvline(x=x_val, colour='grey', linestyle='--', linewidth=0.5)
# Customise the plot
plt.xlabel("x")
plt.ylabel("cos(x)")
# Last structure and show
plt.tight_layout()
plt.present()

Der Funktionsparameter X bezeichnet einen Winkel in Radians (z. B. den Winkel zwischen zwei Vektoren in einem Einbettungsraum), wo Pi/2,, Pi3*Pi/2 und 2*Pisind 90, 180, 270 bzw. 360 Grad.
Um zu verstehen, warum die Cosinusfunktion als nützliche Grundlage für die Gestaltung einer Vektor -Ähnlichkeitsmetrik dienen kann, beachten Sie, dass die grundlegende Cosinusfunktion ohne funktionale Transformationen, wie in Abbildung 1 gezeigt, Maxima bei x = 2* hatA*Piminima bei x = (2*B + 1)*Piund Wurzeln bei x = ((C + 1/2)*Pi Für einige ganze Zahlen AAnwesend BUnd C. Mit anderen Worten, wenn X bezeichnet den Winkel zwischen zwei Vektoren, cos (x) Gibt den größten Wert zurück, wenn die Vektoren in die gleiche Richtung zeigen, den kleinsten Wert, wenn die Vektoren in entgegengesetzte Richtungen zeigen, und Null, wenn die Vektoren orthogonal zueinander sind.
Dieses Verhalten der Cosinusfunktion erfasst das Zusammenspiel zwischen zwei Schlüsselkonzepten in NLP: Semantische Überlappung (vermitteln, wie viel Bedeutung zwischen zwei Texten geteilt wird) und Semantische Polarität (Erfassen Sie die Gegenwart der Bedeutung in Texten). Zum Beispiel hätten die Texte „Ich mochte diesen Movie“ und „Ich habe diesen Movie genossen“ eine hohe semantische Überlappung (sie drücken im Wesentlichen die gleiche Bedeutung aus, obwohl sie unterschiedliche Wörter verwenden) und eine niedrige semantische Polarität (sie drücken nicht entgegengesetzte Bedeutungen aus). Wenn die Einbettungsvektoren für zwei Wörter sowohl semantische Überlappungen als auch Polarität codieren, würden wir erwarten, dass Synonyme eine Cosinus -Ähnlichkeit auf 1 nähern, die Antonyme eine Cosinus -Ähnlichkeit auf -1 und nicht verwandte Wörter haben, um sich mit einer Cosinus -Ähnlichkeit 0 zu nähern.
In der Praxis werden wir den Winkel normalerweise nicht kennen X direkt. Stattdessen müssen wir den Cosinuswert von den Vektoren selbst ableiten. Mit zwei Vektoren U Und Vjeder mit N Elemente, die Cosinus des Winkels zwischen diesen Vektoren – entspricht der Kosinus -Ähnlichkeitsmetrik – wird als Punktprodukt der Vektoren berechnet, die durch das Produkt der Vektorgrößen geteilt sind:

Die obige Formel für den Cosinus des Winkels zwischen zwei Vektoren kann aus der sogenannten Cosinus-Regel abgeleitet werden, wie im Section zwischen den Minuten 12 und 18 dieses Movies gezeigt wird:
In diesem Video wird ein ordentlicher Beweis für die Cosinus -Regel selbst vorgestellt:
Die folgende Python-Implementierung von Cosinus-Ähnlichkeit operationalisiert explizit die oben dargestellten Formeln, ohne sich auf Schwarzbox-Pakete zu verlassen:
import math
def cosine_similarity(U, V):
if len(U) != len(V):
increase ValueError("Vectors should be of the identical size.")
# Compute dot product and magnitudes
dot_product = sum(u * v for u, v in zip(U, V))
magnitude_U = math.sqrt(sum(u ** 2 for u in U))
magnitude_V = math.sqrt(sum(v ** 2 for v in V))
# Zero vector dealing with to keep away from division by zero
if magnitude_U == 0 or magnitude_V == 0:
increase ValueError("Can not compute cosine similarity for zero-magnitude vectors.")
return dot_product / (magnitude_U * magnitude_V)
Interessierte Leser können sich beziehen Das Artikel für eine effizientere Python -Implementierung der Cosinus entfernt Metrik (definiert als 1 minus Cosinus -Ähnlichkeit) unter Verwendung der Numpy- und Scipy -Pakete.
Schließlich lohnt es sich, die mathematische Instinct der Ähnlichkeit der Cosinus (oder der Entfernung) mit der von zu vergleichen Euklidische Entfernungwas den linearen Abstand zwischen zwei Vektoren misst und auch als Vektorähnlichkeitsmetrik dienen kann. Je niedriger der euklidische Abstand zwischen zwei Vektoren ist, desto höher ist ihre semantische Ähnlichkeit wahrscheinlich. Der euklidische Abstand zwischen zwei Vektoren U Und V (jeweils Länge N) kann mit der folgenden Formel berechnet werden:

Unten finden Sie die entsprechende Python -Implementierung:
import math
def euclidean_distance(U, V):
if len(U) != len(V):
increase ValueError("Vectors should be of the identical size.")
# Compute sum of squared variations
sum_squared_diff = sum((u - v) ** 2 for u, v in zip(U, V))
# Take the sq. root of the sum
return math.sqrt(sum_squared_diff)
Beachten Sie, dass die resultierende Metrik immer eine nicht damaging Zahl sein wird, da die elementalen Unterschiede in der euklidischen Entfernungsformel quadratisch sind-Null, wenn die Vektoren ansonsten identisch und positiv sind. Im NLP -Kontext impliziert dies, dass die euklidische Distanz die semantische Polarität nicht so widerspiegelt, wie der Cosinus -Distanz. Solange zwei Vektoren in die gleiche Richtung zeigen, bleibt der Cosinus des Winkels zwischen ihnen unabhängig von den Vektorgrößen gleich. Im Gegensatz dazu wird die euklidische Distanzmetrik durch Unterschiede in der Vektorgröße beeinflusst, was zu irreführenden Interpretationen in der Praxis führen kann (z. B. zwei Texte unterschiedlicher Längen können zu einem hohen euklidischen Abstand führen, obwohl sie semantisch ähnlich sind). Die Ähnlichkeit der Cosinus ist daher die bevorzugte Metrik in vielen NLP -Szenarien, in denen die Bestimmung der Vektor – oder der semantischen – Direktionalität das Hauptanliegen ist.
Theorie versus Praxis
In einem praktischen NLP -Szenario hängt die Interpretation von Cosinus -Ähnlichkeit auf das Ausmaß ab, in dem der Vektor eine Polarität und semantische Überlappung codiert. Im folgenden praktischen Beispiel werden wir die Ähnlichkeit zwischen zwei gegebenen Wörtern unter Verwendung eines vorbereiteten Einbettungsmodells untersuchen, das die Polarität nicht codiert ((All-Minilm-L6-V2) und eine, die (DISTILBERT-BASE-OCKUSTED-FINETUNED-SST-2-ENGLISH). Wir werden auch effizientere Implementierungen von Cosinus -Ähnlichkeit und euklidischer Entfernung verwenden, indem wir Funktionen nutzen, die vom Scipy -Paket bereitgestellt werden.
from scipy.spatial.distance import cosine as cosine_distance
from sentence_transformers import SentenceTransformer
from transformers import AutoTokenizer, AutoModel
import torch
# Phrases to embed
phrases = ("film", "movie", "good", "dangerous", "spoon", "automobile")
# Load a pre-trained embedding mannequin from Hugging Face
model_1 = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
model_2_name = "distilbert-base-uncased-finetuned-sst-2-english"
model_2_tokenizer = AutoTokenizer.from_pretrained(model_2_name)
model_2 = AutoModel.from_pretrained(model_2_name)
# Generate embeddings for mannequin 1
embeddings_1 = dict(zip(phrases, model_1.encode(phrases)))
# Generate embeddings for mannequin 2
inputs = model_2_tokenizer(phrases, padding=True, truncation=True, return_tensors="pt")
with torch.no_grad():
outputs = model_2(**inputs)
embedding_vectors_model_2 = outputs.last_hidden_state.imply(dim=1)
embeddings_2 = {phrase: vector for phrase, vector in zip(phrases, embedding_vectors_model_2)}
# Compute and print cosine similarity (1 - cosine distance) for each embedding fashions
print("Cosine similarity for embedding mannequin 1:")
print("film", "t", "movie", "t", 1 - cosine_distance(embeddings_1("film"), embeddings_1("movie")))
print("good", "t", "dangerous", "t", 1 - cosine_distance(embeddings_1("good"), embeddings_1("dangerous")))
print("spoon", "t", "automobile", "t", 1 - cosine_distance(embeddings_1("spoon"), embeddings_1("automobile")))
print()
print("Cosine similarity for embedding mannequin 2:")
print("film", "t", "movie", "t", 1 - cosine_distance(embeddings_2("film"), embeddings_2("movie")))
print("good", "t", "dangerous", "t", 1 - cosine_distance(embeddings_2("good"), embeddings_2("dangerous")))
print("spoon", "t", "automobile", "t", 1 - cosine_distance(embeddings_2("spoon"), embeddings_2("automobile")))
print()
Ausgabe:
Cosine similarity for embedding mannequin 1:
film movie 0.8426464702276286
good dangerous 0.5871497042685934
spoon automobile 0.22919675707817078
Cosine similarity for embedding mannequin 2:
film movie 0.9638281550070811
good dangerous -0.3416433451550165
spoon automobile 0.5418748837234599
Die Wörter „Movie“ und „Movie“, die typischerweise als Synonyme verwendet werden, haben eine Cosinus -Ähnlichkeit in der Nähe von 1, was wie erwartet eine hohe semantische Überlappung hindeutet. Die Wörter „intestine“ und „schlecht“ sind Antonyme, und wir sehen, dass dies in dem negativen Ergebnis der Kosinus -Ähnlichkeit widerspiegelt werden, wenn das zweite Einbettungsmodell, von dem bekannt ist, dass es semantische Polarität kodiert. Schließlich sind die Wörter „Löffel“ und „Auto“ semantisch nicht verwandt, und die entsprechende Orthogonalität ihrer Vektor -Einbettungen wird durch ihre Kosinus -Ähnlichkeitsergebnisse angezeigt, die näher an Null sind als für „Movie“ und „Movie“.
Der Wrap
Die Kosinusähnlichkeit zwischen zwei Vektoren basiert auf dem Cosinus des Winkels, den sie bilden, und ist – im Gegensatz zu Metriken wie euklidischer Entfernung – nicht empfindlich gegenüber Unterschieden in den Vektorgrößen. Theoretisch sollte die Ähnlichkeit der Kosinus in der Nähe von 1 liegen, wenn die Vektoren in die gleiche Richtung (was auf hohe Ähnlichkeit angibt), nahe -1, wenn die Vektoren in entgegengesetzte Richtungen (was auf hohe Unähnlichkeit anzeigen) und nahe 0, wenn die Vektoren orthogonal sind (was auf Unbeeinflussung hinweist). Die genaue Interpretation der Kosinus -Ähnlichkeit in einem bestimmten NLP -Szenario hängt jedoch von der Artwork des Einbettungsmodells ab, mit dem die Textdaten vektorisiert werden (z. B. unabhängig davon, ob das Einbettungsmodell eine Polarität zusätzlich zu semantischer Überlappung codiert).
